diff options
543 files changed, 4723 insertions, 36478 deletions
diff --git a/Android.bp b/Android.bp index 1d80153fb8cd..35879df4b852 100644 --- a/Android.bp +++ b/Android.bp @@ -465,6 +465,7 @@ java_library { "android.hardware.radio-V1.3-java", "android.hardware.radio-V1.4-java", "android.hardware.radio-V1.5-java", + "android.hardware.radio-V1.6-java", "android.hardware.thermal-V1.0-java-constants", "android.hardware.thermal-V1.0-java", "android.hardware.thermal-V1.1-java", @@ -580,6 +581,7 @@ java_library { "//frameworks/base/apex/blobstore/framework", "//frameworks/base/apex/jobscheduler/framework", "//frameworks/base/packages/Tethering/tests/unit", + "//packages/modules/Connectivity/Tethering/tests/unit", ], } @@ -1173,22 +1175,6 @@ filegroup { } // Avoid including Parcelable classes as we don't want to have two copies of -// Parcelable cross the process. This is used by framework-telephony (frameworks/base/telephony). -filegroup { - name: "framework-telephony-shared-srcs", - srcs: [ - "core/java/android/util/RecurrenceRule.java", - "core/java/com/android/internal/os/SomeArgs.java", - "core/java/com/android/internal/util/BitwiseInputStream.java", - "core/java/com/android/internal/util/BitwiseOutputStream.java", - "core/java/com/android/internal/util/FunctionalUtils.java", - "core/java/com/android/internal/util/HexDump.java", - "core/java/com/android/internal/util/IndentingPrintWriter.java", - "core/java/com/android/internal/util/Preconditions.java", - ], -} - -// Avoid including Parcelable classes as we don't want to have two copies of // Parcelable cross the process. filegroup { name: "framework-cellbroadcast-shared-srcs", @@ -1284,43 +1270,3 @@ build = [ "StubLibraries.bp", "ApiDocs.bp", ] - -java_library { - name: "framework-telephony", - srcs: [ - //":framework-telephony-sources", - //":framework-telephony-shared-srcs", - ], - // TODO: change to framework-system-stub to build against system APIs. - libs: [ - "framework-minus-apex", - "unsupportedappusage", - ], - static_libs: [ - "libphonenumber-platform", - "app-compat-annotations", - ], - sdk_version: "core_platform", - aidl: { - export_include_dirs: ["telephony/java"], - include_dirs: [ - "frameworks/native/aidl/binder", - "frameworks/native/aidl/gui", - ] - }, - jarjar_rules: ":framework-telephony-jarjar-rules", - dxflags: [ - "--core-library", - "--multi-dex", - ], - // This is to break the dependency from boot jars. - dex_preopt: { - enabled: false, - }, - installable: true, -} - -filegroup { - name: "framework-telephony-jarjar-rules", - srcs: ["telephony/framework-telephony-jarjar-rules.txt"], -} diff --git a/StubLibraries.bp b/StubLibraries.bp index 39aa732d929b..9047df5aba5c 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -73,6 +73,7 @@ stubs_defaults { "android.hardware.vibrator-V1.3-java", "framework-protos", ], + high_mem: true, // Lots of sources => high memory use, see b/170701554 installable: false, annotations_enabled: true, previous_api: ":android.api.public.latest", @@ -147,8 +148,8 @@ droidstubs { args: metalava_framework_docs_args, check_api: { current: { - api_file: "non-updatable-api/current.txt", - removed_api_file: "non-updatable-api/removed.txt", + api_file: "core/api/current.txt", + removed_api_file: "core/api/removed.txt", }, last_released: { api_file: ":android-non-updatable.api.public.latest", @@ -207,8 +208,8 @@ droidstubs { args: metalava_framework_docs_args + priv_apps, check_api: { current: { - api_file: "non-updatable-api/system-current.txt", - removed_api_file: "non-updatable-api/system-removed.txt", + api_file: "core/api/system-current.txt", + removed_api_file: "core/api/system-removed.txt", }, last_released: { api_file: ":android-non-updatable.api.system.latest", @@ -218,7 +219,7 @@ droidstubs { api_lint: { enabled: true, new_since: ":android-non-updatable.api.system.latest", - baseline_file: "non-updatable-api/system-lint-baseline.txt", + baseline_file: "core/api/system-lint-baseline.txt", }, }, } @@ -252,46 +253,19 @@ droidstubs { } ///////////////////////////////////////////////////////////////////// -// Following droidstubs modules are for extra APIs for modules, +// Following droidstub module for extra APIs for modules, // namely @SystemApi(client=MODULE_LIBRARIES) APIs. ///////////////////////////////////////////////////////////////////// droidstubs { - name: "module-lib-api", - defaults: ["metalava-full-api-stubs-default"], - arg_files: ["core/res/AndroidManifest.xml"], - args: metalava_framework_docs_args + module_libs, - - // 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", - }, - last_released: { - api_file: ":android.api.module-lib.latest", - removed_api_file: ":removed.api.module-lib.latest", - baseline_file: ":module-lib-api-incompatibilities-with-last-released" - }, - api_lint: { - enabled: true, - new_since: ":android.api.module-lib.latest", - baseline_file: "api/module-lib-lint-baseline.txt", - }, - }, -} - -droidstubs { name: "module-lib-api-stubs-docs-non-updatable", defaults: ["metalava-non-updatable-api-stubs-default"], arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + priv_apps + module_libs, check_api: { current: { - api_file: "non-updatable-api/module-lib-current.txt", - removed_api_file: "non-updatable-api/module-lib-removed.txt", + api_file: "core/api/module-lib-current.txt", + removed_api_file: "core/api/module-lib-removed.txt", }, last_released: { api_file: ":android-non-updatable.api.module-lib.latest", diff --git a/apct-tests/perftests/textclassifier/run.sh b/apct-tests/perftests/textclassifier/run.sh index d36d190a573a..9a0f4f9fab73 100755 --- a/apct-tests/perftests/textclassifier/run.sh +++ b/apct-tests/perftests/textclassifier/run.sh @@ -1,8 +1,8 @@ set -e -build/soong/soong_ui.bash --make-mode TextClassifierPerfTests perf-setup.sh +build/soong/soong_ui.bash --make-mode TextClassifierPerfTests perf-setup adb install ${OUT}/testcases/TextClassifierPerfTests/arm64/TextClassifierPerfTests.apk adb shell cmd package compile -m speed -f com.android.perftests.textclassifier -adb push ${OUT}/obj/EXECUTABLES/perf-setup.sh_intermediates/perf-setup.sh /data/local/tmp/ +adb push ${OUT}/obj/EXECUTABLES/perf-setup_intermediates/perf-setup.sh /data/local/tmp/ adb shell chmod +x /data/local/tmp/perf-setup.sh adb shell /data/local/tmp/perf-setup.sh -adb shell am instrument -w -e package android.view.textclassifier com.android.perftests.textclassifier/androidx.test.runner.AndroidJUnitRunner
\ No newline at end of file +adb shell am instrument -w -e package android.view.textclassifier com.android.perftests.textclassifier/androidx.test.runner.AndroidJUnitRunner diff --git a/apex/Android.bp b/apex/Android.bp index cabed3b44d41..c5b4901a9b79 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -147,141 +147,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/Android.bp b/apex/extservices/testing/Android.bp deleted file mode 100644 index 88a47246c824..000000000000 --- a/apex/extservices/testing/Android.bp +++ /dev/null @@ -1,25 +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_test { - name: "test_com.android.extservices", - visibility: [ - "//system/apex/tests", - ], - defaults: ["com.android.extservices-defaults"], - manifest: "test_manifest.json", - file_contexts: ":com.android.extservices-file_contexts", - // Test APEX, should never be installed - installable: false, -} 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 22b8c456f655..c2e75cd14968 100644 --- a/api/current.txt +++ b/api/current.txt @@ -45977,6 +45977,7 @@ package android.telecom { field public static final int MISSED = 5; // 0x5 field public static final int OTHER = 9; // 0x9 field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; + field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; field public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED"; field public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF"; field public static final int REJECTED = 6; // 0x6 @@ -46887,6 +46888,7 @@ package android.telephony { } public static final class CarrierConfigManager.Ims { + field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool"; field public static final String KEY_PREFIX = "ims."; field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int"; } @@ -47669,6 +47671,7 @@ package android.telephony { method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); method @Nullable public android.telephony.CellIdentity getCellIdentity(); method public int getDomain(); + method public int getNrState(); method @Nullable public String getRegisteredPlmn(); method public int getTransportType(); method public boolean isRegistered(); @@ -47800,6 +47803,7 @@ package android.telephony { method public void onDataConnectionStateChanged(int); method public void onDataConnectionStateChanged(int, int); method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo); + method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo); method public void onMessageWaitingIndicatorChanged(boolean); method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); @@ -48317,7 +48321,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(); @@ -48338,7 +48344,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(); @@ -48386,6 +48393,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 2f0ae78f7e2d..000000000000 --- a/api/module-lib-current.txt +++ /dev/null @@ -1,81 +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.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/system-current.txt b/api/system-current.txt index 6475d81067cd..5ea8e438d064 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6257,6 +6257,7 @@ package android.net { method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 + field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } @@ -8991,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"; @@ -10270,10 +10272,6 @@ package android.telecom { method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference); } - public final class DisconnectCause implements android.os.Parcelable { - field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; - } - public abstract class InCallService extends android.app.Service { method @Deprecated public android.telecom.Phone getPhone(); method @Deprecated public void onPhoneCreated(android.telecom.Phone); @@ -10543,6 +10541,22 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR; } + public final class CallForwardingInfo implements android.os.Parcelable { + ctor public CallForwardingInfo(boolean, int, @Nullable String, int); + method public int describeContents(); + method @Nullable public String getNumber(); + method public int getReason(); + method public int getTimeoutSeconds(); + method public boolean isEnabled(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR; + field public static final int REASON_ALL = 4; // 0x4 + field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5 + field public static final int REASON_BUSY = 1; // 0x1 + field public static final int REASON_NOT_REACHABLE = 3; // 0x3 + field public static final int REASON_NO_REPLY = 2; // 0x2 + field public static final int REASON_UNCONDITIONAL = 0; // 0x0 + } + public final class CallQuality implements android.os.Parcelable { ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean); @@ -10814,8 +10828,10 @@ package android.telephony { public class PhoneStateListener { method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes); - method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); - method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); + method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -11183,6 +11199,8 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); @@ -11230,13 +11248,13 @@ 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(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); @@ -11260,11 +11278,14 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); 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); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); @@ -11297,6 +11318,10 @@ package android.telephony { field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; + field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 + field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1 + field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4 + field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3 field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 @@ -11311,6 +11336,8 @@ package android.telephony { field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff field public static final int KEY_TYPE_EPDG = 1; // 0x1 field public static final int KEY_TYPE_WLAN = 2; // 0x2 + field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1 + field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2 field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L @@ -11351,6 +11378,15 @@ package android.telephony { field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 } + public static interface TelephonyManager.CallForwardingInfoCallback { + method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo); + method public void onError(int); + field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 2; // 0x2 + field public static final int RESULT_ERROR_NOT_SUPPORTED = 3; // 0x3 + field public static final int RESULT_ERROR_UNKNOWN = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + } + public final class UiccAccessRule implements android.os.Parcelable { ctor public UiccAccessRule(byte[], @Nullable String, long); method public int describeContents(); @@ -11428,11 +11464,11 @@ package android.telephony.data { method public int getSuggestedRetryTime(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR; - field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 2; // 0x2 - field public static final int HANDOVER_FAILURE_MODE_LEGACY = 1; // 0x1 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 3; // 0x3 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 4; // 0x4 - field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = 0; // 0x0 + field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1 + field public static final int HANDOVER_FAILURE_MODE_LEGACY = 0; // 0x0 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2; // 0x2 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3; // 0x3 + field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = -1; // 0xffffffff field public static final int LINK_STATUS_ACTIVE = 2; // 0x2 field public static final int LINK_STATUS_DORMANT = 1; // 0x1 field public static final int LINK_STATUS_INACTIVE = 0; // 0x0 @@ -11904,6 +11940,10 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; } + public class ImsManager { + method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int); + } + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; @@ -11939,10 +11979,13 @@ package android.telephony.ims { method public void disableIms(int); method public void enableIms(int); method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public long getImsServiceCapabilities(); method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); + field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L } public final class ImsSsData implements android.os.Parcelable { @@ -12188,6 +12231,10 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } + public class SipDelegateManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException; + } + } package android.telephony.ims.feature { @@ -12437,6 +12484,10 @@ package android.telephony.ims.stub { method public int updateColr(int); } + public class SipTransportImplBase { + ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); + } + } package android.telephony.mbms { diff --git a/api/test-current.txt b/api/test-current.txt index bdf797e80ccc..9c517296d35c 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -876,6 +876,14 @@ package android.media { field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate"; } + public abstract class Image implements java.lang.AutoCloseable { + ctor protected Image(); + } + + public abstract static class Image.Plane { + ctor protected Image.Plane(); + } + public final class MediaCas implements java.lang.AutoCloseable { method public void forceResourceLost(); } @@ -1627,6 +1635,12 @@ package android.telephony { method public static void setMinMatchForTest(int); } + public class PhoneStateListener { + method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); + method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int); + } + public final class PreciseDataConnectionState implements android.os.Parcelable { ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int); } @@ -1658,10 +1672,14 @@ package android.telephony { method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag(); method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int); method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile(); method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String); method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); + field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1 + field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2 field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff } diff --git a/non-updatable-api/Android.bp b/core/api/Android.bp index 00b901992b90..00b901992b90 100644 --- a/non-updatable-api/Android.bp +++ b/core/api/Android.bp diff --git a/non-updatable-api/current.txt b/core/api/current.txt index da3d0f7ff059..ab0aec73346b 100644 --- a/non-updatable-api/current.txt +++ b/core/api/current.txt @@ -44145,6 +44145,7 @@ package android.telecom { field public static final int MISSED = 5; // 0x5 field public static final int OTHER = 9; // 0x9 field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; + field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; field public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED"; field public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF"; field public static final int REJECTED = 6; // 0x6 @@ -45055,6 +45056,7 @@ package android.telephony { } public static final class CarrierConfigManager.Ims { + field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool"; field public static final String KEY_PREFIX = "ims."; field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int"; } @@ -45837,6 +45839,7 @@ package android.telephony { method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); method @Nullable public android.telephony.CellIdentity getCellIdentity(); method public int getDomain(); + method public int getNrState(); method @Nullable public String getRegisteredPlmn(); method public int getTransportType(); method public boolean isRegistered(); @@ -45968,6 +45971,7 @@ package android.telephony { method public void onDataConnectionStateChanged(int); method public void onDataConnectionStateChanged(int, int); method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo); + method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo); method public void onMessageWaitingIndicatorChanged(boolean); method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); @@ -46485,7 +46489,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(); @@ -46506,7 +46512,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(); @@ -46554,6 +46561,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/non-updatable-api/module-lib-current.txt b/core/api/module-lib-current.txt index d4d9f62964c8..198134edbb5b 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -26,6 +26,18 @@ package android.os { } +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 { diff --git a/api/module-lib-removed.txt b/core/api/module-lib-removed.txt index d802177e249b..d802177e249b 100644 --- a/api/module-lib-removed.txt +++ b/core/api/module-lib-removed.txt diff --git a/non-updatable-api/removed.txt b/core/api/removed.txt index 3655af222248..3655af222248 100644 --- a/non-updatable-api/removed.txt +++ b/core/api/removed.txt diff --git a/non-updatable-api/system-current.txt b/core/api/system-current.txt index 7d5d0a65d43e..7db113db8e7e 100644 --- a/non-updatable-api/system-current.txt +++ b/core/api/system-current.txt @@ -6205,6 +6205,7 @@ package android.net { method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 + field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } @@ -7882,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"; @@ -9152,10 +9154,6 @@ package android.telecom { method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference); } - public final class DisconnectCause implements android.os.Parcelable { - field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; - } - public abstract class InCallService extends android.app.Service { method @Deprecated public android.telecom.Phone getPhone(); method @Deprecated public void onPhoneCreated(android.telecom.Phone); @@ -9425,6 +9423,22 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR; } + public final class CallForwardingInfo implements android.os.Parcelable { + ctor public CallForwardingInfo(boolean, int, @Nullable String, int); + method public int describeContents(); + method @Nullable public String getNumber(); + method public int getReason(); + method public int getTimeoutSeconds(); + method public boolean isEnabled(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR; + field public static final int REASON_ALL = 4; // 0x4 + field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5 + field public static final int REASON_BUSY = 1; // 0x1 + field public static final int REASON_NOT_REACHABLE = 3; // 0x3 + field public static final int REASON_NO_REPLY = 2; // 0x2 + field public static final int REASON_UNCONDITIONAL = 0; // 0x0 + } + public final class CallQuality implements android.os.Parcelable { ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean); @@ -9696,8 +9710,10 @@ package android.telephony { public class PhoneStateListener { method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes); - method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); - method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); + method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -10065,6 +10081,8 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); @@ -10112,13 +10130,13 @@ 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(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); @@ -10142,11 +10160,14 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); 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); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); @@ -10179,6 +10200,10 @@ package android.telephony { field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; + field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 + field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1 + field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4 + field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3 field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 @@ -10193,6 +10218,8 @@ package android.telephony { field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff field public static final int KEY_TYPE_EPDG = 1; // 0x1 field public static final int KEY_TYPE_WLAN = 2; // 0x2 + field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1 + field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2 field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L @@ -10233,6 +10260,15 @@ package android.telephony { field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 } + public static interface TelephonyManager.CallForwardingInfoCallback { + method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo); + method public void onError(int); + field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 2; // 0x2 + field public static final int RESULT_ERROR_NOT_SUPPORTED = 3; // 0x3 + field public static final int RESULT_ERROR_UNKNOWN = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + } + public final class UiccAccessRule implements android.os.Parcelable { ctor public UiccAccessRule(byte[], @Nullable String, long); method public int describeContents(); @@ -10310,11 +10346,11 @@ package android.telephony.data { method public int getSuggestedRetryTime(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR; - field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 2; // 0x2 - field public static final int HANDOVER_FAILURE_MODE_LEGACY = 1; // 0x1 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 3; // 0x3 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 4; // 0x4 - field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = 0; // 0x0 + field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1 + field public static final int HANDOVER_FAILURE_MODE_LEGACY = 0; // 0x0 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2; // 0x2 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3; // 0x3 + field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = -1; // 0xffffffff field public static final int LINK_STATUS_ACTIVE = 2; // 0x2 field public static final int LINK_STATUS_DORMANT = 1; // 0x1 field public static final int LINK_STATUS_INACTIVE = 0; // 0x0 @@ -10786,6 +10822,10 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; } + public class ImsManager { + method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int); + } + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; @@ -10821,10 +10861,13 @@ package android.telephony.ims { method public void disableIms(int); method public void enableIms(int); method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public long getImsServiceCapabilities(); method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); + field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L } public final class ImsSsData implements android.os.Parcelable { @@ -11070,6 +11113,10 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } + public class SipDelegateManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException; + } + } package android.telephony.ims.feature { @@ -11319,6 +11366,10 @@ package android.telephony.ims.stub { method public int updateColr(int); } + public class SipTransportImplBase { + ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); + } + } package android.telephony.mbms { diff --git a/non-updatable-api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index 395ddc16913d..395ddc16913d 100644 --- a/non-updatable-api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt diff --git a/non-updatable-api/system-removed.txt b/core/api/system-removed.txt index 0c02c43b1084..0c02c43b1084 100644 --- a/non-updatable-api/system-removed.txt +++ b/core/api/system-removed.txt 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/Instrumentation.java b/core/java/android/app/Instrumentation.java index 721525d9af9d..2ef147b3e903 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -62,6 +62,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * Base class for implementing application instrumentation code. When running @@ -90,6 +91,8 @@ public class Instrumentation { private static final String TAG = "Instrumentation"; + private static final long CONNECT_TIMEOUT_MILLIS = 5000; + /** * @hide */ @@ -2125,6 +2128,13 @@ public class Instrumentation { * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different * flags, the flags on that instance will be changed, and then it will be returned. * </p> + * <p> + * Compatibility mode: This method is infallible for apps targeted for + * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it + * will return null if {@link UiAutomation} fails to connect. The caller can check the return + * value and retry on error. + * </p> + * * @return The UI automation instance. * * @see UiAutomation @@ -2152,6 +2162,12 @@ public class Instrumentation { * If a {@link UiAutomation} exists with different flags, the flags on that instance will be * changed, and then it will be returned. * </p> + * <p> + * Compatibility mode: This method is infallible for apps targeted for + * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it + * will return null if {@link UiAutomation} fails to connect. The caller can check the return + * value and retry on error. + * </p> * * @param flags The flags to be passed to the UiAutomation, for example * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}. @@ -2173,8 +2189,17 @@ public class Instrumentation { } else { mUiAutomation.disconnect(); } - mUiAutomation.connect(flags); - return mUiAutomation; + if (getTargetContext().getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R) { + mUiAutomation.connect(flags); + return mUiAutomation; + } + try { + mUiAutomation.connectWithTimeout(flags, CONNECT_TIMEOUT_MILLIS); + return mUiAutomation; + } catch (TimeoutException e) { + mUiAutomation.destroy(); + mUiAutomation = null; + } } return null; } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 97ef62bf457d..d10e33f1577f 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -131,6 +131,8 @@ import android.net.lowpan.ILowpanManager; import android.net.lowpan.LowpanManager; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; +import android.net.vcn.IVcnManagementService; +import android.net.vcn.VcnManager; import android.net.wifi.WifiFrameworkInitializer; import android.net.wifi.nl80211.WifiNl80211Manager; import android.nfc.NfcManager; @@ -371,6 +373,14 @@ public final class SystemServiceRegistry { ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE)); }}); + registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class, + new CachedServiceFetcher<VcnManager>() { + @Override + public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getService(Context.VCN_MANAGEMENT_SERVICE); + IVcnManagementService service = IVcnManagementService.Stub.asInterface(b); + return new VcnManager(ctx, service); + }}); registerService(Context.IPSEC_SERVICE, IpSecManager.class, new CachedServiceFetcher<IpSecManager>() { diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index a9a06dabc049..e0951bf3f4d2 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -22,6 +22,7 @@ import android.accessibilityservice.AccessibilityService.IAccessibilityServiceCl import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; @@ -60,6 +61,8 @@ import com.android.internal.util.function.pooled.PooledLambda; import libcore.io.IoUtils; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; @@ -116,6 +119,28 @@ public final class UiAutomation { /** Rotation constant: Freeze rotation to 270 degrees . */ public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270; + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + ConnectionState.DISCONNECTED, + ConnectionState.CONNECTING, + ConnectionState.CONNECTED, + ConnectionState.FAILED + }) + private @interface ConnectionState { + /** The initial state before {@link #connect} or after {@link #disconnect} is called. */ + int DISCONNECTED = 0; + /** + * The temporary state after {@link #connect} is called. Will transition to + * {@link #CONNECTED} or {@link #FAILED} depending on whether {@link #connect} succeeds or + * not. + */ + int CONNECTING = 1; + /** The state when {@link #connect} has succeeded. */ + int CONNECTED = 2; + /** The state when {@link #connect} has failed. */ + int FAILED = 3; + } + /** * UiAutomation supresses accessibility services by default. This flag specifies that * existing accessibility services should continue to run, and that new ones may start. @@ -144,12 +169,14 @@ public final class UiAutomation { private long mLastEventTimeMillis; - private boolean mIsConnecting; + private @ConnectionState int mConnectionState = ConnectionState.DISCONNECTED; private boolean mIsDestroyed; private int mFlags; + private int mGenerationId = 0; + /** * Listener for observing the {@link AccessibilityEvent} stream. */ @@ -210,32 +237,55 @@ public final class UiAutomation { } /** - * Connects this UiAutomation to the accessibility introspection APIs with default flags. + * Connects this UiAutomation to the accessibility introspection APIs with default flags + * and default timeout. * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void connect() { - connect(0); + try { + connectWithTimeout(0, CONNECT_TIMEOUT_MILLIS); + } catch (TimeoutException e) { + throw new RuntimeException(e); + } + } + + /** + * Connects this UiAutomation to the accessibility introspection APIs with default timeout. + * + * @hide + */ + public void connect(int flags) { + try { + connectWithTimeout(flags, CONNECT_TIMEOUT_MILLIS); + } catch (TimeoutException e) { + throw new RuntimeException(e); + } } /** * Connects this UiAutomation to the accessibility introspection APIs. * * @param flags Any flags to apply to the automation as it gets connected + * @param timeoutMillis The wait timeout in milliseconds + * + * @throws TimeoutException If not connected within the timeout * * @hide */ - public void connect(int flags) { + public void connectWithTimeout(int flags, long timeoutMillis) throws TimeoutException { synchronized (mLock) { throwIfConnectedLocked(); - if (mIsConnecting) { + if (mConnectionState == ConnectionState.CONNECTING) { return; } - mIsConnecting = true; + mConnectionState = ConnectionState.CONNECTING; mRemoteCallbackThread = new HandlerThread("UiAutomation"); mRemoteCallbackThread.start(); - mClient = new IAccessibilityServiceClientImpl(mRemoteCallbackThread.getLooper()); + // Increment the generation since we are about to interact with a new client + mClient = new IAccessibilityServiceClientImpl( + mRemoteCallbackThread.getLooper(), ++mGenerationId); } try { @@ -248,24 +298,21 @@ public final class UiAutomation { synchronized (mLock) { final long startTimeMillis = SystemClock.uptimeMillis(); - try { - while (true) { - if (isConnectedLocked()) { - break; - } - final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; - final long remainingTimeMillis = CONNECT_TIMEOUT_MILLIS - elapsedTimeMillis; - if (remainingTimeMillis <= 0) { - throw new RuntimeException("Error while connecting " + this); - } - try { - mLock.wait(remainingTimeMillis); - } catch (InterruptedException ie) { - /* ignore */ - } + while (true) { + if (mConnectionState == ConnectionState.CONNECTED) { + break; + } + final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; + final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis; + if (remainingTimeMillis <= 0) { + mConnectionState = ConnectionState.FAILED; + throw new TimeoutException("Timeout while connecting " + this); + } + try { + mLock.wait(remainingTimeMillis); + } catch (InterruptedException ie) { + /* ignore */ } - } finally { - mIsConnecting = false; } } } @@ -289,12 +336,17 @@ public final class UiAutomation { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void disconnect() { synchronized (mLock) { - if (mIsConnecting) { + if (mConnectionState == ConnectionState.CONNECTING) { throw new IllegalStateException( "Cannot call disconnect() while connecting " + this); } - throwIfNotConnectedLocked(); + if (mConnectionState == ConnectionState.DISCONNECTED) { + return; + } + mConnectionState = ConnectionState.DISCONNECTED; mConnectionId = CONNECTION_ID_UNDEFINED; + // Increment the generation so we no longer interact with the existing client + ++mGenerationId; } try { // Calling out without a lock held. @@ -1224,18 +1276,14 @@ public final class UiAutomation { return stringBuilder.toString(); } - private boolean isConnectedLocked() { - return mConnectionId != CONNECTION_ID_UNDEFINED; - } - private void throwIfConnectedLocked() { - if (mConnectionId != CONNECTION_ID_UNDEFINED) { - throw new IllegalStateException("UiAutomation not connected, " + this); + if (mConnectionState == ConnectionState.CONNECTED) { + throw new IllegalStateException("UiAutomation connected, " + this); } } private void throwIfNotConnectedLocked() { - if (!isConnectedLocked()) { + if (mConnectionState != ConnectionState.CONNECTED) { throw new IllegalStateException("UiAutomation not connected, " + this); } } @@ -1252,11 +1300,25 @@ public final class UiAutomation { private class IAccessibilityServiceClientImpl extends IAccessibilityServiceClientWrapper { - public IAccessibilityServiceClientImpl(Looper looper) { + public IAccessibilityServiceClientImpl(Looper looper, int generationId) { super(null, looper, new Callbacks() { + private final int mGenerationId = generationId; + /** + * True if UiAutomation doesn't interact with this client anymore. + * Used by methods below to stop sending notifications or changing members + * of {@link UiAutomation}. + */ + private boolean isGenerationChangedLocked() { + return mGenerationId != UiAutomation.this.mGenerationId; + } + @Override public void init(int connectionId, IBinder windowToken) { synchronized (mLock) { + if (isGenerationChangedLocked()) { + return; + } + mConnectionState = ConnectionState.CONNECTED; mConnectionId = connectionId; mLock.notifyAll(); } @@ -1290,6 +1352,9 @@ public final class UiAutomation { public void onAccessibilityEvent(AccessibilityEvent event) { final OnAccessibilityEventListener listener; synchronized (mLock) { + if (isGenerationChangedLocked()) { + return; + } mLastEventTimeMillis = event.getEventTime(); if (mWaitingForEventDelivery) { mEventQueue.add(AccessibilityEvent.obtain(event)); diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS index 9c21e8fe5e45..7e7710b4d550 100644 --- a/core/java/android/app/backup/OWNERS +++ b/core/java/android/app/backup/OWNERS @@ -1,9 +1,4 @@ -alsutton@google.com -anniemeng@google.com -brufino@google.com -bryanmawhinney@google.com -ctate@google.com -jorlow@google.com -nathch@google.com -rthakohov@google.com +# Bug component: 656484 + +include platform/frameworks/base/services/backup:/OWNERS diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 872c37771128..7047f73393f8 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -686,6 +687,8 @@ public final class BluetoothAdapter { private final Map<LeScanCallback, ScanCallback> mLeScanClients; private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>> sMetadataListeners = new HashMap<>(); + private final Map<BluetoothConnectionCallback, Executor> + mBluetoothConnectionCallbackExecutorMap = new HashMap<>(); /** * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener @@ -3538,6 +3541,133 @@ public final class BluetoothAdapter { @Nullable byte[] value); } + private final IBluetoothConnectionCallback mConnectionCallback = + new IBluetoothConnectionCallback.Stub() { + @Override + public void onDeviceConnected(BluetoothDevice device) { + for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry: + mBluetoothConnectionCallbackExecutorMap.entrySet()) { + BluetoothConnectionCallback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onDeviceConnected(device)); + } + } + + @Override + public void onDeviceDisconnected(BluetoothDevice device) { + for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry: + mBluetoothConnectionCallbackExecutorMap.entrySet()) { + BluetoothConnectionCallback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onDeviceDisconnected(device)); + } + } + }; + + /** + * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device + * (classic or low energy) is connected or disconnected. + * + * @param executor is the callback executor + * @param callback is the connection callback you wish to register + * @return true if the callback was registered successfully, false otherwise + * @throws IllegalArgumentException if the callback is already registered + * @hide + */ + public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull BluetoothConnectionCallback callback) { + if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()"); + if (callback == null) { + return false; + } + + // If the callback map is empty, we register the service-to-app callback + if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) { + return false; + } + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + mBluetoothConnectionCallbackExecutorMap.remove(callback); + } finally { + mServiceLock.readLock().unlock(); + } + } + + // Adds the passed in callback to our map of callbacks to executors + synchronized (mBluetoothConnectionCallbackExecutorMap) { + if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) { + throw new IllegalArgumentException("This callback has already been registered"); + } + mBluetoothConnectionCallbackExecutorMap.put(callback, executor); + } + + return true; + } + + /** + * Unregisters the BluetoothConnectionCallback that was previously registered by the application + * + * @param callback is the connection callback you wish to unregister + * @return true if the callback was unregistered successfully, false otherwise + * @hide + */ + public boolean unregisterBluetoothConnectionCallback( + @NonNull BluetoothConnectionCallback callback) { + if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()"); + if (callback == null) { + return false; + } + + synchronized (mBluetoothConnectionCallbackExecutorMap) { + if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) { + return false; + } + } + + if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) { + return true; + } + + // If the callback map is empty, we unregister the service-to-app callback + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.unregisterBluetoothConnectionCallback(mConnectionCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + return false; + } + + /** + * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth + * Low Energy (BLE) device is either connected or disconnected. + * + * @hide + */ + public abstract class BluetoothConnectionCallback { + /** + * Callback triggered when a bluetooth device (classic or BLE) is connected + * @param device is the connected bluetooth device + */ + public void onDeviceConnected(BluetoothDevice device) {} + + /** + * Callback triggered when a bluetooth device (classic or BLE) is disconnected + * @param device is the disconnected bluetooth device + */ + public void onDeviceDisconnected(BluetoothDevice device) {} + } + /** * Converts old constant of priority to the new for connection policy * diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index e07bc0215a6b..a52fc891790c 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -51,19 +51,25 @@ public final class BluetoothCodecConfig implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface SourceCodecType {} + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_SBC = 0; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_AAC = 1; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_APTX = 2; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_LDAC = 4; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_MAX = 5; - + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; /** @hide */ @@ -75,10 +81,13 @@ public final class BluetoothCodecConfig implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface CodecPriority {} + @UnsupportedAppUsage public static final int CODEC_PRIORITY_DISABLED = -1; + @UnsupportedAppUsage public static final int CODEC_PRIORITY_DEFAULT = 0; + @UnsupportedAppUsage public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; @@ -95,18 +104,25 @@ public final class BluetoothCodecConfig implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface SampleRate {} + @UnsupportedAppUsage public static final int SAMPLE_RATE_NONE = 0; + @UnsupportedAppUsage public static final int SAMPLE_RATE_44100 = 0x1 << 0; + @UnsupportedAppUsage public static final int SAMPLE_RATE_48000 = 0x1 << 1; + @UnsupportedAppUsage public static final int SAMPLE_RATE_88200 = 0x1 << 2; + @UnsupportedAppUsage public static final int SAMPLE_RATE_96000 = 0x1 << 3; + @UnsupportedAppUsage public static final int SAMPLE_RATE_176400 = 0x1 << 4; + @UnsupportedAppUsage public static final int SAMPLE_RATE_192000 = 0x1 << 5; @@ -120,12 +136,16 @@ public final class BluetoothCodecConfig implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface BitsPerSample {} + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_NONE = 0; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_16 = 0x1 << 0; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_24 = 0x1 << 1; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_32 = 0x1 << 2; @@ -138,10 +158,13 @@ public final class BluetoothCodecConfig implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface ChannelMode {} + @UnsupportedAppUsage public static final int CHANNEL_MODE_NONE = 0; + @UnsupportedAppUsage public static final int CHANNEL_MODE_MONO = 0x1 << 0; + @UnsupportedAppUsage public static final int CHANNEL_MODE_STEREO = 0x1 << 1; private final @SourceCodecType int mCodecType; @@ -154,6 +177,7 @@ public final class BluetoothCodecConfig implements Parcelable { private final long mCodecSpecific3; private final long mCodecSpecific4; + @UnsupportedAppUsage public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority, @SampleRate int sampleRate, @BitsPerSample int bitsPerSample, @ChannelMode int channelMode, long codecSpecific1, @@ -170,6 +194,7 @@ public final class BluetoothCodecConfig implements Parcelable { mCodecSpecific4 = codecSpecific4; } + @UnsupportedAppUsage public BluetoothCodecConfig(@SourceCodecType int codecType) { mCodecType = codecType; mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; @@ -391,6 +416,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec type */ + @UnsupportedAppUsage public @SourceCodecType int getCodecType() { return mCodecType; } @@ -411,6 +437,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec priority */ + @UnsupportedAppUsage public @CodecPriority int getCodecPriority() { return mCodecPriority; } @@ -441,6 +468,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec sample rate */ + @UnsupportedAppUsage public @SampleRate int getSampleRate() { return mSampleRate; } @@ -455,6 +483,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec bits per sample */ + @UnsupportedAppUsage public @BitsPerSample int getBitsPerSample() { return mBitsPerSample; } @@ -479,6 +508,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return a codec specific value1. */ + @UnsupportedAppUsage public long getCodecSpecific1() { return mCodecSpecific1; } diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java index 1e394b830d51..7b567b4098e7 100644 --- a/core/java/android/bluetooth/BluetoothCodecStatus.java +++ b/core/java/android/bluetooth/BluetoothCodecStatus.java @@ -17,6 +17,7 @@ package android.bluetooth; import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -38,6 +39,7 @@ public final class BluetoothCodecStatus implements Parcelable { * This extra represents the current codec status of the A2DP * profile. */ + @UnsupportedAppUsage public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS"; @@ -196,6 +198,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return the current codec configuration */ + @UnsupportedAppUsage public @Nullable BluetoothCodecConfig getCodecConfig() { return mCodecConfig; } @@ -205,6 +208,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return an array with the codecs local capabilities */ + @UnsupportedAppUsage public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() { return mCodecsLocalCapabilities; } @@ -214,6 +218,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return an array with the codecs selectable capabilities */ + @UnsupportedAppUsage public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return mCodecsSelectableCapabilities; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index e6609ca969f6..392dd64b3e49 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3402,6 +3402,7 @@ public abstract class Context { VIBRATOR_SERVICE, //@hide: STATUS_BAR_SERVICE, CONNECTIVITY_SERVICE, + VCN_MANAGEMENT_SERVICE, //@hide: IP_MEMORY_STORE_SERVICE, IPSEC_SERVICE, VPN_MANAGEMENT_SERVICE, @@ -3966,6 +3967,16 @@ public abstract class Context { public static final String CONNECTIVITY_SERVICE = "connectivity"; /** + * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.vcn.VcnManager} + * for managing Virtual Carrier Networks + * + * @see #getSystemService(String) + * @see android.net.vcn.VcnManager + * @hide + */ + public static final String VCN_MANAGEMENT_SERVICE = "vcn_management"; + + /** * Use with {@link #getSystemService(String)} to retrieve a * {@link android.net.INetd} for communicating with the network stack * @hide 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/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 72217a1196ea..267057c7b846 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -189,7 +189,7 @@ public final class InputManager { * Waits for the event to be delivered to the application and handled. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 171972397) public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h /** @hide */ diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 327e42bdd2f7..44ebff99f3e9 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -353,10 +353,11 @@ public abstract class NetworkAgent { private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { // The subtype can be changed with (TODO) setLegacySubtype, but it starts - // with the type and an empty description. + // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description. final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, ""); ni.setIsAvailable(true); - ni.setExtraInfo(config.getLegacyExtraInfo()); + ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */, + config.getLegacyExtraInfo()); return ni; } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index be33f4edb5d1..12ddc628f4bd 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -170,6 +170,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_MCX, NET_CAPABILITY_PARTIAL_CONNECTIVITY, NET_CAPABILITY_TEMPORARILY_NOT_METERED, + NET_CAPABILITY_OEM_PRIVATE, }) public @interface NetCapability { } @@ -345,8 +346,15 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; + /** + * Indicates that this network is private to the OEM and meant only for OEM use. + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_OEM_PRIVATE = 26; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_OEM_PRIVATE; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -404,7 +412,8 @@ public final class NetworkCapabilities implements Parcelable { * {@see #maybeMarkCapabilitiesRestricted}. */ private static final long FORCE_RESTRICTED_CAPABILITIES = - (1 << NET_CAPABILITY_OEM_PAID); + (1 << NET_CAPABILITY_OEM_PAID) + | (1 << NET_CAPABILITY_OEM_PRIVATE); /** * Capabilities that suggest that a network is unrestricted. @@ -1910,6 +1919,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_MCX: return "MCX"; case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; + case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; default: return Integer.toString(capability); } } diff --git a/core/java/android/net/TEST_MAPPING b/core/java/android/net/TEST_MAPPING index abac81117deb..8c13ef98bedb 100644 --- a/core/java/android/net/TEST_MAPPING +++ b/core/java/android/net/TEST_MAPPING @@ -17,4 +17,4 @@ "path": "frameworks/opt/net/wifi" } ] -}
\ No newline at end of file +} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl index 0b279b882367..af06906ca2e9 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl +++ b/core/java/android/net/vcn/IVcnManagementService.aidl @@ -1,5 +1,5 @@ -/** - * 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. @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.net; -@JavaOnlyStableParcelable parcelable TetheredClient;
\ No newline at end of file +package android.net.vcn; + +/** + * @hide + */ +interface IVcnManagementService { +} diff --git a/core/java/android/net/vcn/OWNERS b/core/java/android/net/vcn/OWNERS new file mode 100644 index 000000000000..33b9f0f75f81 --- /dev/null +++ b/core/java/android/net/vcn/OWNERS @@ -0,0 +1,7 @@ +set noparent + +benedictwong@google.com +ckesting@google.com +evitayan@google.com +nharold@google.com +jchalard@google.com
\ No newline at end of file diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java new file mode 100644 index 000000000000..d563b0350187 --- /dev/null +++ b/core/java/android/net/vcn/VcnManager.java @@ -0,0 +1,48 @@ +/* + * 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.net.vcn; + +import static java.util.Objects.requireNonNull; + +import android.annotation.NonNull; +import android.annotation.SystemService; +import android.content.Context; + +/** + * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks + * + * @hide + */ +@SystemService(Context.VCN_MANAGEMENT_SERVICE) +public final class VcnManager { + @NonNull private static final String TAG = VcnManager.class.getSimpleName(); + + @NonNull private final Context mContext; + @NonNull private final IVcnManagementService mService; + + /** + * Construct an instance of VcnManager within an application context. + * + * @param ctx the application context for this manager + * @param service the VcnManagementService binder backing this manager + * + * @hide + */ + public VcnManager(@NonNull Context ctx, @NonNull IVcnManagementService service) { + mContext = requireNonNull(ctx, "missing context"); + mService = requireNonNull(service, "missing service"); + } +} diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 8f8d451bbe8e..136f6121e585 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -117,11 +117,6 @@ interface INetworkManagementService void removeRoute(int netId, in RouteInfo route); /** - * Set the specified MTU size - */ - void setMtu(String iface, int mtu); - - /** * Shuts down the service */ void shutdown(); @@ -350,28 +345,8 @@ interface INetworkManagementService */ boolean isNetworkActive(); - /** - * Add an interface to a network. - */ - void addInterfaceToNetwork(String iface, int netId); - - /** - * Remove an Interface from a network. - */ - void removeInterfaceFromNetwork(String iface, int netId); - void addLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid); - void setDefaultNetId(int netId); - void clearDefaultNetId(); - - /** - * Set permission for a network. - * @param permission PERMISSION_NONE to clear permissions. - * PERMISSION_NETWORK or PERMISSION_SYSTEM to set permission. - */ - void setNetworkPermission(int netId, int permission); - /** * Allow UID to call protect(). */ diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 2aa5c13e6e9f..7a48a2a03503 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -724,7 +724,7 @@ public class Process { * Returns the identifier of this process' parent. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 171962076) public static final int myPpid() { return Os.getppid(); } diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java index 75123528a6b8..136e3de731a9 100644 --- a/core/java/android/os/SharedMemory.java +++ b/core/java/android/os/SharedMemory.java @@ -158,7 +158,7 @@ public final class SharedMemory implements Parcelable, Closeable { * * @hide Exposed for native ASharedMemory_dupFromJava() */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 171971817) public int getFd() { return mFileDescriptor.getInt$(); } 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/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 2be50e496b8b..0896f574cc46 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -20,6 +20,7 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.compat.annotation.ChangeId; import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; @@ -923,19 +924,21 @@ public class PhoneStateListener { /** * Callback invoked when the current emergency number list has changed on the registered * subscription. - * Note, the registration subId comes from {@link TelephonyManager} object which registers - * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}. + * + * Note, the registered subscription is associated with {@link TelephonyManager} object + * on which {@link TelephonyManager#listen(PhoneStateListener, int)} was called. * If this TelephonyManager object was created with * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the - * subId. Otherwise, this callback applies to + * given subId. Otherwise, this callback applies to * {@link SubscriptionManager#getDefaultSubscriptionId()}. * - * @param emergencyNumberList Map including the key as the active subscription ID - * (Note: if there is no active subscription, the key is - * {@link SubscriptionManager#getDefaultSubscriptionId}) - * and the value as the list of {@link EmergencyNumber}; - * null if this information is not available. - * @hide + * @param emergencyNumberList Map associating all active subscriptions on the device with the + * list of emergency numbers originating from that subscription. + * If there are no active subscriptions, the map will contain a + * single entry with + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} as + * the key and a list of emergency numbers as the value. If no + * emergency number information is available, the value will be null. */ public void onEmergencyNumberListChanged( @NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList) { @@ -945,27 +948,86 @@ public class PhoneStateListener { /** * Callback invoked when an outgoing call is placed to an emergency number. * - * @param placedEmergencyNumber the emergency number {@link EmergencyNumber} the call is placed - * to. + * This method will be called when an emergency call is placed on any subscription (including + * the no-SIM case), regardless of which subscription this listener was registered on. + * + * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to. + * + * @deprecated Use {@link #onOutgoingEmergencyCall(EmergencyNumber, int)}. * @hide */ @SystemApi + @Deprecated public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) { // default implementation empty } /** + * Callback invoked when an outgoing call is placed to an emergency number. + * + * This method will be called when an emergency call is placed on any subscription (including + * the no-SIM case), regardless of which subscription this listener was registered on. + * + * The default implementation of this method calls + * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes. Do + * not call {@code super(...)} from within your implementation unless you want + * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well. + * + * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to. + * @param subscriptionId The subscription ID used to place the emergency call. If the + * emergency call was placed without a valid subscription (e.g. when there + * are no SIM cards in the device), this will be equal to + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. + * @hide + */ + @SystemApi + @TestApi + public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber, + int subscriptionId) { + // Default implementation for backwards compatibility + onOutgoingEmergencyCall(placedEmergencyNumber); + } + + /** * Callback invoked when an outgoing SMS is placed to an emergency number. * + * This method will be called when an emergency sms is sent on any subscription. * @param sentEmergencyNumber the emergency number {@link EmergencyNumber} the SMS is sent to. + * + * @deprecated Use {@link #onOutgoingEmergencySms(EmergencyNumber, int)}. * @hide */ @SystemApi + @TestApi + @Deprecated public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) { // default implementation empty } /** + * Smsback invoked when an outgoing sms is sent to an emergency number. + * + * This method will be called when an emergency sms is sent on any subscription, + * regardless of which subscription this listener was registered on. + * + * The default implementation of this method calls + * {@link #onOutgoingEmergencySms(EmergencyNumber)} for backwards compatibility purposes. Do + * not call {@code super(...)} from within your implementation unless you want + * {@link #onOutgoingEmergencySms(EmergencyNumber)} to be called as well. + * + * @param sentEmergencyNumber The {@link EmergencyNumber} the emergency sms was sent to. + * @param subscriptionId The subscription ID used to send the emergency sms. + * @hide + */ + @SystemApi + @TestApi + public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber, + int subscriptionId) { + // Default implementation for backwards compatibility + onOutgoingEmergencySms(sentEmergencyNumber); + } + + /** * Callback invoked when OEM hook raw event is received on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}. @@ -1331,22 +1393,25 @@ public class PhoneStateListener { () -> psl.onEmergencyNumberListChanged(emergencyNumberList))); } - public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) { + public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber, + int subscriptionId) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute( - () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber))); + () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber, + subscriptionId))); } - public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) { + public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber, + int subscriptionId) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute( - () -> psl.onOutgoingEmergencySms(sentEmergencyNumber))); + () -> psl.onOutgoingEmergencySms(sentEmergencyNumber, subscriptionId))); } public void onPhoneCapabilityChanged(PhoneCapability capability) { diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java index 3396bceb75d0..a942f6ce2879 100644 --- a/core/java/android/text/Editable.java +++ b/core/java/android/text/Editable.java @@ -137,7 +137,7 @@ extends CharSequence, GetChars, Spannable, Appendable } /** - * Returns a new SpannedStringBuilder from the specified + * Returns a new SpannableStringBuilder from the specified * CharSequence. You can override this to provide * a different kind of Spanned. */ diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index ead4e46cd28b..0093273aaf93 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -64,7 +64,7 @@ public class EventLog { private Exception mLastWtf; // Layout of event log entry received from Android logger. - // see system/core/liblog/include/log/log_read.h + // see system/logging/liblog/include/log/log_read.h private static final int LENGTH_OFFSET = 0; private static final int HEADER_SIZE_OFFSET = 2; private static final int PROCESS_OFFSET = 4; diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java index 4eb7dede7769..43984b59378c 100644 --- a/core/java/com/android/internal/net/LegacyVpnInfo.java +++ b/core/java/com/android/internal/net/LegacyVpnInfo.java @@ -83,8 +83,8 @@ public class LegacyVpnInfo implements Parcelable { * Return best matching {@link LegacyVpnInfo} state based on given * {@link NetworkInfo}. */ - public static int stateFromNetworkInfo(NetworkInfo info) { - switch (info.getDetailedState()) { + public static int stateFromNetworkInfo(NetworkInfo.DetailedState state) { + switch (state) { case CONNECTING: return STATE_CONNECTING; case CONNECTED: @@ -94,8 +94,7 @@ public class LegacyVpnInfo implements Parcelable { case FAILED: return STATE_FAILED; default: - Log.w(TAG, "Unhandled state " + info.getDetailedState() - + " ; treating as disconnected"); + Log.w(TAG, "Unhandled state " + state + " ; treating as disconnected"); return STATE_DISCONNECTED; } } diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index 7dc38711a6ef..c0648ab89c41 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -70,7 +70,8 @@ public class VpnConfig implements Parcelable { intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT); + return PendingIntent.getActivityAsUser(context, 0 /* requestCode */, intent, + PendingIntent.FLAG_IMMUTABLE, null /* options */, UserHandle.CURRENT); } public static CharSequence getVpnLabel(Context context, String packageName) diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index cb9df448db30..aa37334b2c54 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -385,7 +385,6 @@ public class ZygoteInit { "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); - hidlManager.addDependency(hidlBase); SharedLibraryInfo androidTestBase = new SharedLibraryInfo( "/system/framework/android.test.base.jar", null /*packageName*/, diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index b2c5a998e254..d2dc7c283ff7 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -61,8 +61,8 @@ oneway interface IPhoneStateListener { void onRadioPowerStateChanged(in int state); void onCallAttributesChanged(in CallAttributes callAttributes); void onEmergencyNumberListChanged(in Map emergencyNumberList); - void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber); - void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber); + void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber, int subscriptionId); + void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber, int subscriptionId); void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause); void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo); void onRegistrationFailed(in CellIdentity cellIdentity, diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp index e4d138d92621..d65b498404fa 100644 --- a/core/jni/android_opengl_GLES10.cpp +++ b/core/jni/android_opengl_GLES10.cpp @@ -640,7 +640,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -684,7 +684,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -929,7 +929,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -2801,7 +2801,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -3241,7 +3242,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -3301,7 +3302,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp index 1069a1d3acb1..9724e6c2a5dd 100644 --- a/core/jni/android_opengl_GLES11.cpp +++ b/core/jni/android_opengl_GLES11.cpp @@ -464,7 +464,7 @@ android_glBufferData__IILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -509,7 +509,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp index 86d7ecdce44d..1ffa4ec67ae1 100644 --- a/core/jni/android_opengl_GLES11Ext.cpp +++ b/core/jni/android_opengl_GLES11Ext.cpp @@ -893,7 +893,8 @@ android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)image - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -930,7 +931,8 @@ android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)image - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp index 49baa51f2342..d832558aa368 100644 --- a/core/jni/android_opengl_GLES20.cpp +++ b/core/jni/android_opengl_GLES20.cpp @@ -599,7 +599,7 @@ android_glBufferData__IILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -644,7 +644,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -758,7 +758,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -802,7 +802,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -1379,7 +1379,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4273,7 +4273,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4380,7 +4381,7 @@ android_glShaderBinary__I_3IIILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, binary, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset), JNI_FALSE); } if (shaders_base) { _env->ReleaseIntArrayElements(shaders_ref, (jint*)shaders_base, @@ -4445,7 +4446,8 @@ android_glShaderBinary__ILjava_nio_IntBuffer_2ILjava_nio_Buffer_2I exit: if (_binaryArray) { - releasePointer(_env, _binaryArray, binary, JNI_FALSE); + releasePointer(_env, _binaryArray, (void *)((char *)binary - _binaryBufferOffset), + JNI_FALSE); } if (_shadersArray) { _env->ReleaseIntArrayElements(_shadersArray, (jint*)shaders, JNI_ABORT); @@ -4568,7 +4570,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4816,7 +4818,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp index 32a2a24c2d2d..719c6b32fec6 100644 --- a/core/jni/android_opengl_GLES30.cpp +++ b/core/jni/android_opengl_GLES30.cpp @@ -463,7 +463,7 @@ android_glDrawRangeElements__IIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -516,7 +516,7 @@ android_glTexImage3D__IIIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -580,7 +580,7 @@ android_glTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -660,7 +660,7 @@ android_glCompressedTexImage3D__IIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -723,7 +723,7 @@ android_glCompressedTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -5445,7 +5445,8 @@ android_glGetProgramBinary__II_3II_3IILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, binary, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (binaryFormat_base) { _env->ReleaseIntArrayElements(binaryFormat_ref, (jint*)binaryFormat_base, @@ -5519,7 +5520,8 @@ android_glGetProgramBinary__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_ni exit: if (_binaryArray) { - releasePointer(_env, _binaryArray, binary, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _binaryArray, (void *)((char *)binary - _binaryBufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_binaryFormatArray) { _env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, _exception ? JNI_ABORT : 0); @@ -5564,7 +5566,7 @@ android_glProgramBinary__IILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, binary, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp index 07a794d0ef19..7ed754850ea3 100644 --- a/core/jni/android_opengl_GLES32.cpp +++ b/core/jni/android_opengl_GLES32.cpp @@ -863,7 +863,7 @@ android_glDrawElementsBaseVertex__IIILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -911,7 +911,7 @@ android_glDrawRangeElementsBaseVertex__IIIIILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -1048,7 +1048,8 @@ android_glReadnPixels__IIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp index ffc1ddc03355..21de72397384 100644 --- a/core/jni/com_google_android_gles_jni_GLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp @@ -424,7 +424,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -468,7 +468,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -713,7 +713,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, indices, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -3488,7 +3488,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), + _exception ? JNI_FALSE : JNI_TRUE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -3972,7 +3973,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4032,7 +4033,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 (GLvoid *)pixels ); if (_array) { - releasePointer(_env, _array, pixels, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4299,7 +4300,7 @@ android_glBufferData__IILjava_nio_Buffer_2I exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); @@ -4344,7 +4345,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2 exit: if (_array) { - releasePointer(_env, _array, data, JNI_FALSE); + releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE); } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); 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/core/tests/BTtraffic/Android.bp b/core/tests/BTtraffic/Android.bp deleted file mode 100644 index e508570daf03..000000000000 --- a/core/tests/BTtraffic/Android.bp +++ /dev/null @@ -1,7 +0,0 @@ -android_app { - name: "bttraffic", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - sdk_version: "current", - certificate: "platform", -} diff --git a/core/tests/BTtraffic/AndroidManifest.xml b/core/tests/BTtraffic/AndroidManifest.xml deleted file mode 100644 index 00d9707de2bf..000000000000 --- a/core/tests/BTtraffic/AndroidManifest.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.google.android.experimental.bttraffic" > - - <uses-permission android:name="android.permission.BLUETOOTH"/> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> - - <uses-sdk - android:minSdkVersion="18" - android:targetSdkVersion="18" - /> - <application - android:allowBackup="false" - android:label="@string/app_name" > - <service - android:name=".BTtraffic" - android:enabled="true" - android:exported="true" > - </service> - </application> - -</manifest> diff --git a/core/tests/BTtraffic/README b/core/tests/BTtraffic/README deleted file mode 100644 index 430488f656f9..000000000000 --- a/core/tests/BTtraffic/README +++ /dev/null @@ -1,45 +0,0 @@ -This is a tool to generate classic Bluetooth traffic with specified period and package size. -Together with the SvcMonitor, which will be called automatically in this android service, can be -used to measure the CPU usage from the Java layer Bluetooth code and the underlying system service -com.android.bluetooth. - -1. Server (Listener) - Client (Sender) model. Both run as an Android service. -2. No pairing needed. Communicate via unsecured RFcomm. Client establishes the connection by -providing the MAC addr of the server. -3. Bluetooth has to be turned on on both side. -4. Client can configure the traffic by specifying the transfer period and package size. -5. A separate monitor process will be automatically forked and will be reading from /proc file -system to calculate the cpu usage. The measurement is updated once per second. -6. The monitor process (com.google.android.experimental.svcmonitor/.ScvMonitor) can be run as an -independent service to measure cpu usage on any similarly configured tests (e.g. wifi, BLE). Refer -to SvcMonitor's README for usage and details. - -Usage: -To instal the test: -On both the server and client device, install the 2 apk: -$ adb install $OUT/system/app/bttraffic/bttraffic.apk -$ adb install $OUT/system/app/svcmonitor/svcmonitor.apk - -To start the service on the SERVER side: -$ adb shell am startservice -a start --ez ack true \ -com.google.android.experimental.bttraffic/.BTtraffic - -To start the service on the CLIENT side: -$ adb shell am startservice -a start \ --e addr "F8:A9:D0:A8:74:8E" --ei size 1000 --ei period 15 \ -com.google.android.experimental.bttraffic/.BTtraffic - -To stop the test: -On either the server or client: -$ adb shell am startservice -a stop \ -com.google.android.experimental.bttraffic/.BTtraffic - -To look at the data: -$ adb logcat | grep bttraffic - -Options: --e addr: MAC addr of the server, in uppercase letter. ---ei size: package size, unit: byte; default: 1024, MAX: 20MB ---ei period: system sleep time between sending each package, unit: ms, default: 5000 - ** if -1 is provided, client will only send the package once. ---ez ack: whether acknowledge is required (true/false) diff --git a/core/tests/BTtraffic/res/values/strings.xml b/core/tests/BTtraffic/res/values/strings.xml deleted file mode 100644 index e70276e03647..000000000000 --- a/core/tests/BTtraffic/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ -<resources> - <string name="app_name">Bluetooth Test</string> -</resources> diff --git a/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java b/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java deleted file mode 100644 index 286c0aa2915f..000000000000 --- a/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java +++ /dev/null @@ -1,328 +0,0 @@ -package com.google.android.experimental.bttraffic; - -import android.app.Service; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothServerSocket; -import android.bluetooth.BluetoothSocket; -import android.content.Intent; -import android.os.Bundle; -import android.os.IBinder; -import android.os.SystemClock; -import android.util.Log; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.Exception; -import java.lang.Runtime; -import java.lang.RuntimeException; -import java.lang.Process; -import java.nio.ByteBuffer; -import java.util.Random; -import java.util.Set; -import java.util.UUID; - -public class BTtraffic extends Service { - public static final String TAG = "bttraffic"; - static final String SERVICE_NAME = "bttraffic"; - static final String SYS_SERVICE_NAME = "com.android.bluetooth"; - static final UUID SERVICE_UUID = UUID.fromString("5e8945b0-1234-5432-a5e2-0800200c9a67"); - volatile Thread mWorkerThread; - volatile boolean isShuttingDown = false; - volatile boolean isServer = false; - - public BTtraffic() {} - - static void safeClose(Closeable closeable) { - try { - closeable.close(); - } catch (IOException e) { - Log.d(TAG, "Unable to close resource.\n"); - } - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - if (intent == null) { - stopSelf(); - return 0; - } - if ("stop".equals(intent.getAction())) { - stopService(); - } else if ("start".equals(intent.getAction())) { - startWorker(intent); - } else { - Log.d(TAG, "unknown action: + " + intent.getAction()); - } - return 0; - } - - private void startWorker(Intent intent) { - if (mWorkerThread != null) { - Log.d(TAG, "worker thread already active"); - return; - } - isShuttingDown = false; - String remoteAddr = intent.getStringExtra("addr"); - Log.d(TAG, "startWorker: addr=" + remoteAddr); - Runnable worker = - remoteAddr == null - ? new ListenerRunnable(this, intent) - : new SenderRunnable(this, remoteAddr, intent); - isServer = remoteAddr == null ? true: false; - mWorkerThread = new Thread(worker, "BTtrafficWorker"); - try { - startMonitor(); - Log.d(TAG, "Monitor service started"); - mWorkerThread.start(); - Log.d(TAG, "Worker thread started"); - } catch (Exception e) { - Log.d(TAG, "Failed to start service", e); - } - } - - private void startMonitor() - throws Exception { - if (isServer) { - Log.d(TAG, "Start monitor on server"); - String[] startmonitorCmd = { - "/system/bin/am", - "startservice", - "-a", "start", - "-e", "java", SERVICE_NAME, - "-e", "hal", SYS_SERVICE_NAME, - "com.google.android.experimental.svcmonitor/.SvcMonitor" - }; - Process ps = new ProcessBuilder() - .command(startmonitorCmd) - .redirectErrorStream(true) - .start(); - } else { - Log.d(TAG, "No need to start SvcMonitor on client"); - } - } - - private void stopMonitor() - throws Exception { - if (isServer) { - Log.d(TAG, "StopMonitor on server"); - String[] stopmonitorCmd = { - "/system/bin/am", - "startservice", - "-a", "stop", - "com.google.android.experimental.svcmonitor/.SvcMonitor" - }; - Process ps = new ProcessBuilder() - .command(stopmonitorCmd) - .redirectErrorStream(true) - .start(); - } else { - Log.d(TAG, "No need to stop Svcmonitor on client"); - } - } - - public void stopService() { - if (mWorkerThread == null) { - Log.d(TAG, "no active thread"); - return; - } - - isShuttingDown = true; - - try { - stopMonitor(); - } catch (Exception e) { - Log.d(TAG, "Unable to stop SvcMonitor!", e); - } - - if (Thread.currentThread() != mWorkerThread) { - mWorkerThread.interrupt(); - Log.d(TAG, "Interrupting thread"); - try { - mWorkerThread.join(); - } catch (InterruptedException e) { - Log.d(TAG, "Unable to join thread!"); - } - } - - mWorkerThread = null; - stopSelf(); - Log.d(TAG, "Service stopped"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - @Override - public IBinder onBind(Intent intent) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - public static class ListenerRunnable implements Runnable { - private final BTtraffic bttraffic; - private final boolean sendAck; - private Intent intent; - private final int maxbuffersize = 20 * 1024 * 1024; - - public ListenerRunnable(BTtraffic bttraffic, Intent intent) { - this.bttraffic = bttraffic; - this.sendAck = intent.getBooleanExtra("ack", true); - this.intent = intent; - } - - @Override - public void run() { - BluetoothServerSocket serverSocket; - - try { - Log.d(TAG, "getting server socket"); - serverSocket = BluetoothAdapter.getDefaultAdapter() - .listenUsingInsecureRfcommWithServiceRecord( - SERVICE_NAME, SERVICE_UUID); - } catch (IOException e) { - Log.d(TAG, "error creating server socket, stopping thread"); - bttraffic.stopService(); - return; - } - - Log.d(TAG, "got server socket, starting accept loop"); - BluetoothSocket socket = null; - try { - Log.d(TAG, "accepting"); - socket = serverSocket.accept(); - - if (!Thread.interrupted()) { - Log.d(TAG, "accepted, listening"); - doListening(socket.getInputStream(), socket.getOutputStream()); - Log.d(TAG, "listen finished"); - } - } catch (IOException e) { - Log.d(TAG, "error while accepting or listening", e); - } finally { - Log.d(TAG, "Linster interruped"); - Log.d(TAG, "closing socket and stopping service"); - safeClose(serverSocket); - safeClose(socket); - if (!bttraffic.isShuttingDown) - bttraffic.stopService(); - } - - } - - private void doListening(InputStream inputStream, OutputStream outputStream) - throws IOException { - ByteBuffer byteBuffer = ByteBuffer.allocate(maxbuffersize); - - while (!Thread.interrupted()) { - readBytesIntoBuffer(inputStream, byteBuffer, 4); - byteBuffer.flip(); - int length = byteBuffer.getInt(); - if (Thread.interrupted()) - break; - readBytesIntoBuffer(inputStream, byteBuffer, length); - - if (sendAck) - outputStream.write(0x55); - } - } - - void readBytesIntoBuffer(InputStream inputStream, ByteBuffer byteBuffer, int numToRead) - throws IOException { - byteBuffer.clear(); - while (true) { - int position = byteBuffer.position(); - int remaining = numToRead - position; - if (remaining == 0) { - break; - } - int count = inputStream.read(byteBuffer.array(), position, remaining); - if (count < 0) { - throw new IOException("read the EOF"); - } - byteBuffer.position(position + count); - } - } - } - - public static class SenderRunnable implements Runnable { - private final BTtraffic bttraffic; - private final String remoteAddr; - private final int pkgsize, period; - private final int defaultpkgsize = 1024; - private final int defaultperiod = 5000; - private static ByteBuffer lengthBuffer = ByteBuffer.allocate(4); - - public SenderRunnable(BTtraffic bttraffic, String remoteAddr, Intent intent) { - this.bttraffic = bttraffic; - this.remoteAddr = remoteAddr; - this.pkgsize = intent.getIntExtra("size", defaultpkgsize); - this.period = intent.getIntExtra("period", defaultperiod); - } - - @Override - public void run() { - BluetoothDevice device = null; - try { - device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); - } catch (IllegalArgumentException e) { - Log.d(TAG, "Invalid BT MAC address!\n"); - } - if (device == null) { - Log.d(TAG, "can't find matching device, stopping thread and service"); - bttraffic.stopService(); - return; - } - - BluetoothSocket socket = null; - try { - Log.d(TAG, "connecting to device with MAC addr: " + remoteAddr); - socket = device.createInsecureRfcommSocketToServiceRecord(SERVICE_UUID); - socket.connect(); - Log.d(TAG, "connected, starting to send"); - doSending(socket.getOutputStream()); - Log.d(TAG, "send stopped, stopping service"); - } catch (Exception e) { - Log.d(TAG, "error while sending", e); - } finally { - Log.d(TAG, "finishing, closing thread and service"); - safeClose(socket); - if (!bttraffic.isShuttingDown) - bttraffic.stopService(); - } - } - - private void doSending(OutputStream outputStream) throws IOException { - Log.w(TAG, "doSending"); - try { - Random random = new Random(System.currentTimeMillis()); - - byte[] bytes = new byte[pkgsize]; - random.nextBytes(bytes); - while (!Thread.interrupted()) { - writeBytes(outputStream, bytes.length); - outputStream.write(bytes, 0, bytes.length); - if (period < 0) - break; - if (period == 0) - continue; - - SystemClock.sleep(period); - } - Log.d(TAG, "Sender interrupted"); - } catch (IOException e) { - Log.d(TAG, "doSending got error", e); - } - } - - private static void writeBytes(OutputStream outputStream, int value) throws IOException { - lengthBuffer.putInt(value); - lengthBuffer.flip(); - outputStream.write(lengthBuffer.array(), lengthBuffer.position(), lengthBuffer.limit()); - } - } - -} diff --git a/core/tests/SvcMonitor/Android.bp b/core/tests/SvcMonitor/Android.bp deleted file mode 100644 index 606e87cb0f4d..000000000000 --- a/core/tests/SvcMonitor/Android.bp +++ /dev/null @@ -1,7 +0,0 @@ -android_app { - name: "svcmonitor", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - sdk_version: "current", - certificate: "platform", -} diff --git a/core/tests/SvcMonitor/AndroidManifest.xml b/core/tests/SvcMonitor/AndroidManifest.xml deleted file mode 100644 index de5a9bdaed41..000000000000 --- a/core/tests/SvcMonitor/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.google.android.experimental.svcmonitor" > - - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> - - <uses-sdk - android:minSdkVersion="18" - android:targetSdkVersion="18" - /> - <application - android:allowBackup="false" - android:label="@string/app_name" > - <service - android:name=".SvcMonitor" - android:enabled="true" - android:exported="true" > - </service> - </application> - -</manifest> diff --git a/core/tests/SvcMonitor/README b/core/tests/SvcMonitor/README deleted file mode 100644 index 13a4380589b4..000000000000 --- a/core/tests/SvcMonitor/README +++ /dev/null @@ -1,27 +0,0 @@ -This Android service measures CPU usage of a program and an underlying system service it relies on. -An example of this would be an android app XYZ communicates to some other device via Bluetooth. The -SvcMonitor service can monitor the CPU usage of XYZ and com.android.bluetooth. - -Usage: - -To start the service: -$ adb shell am startservice -a start \ --e java XYZ -e hal com.android.bluetooth \ -com.google.android.experimental.svcmonitor/.SvcMonitor - -To stop the service: -$ adb shell am startservice -a stop \ -com.google.android.experimental.svcmonitor/.SvcMonitor - -To stop the service config: -$ adb shell am startservice -a change \ --e java NewName -e hal NewService \ -com.google.android.experimental.svcmonitor/.SvcMonitor - -To monitor the data: -$ adb logcat | grep XYZ - -Options: --e java NameOfProgram: any running process’s name. --e hal NameOfSysService: name of the system service the previous process relies on. ---ei period: period between each measurement (frequency). Unit: ms, Default:1000, Min: 100 diff --git a/core/tests/SvcMonitor/res/values/strings.xml b/core/tests/SvcMonitor/res/values/strings.xml deleted file mode 100644 index e70276e03647..000000000000 --- a/core/tests/SvcMonitor/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ -<resources> - <string name="app_name">Bluetooth Test</string> -</resources> diff --git a/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java b/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java deleted file mode 100644 index a451445530cd..000000000000 --- a/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.google.android.experimental.svcmonitor; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.os.SystemClock; -import android.util.Log; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.lang.Runnable; -import java.lang.Thread; -import java.util.Set; - -public class SvcMonitor extends Service { - public static final String TAG = "svcmonitor"; - String javaProc, halProc; - volatile Thread tMonitor; - int period; - - public SvcMonitor() {}; - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - if (intent == null) { - stopSelf(); - return 0; - } - Log.d(TAG, "Starting SvcMonitor"); - if ("stop".equals(intent.getAction())) { - stopService(); - } else if ("start".equals(intent.getAction())) { - startMonitor(intent); - } else if ("change".equals(intent.getAction())) { - changeConfig(intent); - } else { - Log.d(TAG, "unknown action: + " + intent.getAction()); - } - return 0; - } - - private void changeConfig(Intent intent) { - if (tMonitor == null) { - Log.d(TAG, "Service not active. Start service first"); - return; - } - stopThread(); - startMonitor(intent); - } - - private void startMonitor(Intent intent) { - if (tMonitor != null) { - Log.d(TAG, "thread already active"); - return; - } - javaProc = intent.getStringExtra("java"); - halProc = intent.getStringExtra("hal"); - period = intent.getIntExtra("period", 1000); - if (javaProc == null || halProc == null || period < 100) { - Log.d(TAG, "Failed starting monitor, invalid arguments."); - stopSelf(); - return; - } - Runnable monitor = new MonitorRunnable(this); - tMonitor = new Thread(monitor); - tMonitor.start(); - } - - private void stopService() { - stopThread(); - stopSelf(); - Log.d(TAG, "SvcMonitor stopped"); - } - - private void stopThread() { - if (tMonitor == null) { - Log.d(TAG, "no active thread"); - return; - } - Log.d(TAG, "interrupting monitor thread"); - tMonitor.interrupt(); - try { - tMonitor.join(); - } catch (InterruptedException e) { - Log.d(TAG, "Unable to finish monitor thread"); - } - tMonitor = null; - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - @Override - public IBinder onBind(Intent intent) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - public static class MonitorRunnable implements Runnable { - long java_time_old, hal_time_old, cpu_time_old = -1; - String javaPID, halPID; - SvcMonitor svcmonitor; - static String javaProcTAG; - int period; - - public MonitorRunnable(SvcMonitor svcmonitor) { - this.svcmonitor = svcmonitor; - this.period = svcmonitor.period; - javaPID = getPIDof(svcmonitor.javaProc); - halPID = getPIDof(svcmonitor.halProc); - java_time_old = getPsTime(javaPID); - hal_time_old = getPsTime(halPID); - cpu_time_old = getPsTime(""); - javaProcTAG = String.valueOf(svcmonitor.javaProc.toCharArray()); - } - - @Override - public void run() { - if (halPID.isEmpty() || javaPID.isEmpty()) { - Log.d(javaProcTAG, "No such process: " + - (halPID.isEmpty() ? svcmonitor.halProc : svcmonitor.javaProc)); - return; - } - while (!Thread.interrupted()) { - calculateUsage(); - SystemClock.sleep(period); - } - Log.d(TAG, "Stopping monitor thread"); - } - - private void calculateUsage() { - long java_time = getPsTime(javaPID); - long hal_time = getPsTime(halPID); - long cpu_time = getPsTime(""); - - if (cpu_time_old >= 0) { - float java_diff = (float) (java_time - java_time_old); - float hal_diff = (float) (hal_time - hal_time_old); - float cpu_diff = (float) (cpu_time - cpu_time_old); - Log.w(javaProcTAG, "\n----------------\n"); - Log.w(javaProcTAG, "JAVA level CPU: " - + (java_diff * 100.0 / cpu_diff) + "%\n"); - Log.w(javaProcTAG, " HAL level CPU: " - + (hal_diff * 100.0 / cpu_diff) + "%\n"); - Log.w(javaProcTAG, " SYS level CPU: " - + ((java_diff + hal_diff) * 100.0 / cpu_diff) + "%\n"); - } else { - Log.w(TAG, "Waiting for status\n"); - } - - java_time_old = java_time; - hal_time_old = hal_time; - cpu_time_old = cpu_time; - } - - private String getPIDof(String psName) { - String pid = ""; - - try { - String[] cmd = {"/system/bin/sh", "-c", "ps | grep " + psName}; - Process ps = Runtime.getRuntime().exec(cmd); - BufferedReader in = new BufferedReader( - new InputStreamReader(ps.getInputStream())); - String temp = in.readLine(); - if (temp == null || temp.isEmpty()) - throw new IOException("No such process: " + psName); - pid = temp.split(" +")[1]; - in.close(); - } catch (IOException e) { - Log.d(javaProcTAG, "Error finding PID of process: " + psName + "\n", e); - } - return pid; - } - - private long getPsTime(String pid) { - String psStat = getPsStat("/" + pid); - String[] statBreakDown = psStat.split(" +"); - long psTime; - - if (pid.isEmpty()) { - psTime = Long.parseLong(statBreakDown[1]) - + Long.parseLong(statBreakDown[2]) - + Long.parseLong(statBreakDown[3]) - + Long.parseLong(statBreakDown[4]); - } else { - psTime = Long.parseLong(statBreakDown[13]) - + Long.parseLong(statBreakDown[14]); - } - - return psTime; - } - - private String getPsStat(String psname) { - String stat = ""; - try { - FileInputStream fs = new FileInputStream("/proc" + psname + "/stat"); - BufferedReader br = new BufferedReader(new InputStreamReader(fs)); - stat = br.readLine(); - fs.close(); - } catch (IOException e) { - Log.d(TAG, "Error retreiving stat. \n"); - } - return stat; - } - } -} diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 5f159a1bab81..c51248dac767 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -236,8 +236,7 @@ <library name="android.hidl.base-V1.0-java" file="/system/framework/android.hidl.base-V1.0-java.jar" /> <library name="android.hidl.manager-V1.0-java" - file="/system/framework/android.hidl.manager-V1.0-java.jar" - dependency="android.hidl.base-V1.0-java" /> + file="/system/framework/android.hidl.manager-V1.0-java.jar" /> <!-- These are the standard packages that are white-listed to always have internet access while in power save mode, even if they aren't in the foreground. --> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 419398df20eb..0806e7151997 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -164,6 +164,7 @@ applications that come with the platform <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.LOCAL_MAC_ADDRESS"/> <permission name="android.permission.MANAGE_USERS"/> + <permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS" /> <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.PACKAGE_USAGE_STATS"/> <permission name="android.permission.PERFORM_CDMA_PROVISIONING"/> 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/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java index cc5286d70cab..970726051e11 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java @@ -177,7 +177,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { && (keymasterSwEnforcedUserAuthenticators == 0); boolean userAuthenticationValidWhileOnBody = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY); - boolean trustedUserPresenceRequred = + boolean trustedUserPresenceRequired = keyCharacteristics.hwEnforced.getBoolean( KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED); @@ -209,7 +209,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keymasterHwEnforcedUserAuthenticators, userAuthenticationRequirementEnforcedBySecureHardware, userAuthenticationValidWhileOnBody, - trustedUserPresenceRequred, + trustedUserPresenceRequired, invalidatedByBiometricEnrollment, userConfirmationRequired); } diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java index 773729e7e7df..c82b6e6bc6fe 100644 --- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java +++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java @@ -48,7 +48,7 @@ abstract class KeyStoreCryptoOperationUtils { return null; } - // An error occured. However, some errors should not lead to init throwing an exception. + // An error occurred. However, some errors should not lead to init throwing an exception. // See below. InvalidKeyException e = keyStore.getInvalidKeyException(key.getAlias(), key.getUid(), beginOpResultCode); diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 79b861136b64..610bffe13eae 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -17,6 +17,7 @@ package android.media; import android.annotation.Nullable; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Rect; import android.hardware.HardwareBuffer; @@ -58,6 +59,7 @@ public abstract class Image implements AutoCloseable { * @hide */ @UnsupportedAppUsage + @TestApi protected Image() { } @@ -387,6 +389,7 @@ public abstract class Image implements AutoCloseable { * @hide */ @UnsupportedAppUsage + @TestApi protected Plane() { } diff --git a/native/android/Android.bp b/native/android/Android.bp index 797d3fd8c2ff..02e1ebe05b02 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -105,6 +105,7 @@ cc_library_shared { cc_library_shared { name: "libandroid_net", defaults: ["libandroid_defaults"], + llndk_stubs: "libandroid_net.llndk", srcs: ["net.c"], shared_libs: ["libnetd_client"], @@ -113,7 +114,7 @@ cc_library_shared { } llndk_library { - name: "libandroid_net", + name: "libandroid_net.llndk", export_include_dirs: ["include"], symbol_file: "libandroid_net.map.txt", unversioned: true, diff --git a/non-updatable-api/module-lib-removed.txt b/non-updatable-api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/non-updatable-api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml index 719fc73bd225..bfeef0aa8c7b 100644 --- a/packages/DynamicSystemInstallationService/res/values/strings.xml +++ b/packages/DynamicSystemInstallationService/res/values/strings.xml @@ -37,6 +37,9 @@ <string name="toast_dynsystem_discarded">Discarded dynamic system</string> <!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=128] --> <string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string> + <!-- Toast when we fail to disable Dynamic System [CHAR LIMIT=128] --> + <string name="toast_failed_to_disable_dynsystem">Failed to disable dynamic system</string> + <!-- URL of Dynamic System Key Revocation List [DO NOT TRANSLATE] --> <string name="key_revocation_list_url" translatable="false">https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json</string> diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index f7f3cbb7d332..ac2758011816 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -375,8 +375,17 @@ public class DynamicSystemInstallationService extends Service return; } - // Per current design, we don't have disable() API. AOT is disabled on next reboot. - // TODO: Use better status query when b/125079548 is done. + if (!mDynSystem.setEnable(/* enable = */ false, /* oneShot = */ false)) { + Log.e(TAG, "Failed to disable DynamicSystem."); + + // Dismiss status bar and show a toast. + sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + Toast.makeText(this, + getString(R.string.toast_failed_to_disable_dynsystem), + Toast.LENGTH_LONG).show(); + return; + } + PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); if (powerManager != null) { @@ -422,7 +431,7 @@ public class DynamicSystemInstallationService extends Service private PendingIntent createPendingIntent(String action) { Intent intent = new Intent(this, DynamicSystemInstallationService.class); intent.setAction(action); - return PendingIntent.getService(this, 0, intent, 0); + return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); } private Notification buildNotification(int status, int cause) { diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS index 541dd8787545..7e7710b4d550 100644 --- a/packages/SettingsProvider/src/android/provider/settings/OWNERS +++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS @@ -1,5 +1,4 @@ -# Please reach out to Android B&R when making Settings backup changes -alsutton@google.com -nathch@google.com -rthakohov@google.com +# Bug component: 656484 + +include platform/frameworks/base/services/backup:/OWNERS diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS index f3241ea9d1f9..7e7710b4d550 100644 --- a/packages/SettingsProvider/test/src/android/provider/OWNERS +++ b/packages/SettingsProvider/test/src/android/provider/OWNERS @@ -1,4 +1,4 @@ -per-file * = * +# Bug component: 656484 + +include platform/frameworks/base/services/backup:/OWNERS -# Please reach out to the Android B&R team for settings backup changes -per-file SettingsBackupTest.java = alsutton@google.com, nathch@google.com, rthakohov@google.com 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/Tethering/Android.bp b/packages/Tethering/Android.bp deleted file mode 100644 index 5526c657b874..000000000000 --- a/packages/Tethering/Android.bp +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -java_defaults { - name: "TetheringAndroidLibraryDefaults", - sdk_version: "module_current", - srcs: [ - "src/**/*.java", - ":framework-tethering-shared-srcs", - ":tethering-module-utils-srcs", - ":services-tethering-shared-srcs", - ], - static_libs: [ - "androidx.annotation_annotation", - "netd_aidl_interface-unstable-java", - "netlink-client", - // TODO: use networkstack-client instead of just including the AIDL interface - "networkstack-aidl-interfaces-unstable-java", - "android.hardware.tetheroffload.config-V1.0-java", - "android.hardware.tetheroffload.control-V1.0-java", - "net-utils-framework-common", - "net-utils-device-common", - ], - libs: [ - "framework-statsd.stubs.module_lib", - "framework-tethering.impl", - "framework-wifi", - "unsupportedappusage", - ], - plugins: ["java_api_finder"], - manifest: "AndroidManifestBase.xml", -} - -// Build tethering static library, used to compile both variants of the tethering. -android_library { - name: "TetheringApiCurrentLib", - defaults: ["TetheringAndroidLibraryDefaults"], -} - -// Due to b/143733063, APK can't access a jni lib that is in APEX (but not in the APK). -cc_library { - name: "libtetherutilsjni", - sdk_version: "current", - apex_available: [ - "//apex_available:platform", // Used by InProcessTethering - "com.android.tethering", - ], - min_sdk_version: "current", - srcs: [ - "jni/android_net_util_TetheringUtils.cpp", - ], - shared_libs: [ - "liblog", - "libnativehelper_compat_libc++", - ], - - // We cannot use plain "libc++" here to link libc++ dynamically because it results in: - // java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found - // even if "libc++" is added into jni_libs below. Adding "libc++_shared" into jni_libs doesn't - // build because soong complains of: - // module Tethering missing dependencies: libc++_shared - // - // So, link libc++ statically. This means that we also need to ensure that all the C++ libraries - // we depend on do not dynamically link libc++. This is currently the case, because liblog is - // C-only and libnativehelper_compat_libc also uses stl: "c++_static". - stl: "c++_static", - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wthread-safety", - ], - - ldflags: ["-Wl,--exclude-libs=ALL,-error-limit=0"], -} - -// Common defaults for compiling the actual APK. -java_defaults { - name: "TetheringAppDefaults", - sdk_version: "module_current", - privileged: true, - jni_libs: [ - "libtetherutilsjni", - ], - resource_dirs: [ - "res", - ], - libs: [ - "framework-tethering", - "framework-wifi", - ], - jarjar_rules: "jarjar-rules.txt", - optimize: { - proguard_flags_files: ["proguard.flags"], - }, -} - -// Non-updatable tethering running in the system server process for devices not using the module -android_app { - name: "InProcessTethering", - defaults: ["TetheringAppDefaults"], - static_libs: ["TetheringApiCurrentLib"], - certificate: "platform", - manifest: "AndroidManifest_InProcess.xml", - // InProcessTethering is a replacement for Tethering - overrides: ["Tethering"], - apex_available: ["com.android.tethering"], - min_sdk_version: "current", -} - -// Updatable tethering packaged as an application -android_app { - name: "Tethering", - defaults: ["TetheringAppDefaults"], - static_libs: ["TetheringApiCurrentLib"], - certificate: "networkstack", - manifest: "AndroidManifest.xml", - use_embedded_native_libs: true, - // The permission configuration *must* be included to ensure security of the device - required: ["NetworkPermissionConfig"], - apex_available: ["com.android.tethering"], - min_sdk_version: "current", -} diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml deleted file mode 100644 index e6444f3ead5c..000000000000 --- a/packages/Tethering/AndroidManifest.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.networkstack.tethering" - android:sharedUserId="android.uid.networkstack"> - <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" /> - - <!-- Permissions must be defined here, and not in the base manifest, as the tethering - running in the system server process does not need any permission, and having - privileged permissions added would cause crashes on startup unless they are also - added to the privileged permissions allowlist for that package. --> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <uses-permission android:name="android.permission.BLUETOOTH" /> - <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> - <uses-permission android:name="android.permission.BROADCAST_STICKY" /> - <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> - <uses-permission android:name="android.permission.MANAGE_USB" /> - <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> - <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> - <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> - <uses-permission android:name="android.permission.READ_PHONE_STATE"/> - <uses-permission android:name="android.permission.TETHER_PRIVILEGED" /> - <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> - <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> - <uses-permission android:name="android.permission.WRITE_SETTINGS" /> - - <protected-broadcast android:name="com.android.server.connectivity.tethering.DISABLE_TETHERING" /> - - <application - android:process="com.android.networkstack.process" - android:extractNativeLibs="false" - android:persistent="true"> - <service android:name="com.android.networkstack.tethering.TetheringService" - android:permission="android.permission.MAINLINE_NETWORK_STACK" - android:exported="true"> - <intent-filter> - <action android:name="android.net.ITetheringConnector"/> - </intent-filter> - </service> - </application> -</manifest> diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml deleted file mode 100644 index 97c3988829fe..000000000000 --- a/packages/Tethering/AndroidManifestBase.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.networkstack.tethering" - android:versionCode="1" - android:versionName="R-initial"> - <application - android:label="Tethering" - android:defaultToDeviceProtectedStorage="true" - android:directBootAware="true" - android:usesCleartextTraffic="true"> - </application> -</manifest> diff --git a/packages/Tethering/AndroidManifest_InProcess.xml b/packages/Tethering/AndroidManifest_InProcess.xml deleted file mode 100644 index b1f124097c79..000000000000 --- a/packages/Tethering/AndroidManifest_InProcess.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.networkstack.tethering.inprocess" - android:sharedUserId="android.uid.system" - android:process="system"> - <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" /> - <application> - <service android:name="com.android.networkstack.tethering.TetheringService" - android:process="system" - android:permission="android.permission.MAINLINE_NETWORK_STACK" - android:exported="true"> - <intent-filter> - <action android:name="android.net.ITetheringConnector.InProcess"/> - </intent-filter> - </service> - </application> -</manifest> diff --git a/packages/Tethering/OWNERS b/packages/Tethering/OWNERS deleted file mode 100644 index 5b42d490411e..000000000000 --- a/packages/Tethering/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -include platform/packages/modules/NetworkStack/:/OWNERS -markchien@google.com diff --git a/packages/Tethering/TEST_MAPPING b/packages/Tethering/TEST_MAPPING deleted file mode 100644 index 5617b0c13c1c..000000000000 --- a/packages/Tethering/TEST_MAPPING +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presubmit": [ - { - "name": "TetheringTests" - } - ], - "postsubmit": [ - { - "name": "TetheringIntegrationTests" - } - ] -} diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp deleted file mode 100644 index 05243749f765..000000000000 --- a/packages/Tethering/apex/Android.bp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -apex { - name: "com.android.tethering", - updatable: true, - min_sdk_version: "current", - java_libs: ["framework-tethering"], - bpfs: ["offload.o"], - apps: ["Tethering"], - manifest: "manifest.json", - key: "com.android.tethering.key", - - androidManifest: "AndroidManifest.xml", -} - -apex_key { - name: "com.android.tethering.key", - public_key: "com.android.tethering.avbpubkey", - private_key: "com.android.tethering.pem", -} - -android_app_certificate { - name: "com.android.tethering.certificate", - certificate: "com.android.tethering", -} - -override_apex { - name: "com.android.tethering.inprocess", - base: "com.android.tethering", - package_name: "com.android.tethering.inprocess", - apps: [ - "InProcessTethering", - ], -} diff --git a/packages/Tethering/apex/AndroidManifest.xml b/packages/Tethering/apex/AndroidManifest.xml deleted file mode 100644 index 4aae3cc3000d..000000000000 --- a/packages/Tethering/apex/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tethering"> - <!-- APEX does not have classes.dex --> - <application android:hasCode="false" /> - <!-- b/145383354: Current minSdk is locked to Q for development cycle, lock it to next version - before ship. --> - <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 --> - <!--uses-sdk - android:minSdkVersion="29" - android:targetSdkVersion="29" - /> - --> -</manifest> diff --git a/packages/Tethering/apex/com.android.tethering.avbpubkey b/packages/Tethering/apex/com.android.tethering.avbpubkey Binary files differdeleted file mode 100644 index 9a2c0174e496..000000000000 --- a/packages/Tethering/apex/com.android.tethering.avbpubkey +++ /dev/null diff --git a/packages/Tethering/apex/com.android.tethering.pem b/packages/Tethering/apex/com.android.tethering.pem deleted file mode 100644 index d4f39abd3bb2..000000000000 --- a/packages/Tethering/apex/com.android.tethering.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKgIBAAKCAgEA+AWTp03PBRMGt4mVNLt5PDoFFSfmFOVTM7jt5AJXnQMIDsAM -1cyWGWRridGIpoHAaCALVgW5aRySgi8yV5xP4w0YHcKbfh9M6I9oz4RUo4GQBZfX -+lFIGaLjb6I3tEJxPuxps4sW26Io63ihwTnKeGyADHdHGWDUs9WU0Ml+QTvKrdjy -qC03M0dehYXILGiA9m+UXwKoKxhWgfDUhWLhDBUtLJLPL4WeqKc9sG9h+zzVqE+8 -LzJsfrodKhTTrLpWOXi6YLRTk8dzsuPz/Nu98sJd1w3fHd20DrmkqsxVhgN1h+nk -zcPpxyGYIP6qYVZCmIXCwZZNtPeb7y/tOs967VHoZ4Qj7p2tE0CAWFMZFGjA/pcZ -7fi6CsIuMOYBbj4+wRlJwpG1g5zSJBCjzhv7dZp8S5oXmLShNYOMYEdsPfaZbm08 -3pVY+k8DVf7idcANXNw1lM+sPbE2hp5VuEuVpK+ca5x8hIMpTqJ84wDAjnC1kCwm -X2xfNvYPKNF58SvqlNCPN8X7hQjoeaEb7w24vCdZMRqeGBmu1GNQvCyzbBO0huQm -f5CQPrZjPcnoImlP879VPxY4YB6tAjsA/ZLiub9VdT108lCjb5r8criMzpMAA/AQ -NqQLWFI3M43xPemGBTiIguTYgpRgGcdRZf7XuTgTY5qzQZZuZMVuwaqSD2cCAwEA -AQKCAgEA0jMvw3BPTrakT7Lb8JgelKt7mUV6WyVMUZ6eh0pw5JIoJxAfEKfWYmjY -NzKNRMjcv6LA2MP7MplTld/YI6ZHkl+Lm9VOISL39HVuV8mIThbFb+gT1INEvu1t -IjRyT2SsQ67rmo377mLNmVtgg7mt3kfecjI44MpPGqad/CF4zmKVUKd4aI4BpYUM -F8+dKf3bpoBEWA2RZwy2bGQmSXHW132vDoLR8y2knL04rCqJ+PrC/WWuULXEe9bS -VtLV3yMBZq3qD4Fk/+7fILLPGvNFVdPi4htQiChYrM4rP9HzfaO63VieYMF0hR70 -pqoOznXj9Q4QVC9FZmUgFCQjQ1+KhqJw3OldIo0SnvpsLdTO/inKkhQWKC5HlPyh -/rqvro2j3pTHWPAziuBr+oQPcdVCOlCBZ+B99L1tO7aGktVPEIVQG7G7jlFMBiJ1 -j/kRGk2RTX8RaPQJTnwUqp8mWUV2fwxHiXNadjejA5ZU3eQT2eAOhXl1w6Lv2jEl -0wMOwPMJGcF77CcqnnWHON8fkxCbAfyy5Uo6Pm9g/Zzecn+ji2sabG7Ge5t0gzdL -LKRcGoyakN2CrbQ8pxlCTgE4HX5oPY+VuqOf8L3AIWIJBsyLbXHVkL1mqQ/Ed2uz -zaaSFYUZw81+m/5bl8JLPaIFNPyikZrXTD0YRer3V06XiyP/kYECggEBAP033xeF -OhgRwkRTjd68hwRJpyHsZDWxHiUqQf6l6yFv5mEE355G2IGI7cZmR2+tUDjQdxLv -tAZIszTK4PFCdVTeWfGVFbVF84eNWLB124pHDMM79GN/AMcuHnQPR756a8IO1hIy -4KxIUE1a1PKN5b9IgE5Lu4TZM96HDpFcUAmCT5urdYDmg3++IWT9PYQlGS7Hhiar -r+Hh646waM8Qx619CwXBqy+Y37+WHVbYqJClr6AcpVMrGA+6cgpskFpZAPLsoy7G -RSsVfyV8pH2JKm/hzk7XCwIpczxeWQSfpJWZ+oOPFHu+zM60Cdj2UrQyKrNHwew8 -+WYe9eCA+MiNBcECggEBAPq/F1vdqROiLv9uzhKb8ybgdL7CmREELiqwK+MvNE9t -W7lQz7lcWzav+b2n0M+VJBxUWB3XClgoIvA/AllgTgsYXfKAxNakhKLSBoMmvKCW -HtWcGr/D3RcmacK+DTMWlVS/LuueAFLuH6UmBIUFKc+qA5x7oQecAFALBFupE3G4 -LtAspLBI6P8gRtRav5p2whs9H8qjYcyf2f6liWpkmFITcXvPvAxFHicR6ZJdwZ/S -PiX2LJQnOpT7L3+2PWnYwzFStb4MkMGlFKcscU9CvS53JcP/J4Asjk0I4zDB2gri -xzFHPlVzCr2IVVGptKCQ3sdYiMIzQKzEXQHCU8h37ycCggEBAJu8aC48Fz3Edlm1 -ldS+2L9vWSaJEBzhoSu0cMBgZVu8SdGzwKDE69XHVI4oS5lI28UFmaaA3JTc07MN -cAmSGT2oP2NQkPhbXGsrKLfm1K6YAiZ1Ulp7OwxFth8lYreo7Wt92nV46yuqkhDx -Y3UGhp39xkPhWiRbvgYHxJLsVqFyjumsK2mq3IeNdVZ6VgJXGsTlnAFeqJ7hZxHs -N5natSRjeosA0PtGJ57agZLvT8Ue0gREef3LzFGoFwmIOcQHZ4kAt2BGOzZDU17H -6Rb4bKxBEbT1l2St/5zKXi90zDHicOvG7Q8qiyY6HrBc1wLSs+ZtpLxZx/3h3tFE -IT6fVUECggEBAMSAQm8Ey76OJ+SXUjk1K50442SnHcs/Cmr7urkEQitImUwl71Pk -87pst/uP6szypOTqmE9yOTIS6iZ6Sn3+QcriIqWrkhZfwW3Tx7S6A7KZUrq15iSH -+thsiw9JXxC9TvOmC8AsBzb2U6hZncsc28JZCxFztSNAduJDb/vhCVLiMxWDFuDr -kmR1R+yc3XDQRpeQFDz6QudYEj9EPOc6xD/16sZLaqP2+oVFvVSt0tJLsdaQECle -gMNGAdhE2eX8MCOUHMc+E6cdlozYAEhMFfO2/cqWR79jq3TlVR3dnOFRDScqHMhc -KnuTvsELjHkUbvGsCSiff7yk+fop7vy4OJsCggEAPemJdItO2rhib8EofrZdY72I -oifX1jhPZ1BWD2GKgcx+eVyJGbONBbJVexvvskTfZBvCcAegmgp+sngP6MO6yZkr -cHMfAJeApYZnshsgXksHGMDtSB50/w1JLrc/nqpxdpy/aTazt0Eu1pLWpze1HFZ/ -Xyu4PcmrU+4P1vN7c396slHMktEvly6QqOn4nfBbGDJ17Ow6X1XFvGjAxQPIDTB+ -6loV14AHymwmqwMrGn84O72rzqyw+41GxW5+oXhOZ4MeXF3u89TBLWvXDpPy/YQU -EiKpodN0YeEn6Ghzplan8rUha+7TP7AYnS5pCszsCHKd03Py0lMLkF+uAfVsDA== ------END RSA PRIVATE KEY----- diff --git a/packages/Tethering/apex/com.android.tethering.pk8 b/packages/Tethering/apex/com.android.tethering.pk8 Binary files differdeleted file mode 100644 index 3b94405945cb..000000000000 --- a/packages/Tethering/apex/com.android.tethering.pk8 +++ /dev/null diff --git a/packages/Tethering/apex/com.android.tethering.x509.pem b/packages/Tethering/apex/com.android.tethering.x509.pem deleted file mode 100644 index a1786e35e854..000000000000 --- a/packages/Tethering/apex/com.android.tethering.x509.pem +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGKTCCBBGgAwIBAgIUNiSs5EMqxCZ31gWWCcRJVp9HffAwDQYJKoZIhvcNAQEL -BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy -b2lkMR4wHAYDVQQDDBVjb20uYW5kcm9pZC50ZXRoZXJpbmcxIjAgBgkqhkiG9w0B -CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjE4MDcwMDQ4WhgPNDc1NzEx -MTMwNzAwNDhaMIGiMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW -MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE -CwwHQW5kcm9pZDEeMBwGA1UEAwwVY29tLmFuZHJvaWQudGV0aGVyaW5nMSIwIAYJ -KoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAxvTUA4seblYjZLfTVNwZuJH914QVNFTj+vD94pWmt5Aq -sH1DVTpBvpXXegc/P5HI2XF/71poSBib1WaQSuXG0fU5K75T18bOGL0qF+fhMtBO -wUyvulcjO0h4XE/xf0txY54exUjAA4JS9ERGJOgb4GOwSbPyzekfmzIyCZ2Yawwu -+oGwD2ZNzZRaPOoWxjwohBWQ6mySuvF9RRRb300qmxxUGFM9Ki3aqrWlYlHEOwOC -M+gIXxYFO7S+yUzf6/gMZLOz2YqfcTOup4hAxtExR7niutxJSsRLPBL237exAJoz -OupoXjtWAlPK4ZwZ/Nl1jdTWauJ+Kv3WqzhHGEb2gn3ZpeO3IdOjJhDgFJ6m1OT/ -kjRbW1LCuKGrKaoqsEDT2X3a7Izfripn65hSNTfR5gNLtgELaI3/vXi8Fmzw1AfH -+qi6ulElZvSwx0qm+S0QiPyGFlxrsdnHoGJl1tzjJW8KdNZRvzRLUQtbphPp+VkL -5i0bNKum+AwbfdUkLkNLfw9XdbujgBkZTZDQbZGsNjgrvyXcPO2KiJee0hVCZRs0 -rhDi5Pfm7BnN/I2vaTRz/W4mdct9H2RWMuqlSH90JvmKtWcND8ahmOJ3sggrvzfO -QNs3k4JTRecamMzqIkylhlnEC4FjWc6Bx4wsEpwBMZOkF/tGGMZYf2C09a8tpP0C -AwEAAaNTMFEwHQYDVR0OBBYEFNP5gIpNWmq0xa411M1GaRPbEijvMB8GA1UdIwQY -MBaAFNP5gIpNWmq0xa411M1GaRPbEijvMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI -hvcNAQELBQADggIBADJGmU3QP4EGbt6eBhVPeo/efsqrHsuB2fvFzvIobJbfkSob -cmvjbzIikOlPAgFWj8lT5SDcIWRorFf1u2JylClJ0nSDcqJMHVKmT7wseV/KtX// -1yUyJFRQVzmjC89dp8OIc00GmItivKLer3NbJdkR3rTUjg7+bNUO27Qp3AFREmiJ -P+M7ouvcQRvByUWbp/LOrJpMdJLysRBO562RwrtwTjltdvufyYswbBZOKEiUh1Jc -Ged+3+SJdhwq3Wy+R3Uj7YE7mUMu1QNbANIMrwF8W93EA53eoL2+cKmuaVU6ZURL -xgSJaY6TrunnSI9XTROLtjsFlJorYWy2tvG7Q5Hw3OkO2Xdz/mm85VTkiusg9DMB -WWTv607YtsIO0FhKmcV4bp3q/EkRj3t/zLvL9uFJrWDGkuShZq6fQvqbCvaokOPY -+M0ZRIwgwa9UpEE0BMklVWqR6BGyap614gOgcOjYM70WRNl59Qne+g128ZN7g9nz -61F70i7kUngV0ZUz1/Fu/NCG+6wGF85ZbFmQl60YHPDw1FtjVUuKyBblaDzdJunx -yQr2t9RUokzFBFK0lGW3+yf0WDQ5fqTMs5h8bz1FCq8/HzWmpdOfqePLe4zsld3b -1nFuSohaIfbn/HDdTNtTBGQPgz8ZswQ6ejJJqTLz9D/odbqn9LeIhDZXcQTf ------END CERTIFICATE----- diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json deleted file mode 100644 index 8836c4e50333..000000000000 --- a/packages/Tethering/apex/manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.tethering", - "version": 300900700 -} diff --git a/packages/Tethering/bpf_progs/Android.bp b/packages/Tethering/bpf_progs/Android.bp deleted file mode 100644 index d54f86148665..000000000000 --- a/packages/Tethering/bpf_progs/Android.bp +++ /dev/null @@ -1,33 +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. -// - -// -// bpf kernel programs -// -bpf { - name: "offload.o", - srcs: ["offload.c"], - cflags: [ - "-Wall", - "-Werror", - ], - include_dirs: [ - // TODO: get rid of system/netd. - "system/netd/bpf_progs", // for bpf_net_helpers.h - "system/netd/libnetdbpf/include", // for bpf_shared.h - "system/netd/libnetdutils/include", // for UidConstants.h - ], -} diff --git a/packages/Tethering/bpf_progs/offload.c b/packages/Tethering/bpf_progs/offload.c deleted file mode 100644 index cc5af3127b02..000000000000 --- a/packages/Tethering/bpf_progs/offload.c +++ /dev/null @@ -1,207 +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. - */ - -#include <linux/if.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/pkt_cls.h> -#include <linux/tcp.h> - -#include "bpf_helpers.h" -#include "bpf_net_helpers.h" -#include "netdbpf/bpf_shared.h" - -DEFINE_BPF_MAP_GRW(tether_ingress_map, HASH, TetherIngressKey, TetherIngressValue, 64, - AID_NETWORK_STACK) - -// Tethering stats, indexed by upstream interface. -DEFINE_BPF_MAP_GRW(tether_stats_map, HASH, uint32_t, TetherStatsValue, 16, AID_NETWORK_STACK) - -// Tethering data limit, indexed by upstream interface. -// (tethering allowed when stats[iif].rxBytes + stats[iif].txBytes < limit[iif]) -DEFINE_BPF_MAP_GRW(tether_limit_map, HASH, uint32_t, uint64_t, 16, AID_NETWORK_STACK) - -static inline __always_inline int do_forward(struct __sk_buff* skb, bool is_ethernet) { - int l2_header_size = is_ethernet ? sizeof(struct ethhdr) : 0; - void* data = (void*)(long)skb->data; - const void* data_end = (void*)(long)skb->data_end; - struct ethhdr* eth = is_ethernet ? data : NULL; // used iff is_ethernet - struct ipv6hdr* ip6 = is_ethernet ? (void*)(eth + 1) : data; - - // Must be meta-ethernet IPv6 frame - if (skb->protocol != htons(ETH_P_IPV6)) return TC_ACT_OK; - - // Must have (ethernet and) ipv6 header - if (data + l2_header_size + sizeof(*ip6) > data_end) return TC_ACT_OK; - - // Ethertype - if present - must be IPv6 - if (is_ethernet && (eth->h_proto != htons(ETH_P_IPV6))) return TC_ACT_OK; - - // IP version must be 6 - if (ip6->version != 6) return TC_ACT_OK; - - // Cannot decrement during forward if already zero or would be zero, - // Let the kernel's stack handle these cases and generate appropriate ICMP errors. - if (ip6->hop_limit <= 1) return TC_ACT_OK; - - // Protect against forwarding packets sourced from ::1 or fe80::/64 or other weirdness. - __be32 src32 = ip6->saddr.s6_addr32[0]; - if (src32 != htonl(0x0064ff9b) && // 64:ff9b:/32 incl. XLAT464 WKP - (src32 & htonl(0xe0000000)) != htonl(0x20000000)) // 2000::/3 Global Unicast - return TC_ACT_OK; - - TetherIngressKey k = { - .iif = skb->ifindex, - .neigh6 = ip6->daddr, - }; - - TetherIngressValue* v = bpf_tether_ingress_map_lookup_elem(&k); - - // If we don't find any offload information then simply let the core stack handle it... - if (!v) return TC_ACT_OK; - - uint32_t stat_and_limit_k = skb->ifindex; - - TetherStatsValue* stat_v = bpf_tether_stats_map_lookup_elem(&stat_and_limit_k); - - // If we don't have anywhere to put stats, then abort... - if (!stat_v) return TC_ACT_OK; - - uint64_t* limit_v = bpf_tether_limit_map_lookup_elem(&stat_and_limit_k); - - // If we don't have a limit, then abort... - if (!limit_v) return TC_ACT_OK; - - // Required IPv6 minimum mtu is 1280, below that not clear what we should do, abort... - const int pmtu = v->pmtu; - if (pmtu < IPV6_MIN_MTU) return TC_ACT_OK; - - // Approximate handling of TCP/IPv6 overhead for incoming LRO/GRO packets: default - // outbound path mtu of 1500 is not necessarily correct, but worst case we simply - // undercount, which is still better then not accounting for this overhead at all. - // Note: this really shouldn't be device/path mtu at all, but rather should be - // derived from this particular connection's mss (ie. from gro segment size). - // This would require a much newer kernel with newer ebpf accessors. - // (This is also blindly assuming 12 bytes of tcp timestamp option in tcp header) - uint64_t packets = 1; - uint64_t bytes = skb->len; - if (bytes > pmtu) { - const int tcp_overhead = sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 12; - const int mss = pmtu - tcp_overhead; - const uint64_t payload = bytes - tcp_overhead; - packets = (payload + mss - 1) / mss; - bytes = tcp_overhead * packets + payload; - } - - // Are we past the limit? If so, then abort... - // Note: will not overflow since u64 is 936 years even at 5Gbps. - // Do not drop here. Offload is just that, whenever we fail to handle - // a packet we let the core stack deal with things. - // (The core stack needs to handle limits correctly anyway, - // since we don't offload all traffic in both directions) - if (stat_v->rxBytes + stat_v->txBytes + bytes > *limit_v) return TC_ACT_OK; - - if (!is_ethernet) { - is_ethernet = true; - l2_header_size = sizeof(struct ethhdr); - // Try to inject an ethernet header, and simply return if we fail - if (bpf_skb_change_head(skb, l2_header_size, /*flags*/ 0)) { - __sync_fetch_and_add(&stat_v->rxErrors, 1); - return TC_ACT_OK; - } - - // bpf_skb_change_head() invalidates all pointers - reload them - data = (void*)(long)skb->data; - data_end = (void*)(long)skb->data_end; - eth = data; - ip6 = (void*)(eth + 1); - - // I do not believe this can ever happen, but keep the verifier happy... - if (data + l2_header_size + sizeof(*ip6) > data_end) { - __sync_fetch_and_add(&stat_v->rxErrors, 1); - return TC_ACT_SHOT; - } - }; - - // CHECKSUM_COMPLETE is a 16-bit one's complement sum, - // thus corrections for it need to be done in 16-byte chunks at even offsets. - // IPv6 nexthdr is at offset 6, while hop limit is at offset 7 - uint8_t old_hl = ip6->hop_limit; - --ip6->hop_limit; - uint8_t new_hl = ip6->hop_limit; - - // bpf_csum_update() always succeeds if the skb is CHECKSUM_COMPLETE and returns an error - // (-ENOTSUPP) if it isn't. - bpf_csum_update(skb, 0xFFFF - ntohs(old_hl) + ntohs(new_hl)); - - __sync_fetch_and_add(&stat_v->rxPackets, packets); - __sync_fetch_and_add(&stat_v->rxBytes, bytes); - - // Overwrite any mac header with the new one - *eth = v->macHeader; - - // Redirect to forwarded interface. - // - // Note that bpf_redirect() cannot fail unless you pass invalid flags. - // The redirect actually happens after the ebpf program has already terminated, - // and can fail for example for mtu reasons at that point in time, but there's nothing - // we can do about it here. - return bpf_redirect(v->oif, 0 /* this is effectively BPF_F_EGRESS */); -} - -SEC("schedcls/ingress/tether_ether") -int sched_cls_ingress_tether_ether(struct __sk_buff* skb) { - return do_forward(skb, true); -} - -// Note: section names must be unique to prevent programs from appending to each other, -// so instead the bpf loader will strip everything past the final $ symbol when actually -// pinning the program into the filesystem. -// -// bpf_skb_change_head() is only present on 4.14+ and 2 trivial kernel patches are needed: -// ANDROID: net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head -// ANDROID: net: bpf: permit redirect from ingress L3 to egress L2 devices at near max mtu -// (the first of those has already been upstreamed) -// -// 5.4 kernel support was only added to Android Common Kernel in R, -// and thus a 5.4 kernel always supports this. -// -// Hence, this mandatory (must load successfully) implementation for 5.4+ kernels: -DEFINE_BPF_PROG_KVER("schedcls/ingress/tether_rawip$5_4", AID_ROOT, AID_ROOT, - sched_cls_ingress_tether_rawip_5_4, KVER(5, 4, 0)) -(struct __sk_buff* skb) { - return do_forward(skb, false); -} - -// and this identical optional (may fail to load) implementation for [4.14..5.4) patched kernels: -DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/ingress/tether_rawip$4_14", AID_ROOT, AID_ROOT, - sched_cls_ingress_tether_rawip_4_14, KVER(4, 14, 0), - KVER(5, 4, 0)) -(struct __sk_buff* skb) { - return do_forward(skb, false); -} - -// and define a no-op stub for [4.9,4.14) and unpatched [4.14,5.4) kernels. -// (if the above real 4.14+ program loaded successfully, then bpfloader will have already pinned -// it at the same location this one would be pinned at and will thus skip loading this stub) -DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress/tether_rawip$stub", AID_ROOT, AID_ROOT, - sched_cls_ingress_tether_rawip_stub, KVER_NONE, KVER(5, 4, 0)) -(struct __sk_buff* skb) { - return TC_ACT_OK; -} - -LICENSE("Apache 2.0"); -CRITICAL("netd"); diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp deleted file mode 100644 index bf643cdcecc5..000000000000 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_sdk_library { - name: "framework-tethering", - defaults: ["framework-module-defaults"], - impl_library_visibility: ["//frameworks/base/packages/Tethering:__subpackages__"], - - srcs: [":framework-tethering-srcs"], - - jarjar_rules: "jarjar-rules.txt", - installable: true, - - hostdex: true, // for hiddenapi check - apex_available: ["com.android.tethering"], - permitted_packages: ["android.net"], -} - -filegroup { - name: "framework-tethering-srcs", - srcs: [ - "src/android/net/TetheredClient.aidl", - "src/android/net/TetheredClient.java", - "src/android/net/TetheringManager.java", - "src/android/net/TetheringConstants.java", - "src/android/net/IIntResultListener.aidl", - "src/android/net/ITetheringEventCallback.aidl", - "src/android/net/ITetheringConnector.aidl", - "src/android/net/TetheringCallbackStartedParcel.aidl", - "src/android/net/TetheringConfigurationParcel.aidl", - "src/android/net/TetheringRequestParcel.aidl", - "src/android/net/TetherStatesParcel.aidl", - ], - path: "src" -} diff --git a/packages/Tethering/common/TetheringLib/api/current.txt b/packages/Tethering/common/TetheringLib/api/current.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/packages/Tethering/common/TetheringLib/api/current.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-current.txt b/packages/Tethering/common/TetheringLib/api/module-lib-current.txt deleted file mode 100644 index 6ddb122936e7..000000000000 --- a/packages/Tethering/common/TetheringLib/api/module-lib-current.txt +++ /dev/null @@ -1,41 +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(); - } - -} - diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt b/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Tethering/common/TetheringLib/api/removed.txt b/packages/Tethering/common/TetheringLib/api/removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/packages/Tethering/common/TetheringLib/api/removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Tethering/common/TetheringLib/api/system-current.txt b/packages/Tethering/common/TetheringLib/api/system-current.txt deleted file mode 100644 index edd1ebb5f751..000000000000 --- a/packages/Tethering/common/TetheringLib/api/system-current.txt +++ /dev/null @@ -1,99 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public final class TetheredClient implements android.os.Parcelable { - ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int); - method public int describeContents(); - method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses(); - method @NonNull public android.net.MacAddress getMacAddress(); - method public int getTetheringType(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR; - } - - public static final class TetheredClient.AddressInfo implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public android.net.LinkAddress getAddress(); - method @Nullable public String getHostname(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR; - } - - public class TetheringManager { - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering(); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback); - field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED"; - field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY"; - field public static final String EXTRA_ACTIVE_TETHER = "tetherArray"; - field public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; - field public static final String EXTRA_ERRORED_TETHER = "erroredArray"; - field public static final int TETHERING_BLUETOOTH = 2; // 0x2 - field public static final int TETHERING_ETHERNET = 5; // 0x5 - field public static final int TETHERING_INVALID = -1; // 0xffffffff - field public static final int TETHERING_NCM = 4; // 0x4 - field public static final int TETHERING_USB = 1; // 0x1 - field public static final int TETHERING_WIFI = 0; // 0x0 - field public static final int TETHERING_WIFI_P2P = 3; // 0x3 - field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc - field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9 - field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8 - field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd - field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa - field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5 - field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf - field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe - field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0 - field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb - field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2 - field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6 - field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4 - field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1 - field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10 - field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3 - field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7 - field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2 - field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1 - field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0 - } - - public static interface TetheringManager.OnTetheringEntitlementResultListener { - method public void onTetheringEntitlementResult(int); - } - - public static interface TetheringManager.StartTetheringCallback { - method public default void onTetheringFailed(int); - method public default void onTetheringStarted(); - } - - public static interface TetheringManager.TetheringEventCallback { - method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>); - method public default void onError(@NonNull String, int); - method public default void onOffloadStatusChanged(int); - method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>); - method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>); - method public default void onTetheringSupported(boolean); - method public default void onUpstreamChanged(@Nullable android.net.Network); - } - - public static class TetheringManager.TetheringRequest { - method @Nullable public android.net.LinkAddress getClientStaticIpv4Address(); - method @Nullable public android.net.LinkAddress getLocalIpv4Address(); - method public boolean getShouldShowEntitlementUi(); - method public int getTetheringType(); - method public boolean isExemptFromEntitlementCheck(); - } - - public static class TetheringManager.TetheringRequest.Builder { - ctor public TetheringManager.TetheringRequest.Builder(int); - method @NonNull public android.net.TetheringManager.TetheringRequest build(); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress); - } - -} - diff --git a/packages/Tethering/common/TetheringLib/api/system-removed.txt b/packages/Tethering/common/TetheringLib/api/system-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/packages/Tethering/common/TetheringLib/api/system-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt deleted file mode 100644 index e459fad54993..000000000000 --- a/packages/Tethering/common/TetheringLib/jarjar-rules.txt +++ /dev/null @@ -1 +0,0 @@ -# jarjar rules for the bootclasspath tethering framework library here
\ No newline at end of file diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl deleted file mode 100644 index cf094aac2cbe..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.net.IIntResultListener; -import android.net.ITetheringEventCallback; -import android.net.TetheringRequestParcel; -import android.os.ResultReceiver; - -/** @hide */ -oneway interface ITetheringConnector { - void tether(String iface, String callerPkg, String callingAttributionTag, - IIntResultListener receiver); - - void untether(String iface, String callerPkg, String callingAttributionTag, - IIntResultListener receiver); - - void setUsbTethering(boolean enable, String callerPkg, - String callingAttributionTag, IIntResultListener receiver); - - void startTethering(in TetheringRequestParcel request, String callerPkg, - String callingAttributionTag, IIntResultListener receiver); - - void stopTethering(int type, String callerPkg, String callingAttributionTag, - IIntResultListener receiver); - - void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver, - boolean showEntitlementUi, String callerPkg, String callingAttributionTag); - - void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); - - void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); - - void isTetheringSupported(String callerPkg, String callingAttributionTag, - IIntResultListener receiver); - - void stopAllTethering(String callerPkg, String callingAttributionTag, - IIntResultListener receiver); -} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl deleted file mode 100644 index b4e3ba46791c..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.net.Network; -import android.net.TetheredClient; -import android.net.TetheringConfigurationParcel; -import android.net.TetheringCallbackStartedParcel; -import android.net.TetherStatesParcel; - -/** - * Callback class for receiving tethering changed events. - * @hide - */ -oneway interface ITetheringEventCallback -{ - /** Called immediately after the callbacks are registered */ - void onCallbackStarted(in TetheringCallbackStartedParcel parcel); - void onCallbackStopped(int errorCode); - void onUpstreamChanged(in Network network); - void onConfigurationChanged(in TetheringConfigurationParcel config); - void onTetherStatesChanged(in TetherStatesParcel states); - void onTetherClientsChanged(in List<TetheredClient> clients); - void onOffloadStatusChanged(int status); -} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java deleted file mode 100644 index 0b223f42b954..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Objects; - -/** - * Information on a tethered downstream client. - * @hide - */ -@SystemApi -public final class TetheredClient implements Parcelable { - @NonNull - private final MacAddress mMacAddress; - @NonNull - private final List<AddressInfo> mAddresses; - // TODO: use an @IntDef here - private final int mTetheringType; - - public TetheredClient(@NonNull MacAddress macAddress, - @NonNull Collection<AddressInfo> addresses, int tetheringType) { - mMacAddress = macAddress; - mAddresses = new ArrayList<>(addresses); - mTetheringType = tetheringType; - } - - private TetheredClient(@NonNull Parcel in) { - this(in.readParcelable(null), in.createTypedArrayList(AddressInfo.CREATOR), in.readInt()); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeParcelable(mMacAddress, flags); - dest.writeTypedList(mAddresses); - dest.writeInt(mTetheringType); - } - - /** - * Get the MAC address used to identify the client. - */ - @NonNull - public MacAddress getMacAddress() { - return mMacAddress; - } - - /** - * Get information on the list of addresses that are associated with the client. - */ - @NonNull - public List<AddressInfo> getAddresses() { - return new ArrayList<>(mAddresses); - } - - /** - * Get the type of tethering used by the client. - * @return one of the {@code TetheringManager#TETHERING_*} constants. - */ - public int getTetheringType() { - return mTetheringType; - } - - /** - * Return a new {@link TetheredClient} that has all the attributes of this instance, plus the - * {@link AddressInfo} of the provided {@link TetheredClient}. - * - * <p>Duplicate addresses are removed. - * @hide - */ - public TetheredClient addAddresses(@NonNull TetheredClient other) { - final LinkedHashSet<AddressInfo> newAddresses = new LinkedHashSet<>( - mAddresses.size() + other.mAddresses.size()); - newAddresses.addAll(mAddresses); - newAddresses.addAll(other.mAddresses); - return new TetheredClient(mMacAddress, newAddresses, mTetheringType); - } - - @Override - public int hashCode() { - return Objects.hash(mMacAddress, mAddresses, mTetheringType); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof TetheredClient)) return false; - final TetheredClient other = (TetheredClient) obj; - return mMacAddress.equals(other.mMacAddress) - && mAddresses.equals(other.mAddresses) - && mTetheringType == other.mTetheringType; - } - - /** - * Information on an lease assigned to a tethered client. - */ - public static final class AddressInfo implements Parcelable { - @NonNull - private final LinkAddress mAddress; - @Nullable - private final String mHostname; - - /** @hide */ - public AddressInfo(@NonNull LinkAddress address, @Nullable String hostname) { - this.mAddress = address; - this.mHostname = hostname; - } - - private AddressInfo(Parcel in) { - this(in.readParcelable(null), in.readString()); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeParcelable(mAddress, flags); - dest.writeString(mHostname); - } - - /** - * Get the link address (including prefix length and lifetime) used by the client. - * - * This may be an IPv4 or IPv6 address. - */ - @NonNull - public LinkAddress getAddress() { - return mAddress; - } - - /** - * Get the hostname that was advertised by the client when obtaining its address, if any. - */ - @Nullable - public String getHostname() { - return mHostname; - } - - /** - * Get the expiration time of the address assigned to the client. - * @hide - */ - public long getExpirationTime() { - return mAddress.getExpirationTime(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public int hashCode() { - return Objects.hash(mAddress, mHostname); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof AddressInfo)) return false; - final AddressInfo other = (AddressInfo) obj; - // Use .equals() for addresses as all changes, including address expiry changes, - // should be included. - return other.mAddress.equals(mAddress) - && Objects.equals(mHostname, other.mHostname); - } - - @NonNull - public static final Creator<AddressInfo> CREATOR = new Creator<AddressInfo>() { - @NonNull - @Override - public AddressInfo createFromParcel(@NonNull Parcel in) { - return new AddressInfo(in); - } - - @NonNull - @Override - public AddressInfo[] newArray(int size) { - return new AddressInfo[size]; - } - }; - - @NonNull - @Override - public String toString() { - return "AddressInfo {" - + mAddress - + (mHostname != null ? ", hostname " + mHostname : "") - + "}"; - } - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull - public static final Creator<TetheredClient> CREATOR = new Creator<TetheredClient>() { - @NonNull - @Override - public TetheredClient createFromParcel(@NonNull Parcel in) { - return new TetheredClient(in); - } - - @NonNull - @Override - public TetheredClient[] newArray(int size) { - return new TetheredClient[size]; - } - }; - - @NonNull - @Override - public String toString() { - return "TetheredClient {hwAddr " + mMacAddress - + ", addresses " + mAddresses - + ", tetheringType " + mTetheringType - + "}"; - } -} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl deleted file mode 100644 index 89f38132ffad..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * Configuration details for tethering. - * @hide - */ -parcelable TetheringConfigurationParcel { - int subId; - String[] tetherableUsbRegexs; - String[] tetherableWifiRegexs; - String[] tetherableBluetoothRegexs; - boolean isDunRequired; - boolean chooseUpstreamAutomatically; - int[] preferredUpstreamIfaceTypes; - String[] legacyDhcpRanges; - String[] defaultIPv4DNS; - boolean enableLegacyDhcpServer; - String[] provisioningApp; - String provisioningAppNoUi; - int provisioningCheckPeriod; -} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java deleted file mode 100644 index f14def6a3a02..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; - -import android.annotation.SystemApi; -import android.os.ResultReceiver; - -/** - * Collections of constants for internal tethering usage. - * - * <p>These hidden constants are not in TetheringManager as they are not part of the API stubs - * generated for TetheringManager, which prevents the tethering module from linking them at - * build time. - * TODO: investigate changing the tethering build rules so that Tethering can reference hidden - * symbols from framework-tethering even when they are in a non-hidden class. - * @hide - */ -@SystemApi(client = MODULE_LIBRARIES) -public final class TetheringConstants { - /** An explicit private class to avoid exposing constructor.*/ - private TetheringConstants() { } - - /** - * Extra used for communicating with the TetherService and TetherProvisioningActivity. - * Includes the type of tethering to enable if any. - */ - public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType"; - /** - * Extra used for communicating with the TetherService. Includes the type of tethering for - * which to cancel provisioning. - */ - public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType"; - /** - * Extra used for communicating with the TetherService. True to schedule a recheck of tether - * provisioning. - */ - public static final String EXTRA_SET_ALARM = "extraSetAlarm"; - /** - * Tells the TetherService to run a provision check now. - */ - public static final String EXTRA_RUN_PROVISION = "extraRunProvision"; - /** - * Extra used for communicating with the TetherService and TetherProvisioningActivity. - * Contains the {@link ResultReceiver} which will receive provisioning results. - * Can not be empty. - */ - public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback"; - - /** - * Extra used for communicating with the TetherService and TetherProvisioningActivity. - * Contains the subId of current active cellular upstream. - * @hide - */ - public static final String EXTRA_TETHER_SUBID = "android.net.extra.TETHER_SUBID"; - - /** - * Extra used for telling TetherProvisioningActivity the entitlement package name and class - * name to start UI entitlement check. - * @hide - */ - public static final String EXTRA_TETHER_UI_PROVISIONING_APP_NAME = - "android.net.extra.TETHER_UI_PROVISIONING_APP_NAME"; - - /** - * Extra used for telling TetherService the intent action to start silent entitlement check. - * @hide - */ - public static final String EXTRA_TETHER_SILENT_PROVISIONING_ACTION = - "android.net.extra.TETHER_SILENT_PROVISIONING_ACTION"; - - /** - * Extra used for TetherService to receive the response of provisioning check. - * @hide - */ - public static final String EXTRA_TETHER_PROVISIONING_RESPONSE = - "android.net.extra.TETHER_PROVISIONING_RESPONSE"; -} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java deleted file mode 100644 index 97fb4974d0f6..000000000000 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; - -import android.Manifest; -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.util.ArrayMap; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.Executor; -import java.util.function.Supplier; - -/** - * This class provides the APIs to control the tethering service. - * <p> The primary responsibilities of this class are to provide the APIs for applications to - * start tethering, stop tethering, query configuration and query status. - * - * @hide - */ -@SystemApi -public class TetheringManager { - private static final String TAG = TetheringManager.class.getSimpleName(); - private static final int DEFAULT_TIMEOUT_MS = 60_000; - private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L; - - @GuardedBy("mConnectorWaitQueue") - @Nullable - private ITetheringConnector mConnector; - @GuardedBy("mConnectorWaitQueue") - @NonNull - private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>(); - private final Supplier<IBinder> mConnectorSupplier; - - private final TetheringCallbackInternal mCallback; - private final Context mContext; - private final ArrayMap<TetheringEventCallback, ITetheringEventCallback> - mTetheringEventCallbacks = new ArrayMap<>(); - - private volatile TetheringConfigurationParcel mTetheringConfiguration; - private volatile TetherStatesParcel mTetherStatesParcel; - - /** - * Broadcast Action: A tetherable connection has come or gone. - * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER}, - * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY}, - * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and - * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate - * the current state of tethering. Each include a list of - * interface names in that state (may be empty). - */ - public static final String ACTION_TETHER_STATE_CHANGED = - "android.net.conn.TETHER_STATE_CHANGED"; - - /** - * gives a String[] listing all the interfaces configured for - * tethering and currently available for tethering. - */ - public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; - - /** - * gives a String[] listing all the interfaces currently in local-only - * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding) - */ - public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY"; - - /** - * gives a String[] listing all the interfaces currently tethered - * (ie, has DHCPv4 support and packets potentially forwarded/NATed) - */ - public static final String EXTRA_ACTIVE_TETHER = "tetherArray"; - - /** - * gives a String[] listing all the interfaces we tried to tether and - * failed. Use {@link #getLastTetherError} to find the error code - * for any interfaces listed here. - */ - public static final String EXTRA_ERRORED_TETHER = "erroredArray"; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = false, value = { - TETHERING_WIFI, - TETHERING_USB, - TETHERING_BLUETOOTH, - TETHERING_WIFI_P2P, - TETHERING_NCM, - TETHERING_ETHERNET, - }) - public @interface TetheringType { - } - - /** - * Invalid tethering type. - * @see #startTethering. - */ - public static final int TETHERING_INVALID = -1; - - /** - * Wifi tethering type. - * @see #startTethering. - */ - public static final int TETHERING_WIFI = 0; - - /** - * USB tethering type. - * @see #startTethering. - */ - public static final int TETHERING_USB = 1; - - /** - * Bluetooth tethering type. - * @see #startTethering. - */ - public static final int TETHERING_BLUETOOTH = 2; - - /** - * Wifi P2p tethering type. - * Wifi P2p tethering is set through events automatically, and don't - * need to start from #startTethering. - */ - public static final int TETHERING_WIFI_P2P = 3; - - /** - * Ncm local tethering type. - * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) - */ - public static final int TETHERING_NCM = 4; - - /** - * Ethernet tethering type. - * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) - */ - public static final int TETHERING_ETHERNET = 5; - - /** - * WIGIG tethering type. Use a separate type to prevent - * conflicts with TETHERING_WIFI - * This type is only used internally by the tethering module - * @hide - */ - public static final int TETHERING_WIGIG = 6; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - TETHER_ERROR_NO_ERROR, - TETHER_ERROR_PROVISIONING_FAILED, - TETHER_ERROR_ENTITLEMENT_UNKNOWN, - }) - public @interface EntitlementResult { - } - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - TETHER_ERROR_NO_ERROR, - TETHER_ERROR_UNKNOWN_IFACE, - TETHER_ERROR_SERVICE_UNAVAIL, - TETHER_ERROR_INTERNAL_ERROR, - TETHER_ERROR_TETHER_IFACE_ERROR, - TETHER_ERROR_ENABLE_FORWARDING_ERROR, - TETHER_ERROR_DISABLE_FORWARDING_ERROR, - TETHER_ERROR_IFACE_CFG_ERROR, - TETHER_ERROR_DHCPSERVER_ERROR, - }) - public @interface TetheringIfaceError { - } - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - TETHER_ERROR_SERVICE_UNAVAIL, - TETHER_ERROR_INTERNAL_ERROR, - TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, - TETHER_ERROR_UNKNOWN_TYPE, - }) - public @interface StartTetheringError { - } - - public static final int TETHER_ERROR_NO_ERROR = 0; - public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; - public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; - public static final int TETHER_ERROR_UNSUPPORTED = 3; - public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; - public static final int TETHER_ERROR_INTERNAL_ERROR = 5; - public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; - public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; - public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; - public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; - public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; - public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; - public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; - public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; - public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; - public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; - public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = false, value = { - TETHER_HARDWARE_OFFLOAD_STOPPED, - TETHER_HARDWARE_OFFLOAD_STARTED, - TETHER_HARDWARE_OFFLOAD_FAILED, - }) - public @interface TetherOffloadStatus { - } - - /** Tethering offload status is stopped. */ - public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; - /** Tethering offload status is started. */ - public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; - /** Fail to start tethering offload. */ - public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; - - /** - * Create a TetheringManager object for interacting with the tethering service. - * - * @param context Context for the manager. - * @param connectorSupplier Supplier for the manager connector; may return null while the - * service is not connected. - * {@hide} - */ - @SystemApi(client = MODULE_LIBRARIES) - public TetheringManager(@NonNull final Context context, - @NonNull Supplier<IBinder> connectorSupplier) { - mContext = context; - mCallback = new TetheringCallbackInternal(); - mConnectorSupplier = connectorSupplier; - - final String pkgName = mContext.getOpPackageName(); - - final IBinder connector = mConnectorSupplier.get(); - // If the connector is available on start, do not start a polling thread. This introduces - // differences in the thread that sends the oneway binder calls to the service between the - // first few seconds after boot and later, but it avoids always having differences between - // the first usage of TetheringManager from a process and subsequent usages (so the - // difference is only on boot). On boot binder calls may be queued until the service comes - // up and be sent from a worker thread; later, they are always sent from the caller thread. - // Considering that it's just oneway binder calls, and ordering is preserved, this seems - // better than inconsistent behavior persisting after boot. - if (connector != null) { - mConnector = ITetheringConnector.Stub.asInterface(connector); - } else { - startPollingForConnector(); - } - - Log.i(TAG, "registerTetheringEventCallback:" + pkgName); - getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName)); - } - - private void startPollingForConnector() { - new Thread(() -> { - while (true) { - try { - Thread.sleep(CONNECTOR_POLL_INTERVAL_MILLIS); - } catch (InterruptedException e) { - // Not much to do here, the system needs to wait for the connector - } - - final IBinder connector = mConnectorSupplier.get(); - if (connector != null) { - onTetheringConnected(ITetheringConnector.Stub.asInterface(connector)); - return; - } - } - }).start(); - } - - private interface ConnectorConsumer { - void onConnectorAvailable(ITetheringConnector connector) throws RemoteException; - } - - private void onTetheringConnected(ITetheringConnector connector) { - // Process the connector wait queue in order, including any items that are added - // while processing. - // - // 1. Copy the queue to a local variable under lock. - // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands - // would block on the lock). - // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1. - // If not, set mConnector to non-null so future tasks are run immediately, not queued. - // - // For this to work, all calls to the tethering service must use getConnector(), which - // ensures that tasks are added to the queue with the lock held. - // - // Once mConnector is set to non-null, it will never be null again. If the network stack - // process crashes, no recovery is possible. - // TODO: evaluate whether it is possible to recover from network stack process crashes - // (though in most cases the system will have crashed when the network stack process - // crashes). - do { - final List<ConnectorConsumer> localWaitQueue; - synchronized (mConnectorWaitQueue) { - localWaitQueue = new ArrayList<>(mConnectorWaitQueue); - mConnectorWaitQueue.clear(); - } - - // Allow more tasks to be added at the end without blocking while draining the queue. - for (ConnectorConsumer task : localWaitQueue) { - try { - task.onConnectorAvailable(connector); - } catch (RemoteException e) { - // Most likely the network stack process crashed, which is likely to crash the - // system. Keep processing other requests but report the error loudly. - Log.wtf(TAG, "Error processing request for the tethering connector", e); - } - } - - synchronized (mConnectorWaitQueue) { - if (mConnectorWaitQueue.size() == 0) { - mConnector = connector; - return; - } - } - } while (true); - } - - /** - * Asynchronously get the ITetheringConnector to execute some operation. - * - * <p>If the connector is already available, the operation will be executed on the caller's - * thread. Otherwise it will be queued and executed on a worker thread. The operation should be - * limited to performing oneway binder calls to minimize differences due to threading. - */ - private void getConnector(ConnectorConsumer consumer) { - final ITetheringConnector connector; - synchronized (mConnectorWaitQueue) { - connector = mConnector; - if (connector == null) { - mConnectorWaitQueue.add(consumer); - return; - } - } - - try { - consumer.onConnectorAvailable(connector); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - private interface RequestHelper { - void runRequest(ITetheringConnector connector, IIntResultListener listener); - } - - // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to - // return results and perform operations synchronously. - // TODO: remove once there are no callers of these legacy methods. - private class RequestDispatcher { - private final ConditionVariable mWaiting; - public volatile int mRemoteResult; - - private final IIntResultListener mListener = new IIntResultListener.Stub() { - @Override - public void onResult(final int resultCode) { - mRemoteResult = resultCode; - mWaiting.open(); - } - }; - - RequestDispatcher() { - mWaiting = new ConditionVariable(); - } - - int waitForResult(final RequestHelper request) { - getConnector(c -> request.runRequest(c, mListener)); - if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) { - throw new IllegalStateException("Callback timeout"); - } - - throwIfPermissionFailure(mRemoteResult); - - return mRemoteResult; - } - } - - private void throwIfPermissionFailure(final int errorCode) { - switch (errorCode) { - case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION: - throw new SecurityException("No android.permission.TETHER_PRIVILEGED" - + " or android.permission.WRITE_SETTINGS permission"); - case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION: - throw new SecurityException( - "No android.permission.ACCESS_NETWORK_STATE permission"); - } - } - - private class TetheringCallbackInternal extends ITetheringEventCallback.Stub { - private volatile int mError = TETHER_ERROR_NO_ERROR; - private final ConditionVariable mWaitForCallback = new ConditionVariable(); - - @Override - public void onCallbackStarted(TetheringCallbackStartedParcel parcel) { - mTetheringConfiguration = parcel.config; - mTetherStatesParcel = parcel.states; - mWaitForCallback.open(); - } - - @Override - public void onCallbackStopped(int errorCode) { - mError = errorCode; - mWaitForCallback.open(); - } - - @Override - public void onUpstreamChanged(Network network) { } - - @Override - public void onConfigurationChanged(TetheringConfigurationParcel config) { - mTetheringConfiguration = config; - } - - @Override - public void onTetherStatesChanged(TetherStatesParcel states) { - mTetherStatesParcel = states; - } - - @Override - public void onTetherClientsChanged(List<TetheredClient> clients) { } - - @Override - public void onOffloadStatusChanged(int status) { } - - public void waitForStarted() { - mWaitForCallback.block(DEFAULT_TIMEOUT_MS); - throwIfPermissionFailure(mError); - } - } - - /** - * Attempt to tether the named interface. This will setup a dhcp server - * on the interface, forward and NAT IP v4 packets and forward DNS requests - * to the best active upstream network interface. Note that if no upstream - * IP network interface is available, dhcp will still run and traffic will be - * allowed between the tethered devices and this device, though upstream net - * access will of course fail until an upstream network interface becomes - * active. - * - * @deprecated The only usages is PanService. It uses this for legacy reasons - * and will migrate away as soon as possible. - * - * @param iface the interface name to tether. - * @return error a {@code TETHER_ERROR} value indicating success or failure type - * - * {@hide} - */ - @Deprecated - @SystemApi(client = MODULE_LIBRARIES) - public int tether(@NonNull final String iface) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "tether caller:" + callerPkg); - final RequestDispatcher dispatcher = new RequestDispatcher(); - - return dispatcher.waitForResult((connector, listener) -> { - try { - connector.tether(iface, callerPkg, getAttributionTag(), listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - }); - } - - /** - * @return the context's attribution tag - */ - private @Nullable String getAttributionTag() { - return null; - } - - /** - * Stop tethering the named interface. - * - * @deprecated The only usages is PanService. It uses this for legacy reasons - * and will migrate away as soon as possible. - * - * {@hide} - */ - @Deprecated - @SystemApi(client = MODULE_LIBRARIES) - public int untether(@NonNull final String iface) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "untether caller:" + callerPkg); - - final RequestDispatcher dispatcher = new RequestDispatcher(); - - return dispatcher.waitForResult((connector, listener) -> { - try { - connector.untether(iface, callerPkg, getAttributionTag(), listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - }); - } - - /** - * Attempt to both alter the mode of USB and Tethering of USB. - * - * @deprecated New client should not use this API anymore. All clients should use - * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is - * used and an entitlement check is needed, downstream USB tethering will be enabled but will - * not have any upstream. - * - * {@hide} - */ - @Deprecated - @SystemApi(client = MODULE_LIBRARIES) - public int setUsbTethering(final boolean enable) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "setUsbTethering caller:" + callerPkg); - - final RequestDispatcher dispatcher = new RequestDispatcher(); - - return dispatcher.waitForResult((connector, listener) -> { - try { - connector.setUsbTethering(enable, callerPkg, getAttributionTag(), - listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - }); - } - - /** - * Use with {@link #startTethering} to specify additional parameters when starting tethering. - */ - public static class TetheringRequest { - /** A configuration set for TetheringRequest. */ - private final TetheringRequestParcel mRequestParcel; - - private TetheringRequest(final TetheringRequestParcel request) { - mRequestParcel = request; - } - - /** Builder used to create TetheringRequest. */ - public static class Builder { - private final TetheringRequestParcel mBuilderParcel; - - /** Default constructor of Builder. */ - public Builder(@TetheringType final int type) { - mBuilderParcel = new TetheringRequestParcel(); - mBuilderParcel.tetheringType = type; - mBuilderParcel.localIPv4Address = null; - mBuilderParcel.staticClientAddress = null; - mBuilderParcel.exemptFromEntitlementCheck = false; - mBuilderParcel.showProvisioningUi = true; - } - - /** - * Configure tethering with static IPv4 assignment. - * - * A DHCP server will be started, but will only be able to offer the client address. - * The two addresses must be in the same prefix. - * - * @param localIPv4Address The preferred local IPv4 link address to use. - * @param clientAddress The static client address. - */ - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - @NonNull - public Builder setStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address, - @NonNull final LinkAddress clientAddress) { - Objects.requireNonNull(localIPv4Address); - Objects.requireNonNull(clientAddress); - if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) { - throw new IllegalArgumentException("Invalid server or client addresses"); - } - - mBuilderParcel.localIPv4Address = localIPv4Address; - mBuilderParcel.staticClientAddress = clientAddress; - return this; - } - - /** Start tethering without entitlement checks. */ - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - @NonNull - public Builder setExemptFromEntitlementCheck(boolean exempt) { - mBuilderParcel.exemptFromEntitlementCheck = exempt; - return this; - } - - /** - * If an entitlement check is needed, sets whether to show the entitlement UI or to - * perform a silent entitlement check. By default, the entitlement UI is shown. - */ - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - @NonNull - public Builder setShouldShowEntitlementUi(boolean showUi) { - mBuilderParcel.showProvisioningUi = showUi; - return this; - } - - /** Build {@link TetheringRequest] with the currently set configuration. */ - @NonNull - public TetheringRequest build() { - return new TetheringRequest(mBuilderParcel); - } - } - - /** - * Get the local IPv4 address, if one was configured with - * {@link Builder#setStaticIpv4Addresses}. - */ - @Nullable - public LinkAddress getLocalIpv4Address() { - return mRequestParcel.localIPv4Address; - } - - /** - * Get the static IPv4 address of the client, if one was configured with - * {@link Builder#setStaticIpv4Addresses}. - */ - @Nullable - public LinkAddress getClientStaticIpv4Address() { - return mRequestParcel.staticClientAddress; - } - - /** Get tethering type. */ - @TetheringType - public int getTetheringType() { - return mRequestParcel.tetheringType; - } - - /** Check if exempt from entitlement check. */ - public boolean isExemptFromEntitlementCheck() { - return mRequestParcel.exemptFromEntitlementCheck; - } - - /** Check if show entitlement ui. */ - public boolean getShouldShowEntitlementUi() { - return mRequestParcel.showProvisioningUi; - } - - /** - * Check whether the two addresses are ipv4 and in the same prefix. - * @hide - */ - public static boolean checkStaticAddressConfiguration( - @NonNull final LinkAddress localIPv4Address, - @NonNull final LinkAddress clientAddress) { - return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength() - && localIPv4Address.isIpv4() && clientAddress.isIpv4() - && new IpPrefix(localIPv4Address.toString()).equals( - new IpPrefix(clientAddress.toString())); - } - - /** - * Get a TetheringRequestParcel from the configuration - * @hide - */ - public TetheringRequestParcel getParcel() { - return mRequestParcel; - } - - /** String of TetheringRequest detail. */ - public String toString() { - return "TetheringRequest [ type= " + mRequestParcel.tetheringType - + ", localIPv4Address= " + mRequestParcel.localIPv4Address - + ", staticClientAddress= " + mRequestParcel.staticClientAddress - + ", exemptFromEntitlementCheck= " - + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= " - + mRequestParcel.showProvisioningUi + " ]"; - } - } - - /** - * Callback for use with {@link #startTethering} to find out whether tethering succeeded. - */ - public interface StartTetheringCallback { - /** - * Called when tethering has been successfully started. - */ - default void onTetheringStarted() {} - - /** - * Called when starting tethering failed. - * - * @param error The error that caused the failure. - */ - default void onTetheringFailed(@StartTetheringError final int error) {} - } - - /** - * Starts tethering and runs tether provisioning for the given type if needed. If provisioning - * fails, stopTethering will be called automatically. - * - * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will - * fail if a tethering entitlement check is required. - * - * @param request a {@link TetheringRequest} which can specify the preferred configuration. - * @param executor {@link Executor} to specify the thread upon which the callback of - * TetheringRequest will be invoked. - * @param callback A callback that will be called to indicate the success status of the - * tethering start request. - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS - }) - public void startTethering(@NonNull final TetheringRequest request, - @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "startTethering caller:" + callerPkg); - - final IIntResultListener listener = new IIntResultListener.Stub() { - @Override - public void onResult(final int resultCode) { - executor.execute(() -> { - if (resultCode == TETHER_ERROR_NO_ERROR) { - callback.onTetheringStarted(); - } else { - callback.onTetheringFailed(resultCode); - } - }); - } - }; - getConnector(c -> c.startTethering(request.getParcel(), callerPkg, - getAttributionTag(), listener)); - } - - /** - * Starts tethering and runs tether provisioning for the given type if needed. If provisioning - * fails, stopTethering will be called automatically. - * - * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will - * fail if a tethering entitlement check is required. - * - * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants. - * @param executor {@link Executor} to specify the thread upon which the callback of - * TetheringRequest will be invoked. - * @hide - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS - }) - @SystemApi(client = MODULE_LIBRARIES) - public void startTethering(int type, @NonNull final Executor executor, - @NonNull final StartTetheringCallback callback) { - startTethering(new TetheringRequest.Builder(type).build(), executor, callback); - } - - /** - * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if - * applicable. - * - * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will - * fail if a tethering entitlement check is required. - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS - }) - public void stopTethering(@TetheringType final int type) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "stopTethering caller:" + callerPkg); - - getConnector(c -> c.stopTethering(type, callerPkg, getAttributionTag(), - new IIntResultListener.Stub() { - @Override - public void onResult(int resultCode) { - // TODO: provide an API to obtain result - // This has never been possible as stopTethering has always been void and never - // taken a callback object. The only indication that callers have is if the call - // results in a TETHER_STATE_CHANGE broadcast. - } - })); - } - - /** - * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether - * entitlement succeeded. - */ - public interface OnTetheringEntitlementResultListener { - /** - * Called to notify entitlement result. - * - * @param resultCode an int value of entitlement result. It may be one of - * {@link #TETHER_ERROR_NO_ERROR}, - * {@link #TETHER_ERROR_PROVISIONING_FAILED}, or - * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}. - */ - void onTetheringEntitlementResult(@EntitlementResult int result); - } - - /** - * Request the latest value of the tethering entitlement check. - * - * <p>This method will only return the latest entitlement result if it is available. If no - * cached entitlement result is available, and {@code showEntitlementUi} is false, - * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is - * true, entitlement will be run. - * - * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will - * fail if a tethering entitlement check is required. - * - * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants. - * @param showEntitlementUi a boolean indicating whether to check result for the UI-based - * entitlement check or the silent entitlement check. - * @param executor the executor on which callback will be invoked. - * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to - * notify the caller of the result of entitlement check. The listener may be called zero - * or one time. - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS - }) - public void requestLatestTetheringEntitlementResult(@TetheringType int type, - boolean showEntitlementUi, - @NonNull Executor executor, - @NonNull final OnTetheringEntitlementResultListener listener) { - if (listener == null) { - throw new IllegalArgumentException( - "OnTetheringEntitlementResultListener cannot be null."); - } - - ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - executor.execute(() -> { - listener.onTetheringEntitlementResult(resultCode); - }); - } - }; - - requestLatestTetheringEntitlementResult(type, wrappedListener, - showEntitlementUi); - } - - /** - * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible - * with ConnectivityManager#getLatestTetheringEntitlementResult - * - * {@hide} - */ - // TODO: improve the usage of ResultReceiver, b/145096122 - @SystemApi(client = MODULE_LIBRARIES) - public void requestLatestTetheringEntitlementResult(@TetheringType final int type, - @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg); - - getConnector(c -> c.requestLatestTetheringEntitlementResult( - type, receiver, showEntitlementUi, callerPkg, getAttributionTag())); - } - - /** - * Callback for use with {@link registerTetheringEventCallback} to find out tethering - * upstream status. - */ - public interface TetheringEventCallback { - /** - * Called when tethering supported status changed. - * - * <p>This will be called immediately after the callback is registered, and may be called - * multiple times later upon changes. - * - * <p>Tethering may be disabled via system properties, device configuration, or device - * policy restrictions. - * - * @param supported The new supported status - */ - default void onTetheringSupported(boolean supported) {} - - /** - * Called when tethering upstream changed. - * - * <p>This will be called immediately after the callback is registered, and may be called - * multiple times later upon changes. - * - * @param network the {@link Network} of tethering upstream. Null means tethering doesn't - * have any upstream. - */ - default void onUpstreamChanged(@Nullable Network network) {} - - /** - * Called when there was a change in tethering interface regular expressions. - * - * <p>This will be called immediately after the callback is registered, and may be called - * multiple times later upon changes. - * @param reg The new regular expressions. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - default void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {} - - /** - * Called when there was a change in the list of tetherable interfaces. Tetherable - * interface means this interface is available and can be used for tethering. - * - * <p>This will be called immediately after the callback is registered, and may be called - * multiple times later upon changes. - * @param interfaces The list of tetherable interface names. - */ - default void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {} - - /** - * Called when there was a change in the list of tethered interfaces. - * - * <p>This will be called immediately after the callback is registered, and may be called - * multiple times later upon changes. - * @param interfaces The list of 0 or more String of currently tethered interface names. - */ - default void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {} - - /** - * Called when an error occurred configuring tethering. - * - * <p>This will be called immediately after the callback is registered if the latest status - * on the interface is an error, and may be called multiple times later upon changes. - * @param ifName Name of the interface. - * @param error One of {@code TetheringManager#TETHER_ERROR_*}. - */ - default void onError(@NonNull String ifName, @TetheringIfaceError int error) {} - - /** - * Called when the list of tethered clients changes. - * - * <p>This callback provides best-effort information on connected clients based on state - * known to the system, however the list cannot be completely accurate (and should not be - * used for security purposes). For example, clients behind a bridge and using static IP - * assignments are not visible to the tethering device; or even when using DHCP, such - * clients may still be reported by this callback after disconnection as the system cannot - * determine if they are still connected. - * @param clients The new set of tethered clients; the collection is not ordered. - */ - default void onClientsChanged(@NonNull Collection<TetheredClient> clients) {} - - /** - * Called when tethering offload status changes. - * - * <p>This will be called immediately after the callback is registered. - * @param status The offload status. - */ - default void onOffloadStatusChanged(@TetherOffloadStatus int status) {} - } - - /** - * Regular expressions used to identify tethering interfaces. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static class TetheringInterfaceRegexps { - private final String[] mTetherableBluetoothRegexs; - private final String[] mTetherableUsbRegexs; - private final String[] mTetherableWifiRegexs; - - /** @hide */ - public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs, - @NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) { - mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone(); - mTetherableUsbRegexs = tetherableUsbRegexs.clone(); - mTetherableWifiRegexs = tetherableWifiRegexs.clone(); - } - - @NonNull - public List<String> getTetherableBluetoothRegexs() { - return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs)); - } - - @NonNull - public List<String> getTetherableUsbRegexs() { - return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs)); - } - - @NonNull - public List<String> getTetherableWifiRegexs() { - return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs)); - } - - @Override - public int hashCode() { - return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs, - mTetherableWifiRegexs); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof TetheringInterfaceRegexps)) return false; - final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj; - return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs) - && Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs) - && Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs); - } - } - - /** - * Start listening to tethering change events. Any new added callback will receive the last - * tethering status right away. If callback is registered, - * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering - * has no upstream or disabled, the argument of callback will be null. The same callback object - * cannot be registered twice. - * - * @param executor the executor on which callback will be invoked. - * @param callback the callback to be called when tethering has change events. - */ - @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE) - public void registerTetheringEventCallback(@NonNull Executor executor, - @NonNull TetheringEventCallback callback) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg); - - synchronized (mTetheringEventCallbacks) { - if (mTetheringEventCallbacks.containsKey(callback)) { - throw new IllegalArgumentException("callback was already registered."); - } - final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() { - // Only accessed with a lock on this object - private final HashMap<String, Integer> mErrorStates = new HashMap<>(); - private String[] mLastTetherableInterfaces = null; - private String[] mLastTetheredInterfaces = null; - - @Override - public void onUpstreamChanged(Network network) throws RemoteException { - executor.execute(() -> { - callback.onUpstreamChanged(network); - }); - } - - private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) { - for (int i = 0; i < newStates.erroredIfaceList.length; i++) { - final String iface = newStates.erroredIfaceList[i]; - final Integer lastError = mErrorStates.get(iface); - final int newError = newStates.lastErrorList[i]; - if (newError != TETHER_ERROR_NO_ERROR - && !Objects.equals(lastError, newError)) { - callback.onError(iface, newError); - } - mErrorStates.put(iface, newError); - } - } - - private synchronized void maybeSendTetherableIfacesChangedCallback( - final TetherStatesParcel newStates) { - if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return; - mLastTetherableInterfaces = newStates.availableList.clone(); - callback.onTetherableInterfacesChanged( - Collections.unmodifiableList(Arrays.asList(mLastTetherableInterfaces))); - } - - private synchronized void maybeSendTetheredIfacesChangedCallback( - final TetherStatesParcel newStates) { - if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return; - mLastTetheredInterfaces = newStates.tetheredList.clone(); - callback.onTetheredInterfacesChanged( - Collections.unmodifiableList(Arrays.asList(mLastTetheredInterfaces))); - } - - // Called immediately after the callbacks are registered. - @Override - public void onCallbackStarted(TetheringCallbackStartedParcel parcel) { - executor.execute(() -> { - callback.onTetheringSupported(parcel.tetheringSupported); - callback.onUpstreamChanged(parcel.upstreamNetwork); - sendErrorCallbacks(parcel.states); - sendRegexpsChanged(parcel.config); - maybeSendTetherableIfacesChangedCallback(parcel.states); - maybeSendTetheredIfacesChangedCallback(parcel.states); - callback.onClientsChanged(parcel.tetheredClients); - callback.onOffloadStatusChanged(parcel.offloadStatus); - }); - } - - @Override - public void onCallbackStopped(int errorCode) { - executor.execute(() -> { - throwIfPermissionFailure(errorCode); - }); - } - - private void sendRegexpsChanged(TetheringConfigurationParcel parcel) { - callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps( - parcel.tetherableBluetoothRegexs, - parcel.tetherableUsbRegexs, - parcel.tetherableWifiRegexs)); - } - - @Override - public void onConfigurationChanged(TetheringConfigurationParcel config) { - executor.execute(() -> sendRegexpsChanged(config)); - } - - @Override - public void onTetherStatesChanged(TetherStatesParcel states) { - executor.execute(() -> { - sendErrorCallbacks(states); - maybeSendTetherableIfacesChangedCallback(states); - maybeSendTetheredIfacesChangedCallback(states); - }); - } - - @Override - public void onTetherClientsChanged(final List<TetheredClient> clients) { - executor.execute(() -> callback.onClientsChanged(clients)); - } - - @Override - public void onOffloadStatusChanged(final int status) { - executor.execute(() -> callback.onOffloadStatusChanged(status)); - } - }; - getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg)); - mTetheringEventCallbacks.put(callback, remoteCallback); - } - } - - /** - * Remove tethering event callback previously registered with - * {@link #registerTetheringEventCallback}. - * - * @param callback previously registered callback. - */ - @RequiresPermission(anyOf = { - Manifest.permission.TETHER_PRIVILEGED, - Manifest.permission.ACCESS_NETWORK_STATE - }) - public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg); - - synchronized (mTetheringEventCallbacks) { - ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback); - if (remoteCallback == null) { - throw new IllegalArgumentException("callback was not registered."); - } - - getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg)); - } - } - - /** - * Get a more detailed error code after a Tethering or Untethering - * request asynchronously failed. - * - * @param iface The name of the interface of interest - * @return error The error code of the last error tethering or untethering the named - * interface - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public int getLastTetherError(@NonNull final String iface) { - mCallback.waitForStarted(); - if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR; - - int i = 0; - for (String errored : mTetherStatesParcel.erroredIfaceList) { - if (iface.equals(errored)) return mTetherStatesParcel.lastErrorList[i]; - - i++; - } - return TETHER_ERROR_NO_ERROR; - } - - /** - * Get the list of regular expressions that define any tetherable - * USB network interfaces. If USB tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable usb interfaces. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetherableUsbRegexs() { - mCallback.waitForStarted(); - return mTetheringConfiguration.tetherableUsbRegexs; - } - - /** - * Get the list of regular expressions that define any tetherable - * Wifi network interfaces. If Wifi tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable wifi interfaces. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetherableWifiRegexs() { - mCallback.waitForStarted(); - return mTetheringConfiguration.tetherableWifiRegexs; - } - - /** - * Get the list of regular expressions that define any tetherable - * Bluetooth network interfaces. If Bluetooth tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable bluetooth interfaces. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetherableBluetoothRegexs() { - mCallback.waitForStarted(); - return mTetheringConfiguration.tetherableBluetoothRegexs; - } - - /** - * Get the set of tetherable, available interfaces. This list is limited by - * device configuration and current interface existence. - * - * @return an array of 0 or more Strings of tetherable interface names. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetherableIfaces() { - mCallback.waitForStarted(); - if (mTetherStatesParcel == null) return new String[0]; - - return mTetherStatesParcel.availableList; - } - - /** - * Get the set of tethered interfaces. - * - * @return an array of 0 or more String of currently tethered interface names. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetheredIfaces() { - mCallback.waitForStarted(); - if (mTetherStatesParcel == null) return new String[0]; - - return mTetherStatesParcel.tetheredList; - } - - /** - * Get the set of interface names which attempted to tether but - * failed. Re-attempting to tether may cause them to reset to the Tethered - * state. Alternatively, causing the interface to be destroyed and recreated - * may cause them to reset to the available state. - * {@link TetheringManager#getLastTetherError} can be used to get more - * information on the cause of the errors. - * - * @return an array of 0 or more String indicating the interface names - * which failed to tether. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public @NonNull String[] getTetheringErroredIfaces() { - mCallback.waitForStarted(); - if (mTetherStatesParcel == null) return new String[0]; - - return mTetherStatesParcel.erroredIfaceList; - } - - /** - * Get the set of tethered dhcp ranges. - * - * @deprecated This API just return the default value which is not used in DhcpServer. - * @hide - */ - @Deprecated - public @NonNull String[] getTetheredDhcpRanges() { - mCallback.waitForStarted(); - return mTetheringConfiguration.legacyDhcpRanges; - } - - /** - * Check if the device allows for tethering. It may be disabled via - * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or - * due to device configuration. - * - * @return a boolean - {@code true} indicating Tethering is supported. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public boolean isTetheringSupported() { - final String callerPkg = mContext.getOpPackageName(); - - return isTetheringSupported(callerPkg); - } - - /** - * Check if the device allows for tethering. It may be disabled via {@code ro.tether.denied} - * system property, Settings.TETHER_SUPPORTED or due to device configuration. This is useful - * for system components that query this API on behalf of an app. In particular, Bluetooth - * has @UnsupportedAppUsage calls that will let apps turn on bluetooth tethering if they have - * the right permissions, but such an app needs to know whether it can (permissions as well - * as support from the device) turn on tethering in the first place to show the appropriate UI. - * - * @param callerPkg The caller package name, if it is not matching the calling uid, - * SecurityException would be thrown. - * @return a boolean - {@code true} indicating Tethering is supported. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public boolean isTetheringSupported(@NonNull final String callerPkg) { - - final RequestDispatcher dispatcher = new RequestDispatcher(); - final int ret = dispatcher.waitForResult((connector, listener) -> { - try { - connector.isTetheringSupported(callerPkg, getAttributionTag(), listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - }); - - return ret == TETHER_ERROR_NO_ERROR; - } - - /** - * Stop all active tethering. - * - * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will - * fail if a tethering entitlement check is required. - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS - }) - public void stopAllTethering() { - final String callerPkg = mContext.getOpPackageName(); - Log.i(TAG, "stopAllTethering caller:" + callerPkg); - - getConnector(c -> c.stopAllTethering(callerPkg, getAttributionTag(), - new IIntResultListener.Stub() { - @Override - public void onResult(int resultCode) { - // TODO: add an API parameter to send result to caller. - // This has never been possible as stopAllTethering has always been void - // and never taken a callback object. The only indication that callers have - // is if the call results in a TETHER_STATE_CHANGE broadcast. - } - })); - } -} diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt deleted file mode 100644 index 591861f5b837..000000000000 --- a/packages/Tethering/jarjar-rules.txt +++ /dev/null @@ -1,11 +0,0 @@ -# These must be kept in sync with the framework-tethering-shared-srcs filegroup. -# Classes from the framework-tethering-shared-srcs filegroup. -# If there are files in that filegroup that are not covered below, the classes in the -# module will be overwritten by the ones in the framework. -rule com.android.internal.util.** com.android.networkstack.tethering.util.@1 -rule android.util.LocalLog* com.android.networkstack.tethering.util.LocalLog@1 - -rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1 - -# Classes from net-utils-framework-common -rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1
\ No newline at end of file diff --git a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp deleted file mode 100644 index 94c871d8a366..000000000000 --- a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <error.h> -#include <jni.h> -#include <linux/filter.h> -#include <nativehelper/JNIHelp.h> -#include <nativehelper/JNIHelpCompat.h> -#include <nativehelper/ScopedUtfChars.h> -#include <net/if.h> -#include <netinet/ether.h> -#include <netinet/ip6.h> -#include <netinet/icmp6.h> -#include <sys/socket.h> -#include <stdio.h> - -#define LOG_TAG "TetheringUtils" -#include <android/log.h> - -namespace android { - -static const uint32_t kIPv6NextHeaderOffset = offsetof(ip6_hdr, ip6_nxt); -static const uint32_t kIPv6PayloadStart = sizeof(ip6_hdr); -static const uint32_t kICMPv6TypeOffset = kIPv6PayloadStart + offsetof(icmp6_hdr, icmp6_type); - -static void android_net_util_setupIcmpFilter(JNIEnv *env, jobject javaFd, uint32_t type) { - sock_filter filter_code[] = { - // Check header is ICMPv6. - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIPv6NextHeaderOffset), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3), - - // Check ICMPv6 type. - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kICMPv6TypeOffset), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, type, 0, 1), - - // Accept or reject. - BPF_STMT(BPF_RET | BPF_K, 0xffff), - BPF_STMT(BPF_RET | BPF_K, 0) - }; - - const sock_fprog filter = { - sizeof(filter_code) / sizeof(filter_code[0]), - filter_code, - }; - - int fd = jniGetFDFromFileDescriptor(env, javaFd); - if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno)); - } -} - -static void android_net_util_setupNaSocket(JNIEnv *env, jobject clazz, jobject javaFd) -{ - android_net_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_ADVERT); -} - -static void android_net_util_setupNsSocket(JNIEnv *env, jobject clazz, jobject javaFd) -{ - android_net_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_SOLICIT); -} - -static void android_net_util_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd, - jint ifIndex) -{ - static const int kLinkLocalHopLimit = 255; - - int fd = jniGetFDFromFileDescriptor(env, javaFd); - - // Set an ICMPv6 filter that only passes Router Solicitations. - struct icmp6_filter rs_only; - ICMP6_FILTER_SETBLOCKALL(&rs_only); - ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only); - socklen_t len = sizeof(rs_only); - if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(ICMP6_FILTER): %s", strerror(errno)); - return; - } - - // Most/all of the rest of these options can be set via Java code, but - // because we're here on account of setting an icmp6_filter go ahead - // and do it all natively for now. - - // Set the multicast hoplimit to 255 (link-local only). - int hops = kLinkLocalHopLimit; - len = sizeof(hops); - if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno)); - return; - } - - // Set the unicast hoplimit to 255 (link-local only). - hops = kLinkLocalHopLimit; - len = sizeof(hops); - if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno)); - return; - } - - // Explicitly disable multicast loopback. - int off = 0; - len = sizeof(off); - if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno)); - return; - } - - // Specify the IPv6 interface to use for outbound multicast. - len = sizeof(ifIndex); - if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno)); - return; - } - - // Additional options to be considered: - // - IPV6_TCLASS - // - IPV6_RECVPKTINFO - // - IPV6_RECVHOPLIMIT - - // Bind to [::]. - const struct sockaddr_in6 sin6 = { - .sin6_family = AF_INET6, - .sin6_port = 0, - .sin6_flowinfo = 0, - .sin6_addr = IN6ADDR_ANY_INIT, - .sin6_scope_id = 0, - }; - auto sa = reinterpret_cast<const struct sockaddr *>(&sin6); - len = sizeof(sin6); - if (bind(fd, sa, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "bind(IN6ADDR_ANY): %s", strerror(errno)); - return; - } - - // Join the all-routers multicast group, ff02::2%index. - struct ipv6_mreq all_rtrs = { - .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}}, - .ipv6mr_interface = ifIndex, - }; - len = sizeof(all_rtrs); - if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno)); - return; - } -} - -/* - * JNI registration. - */ -static const JNINativeMethod gMethods[] = { - /* name, signature, funcPtr */ - { "setupNaSocket", "(Ljava/io/FileDescriptor;)V", - (void*) android_net_util_setupNaSocket }, - { "setupNsSocket", "(Ljava/io/FileDescriptor;)V", - (void*) android_net_util_setupNsSocket }, - { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", - (void*) android_net_util_setupRaSocket }, -}; - -int register_android_net_util_TetheringUtils(JNIEnv* env) { - return jniRegisterNativeMethods(env, - "android/net/util/TetheringUtils", - gMethods, NELEM(gMethods)); -} - -extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { - __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed"); - return JNI_ERR; - } - - if (register_android_net_util_TetheringUtils(env) < 0) { - return JNI_ERR; - } - - return JNI_VERSION_1_6; -} - -}; // namespace android diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags deleted file mode 100644 index 86b903353cf5..000000000000 --- a/packages/Tethering/proguard.flags +++ /dev/null @@ -1,9 +0,0 @@ -# Keep class's integer static field for MessageUtils to parsing their name. --keep class com.android.networkstack.tethering.Tethering$TetherMainSM { - static final int CMD_*; - static final int EVENT_*; -} - --keepclassmembers class android.net.ip.IpServer { - static final int CMD_*; -} diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png Binary files differdeleted file mode 100644 index 9451174d65d7..000000000000 --- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png Binary files differdeleted file mode 100644 index 79d5756ae38e..000000000000 --- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png Binary files differdeleted file mode 100644 index cae1bd1b2574..000000000000 --- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png Binary files differdeleted file mode 100644 index ffe8e8c98232..000000000000 --- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png Binary files differdeleted file mode 100644 index ca20f7352090..000000000000 --- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png Binary files differdeleted file mode 100644 index 65e907565ec1..000000000000 --- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png Binary files differdeleted file mode 100644 index f42dae0fdcb9..000000000000 --- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png Binary files differdeleted file mode 100644 index 065516185ad4..000000000000 --- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png Binary files differdeleted file mode 100644 index 2e2b8ca2e9cb..000000000000 --- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png Binary files differdeleted file mode 100644 index 3f57d1c76ccb..000000000000 --- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png Binary files differdeleted file mode 100644 index 34b0cb36736a..000000000000 --- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png Binary files differdeleted file mode 100644 index 36afe485b5bb..000000000000 --- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png Binary files differdeleted file mode 100644 index 25acfbb01ba4..000000000000 --- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png Binary files differdeleted file mode 100644 index 5c656012e615..000000000000 --- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png +++ /dev/null diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png Binary files differdeleted file mode 100644 index 28b4b5438e55..000000000000 --- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png +++ /dev/null diff --git a/packages/Tethering/res/values-af/strings.xml b/packages/Tethering/res/values-af/strings.xml deleted file mode 100644 index 056168b12e89..000000000000 --- a/packages/Tethering/res/values-af/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Verbinding of warmkol is aktief"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tik om op te stel."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Verbinding is gedeaktiveer"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontak jou administrateur vir besonderhede"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Warmkol- en verbindingstatus"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-am/strings.xml b/packages/Tethering/res/values-am/strings.xml deleted file mode 100644 index ac468dd14414..000000000000 --- a/packages/Tethering/res/values-am/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"እንደ ሞደም መሰካት ወይም መገናኛ ነጥብ ገባሪ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ለማዋቀር መታ ያድርጉ።"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"እንደ ሞደም መሰካት ተሰናክሏል"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ለዝርዝሮች የእርስዎን አስተዳዳሪ ያነጋግሩ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"መገናኛ ነጥብ እና እንደ ሞደም የመሰካት ሁኔታ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ar/strings.xml b/packages/Tethering/res/values-ar/strings.xml deleted file mode 100644 index 7d5bad34da04..000000000000 --- a/packages/Tethering/res/values-ar/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"النطاق نشط أو نقطة الاتصال نشطة"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"انقر للإعداد."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"التوصيل متوقف."</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"تواصَل مع المشرف للحصول على التفاصيل."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"حالة نقطة الاتصال والتوصيل"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-as/strings.xml b/packages/Tethering/res/values-as/strings.xml deleted file mode 100644 index 091350455ba0..000000000000 --- a/packages/Tethering/res/values-as/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"টে\'ডাৰিং অথবা হ\'টস্প\'ট সক্ৰিয় অৱস্থাত আছে"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ছেট আপ কৰিবলৈ টিপক।"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"টে\'ডাৰিঙৰ সুবিধাটো অক্ষম কৰি থোৱা হৈছে"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"সবিশেষ জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"হ’টস্প\'ট আৰু টে\'ডাৰিঙৰ স্থিতি"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-az/strings.xml b/packages/Tethering/res/values-az/strings.xml deleted file mode 100644 index dce70da178f1..000000000000 --- a/packages/Tethering/res/values-az/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Birləşmə və ya hotspot aktivdir"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ayarlamaq üçün toxunun."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Birləşmə deaktivdir"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Detallar üçün adminlə əlaqə saxlayın"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot & birləşmə statusu"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-b+sr+Latn/strings.xml b/packages/Tethering/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index b0774ec9a840..000000000000 --- a/packages/Tethering/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Privezivanje ili hotspot je aktivan"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da biste podesili."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Privezivanje je onemogućeno"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Potražite detalje od administratora"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status hotspota i privezivanja"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-be/strings.xml b/packages/Tethering/res/values-be/strings.xml deleted file mode 100644 index a8acebe2e992..000000000000 --- a/packages/Tethering/res/values-be/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Мадэм або хот-спот актыўныя"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Дакраніцеся, каб наладзіць."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Рэжым мадэма выключаны"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Звярніцеся да адміністратара па падрабязную інфармацыю"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Стан \"Хот-спот і мадэм\""</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-bg/strings.xml b/packages/Tethering/res/values-bg/strings.xml deleted file mode 100644 index 94fb2d8f176a..000000000000 --- a/packages/Tethering/res/values-bg/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Има активна споделена връзка или точка за достъп"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Докоснете, за да настроите."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Функцията за тетъринг е деактивирана"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Свържете се с администратора си за подробности"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Състояние на функцията за точка за достъп и тетъринг"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-bn/strings.xml b/packages/Tethering/res/values-bn/strings.xml deleted file mode 100644 index aea02b9ddff8..000000000000 --- a/packages/Tethering/res/values-bn/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"টিথারিং বা হটস্পট চালু আছে"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"সেট-আপ করতে ট্যাপ করুন।"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"টিথারিং বন্ধ করা আছে"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"বিশদে জানতে অ্যাডমিনের সাথে যোগাযোগ করুন"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"হটস্পট ও টিথারিং স্ট্যাটাস"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-bs/strings.xml b/packages/Tethering/res/values-bs/strings.xml deleted file mode 100644 index de232724c5d9..000000000000 --- a/packages/Tethering/res/values-bs/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Aktivno je povezivanje putem mobitela ili pristupna tačka"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da postavite."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Povezivanje putem mobitela je onemogućeno"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontaktirajte svog administratora za detalje"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status pristupne tačke i povezivanja putem mobitela"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ca/strings.xml b/packages/Tethering/res/values-ca/strings.xml deleted file mode 100644 index 88b795c1f8b2..000000000000 --- a/packages/Tethering/res/values-ca/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Compartició de xarxa o punt d\'accés Wi‑Fi actius"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toca per configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"La compartició de xarxa està desactivada"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacta amb el teu administrador per obtenir més informació"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estat del punt d\'accés Wi‑Fi i de la compartició de xarxa"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-cs/strings.xml b/packages/Tethering/res/values-cs/strings.xml deleted file mode 100644 index 8c1b83bf3ee3..000000000000 --- a/packages/Tethering/res/values-cs/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering nebo hotspot je aktivní"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Klepnutím zahájíte nastavení."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering je zakázán"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"O podrobnosti požádejte administrátora"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stav hotspotu a tetheringu"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-da/strings.xml b/packages/Tethering/res/values-da/strings.xml deleted file mode 100644 index f413e7054819..000000000000 --- a/packages/Tethering/res/values-da/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Netdeling eller hotspot er aktivt"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tryk for at konfigurere."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Netdeling er deaktiveret"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakt din administrator for at få oplysninger"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status for hotspot og netdeling"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-de/strings.xml b/packages/Tethering/res/values-de/strings.xml deleted file mode 100644 index f057d7824e81..000000000000 --- a/packages/Tethering/res/values-de/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering oder Hotspot aktiv"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Zum Einrichten tippen."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering ist deaktiviert"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Bitte wende dich für weitere Informationen an den Administrator"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot- und Tethering-Status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-el/strings.xml b/packages/Tethering/res/values-el/strings.xml deleted file mode 100644 index b3c986bdafd6..000000000000 --- a/packages/Tethering/res/values-el/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Πρόσδεση ή σύνδεση σημείου πρόσβασης ενεργή"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Πατήστε για ρύθμιση."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Η σύνδεση είναι απενεργοποιημένη"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Επικοινωνήστε με τον διαχειριστή σας για λεπτομέρειες"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Κατάσταση σημείου πρόσβασης Wi-Fi και σύνδεσης"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-en-rAU/strings.xml b/packages/Tethering/res/values-en-rAU/strings.xml deleted file mode 100644 index 769e01208afc..000000000000 --- a/packages/Tethering/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-en-rCA/strings.xml b/packages/Tethering/res/values-en-rCA/strings.xml deleted file mode 100644 index 769e01208afc..000000000000 --- a/packages/Tethering/res/values-en-rCA/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-en-rGB/strings.xml b/packages/Tethering/res/values-en-rGB/strings.xml deleted file mode 100644 index 769e01208afc..000000000000 --- a/packages/Tethering/res/values-en-rGB/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-en-rIN/strings.xml b/packages/Tethering/res/values-en-rIN/strings.xml deleted file mode 100644 index 769e01208afc..000000000000 --- a/packages/Tethering/res/values-en-rIN/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-en-rXC/strings.xml b/packages/Tethering/res/values-en-rXC/strings.xml deleted file mode 100644 index f1674bed4eb7..000000000000 --- a/packages/Tethering/res/values-en-rXC/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot & tethering status"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-es-rUS/strings.xml b/packages/Tethering/res/values-es-rUS/strings.xml deleted file mode 100644 index 63689f43997c..000000000000 --- a/packages/Tethering/res/values-es-rUS/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión a red o hotspot conectados"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Presiona para configurar esta opción."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Se inhabilitó la conexión mediante dispositivo portátil"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Para obtener más información, comunícate con el administrador"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado del hotspot y la conexión mediante dispositivo portátil"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-es/strings.xml b/packages/Tethering/res/values-es/strings.xml deleted file mode 100644 index 9a34ed5e388a..000000000000 --- a/packages/Tethering/res/values-es/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión compartida o punto de acceso activos"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toca para configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"La conexión compartida está inhabilitada"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Solicita más información a tu administrador"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado del punto de acceso y de la conexión compartida"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-et/strings.xml b/packages/Tethering/res/values-et/strings.xml deleted file mode 100644 index 0970341ab0cd..000000000000 --- a/packages/Tethering/res/values-et/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Jagamine või kuumkoht on aktiivne"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Puudutage seadistamiseks."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Jagamine on keelatud"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Lisateabe saamiseks võtke ühendust oma administraatoriga"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Kuumkoha ja jagamise olek"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-eu/strings.xml b/packages/Tethering/res/values-eu/strings.xml deleted file mode 100644 index 632019e2ef1b..000000000000 --- a/packages/Tethering/res/values-eu/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Konexioa partekatzea edo wifi-gunea aktibo dago"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Sakatu konfiguratzeko."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Desgaituta dago konexioa partekatzeko aukera"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Xehetasunak lortzeko, jarri administratzailearekin harremanetan"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Wifi-gunearen eta konexioa partekatzeko eginbidearen egoera"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-fa/strings.xml b/packages/Tethering/res/values-fa/strings.xml deleted file mode 100644 index 2e21c85fa179..000000000000 --- a/packages/Tethering/res/values-fa/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"اشتراکگذاری اینترنت یا نقطه اتصال فعال"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"برای راهاندازی ضربه بزنید."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"اشتراکگذاری اینترنت غیرفعال است"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"برای جزئیات، با سرپرستتان تماس بگیرید"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"وضعیت نقطه اتصال و اشتراکگذاری اینترنت"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-fi/strings.xml b/packages/Tethering/res/values-fi/strings.xml deleted file mode 100644 index 413db3f0f8c9..000000000000 --- a/packages/Tethering/res/values-fi/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Yhteyden jakaminen tai hotspot käytössä"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ota käyttöön napauttamalla."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Yhteyden jakaminen on poistettu käytöstä"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Pyydä lisätietoja järjestelmänvalvojalta"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspotin ja yhteyden jakamisen tila"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-fr-rCA/strings.xml b/packages/Tethering/res/values-fr-rCA/strings.xml deleted file mode 100644 index eb2e4ba54000..000000000000 --- a/packages/Tethering/res/values-fr-rCA/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Partage de connexion ou point d\'accès sans fil activé"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Touchez pour configurer."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Le partage de connexion est désactivé"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Communiquez avec votre administrateur pour obtenir plus de détails"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Point d\'accès et partage de connexion"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-fr/strings.xml b/packages/Tethering/res/values-fr/strings.xml deleted file mode 100644 index 22259c52ab9e..000000000000 --- a/packages/Tethering/res/values-fr/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Partage de connexion ou point d\'accès activé"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Appuyez pour effectuer la configuration."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Le partage de connexion est désactivé"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Pour en savoir plus, contactez votre administrateur"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"État du point d\'accès et du partage de connexion"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-gl/strings.xml b/packages/Tethering/res/values-gl/strings.xml deleted file mode 100644 index ded82fcd54ad..000000000000 --- a/packages/Tethering/res/values-gl/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión compartida ou zona wifi activada"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toca para configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"A conexión compartida está desactivada"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacta co administrador para obter información"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado da zona wifi e da conexión compartida"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-gu/strings.xml b/packages/Tethering/res/values-gu/strings.xml deleted file mode 100644 index 7cbbc2de3d91..000000000000 --- a/packages/Tethering/res/values-gu/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ઇન્ટરનેટ શેર કરવાની સુવિધા અથવા હૉટસ્પૉટ સક્રિય છે"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"સેટઅપ કરવા માટે ટૅપ કરો."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરી છે"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"વિગતો માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"હૉટસ્પૉટ અને ઇન્ટરનેટ શેર કરવાની સુવિધાનું સ્ટેટસ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-hi/strings.xml b/packages/Tethering/res/values-hi/strings.xml deleted file mode 100644 index 08af81b826b3..000000000000 --- a/packages/Tethering/res/values-hi/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिंग या हॉटस्पॉट चालू है"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"सेट अप करने के लिए टैप करें."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिंग बंद है"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"जानकारी के लिए अपने एडमिन से संपर्क करें"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हॉटस्पॉट और टेदरिंग की स्थिति"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-hr/strings.xml b/packages/Tethering/res/values-hr/strings.xml deleted file mode 100644 index 827c135f205d..000000000000 --- a/packages/Tethering/res/values-hr/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Modemsko povezivanje ili žarišna točka aktivni"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da biste postavili."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Modemsko je povezivanje onemogućeno"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Obratite se administratoru da biste saznali pojedinosti"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status žarišne točke i modemskog povezivanja"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-hu/strings.xml b/packages/Tethering/res/values-hu/strings.xml deleted file mode 100644 index eb68d6babf8f..000000000000 --- a/packages/Tethering/res/values-hu/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Megosztás vagy aktív hotspot"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Koppintson a beállításhoz."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Az internetmegosztás le van tiltva"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"A részletekért forduljon rendszergazdájához"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot és internetmegosztás állapota"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-hy/strings.xml b/packages/Tethering/res/values-hy/strings.xml deleted file mode 100644 index 912941e53835..000000000000 --- a/packages/Tethering/res/values-hy/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Մոդեմի ռեժիմը միացված է"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Հպեք՝ կարգավորելու համար։"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Մոդեմի ռեժիմն անջատված է"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Մանրամասների համար դիմեք ձեր ադմինիստրատորին"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Թեժ կետի և մոդեմի ռեժիմի կարգավիճակը"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-in/strings.xml b/packages/Tethering/res/values-in/strings.xml deleted file mode 100644 index a4e175a439e9..000000000000 --- a/packages/Tethering/res/values-in/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering atau hotspot aktif"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ketuk untuk menyiapkan."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering dinonaktifkan"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hubungi admin untuk mengetahui detailnya"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status hotspot & tethering"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-is/strings.xml b/packages/Tethering/res/values-is/strings.xml deleted file mode 100644 index e9f6670bcd09..000000000000 --- a/packages/Tethering/res/values-is/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Kveikt á tjóðrun eða aðgangsstað"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ýttu til að setja upp."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Slökkt er á tjóðrun"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hafðu samband við kerfisstjórann til að fá upplýsingar"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Staða heits reits og tjóðrunar"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-it/strings.xml b/packages/Tethering/res/values-it/strings.xml deleted file mode 100644 index ffb9196f5ee3..000000000000 --- a/packages/Tethering/res/values-it/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Hotspot o tethering attivo"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tocca per impostare."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering disattivato"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contatta il tuo amministratore per avere informazioni dettagliate"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stato hotspot e tethering"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-iw/strings.xml b/packages/Tethering/res/values-iw/strings.xml deleted file mode 100644 index 7adcb47350c1..000000000000 --- a/packages/Tethering/res/values-iw/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"נקודה לשיתוף אינטרנט או שיתוף אינטרנט בין מכשירים: בסטטוס פעיל"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"יש להקיש כדי להגדיר."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"שיתוף האינטרנט בין מכשירים מושבת"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"לפרטים, יש לפנות למנהל המערכת"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"סטטוס של נקודה לשיתוף אינטרנט ושיתוף אינטרנט בין מכשירים"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ja/strings.xml b/packages/Tethering/res/values-ja/strings.xml deleted file mode 100644 index f68a73010b36..000000000000 --- a/packages/Tethering/res/values-ja/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"テザリングまたはアクセス ポイントが有効です"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"タップしてセットアップします。"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"テザリングは無効に設定されています"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"詳しくは、管理者にお問い合わせください"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"アクセス ポイントとテザリングのステータス"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ka/strings.xml b/packages/Tethering/res/values-ka/strings.xml deleted file mode 100644 index 7c22e82bd370..000000000000 --- a/packages/Tethering/res/values-ka/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ტეტერინგი ან უსადენო ქსელი აქტიურია"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"შეეხეთ დასაყენებლად."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ტეტერინგი გათიშულია"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"დამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"უსადენო ქსელის და ტეტერინგის სტატუსი"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-kk/strings.xml b/packages/Tethering/res/values-kk/strings.xml deleted file mode 100644 index 0857d06de243..000000000000 --- a/packages/Tethering/res/values-kk/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Тетеринг немесе хотспот қосулы"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Реттеу үшін түртіңіз."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Тетеринг өшірілді."</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Мәліметтерді әкімшіден алыңыз."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Хотспот және тетеринг күйі"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-km/strings.xml b/packages/Tethering/res/values-km/strings.xml deleted file mode 100644 index 536e3d1703b1..000000000000 --- a/packages/Tethering/res/values-km/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ការភ្ជាប់ ឬហតស្ប៉តកំពុងដំណើរការ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ចុចដើម្បីរៀបចំ។"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ការភ្ជាប់ត្រូវបានបិទ"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក ដើម្បីទទួលបានព័ត៌មានលម្អិត"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ស្ថានភាពនៃការភ្ជាប់ និងហតស្ប៉ត"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-kn/strings.xml b/packages/Tethering/res/values-kn/strings.xml deleted file mode 100644 index 32f54926f4bf..000000000000 --- a/packages/Tethering/res/values-kn/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ಟೆಥರಿಂಗ್ ಅಥವಾ ಹಾಟ್ಸ್ಪಾಟ್ ಸಕ್ರಿಯವಾಗಿದೆ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ಸೆಟಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ಟೆಥರಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ವಿವರಗಳಿಗಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ಹಾಟ್ಸ್ಪಾಟ್ ಮತ್ತು ಟೆಥರಿಂಗ್ ಸ್ಥಿತಿ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ko/strings.xml b/packages/Tethering/res/values-ko/strings.xml deleted file mode 100644 index 156b24786db5..000000000000 --- a/packages/Tethering/res/values-ko/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"테더링 또는 핫스팟 사용"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"설정하려면 탭하세요."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"테더링이 사용 중지됨"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"자세한 정보는 관리자에게 문의하세요."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"핫스팟 및 테더링 상태"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ky/strings.xml b/packages/Tethering/res/values-ky/strings.xml deleted file mode 100644 index 18ee5fd35718..000000000000 --- a/packages/Tethering/res/values-ky/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Модем режими күйүп турат"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Жөндөө үчүн таптап коюңуз."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Телефонду модем катары колдонууга болбойт"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Кеңири маалымат үчүн администраторуңузга кайрылыңыз"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Байланыш түйүнүнүн жана модем режиминин статусу"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-lo/strings.xml b/packages/Tethering/res/values-lo/strings.xml deleted file mode 100644 index b12767018c3a..000000000000 --- a/packages/Tethering/res/values-lo/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ເປີດການປ່ອຍສັນຍານ ຫຼື ຮັອດສະປອດແລ້ວ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ແຕະເພື່ອຕັ້ງຄ່າ."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ການປ່ອຍສັນຍານຖືກປິດໄວ້"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບສຳລັບລາຍລະອຽດ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ສະຖານະຮັອດສະປອດ ແລະ ການປ່ອຍສັນຍານ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-lt/strings.xml b/packages/Tethering/res/values-lt/strings.xml deleted file mode 100644 index 8427baf39f31..000000000000 --- a/packages/Tethering/res/values-lt/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Įrenginys naudojamas kaip modemas arba įjungtas viešosios interneto prieigos taškas"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Palieskite, kad nustatytumėte."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Įrenginio kaip modemo naudojimas išjungtas"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Jei reikia išsamios informacijos, susisiekite su administratoriumi"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Viešosios interneto prieigos taško ir įrenginio kaip modemo naudojimo būsena"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-lv/strings.xml b/packages/Tethering/res/values-lv/strings.xml deleted file mode 100644 index aa2d6990e04f..000000000000 --- a/packages/Tethering/res/values-lv/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Piesaiste vai tīklājs ir aktīvs."</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Pieskarieties, lai to iestatītu."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Piesaiste ir atspējota"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Lai iegūtu detalizētu informāciju, sazinieties ar savu administratoru."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Tīklāja un piesaistes statuss"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml deleted file mode 100644 index 19d659c6ce36..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Verbinding het nie internet nie"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Toestelle kan nie koppel nie"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Skakel verbinding af"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Warmkol of verbinding is aan"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Bykomende heffings kan geld terwyl jy swerf"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml deleted file mode 100644 index 8995430b4f09..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ማስተሳሰር ምንም በይነመረብ የለውም"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"መሣሪያዎችን ማገናኘት አይቻልም"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ማስተሳሰርን አጥፋ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"መገናኛ ነጥብ ወይም ማስተሳሰር በርቷል"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"በሚያንዣብብበት ጊዜ ተጨማሪ ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml deleted file mode 100644 index 54f3b5389ae9..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ما مِن اتصال بالإنترنت خلال التوصيل"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"تعذّر اتصال الأجهزة"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"إيقاف التوصيل"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"نقطة الاتصال أو التوصيل مفعّلان"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"قد يتم تطبيق رسوم إضافية أثناء التجوال."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml deleted file mode 100644 index e215141c9eb6..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"টে\'ডাৰিঙৰ ইণ্টাৰনেট নাই"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ডিভাইচসমূহ সংযোগ কৰিব নোৱাৰি"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"টে\'ডাৰিং অফ কৰক"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"হটস্পট অথবা টে\'ডাৰিং অন আছে"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ৰ\'মিঙত থাকিলে অতিৰিক্ত মাচুল প্ৰযোজ্য হ’ব পাৰে"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml deleted file mode 100644 index 1fd8e4c963a7..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modemin internetə girişi yoxdur"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Cihazları qoşmaq mümkün deyil"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Modemi deaktiv edin"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot və ya modem aktivdir"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rouminq zamanı əlavə ödənişlər tətbiq edilə bilər"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml deleted file mode 100644 index 1abe4f3aa3c7..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Privezivanje nema pristup internetu"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Povezivanje uređaja nije uspelo"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključi privezivanje"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Uključen je hotspot ili privezivanje"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Možda važe dodatni troškovi u romingu"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml deleted file mode 100644 index 38dbd1e3914f..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Рэжым мадэма выкарыстоўваецца без доступу да інтэрнэту"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Не ўдалося падключыць прылады"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Выключыць рэжым мадэма"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Хот-спот або рэжым мадэма ўключаны"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Пры выкарыстанні роўмінгу можа спаганяцца дадатковая плата"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml deleted file mode 100644 index 04b44db5c1a4..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Тетърингът няма връзка с интернет"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Устройствата не могат да установят връзка"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Изключване на тетъринга"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Точката за достъп или тетърингът са включени"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Възможно е да ви бъдат начислени допълнителни такси при роуминг"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml deleted file mode 100644 index 579d1be1c1ea..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"টিথারিং করার জন্য কোনও ইন্টারনেট কানেকশন নেই"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ডিভাইস কানেক্ট করতে পারছে না"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"টিথারিং বন্ধ করুন"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"হটস্পট বা টিথারিং চালু আছে"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"রোমিংয়ের সময় অতিরিক্ত চার্জ করা হতে পারে"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml deleted file mode 100644 index 9ce3efe6c39d..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Povezivanje putem mobitela nema internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Uređaji se ne mogu povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključi povezivanje putem mobitela"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Pristupna tačka ili povezivanje putem mobitela je uključeno"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Mogu nastati dodatni troškovi u romingu"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml deleted file mode 100644 index 46d4c35b9b83..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"La compartició de xarxa no té accés a Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"No es poden connectar els dispositius"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactiva la compartició de xarxa"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"S\'ha activat el punt d\'accés Wi‑Fi o la compartició de xarxa"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"És possible que s\'apliquin costos addicionals en itinerància"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml deleted file mode 100644 index cc13860b3da1..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nemá připojení k internetu"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Zařízení se nemůžou připojit"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vypnout tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Je zapnutý hotspot nebo tethering"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Při roamingu mohou být účtovány dodatečné poplatky"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml deleted file mode 100644 index 92c3ae11567d..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Netdeling har ingen internetforbindelse"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enheder kan ikke oprette forbindelse"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Deaktiver netdeling"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot eller netdeling er aktiveret"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Der opkræves muligvis yderligere gebyrer ved roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml deleted file mode 100644 index 967eb4db2e77..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering hat keinen Internetzugriff"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Geräte können sich nicht verbinden"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering deaktivieren"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot oder Tethering ist aktiviert"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Für das Roaming können zusätzliche Gebühren anfallen"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml deleted file mode 100644 index 5fb497451f6d..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Η σύνδεση δεν έχει πρόσβαση στο διαδίκτυο"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Δεν είναι δυνατή η σύνδεση των συσκευών"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Απενεργοποιήστε τη σύνδεση"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ενεργό σημείο πρόσβασης Wi-Fi ή ενεργή σύνδεση"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ενδέχεται να ισχύουν επιπλέον χρεώσεις κατά την περιαγωγή."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml deleted file mode 100644 index 45647f93f246..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml deleted file mode 100644 index 45647f93f246..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml deleted file mode 100644 index 45647f93f246..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml deleted file mode 100644 index 45647f93f246..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml deleted file mode 100644 index 7877074afc66..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml deleted file mode 100644 index 08edd81a6b04..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"La conexión mediante dispositivo móvil no tiene Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"No se pueden conectar los dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión mediante dispositivo móvil"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Se activó el hotspot o la conexión mediante dispositivo móvil"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Es posible que se apliquen cargos adicionales por roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml deleted file mode 100644 index 79f51d00e2e8..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"La conexión no se puede compartir, porque no hay acceso a Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Los dispositivos no se pueden conectar"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión compartida"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Punto de acceso o conexión compartida activados"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Puede que se apliquen cargos adicionales en itinerancia"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml deleted file mode 100644 index 2da5f8a6d62a..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Jagamisel puudub internetiühendus"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Seadmed ei saa ühendust luua"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Lülita jagamine välja"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Kuumkoht või jagamine on sisse lülitatud"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rändluse kasutamisega võivad kaasneda lisatasud"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml deleted file mode 100644 index 2073f2806c18..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Konexioa partekatzeko aukerak ez du Interneteko konexiorik"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Ezin dira konektatu gailuak"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desaktibatu konexioa partekatzeko aukera"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Wifi-gunea edo konexioa partekatzeko aukera aktibatuta dago"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Baliteke kostu gehigarriak ordaindu behar izatea ibiltaritzan"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml deleted file mode 100644 index e21b2a0852c7..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"«اشتراکگذاری اینترنت» به اینترنت دسترسی ندارد"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"دستگاهها متصل نمیشوند"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"خاموش کردن «اشتراکگذاری اینترنت»"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"«نقطه اتصال» یا «اشتراکگذاری اینترنت» روشن است"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ممکن است درحین فراگردی تغییرات دیگر اعمال شود"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml deleted file mode 100644 index 88b0b13eb4b5..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ei jaettavaa internetyhteyttä"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Laitteet eivät voi muodostaa yhteyttä"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Laita yhteyden jakaminen pois päältä"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot tai yhteyden jakaminen on päällä"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Roaming voi aiheuttaa lisämaksuja"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml deleted file mode 100644 index 3b781bc8db31..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Le partage de connexion n\'est pas connecté à Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossible de connecter les appareils"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Désactiver le partage de connexion"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Le point d\'accès ou le partage de connexion est activé"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml deleted file mode 100644 index 51d7203c3652..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Aucune connexion à Internet n\'est disponible pour le partage de connexion"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossible de connecter les appareils"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Désactiver le partage de connexion"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Le point d\'accès ou le partage de connexion est activé"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml deleted file mode 100644 index 008ccb475d66..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"A conexión compartida non ten Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Non se puideron conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión compartida"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Está activada a zona wifi ou a conexión compartida"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pódense aplicar cargos adicionais en itinerancia"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml deleted file mode 100644 index f2e3b4df782f..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ઇન્ટરનેટ શેર કરવાની સુવિધામાં ઇન્ટરનેટ નથી"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ડિવાઇસ કનેક્ટ કરી શકાતા નથી"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરો"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"હૉટસ્પૉટ અથવા ઇન્ટરનેટ શેર કરવાની સુવિધા ચાલુ છે"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"રોમિંગમાં વધારાના શુલ્ક લાગી શકે છે"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml deleted file mode 100644 index b11839d760c8..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिंग से इंटरनेट नहीं चल रहा"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"डिवाइस कनेक्ट नहीं हो पा रहे"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिंग बंद करें"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हॉटस्पॉट या टेदरिंग चालू है"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिंग के दौरान अतिरिक्त शुल्क लग सकता है"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml deleted file mode 100644 index 0a5aca25b1a9..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modemsko povezivanje nema internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Uređaji se ne mogu povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključivanje modemskog povezivanja"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Uključena je žarišna točka ili modemsko povezivanje"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"U roamingu su mogući dodatni troškovi"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml deleted file mode 100644 index 21c689a44ef8..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nincs internetkapcsolat az internet megosztásához"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Az eszközök nem tudnak csatlakozni"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Internetmegosztás kikapcsolása"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"A hotspot vagy az internetmegosztás be van kapcsolva"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Roaming során további díjak léphetnek fel"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml deleted file mode 100644 index 689d92870e50..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Մոդեմի ռեժիմի կապը բացակայում է"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Չհաջողվեց միացնել սարքը"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Անջատել մոդեմի ռեժիմը"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Թեժ կետը կամ մոդեմի ռեժիմը միացված է"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ռոումինգում կարող են լրացուցիչ վճարներ գանձվել"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml deleted file mode 100644 index a5f4d19abfe9..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tidak ada koneksi internet di tethering"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Perangkat tidak dapat terhubung"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Nonaktifkan tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot atau tethering aktif"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Biaya tambahan mungkin berlaku saat roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml deleted file mode 100644 index fc7e8aaf4e42..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tjóðrun er ekki með internettengingu"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Tæki geta ekki tengst"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Slökkva á tjóðrun"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Kveikt er á heitum reit eða tjóðrun"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Viðbótargjöld kunna að eiga við í reiki"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml deleted file mode 100644 index 6456dd1b806a..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nessuna connessione a Internet per il tethering"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossibile connettere i dispositivi"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Disattiva il tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot o tethering attivi"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Potrebbero essere applicati costi aggiuntivi durante il roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml deleted file mode 100644 index 46b24bd3c508..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"אי אפשר להפעיל את תכונת שיתוף האינטרנט בין מכשירים כי אין חיבור לאינטרנט"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"למכשירים אין אפשרות להתחבר"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"השבתה של שיתוף האינטרנט בין מכשירים"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"תכונת הנקודה לשיתוף אינטרנט או תכונת שיתוף האינטרנט בין מכשירים פועלת"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ייתכנו חיובים נוספים בעת נדידה"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml deleted file mode 100644 index e6eb277b90dd..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"テザリングがインターネットに接続されていません"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"デバイスを接続できません"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"テザリングを OFF にする"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"アクセス ポイントまたはテザリングが ON です"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ローミング時に追加料金が発生することがあります"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml deleted file mode 100644 index aeddd7101da0..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ტეტერინგს არ აქვს ინტერნეტზე წვდომა"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"მოწყობილობები ვერ ახერხებენ დაკავშირებას"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ტეტერინგის გამორთვა"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ჩართულია უსადენო ქსელი ან ტეტერინგი"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"როუმინგის გამოყენებისას შეიძლება ჩამოგეჭრათ დამატებითი საფასური"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml deleted file mode 100644 index 255f0a276f95..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Тетеринг режимі интернет байланысынсыз пайдаланылуда"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Құрылғыларды байланыстыру мүмкін емес"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Тетерингіні өшіру"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Хотспот немесе тетеринг қосулы"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роуминг кезінде қосымша ақы алынуы мүмкін."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml deleted file mode 100644 index 2bceb1cf7788..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ការភ្ជាប់មិនមានអ៊ីនធឺណិតទេ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"មិនអាចភ្ជាប់ឧបករណ៍បានទេ"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"បិទការភ្ជាប់"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ហតស្ប៉ត ឬការភ្ជាប់ត្រូវបានបើក"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"អាចមានការគិតថ្លៃបន្ថែម នៅពេលរ៉ូមីង"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml deleted file mode 100644 index ed769305a679..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ಟೆಥರಿಂಗ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಹೊಂದಿಲ್ಲ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ಸಾಧನಗಳನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ಟೆಥರಿಂಗ್ ಆಫ್ ಮಾಡಿ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ಹಾಟ್ಸ್ಪಾಟ್ ಅಥವಾ ಟೆಥರಿಂಗ್ ಆನ್ ಆಗಿದೆ"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಹೆಚ್ಚುವರಿ ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml deleted file mode 100644 index 6e504941eb8b..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"테더링으로 인터넷을 사용할 수 없음"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"기기에서 연결할 수 없음"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"테더링 사용 중지"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"핫스팟 또는 테더링 켜짐"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"로밍 중에는 추가 요금이 발생할 수 있습니다."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml deleted file mode 100644 index d68128b9a554..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Модем режими Интернети жок колдонулууда"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Түзмөктөр туташпай жатат"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Модем режимин өчүрүү"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Байланыш түйүнү же модем режими күйүк"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роумингде кошумча акы алынышы мүмкүн"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml deleted file mode 100644 index 03e134a0fc79..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ການປ່ອຍສັນຍານບໍ່ມີອິນເຕີເນັດ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ອຸປະກອນບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ປິດການປ່ອຍສັນຍານ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ເປີດໃຊ້ຮັອດສະປອດ ຫຼື ການປ່ອຍສັນຍານຢູ່"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ອາດມີຄ່າໃຊ້ຈ່າຍເພີ່ມເຕີມໃນລະຫວ່າງການໂຣມມິງ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml deleted file mode 100644 index 652cedc6e6ae..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nėra įrenginio kaip modemo naudojimo interneto ryšio"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Nepavyko susieti įrenginių"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Išjungti įrenginio kaip modemo naudojimą"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Įjungtas viešosios interneto prieigos taškas arba įrenginio kaip modemo naudojimas"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Veikiant tarptinkliniam ryšiui gali būti taikomi papildomi mokesčiai"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml deleted file mode 100644 index 221972298c18..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Piesaistei nav interneta savienojuma"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Nevar savienot ierīces"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Izslēgt piesaisti"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ir ieslēgts tīklājs vai piesaiste"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Viesabonēšanas laikā var tikt piemērota papildu samaksa"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml deleted file mode 100644 index 227f9e346651..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Нема интернет преку мобилен"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Уредите не може да се поврзат"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Исклучи интернет преку мобилен"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Точката на пристап или интернетот преку мобилен е вклучен"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"При роаминг може да се наплатат дополнителни трошоци"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml deleted file mode 100644 index ec4388512645..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ടെതറിംഗിന് ഇന്റർനെറ്റ് ഇല്ല"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ഉപകരണങ്ങൾ കണക്റ്റ് ചെയ്യാനാവില്ല"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ടെതറിംഗ് ഓഫാക്കുക"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ഹോട്ട്സ്പോട്ട് അല്ലെങ്കിൽ ടെതറിംഗ് ഓണാണ്"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"റോമിംഗ് ചെയ്യുമ്പോൾ അധിക നിരക്കുകൾ ബാധകമായേക്കാം"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml deleted file mode 100644 index e263573799ed..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Модемд интернэт алга байна"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Төхөөрөмжүүд холбогдох боломжгүй байна"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Модем болгохыг унтраах"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Сүлжээний цэг эсвэл модем болгох асаалттай байна"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роумингийн үеэр нэмэлт төлбөр нэхэмжилж болзошгүй"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml deleted file mode 100644 index adf845d078bf..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिंगला इंटरनेट नाही"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"डिव्हाइस कनेक्ट होऊ शकत नाहीत"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिंग बंद करा"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हॉटस्पॉट किंवा टेदरिंग सुरू आहे"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिंगदरम्यान अतिरिक्त शुल्क लागू होऊ शकतात"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml deleted file mode 100644 index f65c451e4c21..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Penambatan tiada Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Peranti tidak dapat disambungkan"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Matikan penambatan"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Tempat liputan atau penambatan dihidupkan"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Caj tambahan mungkin digunakan semasa perayauan"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml deleted file mode 100644 index 4118e775cd84..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းတွင် အင်တာနက် မရှိပါ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"စက်များ ချိတ်ဆက်၍ မရပါ"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ပိတ်ရန်"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ဟော့စပေါ့ (သို့) မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ဖွင့်ထားသည်"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်သည့်အခါ နောက်ထပ်ကျသင့်မှုများ ရှိနိုင်သည်"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml deleted file mode 100644 index 36853583ce82..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Internettdeling har ikke internettilgang"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enhetene kan ikke koble til"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Slå av internettdeling"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Wi-Fi-sone eller internettdeling er på"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ytterligere kostnader kan påløpe under roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml deleted file mode 100644 index 1d888942f49b..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering heeft geen internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Apparaten kunnen niet worden verbonden"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering uitschakelen"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot of tethering is ingeschakeld"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Er kunnen extra kosten voor roaming in rekening worden gebracht."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml deleted file mode 100644 index 8038815fe804..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ଟିଥରିଂ ପାଇଁ କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ଡିଭାଇସଗୁଡ଼ିକ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ଟିଥରିଂ ବନ୍ଦ କରନ୍ତୁ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ହଟସ୍ପଟ୍ କିମ୍ବା ଟିଥରିଂ ଚାଲୁ ଅଛି"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ରୋମିଂରେ ଥିବା ସମୟରେ ଅତିରିକ୍ତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml deleted file mode 100644 index 819833eab07f..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ਟੈਦਰਿੰਗ ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"ਡੀਵਾਈਸ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ਟੈਦਰਿੰਗ ਬੰਦ ਕਰੋ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ਹੌਟਸਪੌਟ ਜਾਂ ਟੈਦਰਿੰਗ ਚਾਲੂ ਹੈ"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ਰੋਮਿੰਗ ਦੌਰਾਨ ਵਧੀਕ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml deleted file mode 100644 index 65e4380e3916..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nie ma internetu"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Urządzenia nie mogą się połączyć"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Wyłącz tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot lub tethering jest włączony"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Podczas korzystania z roamingu mogą zostać naliczone dodatkowe opłaty"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml deleted file mode 100644 index d8866170c191..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"O tethering não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar o tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ponto de acesso ou tethering ativado"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pode haver cobranças extras durante o roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml deleted file mode 100644 index bfd45ca0a3e1..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"A ligação (à Internet) via telemóvel não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível ligar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar ligação (à Internet) via telemóvel"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"A zona Wi-Fi ou a ligação (à Internet) via telemóvel está ativada"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Podem aplicar-se custos adicionais em roaming."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml deleted file mode 100644 index d8866170c191..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"O tethering não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar o tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ponto de acesso ou tethering ativado"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pode haver cobranças extras durante o roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml deleted file mode 100644 index 8d87a9e516ad..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Procesul de tethering nu are internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Dispozitivele nu se pot conecta"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Dezactivați procesul de tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"S-a activat hotspotul sau tethering"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Se pot aplica taxe suplimentare pentru roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml deleted file mode 100644 index dbdb9ebe4931..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Режим модема используется без доступа к Интернету"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Невозможно подключить устройства."</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Отключить режим модема"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Включены точка доступа или режим модема"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"За использование услуг связи в роуминге может взиматься дополнительная плата."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml deleted file mode 100644 index d8301e41c2b2..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ටෙදරින් හට අන්තර්ජාලය නැත"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"උපාංගවලට සම්බන්ධ විය නොහැකිය"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ටෙදරින් ක්රියාවිරහිත කරන්න"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"හොට්ස්පොට් හෝ ටෙදරින් ක්රියාත්මකයි"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"රෝමිං අතරතුර අමතර ගාස්තු අදාළ විය හැකිය"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml deleted file mode 100644 index bef71363f450..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nemá internetové pripojenie"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Zariadenia sa nemôžu pripojiť"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vypnúť tethering"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Je zapnutý hotspot alebo tethering"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Počas roamingu vám môžu byť účtované ďalšie poplatky"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml deleted file mode 100644 index 3202c62e8a3a..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Internetna povezava prek mobilnega telefona ni vzpostavljena"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Napravi se ne moreta povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Izklopi internetno povezavo prek mobilnega telefona"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Dostopna točka ali internetna povezava prek mobilnega telefona je vklopljena"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Med gostovanjem lahko nastanejo dodatni stroški"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml deleted file mode 100644 index 37f6ad286880..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ndarja e internetit nuk ka internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Pajisjet nuk mund të lidhen"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Çaktivizo ndarjen e internetit"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Zona e qasjes për internet ose ndarja e internetit është aktive"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Mund të zbatohen tarifime shtesë kur je në roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml deleted file mode 100644 index 5566d03ed13a..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Привезивање нема приступ интернету"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Повезивање уређаја није успело"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Искључи привезивање"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Укључен је хотспот или привезивање"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Можда важе додатни трошкови у ромингу"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml deleted file mode 100644 index 9765acd0cf46..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Det finns ingen internetanslutning för internetdelningen"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enheterna kan inte anslutas"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Inaktivera internetdelning"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Surfzon eller internetdelning har aktiverats"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ytterligare avgifter kan tillkomma vid roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml deleted file mode 100644 index cf850c9cd222..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Kipengele cha kusambaza mtandao hakina intaneti"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Imeshindwa kuunganisha vifaa"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Zima kipengele cha kusambaza mtandao"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Umewasha kipengele cha kusambaza mtandao au mtandao pepe"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Huenda ukatozwa gharama za ziada ukitumia mitandao ya ng\'ambo"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml deleted file mode 100644 index f4b15aab19b7..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"சாதனங்களால் இணைய முடியவில்லை"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"இணைப்பு முறையை ஆஃப் செய்"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml deleted file mode 100644 index 937d34d52027..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"టెథరింగ్ చేయడానికి ఇంటర్నెట్ కనెక్షన్ లేదు"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"పరికరాలు కనెక్ట్ అవ్వడం లేదు"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"టెథరింగ్ను ఆఫ్ చేయండి"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"హాట్స్పాట్ లేదా టెథరింగ్ ఆన్లో ఉంది"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"రోమింగ్లో ఉన్నప్పుడు అదనపు ఛార్జీలు వర్తించవచ్చు"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml deleted file mode 100644 index f781fae5252e..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือไม่มีอินเทอร์เน็ต"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"อุปกรณ์เชื่อมต่อไม่ได้"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ปิดการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ฮอตสปอตหรือการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือเปิดอยู่"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"อาจมีค่าใช้จ่ายเพิ่มเติมขณะโรมมิ่ง"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml deleted file mode 100644 index 8d5d46537334..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Walang internet ang pag-tether"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Hindi makakonekta ang mga device"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"I-off ang pag-tether"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Naka-on ang Hotspot o pag-tether"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Posibleng magkaroon ng mga karagdagang singil habang nagro-roam"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml deleted file mode 100644 index 80cab33ac05e..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering\'in internet bağlantısı yok"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Cihazlar bağlanamıyor"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering\'i kapat"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot veya tethering açık"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Dolaşım sırasında ek ücretler uygulanabilir"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml deleted file mode 100644 index c05932a5ae7f..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Телефон, який використовується як модем, не підключений до Інтернету"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Не вдається підключити пристрої"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Вимкнути використання телефона як модема"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Увімкнено точку доступу або використання телефона як модема"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"У роумінгу може стягуватися додаткова плата"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml deleted file mode 100644 index d820eee8ba3c..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"ٹیدرنگ میں انٹرنیٹ نہیں ہے"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"آلات منسلک نہیں ہو سکتے"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ٹیدرنگ آف کریں"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ہاٹ اسپاٹ یا ٹیدرنگ آن ہے"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"رومنگ کے دوران اضافی چارجز لاگو ہو سکتے ہیں"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml deleted file mode 100644 index 726148aaee5a..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modem internetga ulanmagan"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Qurilmalar ulanmadi"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Modem rejimini faolsizlantirish"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot yoki modem rejimi yoniq"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rouming vaqtida qoʻshimcha haq olinishi mumkin"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml deleted file mode 100644 index b7cb0456b673..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Không có Internet để chia sẻ kết Internet"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Các thiết bị không thể kết nối"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tắt tính năng chia sẻ Internet"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Điểm phát sóng hoặc tính năng chia sẻ Internet đang bật"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Bạn có thể mất thêm phí dữ liệu khi chuyển vùng"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml deleted file mode 100644 index af91afff9a4c..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"共享网络未连接到互联网"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"设备无法连接"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"关闭网络共享"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"热点或网络共享已开启"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"漫游时可能会产生额外的费用"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml deleted file mode 100644 index 28e6b80c01a9..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過網絡共享連線至互聯網"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"裝置無法連接"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉網絡共享"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"熱點或網絡共享已開啟"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"漫遊時可能需要支付額外費用"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml deleted file mode 100644 index 11eb66621971..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ukusebenzisa ifoni njengemodemu akunayo i-inthanethi"</string> - <string name="no_upstream_notification_message" msgid="3843613362272973447">"Amadivayisi awakwazi ukuxhumeka"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vala ukusebenzisa ifoni njengemodemu"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"I-hotspot noma ukusebenzisa ifoni njengemodemu kuvuliwe"</string> - <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Kungaba nezinkokhelo ezengeziwe uma uzula"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004/strings.xml b/packages/Tethering/res/values-mcc310-mnc004/strings.xml deleted file mode 100644 index ce9ff6080717..000000000000 --- a/packages/Tethering/res/values-mcc310-mnc004/strings.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?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. ---> -<resources> - <!-- String for no upstream notification title [CHAR LIMIT=200] --> - <string name="no_upstream_notification_title">Tethering has no internet</string> - <!-- String for no upstream notification title [CHAR LIMIT=200] --> - <string name="no_upstream_notification_message">Devices can\u2019t connect</string> - <!-- String for no upstream notification disable button [CHAR LIMIT=200] --> - <string name="no_upstream_notification_disable_button">Turn off tethering</string> - - <!-- String for cellular roaming notification title [CHAR LIMIT=200] --> - <string name="upstream_roaming_notification_title">Hotspot or tethering is on</string> - <!-- String for cellular roaming notification message [CHAR LIMIT=500] --> - <string name="upstream_roaming_notification_message">Additional charges may apply while roaming</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml deleted file mode 100644 index 9bfa5317a9e4..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Verbinding het nie internet nie"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Toestelle kan nie koppel nie"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Skakel verbinding af"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Warmkol of verbinding is aan"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Bykomende heffings kan geld terwyl jy swerf"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml deleted file mode 100644 index 5949dfa776d7..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ማስተሳሰር ምንም በይነመረብ የለውም"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"መሣሪያዎችን ማገናኘት አይቻልም"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ማስተሳሰርን አጥፋ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"መገናኛ ነጥብ ወይም ማስተሳሰር በርቷል"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"በሚያንዣብብበት ጊዜ ተጨማሪ ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml deleted file mode 100644 index 8467f9b1f5cf..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ما مِن اتصال بالإنترنت خلال التوصيل"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"تعذّر اتصال الأجهزة"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"إيقاف التوصيل"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"نقطة الاتصال أو التوصيل مفعّلان"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"قد يتم تطبيق رسوم إضافية أثناء التجوال."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml deleted file mode 100644 index 9776bd89da48..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"টে\'ডাৰিঙৰ ইণ্টাৰনেট নাই"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ডিভাইচসমূহ সংযোগ কৰিব নোৱাৰি"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"টে\'ডাৰিং অফ কৰক"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"হটস্পট অথবা টে\'ডাৰিং অন আছে"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ৰ\'মিঙত থাকিলে অতিৰিক্ত মাচুল প্ৰযোজ্য হ’ব পাৰে"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml deleted file mode 100644 index e6d3eaf9f07c..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Modemin internetə girişi yoxdur"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Cihazları qoşmaq mümkün deyil"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Modemi deaktiv edin"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot və ya modem aktivdir"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rouminq zamanı əlavə ödənişlər tətbiq edilə bilər"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml deleted file mode 100644 index 4c8a1df8eece..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Privezivanje nema pristup internetu"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Povezivanje uređaja nije uspelo"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključi privezivanje"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Uključen je hotspot ili privezivanje"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Možda važe dodatni troškovi u romingu"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml deleted file mode 100644 index edfa41e1ffd3..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Рэжым мадэма выкарыстоўваецца без доступу да інтэрнэту"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Не ўдалося падключыць прылады"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Выключыць рэжым мадэма"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Хот-спот або рэжым мадэма ўключаны"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Пры выкарыстанні роўмінгу можа спаганяцца дадатковая плата"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml deleted file mode 100644 index f56398196f51..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Тетърингът няма връзка с интернет"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Устройствата не могат да установят връзка"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Изключване на тетъринга"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Точката за достъп или тетърингът са включени"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Възможно е да ви бъдат начислени допълнителни такси при роуминг"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml deleted file mode 100644 index d8ecd2e988f9..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"টিথারিং করার জন্য কোনও ইন্টারনেট কানেকশন নেই"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ডিভাইস কানেক্ট করতে পারছে না"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"টিথারিং বন্ধ করুন"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"হটস্পট বা টিথারিং চালু আছে"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"রোমিংয়ের সময় অতিরিক্ত চার্জ করা হতে পারে"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml deleted file mode 100644 index b85fd5e28577..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Povezivanje putem mobitela nema internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Uređaji se ne mogu povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključi povezivanje putem mobitela"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Pristupna tačka ili povezivanje putem mobitela je uključeno"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Mogu nastati dodatni troškovi u romingu"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml deleted file mode 100644 index a3572151be6b..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"La compartició de xarxa no té accés a Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"No es poden connectar els dispositius"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactiva la compartició de xarxa"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"S\'ha activat el punt d\'accés Wi‑Fi o la compartició de xarxa"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"És possible que s\'apliquin costos addicionals en itinerància"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml deleted file mode 100644 index 91196be9e557..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nemá připojení k internetu"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Zařízení se nemůžou připojit"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vypnout tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Je zapnutý hotspot nebo tethering"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Při roamingu mohou být účtovány dodatečné poplatky"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml deleted file mode 100644 index 196890011d50..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Netdeling har ingen internetforbindelse"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enheder kan ikke oprette forbindelse"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Deaktiver netdeling"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot eller netdeling er aktiveret"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Der opkræves muligvis yderligere gebyrer ved roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml deleted file mode 100644 index eb3f8c52c0c5..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering hat keinen Internetzugriff"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Geräte können sich nicht verbinden"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering deaktivieren"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot oder Tethering ist aktiviert"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Für das Roaming können zusätzliche Gebühren anfallen"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml deleted file mode 100644 index 56c3d81b634e..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Η σύνδεση δεν έχει πρόσβαση στο διαδίκτυο"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Δεν είναι δυνατή η σύνδεση των συσκευών"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Απενεργοποιήστε τη σύνδεση"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ενεργό σημείο πρόσβασης Wi-Fi ή ενεργή σύνδεση"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ενδέχεται να ισχύουν επιπλέον χρεώσεις κατά την περιαγωγή."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml deleted file mode 100644 index dd1a1971cdd8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml deleted file mode 100644 index dd1a1971cdd8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml deleted file mode 100644 index dd1a1971cdd8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml deleted file mode 100644 index dd1a1971cdd8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml deleted file mode 100644 index d3347aae207d..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml deleted file mode 100644 index 2f0504f07de7..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"La conexión mediante dispositivo móvil no tiene Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"No se pueden conectar los dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión mediante dispositivo móvil"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Se activó el hotspot o la conexión mediante dispositivo móvil"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Es posible que se apliquen cargos adicionales por roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml deleted file mode 100644 index 2d8f88242502..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"La conexión no se puede compartir, porque no hay acceso a Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Los dispositivos no se pueden conectar"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión compartida"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Punto de acceso o conexión compartida activados"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Puede que se apliquen cargos adicionales en itinerancia"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml deleted file mode 100644 index 8493c470710d..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Jagamisel puudub internetiühendus"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Seadmed ei saa ühendust luua"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Lülita jagamine välja"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Kuumkoht või jagamine on sisse lülitatud"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rändluse kasutamisega võivad kaasneda lisatasud"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml deleted file mode 100644 index 33bccab3e88c..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Konexioa partekatzeko aukerak ez du Interneteko konexiorik"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Ezin dira konektatu gailuak"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desaktibatu konexioa partekatzeko aukera"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Wifi-gunea edo konexioa partekatzeko aukera aktibatuta dago"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Baliteke kostu gehigarriak ordaindu behar izatea ibiltaritzan"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml deleted file mode 100644 index cf8a0cc27705..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"«اشتراکگذاری اینترنت» به اینترنت دسترسی ندارد"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"دستگاهها متصل نمیشوند"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"خاموش کردن «اشتراکگذاری اینترنت»"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"«نقطه اتصال» یا «اشتراکگذاری اینترنت» روشن است"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ممکن است درحین فراگردی تغییرات دیگر اعمال شود"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml deleted file mode 100644 index 6a3ab806db98..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Ei jaettavaa internetyhteyttä"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Laitteet eivät voi muodostaa yhteyttä"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Laita yhteyden jakaminen pois päältä"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot tai yhteyden jakaminen on päällä"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Roaming voi aiheuttaa lisämaksuja"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml deleted file mode 100644 index ffb9bf60472e..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Le partage de connexion n\'est pas connecté à Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossible de connecter les appareils"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Désactiver le partage de connexion"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Le point d\'accès ou le partage de connexion est activé"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml deleted file mode 100644 index 768bce3f0ab1..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Aucune connexion à Internet n\'est disponible pour le partage de connexion"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossible de connecter les appareils"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Désactiver le partage de connexion"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Le point d\'accès ou le partage de connexion est activé"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml deleted file mode 100644 index 0c4195a7caf3..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"A conexión compartida non ten Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Non se puideron conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión compartida"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Está activada a zona wifi ou a conexión compartida"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pódense aplicar cargos adicionais en itinerancia"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml deleted file mode 100644 index e9d33a7db259..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ઇન્ટરનેટ શેર કરવાની સુવિધામાં ઇન્ટરનેટ નથી"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ડિવાઇસ કનેક્ટ કરી શકાતા નથી"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરો"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"હૉટસ્પૉટ અથવા ઇન્ટરનેટ શેર કરવાની સુવિધા ચાલુ છે"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"રોમિંગમાં વધારાના શુલ્ક લાગી શકે છે"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml deleted file mode 100644 index aa418ac5d3bb..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिंग से इंटरनेट नहीं चल रहा"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"डिवाइस कनेक्ट नहीं हो पा रहे"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिंग बंद करें"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हॉटस्पॉट या टेदरिंग चालू है"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिंग के दौरान अतिरिक्त शुल्क लग सकता है"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml deleted file mode 100644 index 51c524afbc53..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Modemsko povezivanje nema internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Uređaji se ne mogu povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključivanje modemskog povezivanja"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Uključena je žarišna točka ili modemsko povezivanje"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"U roamingu su mogući dodatni troškovi"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml deleted file mode 100644 index 164e45edd142..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Nincs internetkapcsolat az internet megosztásához"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Az eszközök nem tudnak csatlakozni"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Internetmegosztás kikapcsolása"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"A hotspot vagy az internetmegosztás be van kapcsolva"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Roaming során további díjak léphetnek fel"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml deleted file mode 100644 index e76c0a4c80d5..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Մոդեմի ռեժիմի կապը բացակայում է"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Չհաջողվեց միացնել սարքը"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Անջատել մոդեմի ռեժիմը"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Թեժ կետը կամ մոդեմի ռեժիմը միացված է"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ռոումինգում կարող են լրացուցիչ վճարներ գանձվել"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml deleted file mode 100644 index 2b817f8abd17..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tidak ada koneksi internet di tethering"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Perangkat tidak dapat terhubung"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Nonaktifkan tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot atau tethering aktif"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Biaya tambahan mungkin berlaku saat roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml deleted file mode 100644 index a338d9c7cab8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tjóðrun er ekki með internettengingu"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Tæki geta ekki tengst"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Slökkva á tjóðrun"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Kveikt er á heitum reit eða tjóðrun"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Viðbótargjöld kunna að eiga við í reiki"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml deleted file mode 100644 index 77769c2ac56c..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Nessuna connessione a Internet per il tethering"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossibile connettere i dispositivi"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Disattiva il tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot o tethering attivi"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Potrebbero essere applicati costi aggiuntivi durante il roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml deleted file mode 100644 index 5267b5126435..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"אי אפשר להפעיל את תכונת שיתוף האינטרנט בין מכשירים כי אין חיבור לאינטרנט"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"למכשירים אין אפשרות להתחבר"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"השבתה של שיתוף האינטרנט בין מכשירים"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"תכונת הנקודה לשיתוף אינטרנט או תכונת שיתוף האינטרנט בין מכשירים פועלת"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ייתכנו חיובים נוספים בעת נדידה"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml deleted file mode 100644 index 66a9a6dd35c2..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"テザリングがインターネットに接続されていません"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"デバイスを接続できません"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"テザリングを OFF にする"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"アクセス ポイントまたはテザリングが ON です"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ローミング時に追加料金が発生することがあります"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml deleted file mode 100644 index d8ad8808498f..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ტეტერინგს არ აქვს ინტერნეტზე წვდომა"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"მოწყობილობები ვერ ახერხებენ დაკავშირებას"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ტეტერინგის გამორთვა"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ჩართულია უსადენო ქსელი ან ტეტერინგი"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"როუმინგის გამოყენებისას შეიძლება ჩამოგეჭრათ დამატებითი საფასური"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml deleted file mode 100644 index 1ddd6b419b57..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Тетеринг режимі интернет байланысынсыз пайдаланылуда"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Құрылғыларды байланыстыру мүмкін емес"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Тетерингіні өшіру"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Хотспот немесе тетеринг қосулы"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роуминг кезінде қосымша ақы алынуы мүмкін."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml deleted file mode 100644 index cf5a1379ccc7..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ការភ្ជាប់មិនមានអ៊ីនធឺណិតទេ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"មិនអាចភ្ជាប់ឧបករណ៍បានទេ"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"បិទការភ្ជាប់"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ហតស្ប៉ត ឬការភ្ជាប់ត្រូវបានបើក"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"អាចមានការគិតថ្លៃបន្ថែម នៅពេលរ៉ូមីង"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml deleted file mode 100644 index 68ae68bc1998..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ಟೆಥರಿಂಗ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಹೊಂದಿಲ್ಲ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ಸಾಧನಗಳನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ಟೆಥರಿಂಗ್ ಆಫ್ ಮಾಡಿ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ಹಾಟ್ಸ್ಪಾಟ್ ಅಥವಾ ಟೆಥರಿಂಗ್ ಆನ್ ಆಗಿದೆ"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಹೆಚ್ಚುವರಿ ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml deleted file mode 100644 index 17185ba2d063..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"테더링으로 인터넷을 사용할 수 없음"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"기기에서 연결할 수 없음"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"테더링 사용 중지"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"핫스팟 또는 테더링 켜짐"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"로밍 중에는 추가 요금이 발생할 수 있습니다."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml deleted file mode 100644 index 6a9fb9810cc6..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Модем режими Интернети жок колдонулууда"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Түзмөктөр туташпай жатат"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Модем режимин өчүрүү"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Байланыш түйүнү же модем режими күйүк"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роумингде кошумча акы алынышы мүмкүн"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml deleted file mode 100644 index bcc4b5762678..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ການປ່ອຍສັນຍານບໍ່ມີອິນເຕີເນັດ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ອຸປະກອນບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ປິດການປ່ອຍສັນຍານ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ເປີດໃຊ້ຮັອດສະປອດ ຫຼື ການປ່ອຍສັນຍານຢູ່"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ອາດມີຄ່າໃຊ້ຈ່າຍເພີ່ມເຕີມໃນລະຫວ່າງການໂຣມມິງ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml deleted file mode 100644 index 011c2c11fb88..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Nėra įrenginio kaip modemo naudojimo interneto ryšio"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Nepavyko susieti įrenginių"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Išjungti įrenginio kaip modemo naudojimą"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Įjungtas viešosios interneto prieigos taškas arba įrenginio kaip modemo naudojimas"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Veikiant tarptinkliniam ryšiui gali būti taikomi papildomi mokesčiai"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml deleted file mode 100644 index 5cb2f3b7aac8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Piesaistei nav interneta savienojuma"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Nevar savienot ierīces"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Izslēgt piesaisti"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ir ieslēgts tīklājs vai piesaiste"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Viesabonēšanas laikā var tikt piemērota papildu samaksa"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml deleted file mode 100644 index 4cbfd887c57e..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Нема интернет преку мобилен"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Уредите не може да се поврзат"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Исклучи интернет преку мобилен"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Точката на пристап или интернетот преку мобилен е вклучен"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"При роаминг може да се наплатат дополнителни трошоци"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml deleted file mode 100644 index 9cf4eaf34a97..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ടെതറിംഗിന് ഇന്റർനെറ്റ് ഇല്ല"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ഉപകരണങ്ങൾ കണക്റ്റ് ചെയ്യാനാവില്ല"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ടെതറിംഗ് ഓഫാക്കുക"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ഹോട്ട്സ്പോട്ട് അല്ലെങ്കിൽ ടെതറിംഗ് ഓണാണ്"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"റോമിംഗ് ചെയ്യുമ്പോൾ അധിക നിരക്കുകൾ ബാധകമായേക്കാം"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml deleted file mode 100644 index 47c82c14d9d6..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Модемд интернэт алга байна"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Төхөөрөмжүүд холбогдох боломжгүй байна"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Модем болгохыг унтраах"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Сүлжээний цэг эсвэл модем болгох асаалттай байна"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роумингийн үеэр нэмэлт төлбөр нэхэмжилж болзошгүй"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml deleted file mode 100644 index ad9e809ab27d..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिंगला इंटरनेट नाही"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"डिव्हाइस कनेक्ट होऊ शकत नाहीत"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिंग बंद करा"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हॉटस्पॉट किंवा टेदरिंग सुरू आहे"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिंगदरम्यान अतिरिक्त शुल्क लागू होऊ शकतात"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml deleted file mode 100644 index e708cb8717b3..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Penambatan tiada Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Peranti tidak dapat disambungkan"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Matikan penambatan"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Tempat liputan atau penambatan dihidupkan"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Caj tambahan mungkin digunakan semasa perayauan"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml deleted file mode 100644 index ba5462250b05..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းတွင် အင်တာနက် မရှိပါ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"စက်များ ချိတ်ဆက်၍ မရပါ"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ပိတ်ရန်"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ဟော့စပေါ့ (သို့) မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ဖွင့်ထားသည်"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်သည့်အခါ နောက်ထပ်ကျသင့်မှုများ ရှိနိုင်သည်"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml deleted file mode 100644 index 57db484a2543..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Internettdeling har ikke internettilgang"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enhetene kan ikke koble til"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Slå av internettdeling"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Wi-Fi-sone eller internettdeling er på"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ytterligere kostnader kan påløpe under roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml deleted file mode 100644 index b08133f4e592..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering heeft geen internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Apparaten kunnen niet worden verbonden"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering uitschakelen"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot of tethering is ingeschakeld"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Er kunnen extra kosten voor roaming in rekening worden gebracht."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml deleted file mode 100644 index 1ad4ca354ad5..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ଟିଥରିଂ ପାଇଁ କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ଡିଭାଇସଗୁଡ଼ିକ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ଟିଥରିଂ ବନ୍ଦ କରନ୍ତୁ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ହଟସ୍ପଟ୍ କିମ୍ବା ଟିଥରିଂ ଚାଲୁ ଅଛି"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ରୋମିଂରେ ଥିବା ସମୟରେ ଅତିରିକ୍ତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml deleted file mode 100644 index 88def563d85a..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ਟੈਦਰਿੰਗ ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"ਡੀਵਾਈਸ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ਟੈਦਰਿੰਗ ਬੰਦ ਕਰੋ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ਹੌਟਸਪੌਟ ਜਾਂ ਟੈਦਰਿੰਗ ਚਾਲੂ ਹੈ"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ਰੋਮਿੰਗ ਦੌਰਾਨ ਵਧੀਕ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml deleted file mode 100644 index f9890abdc26b..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nie ma internetu"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Urządzenia nie mogą się połączyć"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Wyłącz tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot lub tethering jest włączony"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Podczas korzystania z roamingu mogą zostać naliczone dodatkowe opłaty"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml deleted file mode 100644 index ce3b88479f09..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"O tethering não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar o tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ponto de acesso ou tethering ativado"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pode haver cobranças extras durante o roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml deleted file mode 100644 index 7e883ea57682..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"A ligação (à Internet) via telemóvel não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível ligar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar ligação (à Internet) via telemóvel"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"A zona Wi-Fi ou a ligação (à Internet) via telemóvel está ativada"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Podem aplicar-se custos adicionais em roaming."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml deleted file mode 100644 index ce3b88479f09..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"O tethering não tem Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível conectar os dispositivos"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar o tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ponto de acesso ou tethering ativado"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pode haver cobranças extras durante o roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml deleted file mode 100644 index 1009417316ed..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Procesul de tethering nu are internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Dispozitivele nu se pot conecta"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Dezactivați procesul de tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"S-a activat hotspotul sau tethering"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Se pot aplica taxe suplimentare pentru roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml deleted file mode 100644 index 88683bed95b8..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Режим модема используется без доступа к Интернету"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Невозможно подключить устройства."</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Отключить режим модема"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Включены точка доступа или режим модема"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"За использование услуг связи в роуминге может взиматься дополнительная плата."</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml deleted file mode 100644 index 176bcdb797c6..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ටෙදරින් හට අන්තර්ජාලය නැත"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"උපාංගවලට සම්බන්ධ විය නොහැකිය"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ටෙදරින් ක්රියාවිරහිත කරන්න"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"හොට්ස්පොට් හෝ ටෙදරින් ක්රියාත්මකයි"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"රෝමිං අතරතුර අමතර ගාස්තු අදාළ විය හැකිය"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml deleted file mode 100644 index b9e2127fa879..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nemá internetové pripojenie"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Zariadenia sa nemôžu pripojiť"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vypnúť tethering"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Je zapnutý hotspot alebo tethering"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Počas roamingu vám môžu byť účtované ďalšie poplatky"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml deleted file mode 100644 index e8140e686a0c..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Internetna povezava prek mobilnega telefona ni vzpostavljena"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Napravi se ne moreta povezati"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Izklopi internetno povezavo prek mobilnega telefona"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Dostopna točka ali internetna povezava prek mobilnega telefona je vklopljena"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Med gostovanjem lahko nastanejo dodatni stroški"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml deleted file mode 100644 index 61e698d6e8ab..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Ndarja e internetit nuk ka internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Pajisjet nuk mund të lidhen"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Çaktivizo ndarjen e internetit"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Zona e qasjes për internet ose ndarja e internetit është aktive"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Mund të zbatohen tarifime shtesë kur je në roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml deleted file mode 100644 index b4c411c35475..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Привезивање нема приступ интернету"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Повезивање уређаја није успело"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Искључи привезивање"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Укључен је хотспот или привезивање"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Можда важе додатни трошкови у ромингу"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml deleted file mode 100644 index 4f543e47b998..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Det finns ingen internetanslutning för internetdelningen"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enheterna kan inte anslutas"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Inaktivera internetdelning"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Surfzon eller internetdelning har aktiverats"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ytterligare avgifter kan tillkomma vid roaming"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml deleted file mode 100644 index ac347ab485e0..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Kipengele cha kusambaza mtandao hakina intaneti"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Imeshindwa kuunganisha vifaa"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Zima kipengele cha kusambaza mtandao"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Umewasha kipengele cha kusambaza mtandao au mtandao pepe"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Huenda ukatozwa gharama za ziada ukitumia mitandao ya ng\'ambo"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml deleted file mode 100644 index 2ea2467e5879..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"சாதனங்களால் இணைய முடியவில்லை"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"இணைப்பு முறையை ஆஃப் செய்"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml deleted file mode 100644 index 9360297dd807..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"టెథరింగ్ చేయడానికి ఇంటర్నెట్ కనెక్షన్ లేదు"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"పరికరాలు కనెక్ట్ అవ్వడం లేదు"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"టెథరింగ్ను ఆఫ్ చేయండి"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"హాట్స్పాట్ లేదా టెథరింగ్ ఆన్లో ఉంది"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"రోమింగ్లో ఉన్నప్పుడు అదనపు ఛార్జీలు వర్తించవచ్చు"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml deleted file mode 100644 index 9c4d7e08f2b6..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือไม่มีอินเทอร์เน็ต"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"อุปกรณ์เชื่อมต่อไม่ได้"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ปิดการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ฮอตสปอตหรือการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือเปิดอยู่"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"อาจมีค่าใช้จ่ายเพิ่มเติมขณะโรมมิ่ง"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml deleted file mode 100644 index a7c78a593267..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Walang internet ang pag-tether"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Hindi makakonekta ang mga device"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"I-off ang pag-tether"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Naka-on ang Hotspot o pag-tether"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Posibleng magkaroon ng mga karagdagang singil habang nagro-roam"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml deleted file mode 100644 index 93da2c3f7981..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering\'in internet bağlantısı yok"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Cihazlar bağlanamıyor"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering\'i kapat"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot veya tethering açık"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Dolaşım sırasında ek ücretler uygulanabilir"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml deleted file mode 100644 index ee0dcd2c4b6a..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Телефон, який використовується як модем, не підключений до Інтернету"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Не вдається підключити пристрої"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Вимкнути використання телефона як модема"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Увімкнено точку доступу або використання телефона як модема"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"У роумінгу може стягуватися додаткова плата"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml deleted file mode 100644 index 41cd28eef9bd..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"ٹیدرنگ میں انٹرنیٹ نہیں ہے"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"آلات منسلک نہیں ہو سکتے"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ٹیدرنگ آف کریں"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ہاٹ اسپاٹ یا ٹیدرنگ آن ہے"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"رومنگ کے دوران اضافی چارجز لاگو ہو سکتے ہیں"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml deleted file mode 100644 index c847bc943bd4..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Modem internetga ulanmagan"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Qurilmalar ulanmadi"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Modem rejimini faolsizlantirish"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot yoki modem rejimi yoniq"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rouming vaqtida qoʻshimcha haq olinishi mumkin"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml deleted file mode 100644 index a74326f09ec5..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Không có Internet để chia sẻ kết Internet"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Các thiết bị không thể kết nối"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tắt tính năng chia sẻ Internet"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Điểm phát sóng hoặc tính năng chia sẻ Internet đang bật"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Bạn có thể mất thêm phí dữ liệu khi chuyển vùng"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml deleted file mode 100644 index d7370036e351..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"共享网络未连接到互联网"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"设备无法连接"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"关闭网络共享"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"热点或网络共享已开启"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"漫游时可能会产生额外的费用"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml deleted file mode 100644 index f378a9dc2cfb..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過網絡共享連線至互聯網"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"裝置無法連接"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉網絡共享"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"熱點或網絡共享已開啟"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"漫遊時可能需要支付額外費用"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml deleted file mode 100644 index 32f6df56f154..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"Ukusebenzisa ifoni njengemodemu akunayo i-inthanethi"</string> - <string name="no_upstream_notification_message" msgid="6508394877641864863">"Amadivayisi awakwazi ukuxhumeka"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vala ukusebenzisa ifoni njengemodemu"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"I-hotspot noma ukusebenzisa ifoni njengemodemu kuvuliwe"</string> - <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Kungaba nezinkokhelo ezengeziwe uma uzula"</string> -</resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480/config.xml b/packages/Tethering/res/values-mcc311-mnc480/config.xml deleted file mode 100644 index 5c5be0466a36..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480/config.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?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. ---> -<resources> - <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to - "0" for disable this feature. --> - <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> - - <!-- Config for showing upstream roaming notification. --> - <bool name="config_upstream_roaming_notification">true</bool> -</resources>
\ No newline at end of file diff --git a/packages/Tethering/res/values-mcc311-mnc480/strings.xml b/packages/Tethering/res/values-mcc311-mnc480/strings.xml deleted file mode 100644 index ce9ff6080717..000000000000 --- a/packages/Tethering/res/values-mcc311-mnc480/strings.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?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. ---> -<resources> - <!-- String for no upstream notification title [CHAR LIMIT=200] --> - <string name="no_upstream_notification_title">Tethering has no internet</string> - <!-- String for no upstream notification title [CHAR LIMIT=200] --> - <string name="no_upstream_notification_message">Devices can\u2019t connect</string> - <!-- String for no upstream notification disable button [CHAR LIMIT=200] --> - <string name="no_upstream_notification_disable_button">Turn off tethering</string> - - <!-- String for cellular roaming notification title [CHAR LIMIT=200] --> - <string name="upstream_roaming_notification_title">Hotspot or tethering is on</string> - <!-- String for cellular roaming notification message [CHAR LIMIT=500] --> - <string name="upstream_roaming_notification_message">Additional charges may apply while roaming</string> -</resources> diff --git a/packages/Tethering/res/values-mk/strings.xml b/packages/Tethering/res/values-mk/strings.xml deleted file mode 100644 index 9ad9b9a58935..000000000000 --- a/packages/Tethering/res/values-mk/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Активно е врзување или точка на пристап"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Допрете за поставување."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Врзувањето е оневозможено"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Контактирајте со администраторот за детали"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус на точката на пристап и врзувањето"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ml/strings.xml b/packages/Tethering/res/values-ml/strings.xml deleted file mode 100644 index 9db79ce220a4..000000000000 --- a/packages/Tethering/res/values-ml/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ടെതറിംഗ് അല്ലെങ്കിൽ ഹോട്ട്സ്പോട്ട് സജീവമാണ്"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"സജ്ജീകരിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ടെതറിംഗ് പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"വിശദാംശങ്ങൾക്ക് നിങ്ങളുടെ അഡ്മിനെ ബന്ധപ്പെടുക"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ഹോട്ട്സ്പോട്ടിന്റെയും ടെതറിംഗിന്റെയും നില"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-mn/strings.xml b/packages/Tethering/res/values-mn/strings.xml deleted file mode 100644 index 42d1edbaceb9..000000000000 --- a/packages/Tethering/res/values-mn/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Модем болгох эсвэл сүлжээний цэг идэвхтэй байна"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Тохируулахын тулд товшино уу."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Модем болгохыг идэвхгүй болгосон"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Дэлгэрэнгүй мэдээлэл авахын тулд админтайгаа холбогдоно уу"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Сүлжээний цэг болон модем болгох төлөв"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-mr/strings.xml b/packages/Tethering/res/values-mr/strings.xml deleted file mode 100644 index 13995b6b8aa5..000000000000 --- a/packages/Tethering/res/values-mr/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिंग किंवा हॉटस्पॉट अॅक्टिव्ह आहे"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"सेट करण्यासाठी टॅप करा."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिंग बंद केले आहे"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"तपशीलांसाठी तुमच्या ॲडमिनशी संपर्क साधा"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हॉटस्पॉट आणि टेदरिंगची स्थिती"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ms/strings.xml b/packages/Tethering/res/values-ms/strings.xml deleted file mode 100644 index d6a67f37b1de..000000000000 --- a/packages/Tethering/res/values-ms/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Penambatan atau tempat liputan aktif"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ketik untuk membuat persediaan."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Penambatan dilumpuhkan"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hubungi pentadbir anda untuk mendapatkan maklumat lanjut"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status tempat liputan & penambatan"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-my/strings.xml b/packages/Tethering/res/values-my/strings.xml deleted file mode 100644 index 49f6b88a7514..000000000000 --- a/packages/Tethering/res/values-my/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း သို့မဟုတ် ဟော့စပေါ့ ဖွင့်ထားသည်"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"စနစ်ထည့်သွင်းရန် တို့ပါ။"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းကို ပိတ်ထားသည်"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"အသေးစိတ်အတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ဟော့စပေါ့နှင့် မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း အခြေအနေ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-nb/strings.xml b/packages/Tethering/res/values-nb/strings.xml deleted file mode 100644 index 9594e0a70a69..000000000000 --- a/packages/Tethering/res/values-nb/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Internettdeling eller Wi-Fi-sone er aktiv"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Trykk for å konfigurere."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Internettdeling er slått av"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Ta kontakt med administratoren din for å få mer informasjon"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status for Wi-Fi-sone og internettdeling"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ne/strings.xml b/packages/Tethering/res/values-ne/strings.xml deleted file mode 100644 index 72ae3a80a928..000000000000 --- a/packages/Tethering/res/values-ne/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिङ वा हटस्पट सक्रिय छ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"सेटअप गर्न ट्याप गर्नुहोस्।"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिङ सुविधा असक्षम पारिएको छ"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"विवरणहरूका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हटस्पट तथा टेदरिङको स्थिति"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-nl/strings.xml b/packages/Tethering/res/values-nl/strings.xml deleted file mode 100644 index 18b2bbfc7670..000000000000 --- a/packages/Tethering/res/values-nl/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering of hotspot actief"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tik om in te stellen."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is uitgeschakeld"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Neem contact op met je beheerder voor meer informatie"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status van hotspot en tethering"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-or/strings.xml b/packages/Tethering/res/values-or/strings.xml deleted file mode 100644 index a15a6db42af6..000000000000 --- a/packages/Tethering/res/values-or/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ଟିଥେରିଂ କିମ୍ୱା ହଟସ୍ପଟ୍ ସକ୍ରିୟ ଅଛି"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ସେଟ୍ ଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ଟିଥେରିଂ ଅକ୍ଷମ କରାଯାଇଛି"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ବିବରଣୀଗୁଡ଼ିକ ପାଇଁ ଆପଣଙ୍କ ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ହଟସ୍ପଟ୍ ଓ ଟିଥେରିଂ ସ୍ଥିତି"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-pa/strings.xml b/packages/Tethering/res/values-pa/strings.xml deleted file mode 100644 index a8235e423e47..000000000000 --- a/packages/Tethering/res/values-pa/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ਟੈਦਰਿੰਗ ਜਾਂ ਹੌਟਸਪੌਟ ਕਿਰਿਆਸ਼ੀਲ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ਟੈਦਰਿੰਗ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ਵੇਰਵਿਆਂ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ਹੌਟਸਪੌਟ ਅਤੇ ਟੈਦਰਿੰਗ ਦੀ ਸਥਿਤੀ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-pl/strings.xml b/packages/Tethering/res/values-pl/strings.xml deleted file mode 100644 index ccb017d43fa8..000000000000 --- a/packages/Tethering/res/values-pl/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Aktywny tethering lub punkt dostępu"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Kliknij, by skonfigurować"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering został wyłączony"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Aby uzyskać szczegółowe informacje, skontaktuj się z administratorem"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot i tethering – stan"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-pt-rBR/strings.xml b/packages/Tethering/res/values-pt-rBR/strings.xml deleted file mode 100644 index a0a4745f9394..000000000000 --- a/packages/Tethering/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Ponto de acesso ou tethering ativo"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering desativado"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Fale com seu administrador para saber detalhes"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status de ponto de acesso e tethering"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-pt-rPT/strings.xml b/packages/Tethering/res/values-pt-rPT/strings.xml deleted file mode 100644 index e3f03fcc6934..000000000000 --- a/packages/Tethering/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Ligação (à Internet) via telemóvel ou zona Wi-Fi ativas"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"A ligação (à Internet) via telemóvel está desativada."</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacte o administrador para obter detalhes."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado da zona Wi-Fi e da ligação (à Internet) via telemóvel"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-pt/strings.xml b/packages/Tethering/res/values-pt/strings.xml deleted file mode 100644 index a0a4745f9394..000000000000 --- a/packages/Tethering/res/values-pt/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Ponto de acesso ou tethering ativo"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering desativado"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Fale com seu administrador para saber detalhes"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status de ponto de acesso e tethering"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ro/strings.xml b/packages/Tethering/res/values-ro/strings.xml deleted file mode 100644 index 5706a4a69c79..000000000000 --- a/packages/Tethering/res/values-ro/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering sau hotspot activ"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Atingeți ca să configurați."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tetheringul este dezactivat"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contactați administratorul pentru detalii"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Starea hotspotului și a tetheringului"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ru/strings.xml b/packages/Tethering/res/values-ru/strings.xml deleted file mode 100644 index 7cb6f7db3fc8..000000000000 --- a/packages/Tethering/res/values-ru/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Включен режим модема или точка доступа"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Нажмите, чтобы настроить."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Использование телефона в качестве модема запрещено"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Чтобы узнать подробности, обратитесь к администратору."</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус хот-спота и режима модема"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-si/strings.xml b/packages/Tethering/res/values-si/strings.xml deleted file mode 100644 index ec34c22de750..000000000000 --- a/packages/Tethering/res/values-si/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ටෙදරින් හෝ හොට්ස්පොට් සක්රීයයි"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"පිහිටුවීමට තට්ටු කරන්න."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ටෙදරින් අබල කර ඇත"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"විස්තර සඳහා ඔබගේ පරිපාලක අමතන්න"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"හොට්ස්පොට් & ටෙදරින් තත්ත්වය"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sk/strings.xml b/packages/Tethering/res/values-sk/strings.xml deleted file mode 100644 index 43e787c84f87..000000000000 --- a/packages/Tethering/res/values-sk/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering alebo prístupový bod je aktívny"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Klepnutím prejdete na nastavenie."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering je deaktivovaný"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"O podrobnosti požiadajte svojho správcu"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stav hotspotu a tetheringu"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sl/strings.xml b/packages/Tethering/res/values-sl/strings.xml deleted file mode 100644 index 59433626a115..000000000000 --- a/packages/Tethering/res/values-sl/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Povezava z internetom prek mobilnega telefona ali dostopna točka je aktivna"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Dotaknite se, če želite nastaviti."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Povezava z internetom prek mobilnega telefona je onemogočena"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Za podrobnosti se obrnite na skrbnika"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stanje dostopne točke in povezave z internetom prek mobilnega telefona"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sq/strings.xml b/packages/Tethering/res/values-sq/strings.xml deleted file mode 100644 index 21e11558bb0b..000000000000 --- a/packages/Tethering/res/values-sq/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Ndarja e internetit ose zona e qasjes së internetit është aktive"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Trokit për ta konfiguruar."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Ndarja e internetit është çaktivizuar"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakto me administratorin për detaje"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Statusi i zonës së qasjes dhe ndarjes së internetit"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sr/strings.xml b/packages/Tethering/res/values-sr/strings.xml deleted file mode 100644 index e2e4dc6361d4..000000000000 --- a/packages/Tethering/res/values-sr/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Привезивање или хотспот је активан"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Додирните да бисте подесили."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Привезивање је онемогућено"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Потражите детаље од администратора"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус хотспота и привезивања"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sv/strings.xml b/packages/Tethering/res/values-sv/strings.xml deleted file mode 100644 index 72702c28587d..000000000000 --- a/packages/Tethering/res/values-sv/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Internetdelning eller surfzon har aktiverats"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Tryck om du vill konfigurera."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Internetdelning har inaktiverats"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakta administratören om du vill veta mer"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Trådlös surfzon och internetdelning har inaktiverats"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-sw/strings.xml b/packages/Tethering/res/values-sw/strings.xml deleted file mode 100644 index 65e4aa8cebb0..000000000000 --- a/packages/Tethering/res/values-sw/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Kusambaza mtandao au mtandaopepe umewashwa"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Gusa ili uweke mipangilio."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Umezima kipengele cha kusambaza mtandao"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Wasiliana na msimamizi wako ili upate maelezo zaidi"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Mtandaopepe na hali ya kusambaza mtandao"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ta/strings.xml b/packages/Tethering/res/values-ta/strings.xml deleted file mode 100644 index 4aba62d4ab46..000000000000 --- a/packages/Tethering/res/values-ta/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"டெதெரிங் அல்லது ஹாட்ஸ்பாட் இயங்குகிறது"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"அமைக்க, தட்டவும்."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"டெதெரிங் முடக்கப்பட்டுள்ளது"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"விவரங்களுக்கு உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ஹாட்ஸ்பாட் & டெதெரிங் நிலை"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-te/strings.xml b/packages/Tethering/res/values-te/strings.xml deleted file mode 100644 index 1f917913416f..000000000000 --- a/packages/Tethering/res/values-te/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"టెథరింగ్ లేదా హాట్స్పాట్ యాక్టివ్గా ఉంది"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"సెటప్ చేయడానికి ట్యాప్ చేయండి."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"టెథరింగ్ డిజేబుల్ చేయబడింది"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"వివరాల కోసం మీ అడ్మిన్ని సంప్రదించండి"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"హాట్స్పాట్ & టెథరింగ్ స్థితి"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-th/strings.xml b/packages/Tethering/res/values-th/strings.xml deleted file mode 100644 index 44171c0db82f..000000000000 --- a/packages/Tethering/res/values-th/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือหรือฮอตสปอตทำงานอยู่"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"แตะเพื่อตั้งค่า"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ปิดใช้การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือแล้ว"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"ติดต่อผู้ดูแลระบบเพื่อขอรายละเอียด"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"สถานะฮอตสปอตและการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-tl/strings.xml b/packages/Tethering/res/values-tl/strings.xml deleted file mode 100644 index 7347dd3e6254..000000000000 --- a/packages/Tethering/res/values-tl/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Aktibo ang pag-tether o hotspot"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"I-tap para i-set up."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Naka-disable ang pag-tether"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Makipag-ugnayan sa iyong admin para sa mga detalye"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status ng hotspot at pag-tether"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-tr/strings.xml b/packages/Tethering/res/values-tr/strings.xml deleted file mode 100644 index 32030f176574..000000000000 --- a/packages/Tethering/res/values-tr/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering veya hotspot etkin"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Ayarlamak için dokunun."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering devre dışı bırakıldı"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Ayrıntılı bilgi için yöneticinize başvurun"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot ve tethering durumu"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-uk/strings.xml b/packages/Tethering/res/values-uk/strings.xml deleted file mode 100644 index 1ca89b3f7813..000000000000 --- a/packages/Tethering/res/values-uk/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Модем чи точка доступу активні"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Натисніть, щоб налаштувати."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Використання телефона як модема вимкнено"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Щоб дізнатися більше, зв\'яжіться з адміністратором"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус точки доступу та модема"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-ur/strings.xml b/packages/Tethering/res/values-ur/strings.xml deleted file mode 100644 index d72c7d419577..000000000000 --- a/packages/Tethering/res/values-ur/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"ٹیدرنگ یا ہاٹ اسپاٹ فعال"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"ٹیدرنگ غیر فعال ہے"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"تفصیلات کے لئے اپنے منتظم سے رابطہ کریں"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ہاٹ اسپاٹ اور ٹیتھرنگ کا اسٹیٹس"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-uz/strings.xml b/packages/Tethering/res/values-uz/strings.xml deleted file mode 100644 index af3b2ebb3500..000000000000 --- a/packages/Tethering/res/values-uz/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Modem rejimi yoki hotspot yoniq"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Sozlash uchun bosing."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Modem rejimi faolsizlantirildi"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Tafsilotlari uchun administratoringizga murojaat qiling"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot va modem rejimi holati"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-vi/strings.xml b/packages/Tethering/res/values-vi/strings.xml deleted file mode 100644 index 21a0735922c3..000000000000 --- a/packages/Tethering/res/values-vi/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Tính năng chia sẻ Internet hoặc điểm phát sóng đang hoạt động"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Hãy nhấn để thiết lập."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Đã tắt tính năng chia sẻ Internet"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hãy liên hệ với quản trị viên của bạn để biết chi tiết"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Trạng thái điểm phát sóng và chia sẻ Internet"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-zh-rCN/strings.xml b/packages/Tethering/res/values-zh-rCN/strings.xml deleted file mode 100644 index 98e3b4b46fdb..000000000000 --- a/packages/Tethering/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"网络共享或热点已启用"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"点按即可设置。"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"网络共享已停用"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"如需了解详情,请与您的管理员联系"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"热点和网络共享状态"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-zh-rHK/strings.xml b/packages/Tethering/res/values-zh-rHK/strings.xml deleted file mode 100644 index 9cafd42dd43f..000000000000 --- a/packages/Tethering/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"網絡共享或熱點已啟用"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"輕按即可設定。"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"網絡共享已停用"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"請聯絡您的管理員以瞭解詳情"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"熱點和網絡共享狀態"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml deleted file mode 100644 index 9a117bbca43f..000000000000 --- a/packages/Tethering/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="3146694234398202601">"網路共用或無線基地台已啟用"</string> - <string name="tethered_notification_message" msgid="2113628520792055377">"輕觸即可進行設定。"</string> - <string name="disable_tether_notification_title" msgid="7526977944111313195">"數據連線已停用"</string> - <string name="disable_tether_notification_message" msgid="2913366428516852495">"詳情請洽你的管理員"</string> -</resources> diff --git a/packages/Tethering/res/values-zu/strings.xml b/packages/Tethering/res/values-zu/strings.xml deleted file mode 100644 index f210f8726ee5..000000000000 --- a/packages/Tethering/res/values-zu/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"Ukusebenzisa njengemodemu noma i-hotspot ephathekayo kuvuliwe"</string> - <string name="tethered_notification_message" msgid="64800879503420696">"Thepha ukuze usethe."</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"Ukusebenzisa ifoni njengemodemu kukhutshaziwe"</string> - <string name="disable_tether_notification_message" msgid="6717523799293901476">"Xhumana nomphathi wakho ukuze uthole imininingwane"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"I-Hotspot nesimo sokusebenzisa ifoni njengemodemu"</string> - <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> - <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> - <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> - <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string> - <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string> -</resources> diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml deleted file mode 100644 index 5f8d2997197f..000000000000 --- a/packages/Tethering/res/values/config.xml +++ /dev/null @@ -1,194 +0,0 @@ -<?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. ---> -<resources> - <!-- - OEMs that wish to change the below settings must do so via a runtime resource overlay package - and *NOT* by changing this file. This file is part of the tethering mainline module. - TODO: define two resources for each config item: a default_* resource and a config_* resource, - config_* is empty by default but may be overridden by RROs. - --> - <!-- List of regexpressions describing the interface (if any) that represent tetherable - USB interfaces. If the device doesn't want to support tethering over USB this should - be empty. An example would be "usb.*" --> - <string-array translatable="false" name="config_tether_usb_regexs"> - <item>"usb\\d"</item> - <item>"rndis\\d"</item> - </string-array> - - <!-- List of regexpressions describing the interface (if any) that represent tetherable - NCM interfaces. If the device doesn't want to support tethering over NCM this should - be empty. --> - <string-array translatable="false" name="config_tether_ncm_regexs"> - </string-array> - - <!-- List of regexpressions describing the interface (if any) that represent tetherable - Wifi interfaces. If the device doesn't want to support tethering over Wifi this - should be empty. An example would be "softap.*" --> - <string-array translatable="false" name="config_tether_wifi_regexs"> - <item>"wlan\\d"</item> - <item>"softap\\d"</item> - </string-array> - - <!-- List of regexpressions describing the interface (if any) that represent tetherable - WiGig interfaces. If the device doesn't want to support tethering over WiGig this - should be empty. An example would be "wigig\\d" --> - <string-array translatable="false" name="config_tether_wigig_regexs"> - <item>"wigig\\d"</item> - </string-array> - - <!-- List of regexpressions describing the interface (if any) that represent tetherable - Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this - should be empty. An example would be "p2p-p2p\\d-.*" --> - <string-array translatable="false" name="config_tether_wifi_p2p_regexs"> - <item>"p2p-p2p\\d-.*"</item> - <item>"p2p\\d"</item> - </string-array> - - <!-- List of regexpressions describing the interface (if any) that represent tetherable - bluetooth interfaces. If the device doesn't want to support tethering over bluetooth this - should be empty. --> - <string-array translatable="false" name="config_tether_bluetooth_regexs"> - <item>"bt-pan"</item> - </string-array> - - <!-- Use the BPF offload for tethering when the kernel has support. True by default. - If the device doesn't want to support tether BPF offload, this should be false. - Note that this setting could be overridden by device config. - --> - <bool translatable="false" name="config_tether_enable_bpf_offload">true</bool> - - <!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. --> - <bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool> - - <!-- Use legacy wifi p2p dedicated address instead of randomize address. --> - <bool translatable="false" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip">false</bool> - - <!-- Dhcp range (min, max) to use for tethering purposes --> - <string-array translatable="false" name="config_tether_dhcp_range"> - </string-array> - - <!-- Used to config periodic polls tether offload stats from tethering offload HAL to make the - data warnings work. 5000(ms) by default. If the device doesn't want to poll tether - offload stats, this should be -1. Note that this setting could be override by - runtime resource overlays. - --> - <integer translatable="false" name="config_tether_offload_poll_interval">5000</integer> - - <!-- Array of ConnectivityManager.TYPE_{BLUETOOTH, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI, - WIFI} values allowable for tethering. - - Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or - [1,7,0] for TYPE_WIFI, TYPE_BLUETOOTH, and TYPE_MOBILE. - - This list is also modified by code within the framework, including: - - - TYPE_ETHERNET (9) is prepended to this list, and - - - the return value of TelephonyManager.isTetheringApnRequired() - determines how the array is further modified: - - * TRUE (DUN REQUIRED). - TYPE_MOBILE is removed (if present). - TYPE_MOBILE_HIPRI is removed (if present). - TYPE_MOBILE_DUN is appended (if not already present). - - * FALSE (DUN NOT REQUIRED). - TYPE_MOBILE_DUN is removed (if present). - If both of TYPE_MOBILE{,_HIPRI} are not present: - TYPE_MOBILE is appended. - TYPE_MOBILE_HIPRI is appended. - - For other changes applied to this list, now and in the future, see - com.android.networkstack.tethering.TetheringConfiguration. - - Note also: the order of this is important. The first upstream type - for which a satisfying network exists is used. - --> - <integer-array translatable="false" name="config_tether_upstream_types"> - </integer-array> - - <!-- When true, the tethering upstream network follows the current default - Internet network (except when the current default network is mobile, - in which case a DUN network will be used if required). - - When true, overrides the config_tether_upstream_types setting above. - --> - <bool translatable="false" name="config_tether_upstream_automatic">true</bool> - - - <!-- If the mobile hotspot feature requires provisioning, a package name and class name - can be provided to launch a supported application that provisions the devices. - EntitlementManager will send an intent to Settings with the specified package name and - class name in extras to launch provision app. - TODO: note what extras here. - - See EntitlementManager#runUiTetherProvisioning and - packages/apps/Settings/src/com/android/settings/network/TetherProvisioningActivity.java - for more details. - - For ui-less/periodic recheck support see config_mobile_hotspot_provision_app_no_ui - --> - <!-- The first element is the package name and the second element is the class name - of the provisioning app --> - <string-array translatable="false" name="config_mobile_hotspot_provision_app"> - <!-- - <item>com.example.provisioning</item> - <item>com.example.provisioning.Activity</item> - --> - </string-array> - - <!-- If the mobile hotspot feature requires provisioning, an action can be provided - that will be broadcast in non-ui cases for checking the provisioning status. - EntitlementManager will pass the specified name to Settings and Settings would - launch provisioning app by sending an intent with the package name. - - A second broadcast, action defined by config_mobile_hotspot_provision_response, - will be sent back to notify if provisioning succeeded or not. The response will - match that of the activity in config_mobile_hotspot_provision_app, but instead - contained within the int extra "EntitlementResult". - TODO: provide the system api for "EntitlementResult" extra and note it here. - - See EntitlementManager#runSilentTetherProvisioning and - packages/apps/Settings/src/com/android/settings/wifi/tether/TetherService.java for more - details. - --> - <string translatable="false" name="config_mobile_hotspot_provision_app_no_ui"></string> - - <!-- Sent in response to a provisioning check. The caller must hold the - permission android.permission.TETHER_PRIVILEGED for Settings to - receive this response. - - See config_mobile_hotspot_provision_response - --> - <string translatable="false" name="config_mobile_hotspot_provision_response"></string> - - <!-- Number of hours between each background provisioning call --> - <integer translatable="false" name="config_mobile_hotspot_provision_check_period">24</integer> - - <!-- ComponentName of the service used to run no ui tether provisioning. --> - <string translatable="false" name="config_wifi_tether_enable">com.android.settings/.wifi.tether.TetherService</string> - - <!-- No upstream notification is shown when there is a downstream but no upstream that is able - to do the tethering. --> - <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to - "-1" for disable this feature. --> - <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer> - - <!-- Cellular roaming notification is shown when upstream is cellular network and in roaming - state. --> - <!-- Config for showing upstream roaming notification. --> - <bool name="config_upstream_roaming_notification">false</bool> -</resources> diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml deleted file mode 100644 index 0ee7a992ee20..000000000000 --- a/packages/Tethering/res/values/overlayable.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?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. ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> - <overlayable name="TetheringConfig"> - <policy type="product|system|vendor"> - <!-- Params from config.xml that can be overlaid --> - <item type="array" name="config_tether_usb_regexs"/> - <item type="array" name="config_tether_ncm_regexs" /> - <item type="array" name="config_tether_wifi_regexs"/> - <item type="array" name="config_tether_wigig_regexs"/> - <item type="array" name="config_tether_wifi_p2p_regexs"/> - <item type="array" name="config_tether_bluetooth_regexs"/> - <item type="array" name="config_tether_dhcp_range"/> - <!-- Use the BPF offload for tethering when the kernel has support. True by default. - If the device doesn't want to support tether BPF offload, this should be false. - Note that this setting could be overridden by device config. - --> - <item type="bool" name="config_tether_enable_bpf_offload"/> - <item type="bool" name="config_tether_enable_legacy_dhcp_server"/> - <item type="bool" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip"/> - <item type="integer" name="config_tether_offload_poll_interval"/> - <item type="array" name="config_tether_upstream_types"/> - <item type="bool" name="config_tether_upstream_automatic"/> - <!-- Configuration values for tethering entitlement check --> - <item type="array" name="config_mobile_hotspot_provision_app"/> - <item type="string" name="config_mobile_hotspot_provision_app_no_ui"/> - <item type="string" name="config_mobile_hotspot_provision_response"/> - <item type="integer" name="config_mobile_hotspot_provision_check_period"/> - <item type="string" name="config_wifi_tether_enable"/> - <!-- Params from config.xml that can be overlaid --> - </policy> - </overlayable> -</resources> diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml deleted file mode 100644 index d63c7c5063cc..000000000000 --- a/packages/Tethering/res/values/strings.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?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. ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- Shown when the device is tethered --> - <!-- String for tethered notification title [CHAR LIMIT=200] --> - <string name="tethered_notification_title">Tethering or hotspot active</string> - <!-- String for tethered notification message [CHAR LIMIT=200] --> - <string name="tethered_notification_message">Tap to set up.</string> - - <!-- This notification is shown when tethering has been disabled on a user's device. - The device is managed by the user's employer. Tethering can't be turned on unless the - IT administrator allows it. The noun "admin" is another reference for "IT administrator." --> - <!-- String for tether disabling notification title [CHAR LIMIT=200] --> - <string name="disable_tether_notification_title">Tethering is disabled</string> - <!-- String for tether disabling notification message [CHAR LIMIT=200] --> - <string name="disable_tether_notification_message">Contact your admin for details</string> - - <!-- This string should be consistent with the "Hotspot & tethering" text in the "Network and - Internet" settings page. That is currently the tether_settings_title_all string. --> - <!-- String for tether notification channel name [CHAR LIMIT=200] --> - <string name="notification_channel_tethering_status">Hotspot & tethering status</string> - - <!-- String for no upstream notification title [CHAR LIMIT=200] --> - <string name="no_upstream_notification_title"></string> - <!-- String for no upstream notification message [CHAR LIMIT=200] --> - <string name="no_upstream_notification_message"></string> - <!-- String for no upstream notification disable button [CHAR LIMIT=200] --> - <string name="no_upstream_notification_disable_button"></string> - - <!-- String for cellular roaming notification title [CHAR LIMIT=200] --> - <string name="upstream_roaming_notification_title"></string> - <!-- String for cellular roaming notification message [CHAR LIMIT=500] --> - <string name="upstream_roaming_notification_message"></string> -</resources> diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java deleted file mode 100644 index 9fda1257b4c9..000000000000 --- a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.dhcp; - -/** - * Convenience wrapper around IDhcpServerCallbacks.Stub that implements getInterfaceVersion(). - * @hide - */ -public abstract class DhcpServerCallbacks extends IDhcpServerCallbacks.Stub { - /** - * Get the version of the aidl interface implemented by the callbacks. - */ - @Override - public int getInterfaceVersion() { - return IDhcpServerCallbacks.VERSION; - } - - @Override - public String getInterfaceHash() { - return IDhcpServerCallbacks.HASH; - } -} diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java deleted file mode 100644 index aaaec17bf922..000000000000 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.dhcp; - -import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; - -import android.net.LinkAddress; -import android.util.ArraySet; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.net.Inet4Address; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; - -/** - * Subclass of {@link DhcpServingParamsParcel} with additional utility methods for building. - * - * <p>This utility class does not check for validity of the parameters: invalid parameters are - * reported by the receiving module when unparceling the parcel. - * - * @see DhcpServingParams - * @hide - */ -public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { - public static final int MTU_UNSET = 0; - - /** - * Set the server address and served prefix for the DHCP server. - * - * <p>This parameter is required. - */ - public DhcpServingParamsParcelExt setServerAddr(@NonNull LinkAddress serverAddr) { - this.serverAddr = inet4AddressToIntHTH((Inet4Address) serverAddr.getAddress()); - this.serverAddrPrefixLength = serverAddr.getPrefixLength(); - return this; - } - - /** - * Set the default routers to be advertised to DHCP clients. - * - * <p>Each router must be inside the served prefix. This may be an empty set, but it must - * always be set explicitly. - */ - public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) { - this.defaultRouters = toIntArray(defaultRouters); - return this; - } - - /** - * Set the default routers to be advertised to DHCP clients. - * - * <p>Each router must be inside the served prefix. This may be an empty list of routers, - * but it must always be set explicitly. - */ - public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) { - return setDefaultRouters(newArraySet(defaultRouters)); - } - - /** - * Convenience method to build the parameters with no default router. - * - * <p>Equivalent to calling {@link #setDefaultRouters(Inet4Address...)} with no address. - */ - public DhcpServingParamsParcelExt setNoDefaultRouter() { - return setDefaultRouters(); - } - - /** - * Set the DNS servers to be advertised to DHCP clients. - * - * <p>This may be an empty set, but it must always be set explicitly. - */ - public DhcpServingParamsParcelExt setDnsServers(@NonNull Set<Inet4Address> dnsServers) { - this.dnsServers = toIntArray(dnsServers); - return this; - } - - /** - * Set the DNS servers to be advertised to DHCP clients. - * - * <p>This may be an empty list of servers, but it must always be set explicitly. - */ - public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) { - return setDnsServers(newArraySet(dnsServers)); - } - - /** - * Convenience method to build the parameters with no DNS server. - * - * <p>Equivalent to calling {@link #setDnsServers(Inet4Address...)} with no address. - */ - public DhcpServingParamsParcelExt setNoDnsServer() { - return setDnsServers(); - } - - /** - * Set excluded addresses that the DHCP server is not allowed to assign to clients. - * - * <p>This parameter is optional. DNS servers and default routers are always excluded - * and do not need to be set here. - */ - public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) { - this.excludedAddrs = toIntArray(excludedAddrs); - return this; - } - - /** - * Set excluded addresses that the DHCP server is not allowed to assign to clients. - * - * <p>This parameter is optional. DNS servers and default routers are always excluded - * and do not need to be set here. - */ - public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) { - return setExcludedAddrs(newArraySet(excludedAddrs)); - } - - /** - * Set the lease time for leases assigned by the DHCP server. - * - * <p>This parameter is required. - */ - public DhcpServingParamsParcelExt setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) { - this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs; - return this; - } - - /** - * Set the link MTU to be advertised to DHCP clients. - * - * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter - * is optional and defaults to {@link #MTU_UNSET}. - */ - public DhcpServingParamsParcelExt setLinkMtu(int linkMtu) { - this.linkMtu = linkMtu; - return this; - } - - /** - * Set whether the DHCP server should send the ANDROID_METERED vendor-specific option. - * - * <p>If not set, the default value is false. - */ - public DhcpServingParamsParcelExt setMetered(boolean metered) { - this.metered = metered; - return this; - } - - /** - * Set the client address to tell DHCP server only offer this address. - * The client's prefix length is the same as server's. - * - * <p>If not set, the default value is null. - */ - public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) { - this.singleClientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr); - return this; - } - - /** - * Set whether the DHCP server should request a new prefix from IpServer when receiving - * DHCPDECLINE message in certain particular link (e.g. there is only one downstream USB - * tethering client). If it's false, process DHCPDECLINE message as RFC2131#4.3.3 suggests. - * - * <p>If not set, the default value is false. - */ - public DhcpServingParamsParcelExt setChangePrefixOnDecline(boolean changePrefixOnDecline) { - this.changePrefixOnDecline = changePrefixOnDecline; - return this; - } - - private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) { - int[] res = new int[addrs.size()]; - int i = 0; - for (Inet4Address addr : addrs) { - res[i] = inet4AddressToIntHTH(addr); - i++; - } - return res; - } - - private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) { - ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length); - Collections.addAll(addrSet, addrs); - return addrSet; - } -} diff --git a/packages/Tethering/src/android/net/ip/DadProxy.java b/packages/Tethering/src/android/net/ip/DadProxy.java deleted file mode 100644 index e2976b78908c..000000000000 --- a/packages/Tethering/src/android/net/ip/DadProxy.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import android.net.util.InterfaceParams; -import android.os.Handler; - -import androidx.annotation.VisibleForTesting; - -/** - * Basic Duplicate address detection proxy. - * - * @hide - */ -public class DadProxy { - private static final String TAG = DadProxy.class.getSimpleName(); - - @VisibleForTesting - public static NeighborPacketForwarder naForwarder; - public static NeighborPacketForwarder nsForwarder; - - public DadProxy(Handler h, InterfaceParams tetheredIface) { - naForwarder = new NeighborPacketForwarder(h, tetheredIface, - NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT); - nsForwarder = new NeighborPacketForwarder(h, tetheredIface, - NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION); - } - - /** Stop NS/NA Forwarders. */ - public void stop() { - naForwarder.stop(); - nsForwarder.stop(); - } - - /** Set upstream iface on both forwarders. */ - public void setUpstreamIface(InterfaceParams upstreamIface) { - naForwarder.setUpstreamIface(upstreamIface); - nsForwarder.setUpstreamIface(upstreamIface); - } -} diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java deleted file mode 100644 index 52d59fcdc19b..000000000000 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ /dev/null @@ -1,1422 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static android.net.RouteInfo.RTN_UNICAST; -import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration; -import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; -import static android.net.util.NetworkConstants.asByte; -import static android.net.util.PrefixUtils.asIpPrefix; -import static android.net.util.TetheringMessageBase.BASE_IPSERVER; -import static android.system.OsConstants.RT_SCOPE_UNIVERSE; - -import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; - -import android.net.INetd; -import android.net.INetworkStackStatusCallback; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.RouteInfo; -import android.net.TetheredClient; -import android.net.TetheringManager; -import android.net.TetheringRequestParcel; -import android.net.dhcp.DhcpLeaseParcelable; -import android.net.dhcp.DhcpServerCallbacks; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.DhcpServingParamsParcelExt; -import android.net.dhcp.IDhcpEventCallbacks; -import android.net.dhcp.IDhcpServer; -import android.net.ip.IpNeighborMonitor.NeighborEvent; -import android.net.ip.RouterAdvertisementDaemon.RaParams; -import android.net.shared.NetdUtils; -import android.net.shared.RouteUtils; -import android.net.util.InterfaceParams; -import android.net.util.InterfaceSet; -import android.net.util.PrefixUtils; -import android.net.util.SharedLog; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.util.Log; -import android.util.SparseArray; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.util.MessageUtils; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.networkstack.tethering.BpfCoordinator; -import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; -import com.android.networkstack.tethering.PrivateAddressCoordinator; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.NetworkInterface; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.Set; - -/** - * Provides the interface to IP-layer serving functionality for a given network - * interface, e.g. for tethering or "local-only hotspot" mode. - * - * @hide - */ -public class IpServer extends StateMachine { - public static final int STATE_UNAVAILABLE = 0; - public static final int STATE_AVAILABLE = 1; - public static final int STATE_TETHERED = 2; - public static final int STATE_LOCAL_ONLY = 3; - - /** Get string name of |state|.*/ - public static String getStateString(int state) { - switch (state) { - case STATE_UNAVAILABLE: return "UNAVAILABLE"; - case STATE_AVAILABLE: return "AVAILABLE"; - case STATE_TETHERED: return "TETHERED"; - case STATE_LOCAL_ONLY: return "LOCAL_ONLY"; - } - return "UNKNOWN: " + state; - } - - private static final byte DOUG_ADAMS = (byte) 42; - - // TODO: have PanService use some visible version of this constant - private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1/24"; - - // TODO: have this configurable - private static final int DHCP_LEASE_TIME_SECS = 3600; - - private static final MacAddress NULL_MAC_ADDRESS = MacAddress.fromString("00:00:00:00:00:00"); - - private static final String TAG = "IpServer"; - private static final boolean DBG = false; - private static final boolean VDBG = false; - private static final Class[] sMessageClasses = { - IpServer.class - }; - private static final SparseArray<String> sMagicDecoderRing = - MessageUtils.findMessageNames(sMessageClasses); - - /** IpServer callback. */ - public static class Callback { - /** - * Notify that |who| has changed its tethering state. - * - * @param who the calling instance of IpServer - * @param state one of STATE_* - * @param lastError one of TetheringManager.TETHER_ERROR_* - */ - public void updateInterfaceState(IpServer who, int state, int lastError) { } - - /** - * Notify that |who| has new LinkProperties. - * - * @param who the calling instance of IpServer - * @param newLp the new LinkProperties to report - */ - public void updateLinkProperties(IpServer who, LinkProperties newLp) { } - - /** - * Notify that the DHCP leases changed in one of the IpServers. - */ - public void dhcpLeasesChanged() { } - - /** - * Request Tethering change. - * - * @param tetheringType the downstream type of this IpServer. - * @param enabled enable or disable tethering. - */ - public void requestEnableTethering(int tetheringType, boolean enabled) { } - } - - /** Capture IpServer dependencies, for injection. */ - public abstract static class Dependencies { - /** - * Create a DadProxy instance to be used by IpServer. - * To support multiple tethered interfaces concurrently DAD Proxy - * needs to be supported per IpServer instead of per upstream. - */ - public DadProxy getDadProxy(Handler handler, InterfaceParams ifParams) { - return new DadProxy(handler, ifParams); - } - - /** Create an IpNeighborMonitor to be used by this IpServer */ - public IpNeighborMonitor getIpNeighborMonitor(Handler handler, SharedLog log, - IpNeighborMonitor.NeighborEventConsumer consumer) { - return new IpNeighborMonitor(handler, log, consumer); - } - - /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/ - public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) { - return new RouterAdvertisementDaemon(ifParams); - } - - /** Get |ifName|'s interface information.*/ - public InterfaceParams getInterfaceParams(String ifName) { - return InterfaceParams.getByName(ifName); - } - - /** Get |ifName|'s interface index. */ - public int getIfindex(String ifName) { - try { - return NetworkInterface.getByName(ifName).getIndex(); - } catch (IOException | NullPointerException e) { - Log.e(TAG, "Can't determine interface index for interface " + ifName); - return 0; - } - } - - /** Create a DhcpServer instance to be used by IpServer. */ - public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, - DhcpServerCallbacks cb); - } - - // request from the user that it wants to tether - public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1; - // request from the user that it wants to untether - public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2; - // notification that this interface is down - public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3; - // notification from the {@link Tethering.TetherMainSM} that it had trouble enabling IP - // Forwarding - public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4; - // notification from the {@link Tethering.TetherMainSM} SM that it had trouble disabling IP - // Forwarding - public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5; - // notification from the {@link Tethering.TetherMainSM} SM that it had trouble starting - // tethering - public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6; - // notification from the {@link Tethering.TetherMainSM} that it had trouble stopping tethering - public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7; - // notification from the {@link Tethering.TetherMainSM} that it had trouble setting the DNS - // forwarders - public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8; - // the upstream connection has changed - public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9; - // new IPv6 tethering parameters need to be processed - public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10; - // new neighbor cache entry on our interface - public static final int CMD_NEIGHBOR_EVENT = BASE_IPSERVER + 11; - // request from DHCP server that it wants to have a new prefix - public static final int CMD_NEW_PREFIX_REQUEST = BASE_IPSERVER + 12; - // request from PrivateAddressCoordinator to restart tethering. - public static final int CMD_NOTIFY_PREFIX_CONFLICT = BASE_IPSERVER + 13; - - private final State mInitialState; - private final State mLocalHotspotState; - private final State mTetheredState; - private final State mUnavailableState; - private final State mWaitingForRestartState; - - private final SharedLog mLog; - private final INetd mNetd; - @NonNull - private final BpfCoordinator mBpfCoordinator; - private final Callback mCallback; - private final InterfaceController mInterfaceCtrl; - private final PrivateAddressCoordinator mPrivateAddressCoordinator; - - private final String mIfaceName; - private final int mInterfaceType; - private final LinkProperties mLinkProperties; - private final boolean mUsingLegacyDhcp; - private final boolean mUsingBpfOffload; - - private final Dependencies mDeps; - - private int mLastError; - private int mServingMode; - private InterfaceSet mUpstreamIfaceSet; // may change over time - private InterfaceParams mInterfaceParams; - // TODO: De-duplicate this with mLinkProperties above. Currently, these link - // properties are those selected by the IPv6TetheringCoordinator and relayed - // to us. By comparison, mLinkProperties contains the addresses and directly - // connected routes that have been formed from these properties iff. we have - // succeeded in configuring them and are able to announce them within Router - // Advertisements (otherwise, we do not add them to mLinkProperties at all). - private LinkProperties mLastIPv6LinkProperties; - private RouterAdvertisementDaemon mRaDaemon; - private DadProxy mDadProxy; - - // To be accessed only on the handler thread - private int mDhcpServerStartIndex = 0; - private IDhcpServer mDhcpServer; - private RaParams mLastRaParams; - - private LinkAddress mStaticIpv4ServerAddr; - private LinkAddress mStaticIpv4ClientAddr; - - @NonNull - private List<TetheredClient> mDhcpLeases = Collections.emptyList(); - - private int mLastIPv6UpstreamIfindex = 0; - - private class MyNeighborEventConsumer implements IpNeighborMonitor.NeighborEventConsumer { - public void accept(NeighborEvent e) { - sendMessage(CMD_NEIGHBOR_EVENT, e); - } - } - - private final IpNeighborMonitor mIpNeighborMonitor; - - private LinkAddress mIpv4Address; - - // TODO: Add a dependency object to pass the data members or variables from the tethering - // object. It helps to reduce the arguments of the constructor. - public IpServer( - String ifaceName, Looper looper, int interfaceType, SharedLog log, - INetd netd, @NonNull BpfCoordinator coordinator, Callback callback, - boolean usingLegacyDhcp, boolean usingBpfOffload, - PrivateAddressCoordinator addressCoordinator, Dependencies deps) { - super(ifaceName, looper); - mLog = log.forSubComponent(ifaceName); - mNetd = netd; - mBpfCoordinator = coordinator; - mCallback = callback; - mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog); - mIfaceName = ifaceName; - mInterfaceType = interfaceType; - mLinkProperties = new LinkProperties(); - mUsingLegacyDhcp = usingLegacyDhcp; - mUsingBpfOffload = usingBpfOffload; - mPrivateAddressCoordinator = addressCoordinator; - mDeps = deps; - resetLinkProperties(); - mLastError = TetheringManager.TETHER_ERROR_NO_ERROR; - mServingMode = STATE_AVAILABLE; - - mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog, - new MyNeighborEventConsumer()); - - // IP neighbor monitor monitors the neighbor events for adding/removing offload - // forwarding rules per client. If BPF offload is not supported, don't start listening - // for neighbor events. See updateIpv6ForwardingRules, addIpv6ForwardingRule, - // removeIpv6ForwardingRule. - if (mUsingBpfOffload && !mIpNeighborMonitor.start()) { - mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName); - } - - mInitialState = new InitialState(); - mLocalHotspotState = new LocalHotspotState(); - mTetheredState = new TetheredState(); - mUnavailableState = new UnavailableState(); - mWaitingForRestartState = new WaitingForRestartState(); - addState(mInitialState); - addState(mLocalHotspotState); - addState(mTetheredState); - addState(mWaitingForRestartState, mTetheredState); - addState(mUnavailableState); - - setInitialState(mInitialState); - } - - /** Interface name which IpServer served.*/ - public String interfaceName() { - return mIfaceName; - } - - /** - * Tethering downstream type. It would be one of TetheringManager#TETHERING_*. - */ - public int interfaceType() { - return mInterfaceType; - } - - /** Last error from this IpServer. */ - public int lastError() { - return mLastError; - } - - /** Serving mode is the current state of IpServer state machine. */ - public int servingMode() { - return mServingMode; - } - - /** The properties of the network link which IpServer is serving. */ - public LinkProperties linkProperties() { - return new LinkProperties(mLinkProperties); - } - - /** The address which IpServer is using. */ - public LinkAddress getAddress() { - return mIpv4Address; - } - - /** - * Get the latest list of DHCP leases that was reported. Must be called on the IpServer looper - * thread. - */ - public List<TetheredClient> getAllLeases() { - return Collections.unmodifiableList(mDhcpLeases); - } - - /** Stop this IpServer. After this is called this IpServer should not be used any more. */ - public void stop() { - sendMessage(CMD_INTERFACE_DOWN); - } - - /** - * Tethering is canceled. IpServer state machine will be available and wait for - * next tethering request. - */ - public void unwanted() { - sendMessage(CMD_TETHER_UNREQUESTED); - } - - /** Internals. */ - - private boolean startIPv4() { - return configureIPv4(true); - } - - /** - * Convenience wrapper around INetworkStackStatusCallback to run callbacks on the IpServer - * handler. - * - * <p>Different instances of this class can be created for each call to IDhcpServer methods, - * with different implementations of the callback, to differentiate handling of success/error in - * each call. - */ - private abstract class OnHandlerStatusCallback extends INetworkStackStatusCallback.Stub { - @Override - public void onStatusAvailable(int statusCode) { - getHandler().post(() -> callback(statusCode)); - } - - public abstract void callback(int statusCode); - - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() { - return this.HASH; - } - } - - private class DhcpServerCallbacksImpl extends DhcpServerCallbacks { - private final int mStartIndex; - - private DhcpServerCallbacksImpl(int startIndex) { - mStartIndex = startIndex; - } - - @Override - public void onDhcpServerCreated(int statusCode, IDhcpServer server) throws RemoteException { - getHandler().post(() -> { - // We are on the handler thread: mDhcpServerStartIndex can be read safely. - if (mStartIndex != mDhcpServerStartIndex) { - // This start request is obsolete. Explicitly stop the DHCP server to shut - // down its thread. When the |server| binder token goes out of scope, the - // garbage collector will finalize it, which causes the network stack process - // garbage collector to collect the server itself. - try { - server.stop(null); - } catch (RemoteException e) { } - return; - } - - if (statusCode != STATUS_SUCCESS) { - mLog.e("Error obtaining DHCP server: " + statusCode); - handleError(); - return; - } - - mDhcpServer = server; - try { - mDhcpServer.startWithCallbacks(new OnHandlerStatusCallback() { - @Override - public void callback(int startStatusCode) { - if (startStatusCode != STATUS_SUCCESS) { - mLog.e("Error starting DHCP server: " + startStatusCode); - handleError(); - } - } - }, new DhcpEventCallback()); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - }); - } - - private void handleError() { - mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; - transitionTo(mInitialState); - } - } - - private class DhcpEventCallback extends IDhcpEventCallbacks.Stub { - @Override - public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) { - final ArrayList<TetheredClient> leases = new ArrayList<>(); - for (DhcpLeaseParcelable lease : leaseParcelables) { - final LinkAddress address = new LinkAddress( - intToInet4AddressHTH(lease.netAddr), lease.prefixLength, - 0 /* flags */, RT_SCOPE_UNIVERSE /* as per RFC6724#3.2 */, - lease.expTime /* deprecationTime */, lease.expTime /* expirationTime */); - - final MacAddress macAddress; - try { - macAddress = MacAddress.fromBytes(lease.hwAddr); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Invalid address received from DhcpServer: " - + Arrays.toString(lease.hwAddr)); - return; - } - - final TetheredClient.AddressInfo addressInfo = new TetheredClient.AddressInfo( - address, lease.hostname); - leases.add(new TetheredClient( - macAddress, - Collections.singletonList(addressInfo), - mInterfaceType)); - } - - getHandler().post(() -> { - mDhcpLeases = leases; - mCallback.dhcpLeasesChanged(); - }); - } - - @Override - public void onNewPrefixRequest(@NonNull final IpPrefix currentPrefix) { - Objects.requireNonNull(currentPrefix); - sendMessage(CMD_NEW_PREFIX_REQUEST, currentPrefix); - } - - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() throws RemoteException { - return this.HASH; - } - } - - private RouteInfo getDirectConnectedRoute(@NonNull final LinkAddress ipv4Address) { - Objects.requireNonNull(ipv4Address); - return new RouteInfo(PrefixUtils.asIpPrefix(ipv4Address), null, mIfaceName, RTN_UNICAST); - } - - private DhcpServingParamsParcel makeServingParams(@NonNull final Inet4Address defaultRouter, - @NonNull final Inet4Address dnsServer, @NonNull LinkAddress serverAddr, - @Nullable Inet4Address clientAddr) { - final boolean changePrefixOnDecline = - (mInterfaceType == TetheringManager.TETHERING_NCM && clientAddr == null); - return new DhcpServingParamsParcelExt() - .setDefaultRouters(defaultRouter) - .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) - .setDnsServers(dnsServer) - .setServerAddr(serverAddr) - .setMetered(true) - .setSingleClientAddr(clientAddr) - .setChangePrefixOnDecline(changePrefixOnDecline); - // TODO: also advertise link MTU - } - - private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) { - if (mUsingLegacyDhcp) { - return true; - } - - final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress(); - final Inet4Address clientAddr = clientLinkAddr == null ? null : - (Inet4Address) clientLinkAddr.getAddress(); - - final DhcpServingParamsParcel params = makeServingParams(addr /* defaultRouter */, - addr /* dnsServer */, serverLinkAddr, clientAddr); - mDhcpServerStartIndex++; - mDeps.makeDhcpServer( - mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex)); - return true; - } - - private void stopDhcp() { - // Make all previous start requests obsolete so servers are not started later - mDhcpServerStartIndex++; - - if (mDhcpServer != null) { - try { - mDhcpServer.stop(new OnHandlerStatusCallback() { - @Override - public void callback(int statusCode) { - if (statusCode != STATUS_SUCCESS) { - mLog.e("Error stopping DHCP server: " + statusCode); - mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; - // Not much more we can do here - } - mDhcpLeases.clear(); - getHandler().post(mCallback::dhcpLeasesChanged); - } - }); - mDhcpServer = null; - } catch (RemoteException e) { - mLog.e("Error stopping DHCP server", e); - // Not much more we can do here - } - } - } - - private boolean configureDhcp(boolean enable, final LinkAddress serverAddr, - final LinkAddress clientAddr) { - if (enable) { - return startDhcp(serverAddr, clientAddr); - } else { - stopDhcp(); - return true; - } - } - - private void stopIPv4() { - configureIPv4(false); - // NOTE: All of configureIPv4() will be refactored out of existence - // into calls to InterfaceController, shared with startIPv4(). - mInterfaceCtrl.clearIPv4Address(); - mPrivateAddressCoordinator.releaseDownstream(this); - mIpv4Address = null; - mStaticIpv4ServerAddr = null; - mStaticIpv4ClientAddr = null; - } - - private boolean configureIPv4(boolean enabled) { - if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); - - if (enabled) { - mIpv4Address = requestIpv4Address(true /* useLastAddress */); - } - - if (mIpv4Address == null) { - mLog.e("No available ipv4 address"); - return false; - } - - if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) { - // BT configures the interface elsewhere: only start DHCP. - // TODO: make all tethering types behave the same way, and delete the bluetooth - // code that calls into NetworkManagementService directly. - return configureDhcp(enabled, mIpv4Address, null /* clientAddress */); - } - - final IpPrefix ipv4Prefix = asIpPrefix(mIpv4Address); - - final Boolean setIfaceUp; - if (mInterfaceType == TetheringManager.TETHERING_WIFI - || mInterfaceType == TetheringManager.TETHERING_WIFI_P2P - || mInterfaceType == TetheringManager.TETHERING_ETHERNET - || mInterfaceType == TetheringManager.TETHERING_WIGIG) { - // The WiFi and Ethernet stack has ownership of the interface up/down state. - // It is unclear whether the Bluetooth or USB stacks will manage their own - // state. - setIfaceUp = null; - } else { - setIfaceUp = enabled; - } - if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) { - mLog.e("Error configuring interface"); - if (!enabled) stopDhcp(); - return false; - } - - if (enabled) { - mLinkProperties.addLinkAddress(mIpv4Address); - mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address)); - } else { - mLinkProperties.removeLinkAddress(mIpv4Address); - mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address)); - } - return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr); - } - - private LinkAddress requestIpv4Address(final boolean useLastAddress) { - if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr; - - if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) { - return new LinkAddress(BLUETOOTH_IFACE_ADDR); - } - - return mPrivateAddressCoordinator.requestDownstreamAddress(this, useLastAddress); - } - - private boolean startIPv6() { - mInterfaceParams = mDeps.getInterfaceParams(mIfaceName); - if (mInterfaceParams == null) { - mLog.e("Failed to find InterfaceParams"); - stopIPv6(); - return false; - } - - mRaDaemon = mDeps.getRouterAdvertisementDaemon(mInterfaceParams); - if (!mRaDaemon.start()) { - stopIPv6(); - return false; - } - - // TODO: use ShimUtils instead of explicitly checking the version here. - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R || "S".equals(Build.VERSION.CODENAME) - || "T".equals(Build.VERSION.CODENAME)) { - // DAD Proxy starts forwarding packets after IPv6 upstream is present. - mDadProxy = mDeps.getDadProxy(getHandler(), mInterfaceParams); - } - - return true; - } - - private void stopIPv6() { - mInterfaceParams = null; - setRaParams(null); - - if (mRaDaemon != null) { - mRaDaemon.stop(); - mRaDaemon = null; - } - - if (mDadProxy != null) { - mDadProxy.stop(); - mDadProxy = null; - } - } - - // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only - // LinkProperties. These have extraneous data filtered out and only the - // necessary prefixes included (per its prefix distribution policy). - // - // TODO: Evaluate using a data structure than is more directly suited to - // communicating only the relevant information. - private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) { - if (mRaDaemon == null) return; - - // Avoid unnecessary work on spurious updates. - if (Objects.equals(mLastIPv6LinkProperties, v6only)) { - return; - } - - RaParams params = null; - String upstreamIface = null; - InterfaceParams upstreamIfaceParams = null; - int upstreamIfIndex = 0; - - if (v6only != null) { - upstreamIface = v6only.getInterfaceName(); - upstreamIfaceParams = mDeps.getInterfaceParams(upstreamIface); - if (upstreamIfaceParams != null) { - upstreamIfIndex = upstreamIfaceParams.index; - } - params = new RaParams(); - params.mtu = v6only.getMtu(); - params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); - - if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); - - for (LinkAddress linkAddr : v6only.getLinkAddresses()) { - if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; - - final IpPrefix prefix = new IpPrefix( - linkAddr.getAddress(), linkAddr.getPrefixLength()); - params.prefixes.add(prefix); - - final Inet6Address dnsServer = getLocalDnsIpFor(prefix); - if (dnsServer != null) { - params.dnses.add(dnsServer); - } - } - - // Add upstream index to name mapping for the tether stats usage in the coordinator. - // Although this mapping could be added by both class Tethering and IpServer, adding - // mapping from IpServer guarantees that the mapping is added before the adding - // forwarding rules. That is because there are different state machines in both - // classes. It is hard to guarantee the link property update order between multiple - // state machines. - mBpfCoordinator.addUpstreamNameToLookupTable(upstreamIfIndex, upstreamIface); - } - - // If v6only is null, we pass in null to setRaParams(), which handles - // deprecation of any existing RA data. - - setRaParams(params); - mLastIPv6LinkProperties = v6only; - - updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, upstreamIfIndex, null); - mLastIPv6UpstreamIfindex = upstreamIfIndex; - if (mDadProxy != null) { - mDadProxy.setUpstreamIface(upstreamIfaceParams); - } - } - - private void removeRoutesFromLocalNetwork(@NonNull final List<RouteInfo> toBeRemoved) { - final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork( - mNetd, toBeRemoved); - if (removalFailures > 0) { - mLog.e(String.format("Failed to remove %d IPv6 routes from local table.", - removalFailures)); - } - - for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); - } - - private void addRoutesToLocalNetwork(@NonNull final List<RouteInfo> toBeAdded) { - try { - // It's safe to call networkAddInterface() even if - // the interface is already in the local_network. - mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName); - try { - // Add routes from local network. Note that adding routes that - // already exist does not cause an error (EEXIST is silently ignored). - RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded); - } catch (IllegalStateException e) { - mLog.e("Failed to add IPv4/v6 routes to local table: " + e); - return; - } - } catch (ServiceSpecificException | RemoteException e) { - mLog.e("Failed to add " + mIfaceName + " to local table: ", e); - return; - } - - for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); - } - - private void configureLocalIPv6Routes( - HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) { - // [1] Remove the routes that are deprecated. - if (!deprecatedPrefixes.isEmpty()) { - removeRoutesFromLocalNetwork(getLocalRoutesFor(mIfaceName, deprecatedPrefixes)); - } - - // [2] Add only the routes that have not previously been added. - if (newPrefixes != null && !newPrefixes.isEmpty()) { - HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone(); - if (mLastRaParams != null) { - addedPrefixes.removeAll(mLastRaParams.prefixes); - } - - if (!addedPrefixes.isEmpty()) { - addRoutesToLocalNetwork(getLocalRoutesFor(mIfaceName, addedPrefixes)); - } - } - } - - private void configureLocalIPv6Dns( - HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) { - // TODO: Is this really necessary? Can we not fail earlier if INetd cannot be located? - if (mNetd == null) { - if (newDnses != null) newDnses.clear(); - mLog.e("No netd service instance available; not setting local IPv6 addresses"); - return; - } - - // [1] Remove deprecated local DNS IP addresses. - if (!deprecatedDnses.isEmpty()) { - for (Inet6Address dns : deprecatedDnses) { - if (!mInterfaceCtrl.removeAddress(dns, RFC7421_PREFIX_LENGTH)) { - mLog.e("Failed to remove local dns IP " + dns); - } - - mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); - } - } - - // [2] Add only the local DNS IP addresses that have not previously been added. - if (newDnses != null && !newDnses.isEmpty()) { - final HashSet<Inet6Address> addedDnses = (HashSet) newDnses.clone(); - if (mLastRaParams != null) { - addedDnses.removeAll(mLastRaParams.dnses); - } - - for (Inet6Address dns : addedDnses) { - if (!mInterfaceCtrl.addAddress(dns, RFC7421_PREFIX_LENGTH)) { - mLog.e("Failed to add local dns IP " + dns); - newDnses.remove(dns); - } - - mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); - } - } - - try { - mNetd.tetherApplyDnsInterfaces(); - } catch (ServiceSpecificException | RemoteException e) { - mLog.e("Failed to update local DNS caching server"); - if (newDnses != null) newDnses.clear(); - } - } - - private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) { - // Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF - // offload is disabled. Add this check just in case. - // TODO: Perhaps remove this protection check. - if (!mUsingBpfOffload) return; - - mBpfCoordinator.tetherOffloadRuleAdd(this, rule); - } - - private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule) { - // TODO: Perhaps remove this protection check. - // See the related comment in #addIpv6ForwardingRule. - if (!mUsingBpfOffload) return; - - mBpfCoordinator.tetherOffloadRuleRemove(this, rule); - } - - private void clearIpv6ForwardingRules() { - if (!mUsingBpfOffload) return; - - mBpfCoordinator.tetherOffloadRuleClear(this); - } - - private void updateIpv6ForwardingRule(int newIfindex) { - // TODO: Perhaps remove this protection check. - // See the related comment in #addIpv6ForwardingRule. - if (!mUsingBpfOffload) return; - - mBpfCoordinator.tetherOffloadRuleUpdate(this, newIfindex); - } - - // Handles all updates to IPv6 forwarding rules. These can currently change only if the upstream - // changes or if a neighbor event is received. - private void updateIpv6ForwardingRules(int prevUpstreamIfindex, int upstreamIfindex, - NeighborEvent e) { - // If we no longer have an upstream, clear forwarding rules and do nothing else. - if (upstreamIfindex == 0) { - clearIpv6ForwardingRules(); - return; - } - - // If the upstream interface has changed, remove all rules and re-add them with the new - // upstream interface. - if (prevUpstreamIfindex != upstreamIfindex) { - updateIpv6ForwardingRule(upstreamIfindex); - } - - // If we're here to process a NeighborEvent, do so now. - // mInterfaceParams must be non-null or the event would not have arrived. - if (e == null) return; - if (!(e.ip instanceof Inet6Address) || e.ip.isMulticastAddress() - || e.ip.isLoopbackAddress() || e.ip.isLinkLocalAddress()) { - return; - } - - // When deleting rules, we still need to pass a non-null MAC, even though it's ignored. - // Do this here instead of in the Ipv6ForwardingRule constructor to ensure that we never - // add rules with a null MAC, only delete them. - MacAddress dstMac = e.isValid() ? e.macAddr : NULL_MAC_ADDRESS; - Ipv6ForwardingRule rule = new Ipv6ForwardingRule(upstreamIfindex, - mInterfaceParams.index, (Inet6Address) e.ip, mInterfaceParams.macAddr, dstMac); - if (e.isValid()) { - addIpv6ForwardingRule(rule); - } else { - removeIpv6ForwardingRule(rule); - } - } - - private void handleNeighborEvent(NeighborEvent e) { - if (mInterfaceParams != null - && mInterfaceParams.index == e.ifindex - && mInterfaceParams.hasMacAddress) { - updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, mLastIPv6UpstreamIfindex, e); - } - } - - private void handleNewPrefixRequest(@NonNull final IpPrefix currentPrefix) { - if (!currentPrefix.contains(mIpv4Address.getAddress()) - || currentPrefix.getPrefixLength() != mIpv4Address.getPrefixLength()) { - Log.e(TAG, "Invalid prefix: " + currentPrefix); - return; - } - - final LinkAddress deprecatedLinkAddress = mIpv4Address; - mIpv4Address = requestIpv4Address(false); - if (mIpv4Address == null) { - mLog.e("Fail to request a new downstream prefix"); - return; - } - final Inet4Address srvAddr = (Inet4Address) mIpv4Address.getAddress(); - - // Add new IPv4 address on the interface. - if (!mInterfaceCtrl.addAddress(srvAddr, currentPrefix.getPrefixLength())) { - mLog.e("Failed to add new IP " + srvAddr); - return; - } - - // Remove deprecated routes from local network. - removeRoutesFromLocalNetwork( - Collections.singletonList(getDirectConnectedRoute(deprecatedLinkAddress))); - mLinkProperties.removeLinkAddress(deprecatedLinkAddress); - - // Add new routes to local network. - addRoutesToLocalNetwork( - Collections.singletonList(getDirectConnectedRoute(mIpv4Address))); - mLinkProperties.addLinkAddress(mIpv4Address); - - // Update local DNS caching server with new IPv4 address, otherwise, dnsmasq doesn't - // listen on the interface configured with new IPv4 address, that results DNS validation - // failure of downstream client even if appropriate routes have been configured. - try { - mNetd.tetherApplyDnsInterfaces(); - } catch (ServiceSpecificException | RemoteException e) { - mLog.e("Failed to update local DNS caching server"); - return; - } - sendLinkProperties(); - - // Notify DHCP server that new prefix/route has been applied on IpServer. - final Inet4Address clientAddr = mStaticIpv4ClientAddr == null ? null : - (Inet4Address) mStaticIpv4ClientAddr.getAddress(); - final DhcpServingParamsParcel params = makeServingParams(srvAddr /* defaultRouter */, - srvAddr /* dnsServer */, mIpv4Address /* serverLinkAddress */, clientAddr); - try { - mDhcpServer.updateParams(params, new OnHandlerStatusCallback() { - @Override - public void callback(int statusCode) { - if (statusCode != STATUS_SUCCESS) { - mLog.e("Error updating DHCP serving params: " + statusCode); - } - } - }); - } catch (RemoteException e) { - mLog.e("Error updating DHCP serving params", e); - } - } - - private byte getHopLimit(String upstreamIface, int adjustTTL) { - try { - int upstreamHopLimit = Integer.parseUnsignedInt( - mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit")); - upstreamHopLimit = upstreamHopLimit + adjustTTL; - // Cap the hop limit to 255. - return (byte) Integer.min(upstreamHopLimit, 255); - } catch (Exception e) { - mLog.e("Failed to find upstream interface hop limit", e); - } - return RaParams.DEFAULT_HOPLIMIT; - } - - private void setRaParams(RaParams newParams) { - if (mRaDaemon != null) { - final RaParams deprecatedParams = - RaParams.getDeprecatedRaParams(mLastRaParams, newParams); - - configureLocalIPv6Routes(deprecatedParams.prefixes, - (newParams != null) ? newParams.prefixes : null); - - configureLocalIPv6Dns(deprecatedParams.dnses, - (newParams != null) ? newParams.dnses : null); - - mRaDaemon.buildNewRa(deprecatedParams, newParams); - } - - mLastRaParams = newParams; - } - - private void logMessage(State state, int what) { - mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what))); - } - - private void sendInterfaceState(int newInterfaceState) { - mServingMode = newInterfaceState; - mCallback.updateInterfaceState(this, newInterfaceState, mLastError); - sendLinkProperties(); - } - - private void sendLinkProperties() { - mCallback.updateLinkProperties(this, new LinkProperties(mLinkProperties)); - } - - private void resetLinkProperties() { - mLinkProperties.clear(); - mLinkProperties.setInterfaceName(mIfaceName); - } - - private void maybeConfigureStaticIp(final TetheringRequestParcel request) { - // Ignore static address configuration if they are invalid or null. In theory, static - // addresses should not be invalid here because TetheringManager do not allow caller to - // specify invalid static address configuration. - if (request == null || request.localIPv4Address == null - || request.staticClientAddress == null || !checkStaticAddressConfiguration( - request.localIPv4Address, request.staticClientAddress)) { - return; - } - - mStaticIpv4ServerAddr = request.localIPv4Address; - mStaticIpv4ClientAddr = request.staticClientAddress; - } - - class InitialState extends State { - @Override - public void enter() { - sendInterfaceState(STATE_AVAILABLE); - } - - @Override - public boolean processMessage(Message message) { - logMessage(this, message.what); - switch (message.what) { - case CMD_TETHER_REQUESTED: - mLastError = TetheringManager.TETHER_ERROR_NO_ERROR; - switch (message.arg1) { - case STATE_LOCAL_ONLY: - maybeConfigureStaticIp((TetheringRequestParcel) message.obj); - transitionTo(mLocalHotspotState); - break; - case STATE_TETHERED: - maybeConfigureStaticIp((TetheringRequestParcel) message.obj); - transitionTo(mTetheredState); - break; - default: - mLog.e("Invalid tethering interface serving state specified."); - } - break; - case CMD_INTERFACE_DOWN: - transitionTo(mUnavailableState); - break; - case CMD_IPV6_TETHER_UPDATE: - updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class BaseServingState extends State { - @Override - public void enter() { - if (!startIPv4()) { - mLastError = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; - return; - } - - try { - NetdUtils.tetherInterface(mNetd, mIfaceName, asIpPrefix(mIpv4Address)); - } catch (RemoteException | ServiceSpecificException | IllegalStateException e) { - mLog.e("Error Tethering", e); - mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; - return; - } - - if (!startIPv6()) { - mLog.e("Failed to startIPv6"); - // TODO: Make this a fatal error once Bluetooth IPv6 is sorted. - return; - } - } - - @Override - public void exit() { - // Note that at this point, we're leaving the tethered state. We can fail any - // of these operations, but it doesn't really change that we have to try them - // all in sequence. - stopIPv6(); - - try { - NetdUtils.untetherInterface(mNetd, mIfaceName); - } catch (RemoteException | ServiceSpecificException e) { - mLastError = TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; - mLog.e("Failed to untether interface: " + e); - } - - stopIPv4(); - - resetLinkProperties(); - } - - @Override - public boolean processMessage(Message message) { - logMessage(this, message.what); - switch (message.what) { - case CMD_TETHER_UNREQUESTED: - transitionTo(mInitialState); - if (DBG) Log.d(TAG, "Untethered (unrequested)" + mIfaceName); - break; - case CMD_INTERFACE_DOWN: - transitionTo(mUnavailableState); - if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); - break; - case CMD_IPV6_TETHER_UPDATE: - updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); - sendLinkProperties(); - break; - case CMD_IP_FORWARDING_ENABLE_ERROR: - case CMD_IP_FORWARDING_DISABLE_ERROR: - case CMD_START_TETHERING_ERROR: - case CMD_STOP_TETHERING_ERROR: - case CMD_SET_DNS_FORWARDERS_ERROR: - mLastError = TetheringManager.TETHER_ERROR_INTERNAL_ERROR; - transitionTo(mInitialState); - break; - case CMD_NEW_PREFIX_REQUEST: - handleNewPrefixRequest((IpPrefix) message.obj); - break; - case CMD_NOTIFY_PREFIX_CONFLICT: - mLog.i("restart tethering: " + mInterfaceType); - mCallback.requestEnableTethering(mInterfaceType, false /* enabled */); - transitionTo(mWaitingForRestartState); - break; - default: - return false; - } - return true; - } - } - - // Handling errors in BaseServingState.enter() by transitioning is - // problematic because transitioning during a multi-state jump yields - // a Log.wtf(). Ultimately, there should be only one ServingState, - // and forwarding and NAT rules should be handled by a coordinating - // functional element outside of IpServer. - class LocalHotspotState extends BaseServingState { - @Override - public void enter() { - super.enter(); - if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) { - transitionTo(mInitialState); - } - - if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName); - sendInterfaceState(STATE_LOCAL_ONLY); - } - - @Override - public boolean processMessage(Message message) { - if (super.processMessage(message)) return true; - - logMessage(this, message.what); - switch (message.what) { - case CMD_TETHER_REQUESTED: - mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode."); - break; - case CMD_TETHER_CONNECTION_CHANGED: - // Ignored in local hotspot state. - break; - default: - return false; - } - return true; - } - } - - // Handling errors in BaseServingState.enter() by transitioning is - // problematic because transitioning during a multi-state jump yields - // a Log.wtf(). Ultimately, there should be only one ServingState, - // and forwarding and NAT rules should be handled by a coordinating - // functional element outside of IpServer. - class TetheredState extends BaseServingState { - @Override - public void enter() { - super.enter(); - if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) { - transitionTo(mInitialState); - } - - if (DBG) Log.d(TAG, "Tethered " + mIfaceName); - sendInterfaceState(STATE_TETHERED); - } - - @Override - public void exit() { - cleanupUpstream(); - super.exit(); - } - - private void cleanupUpstream() { - if (mUpstreamIfaceSet == null) return; - - for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname); - mUpstreamIfaceSet = null; - clearIpv6ForwardingRules(); - } - - private void cleanupUpstreamInterface(String upstreamIface) { - // Note that we don't care about errors here. - // Sometimes interfaces are gone before we get - // to remove their rules, which generates errors. - // Just do the best we can. - try { - mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString()); - } - try { - mNetd.tetherRemoveForward(mIfaceName, upstreamIface); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Exception in disableNat: " + e.toString()); - } - } - - @Override - public boolean processMessage(Message message) { - if (super.processMessage(message)) return true; - - logMessage(this, message.what); - switch (message.what) { - case CMD_TETHER_REQUESTED: - mLog.e("CMD_TETHER_REQUESTED while already tethering."); - break; - case CMD_TETHER_CONNECTION_CHANGED: - final InterfaceSet newUpstreamIfaceSet = (InterfaceSet) message.obj; - if (noChangeInUpstreamIfaceSet(newUpstreamIfaceSet)) { - if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); - break; - } - - if (newUpstreamIfaceSet == null) { - cleanupUpstream(); - break; - } - - for (String removed : upstreamInterfacesRemoved(newUpstreamIfaceSet)) { - cleanupUpstreamInterface(removed); - } - - final Set<String> added = upstreamInterfacesAdd(newUpstreamIfaceSet); - // This makes the call to cleanupUpstream() in the error - // path for any interface neatly cleanup all the interfaces. - mUpstreamIfaceSet = newUpstreamIfaceSet; - - for (String ifname : added) { - try { - mNetd.tetherAddForward(mIfaceName, ifname); - mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Exception enabling NAT: " + e.toString()); - cleanupUpstream(); - mLastError = TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; - transitionTo(mInitialState); - return true; - } - } - break; - case CMD_NEIGHBOR_EVENT: - handleNeighborEvent((NeighborEvent) message.obj); - break; - default: - return false; - } - return true; - } - - private boolean noChangeInUpstreamIfaceSet(InterfaceSet newIfaces) { - if (mUpstreamIfaceSet == null && newIfaces == null) return true; - if (mUpstreamIfaceSet != null && newIfaces != null) { - return mUpstreamIfaceSet.equals(newIfaces); - } - return false; - } - - private Set<String> upstreamInterfacesRemoved(InterfaceSet newIfaces) { - if (mUpstreamIfaceSet == null) return new HashSet<>(); - - final HashSet<String> removed = new HashSet<>(mUpstreamIfaceSet.ifnames); - removed.removeAll(newIfaces.ifnames); - return removed; - } - - private Set<String> upstreamInterfacesAdd(InterfaceSet newIfaces) { - final HashSet<String> added = new HashSet<>(newIfaces.ifnames); - if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames); - return added; - } - } - - /** - * This state is terminal for the per interface state machine. At this - * point, the tethering main state machine should have removed this interface - * specific state machine from its list of possible recipients of - * tethering requests. The state machine itself will hang around until - * the garbage collector finds it. - */ - class UnavailableState extends State { - @Override - public void enter() { - mIpNeighborMonitor.stop(); - mLastError = TetheringManager.TETHER_ERROR_NO_ERROR; - sendInterfaceState(STATE_UNAVAILABLE); - } - } - - class WaitingForRestartState extends State { - @Override - public boolean processMessage(Message message) { - logMessage(this, message.what); - switch (message.what) { - case CMD_TETHER_UNREQUESTED: - transitionTo(mInitialState); - mLog.i("Untethered (unrequested) and restarting " + mIfaceName); - mCallback.requestEnableTethering(mInterfaceType, true /* enabled */); - break; - case CMD_INTERFACE_DOWN: - transitionTo(mUnavailableState); - mLog.i("Untethered (interface down) and restarting" + mIfaceName); - mCallback.requestEnableTethering(mInterfaceType, true /* enabled */); - break; - default: - return false; - } - return true; - } - } - - // Accumulate routes representing "prefixes to be assigned to the local - // interface", for subsequent modification of local_network routing. - private static ArrayList<RouteInfo> getLocalRoutesFor( - String ifname, HashSet<IpPrefix> prefixes) { - final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>(); - for (IpPrefix ipp : prefixes) { - localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST)); - } - return localRoutes; - } - - // Given a prefix like 2001:db8::/64 return an address like 2001:db8::1. - private static Inet6Address getLocalDnsIpFor(IpPrefix localPrefix) { - final byte[] dnsBytes = localPrefix.getRawAddress(); - dnsBytes[dnsBytes.length - 1] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1)); - try { - return Inet6Address.getByAddress(null, dnsBytes, 0); - } catch (UnknownHostException e) { - Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix); - return null; - } - } - - private static byte getRandomSanitizedByte(byte dflt, byte... excluded) { - final byte random = (byte) (new Random()).nextInt(); - for (int value : excluded) { - if (random == value) return dflt; - } - return random; - } -} diff --git a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java deleted file mode 100644 index 73fc833fabf5..000000000000 --- a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.AF_PACKET; -import static android.system.OsConstants.ETH_P_IPV6; -import static android.system.OsConstants.IPPROTO_RAW; -import static android.system.OsConstants.SOCK_DGRAM; -import static android.system.OsConstants.SOCK_NONBLOCK; -import static android.system.OsConstants.SOCK_RAW; - -import android.net.util.InterfaceParams; -import android.net.util.PacketReader; -import android.net.util.SocketUtils; -import android.net.util.TetheringUtils; -import android.os.Handler; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.Inet6Address; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Arrays; - -/** - * Basic IPv6 Neighbor Advertisement Forwarder. - * - * Forward NA packets from upstream iface to tethered iface - * and NS packets from tethered iface to upstream iface. - * - * @hide - */ -public class NeighborPacketForwarder extends PacketReader { - private final String mTag; - - private FileDescriptor mFd; - - // TODO: get these from NetworkStackConstants. - private static final int IPV6_ADDR_LEN = 16; - private static final int IPV6_DST_ADDR_OFFSET = 24; - private static final int IPV6_HEADER_LEN = 40; - private static final int ETH_HEADER_LEN = 14; - - private InterfaceParams mListenIfaceParams, mSendIfaceParams; - - private final int mType; - public static final int ICMPV6_NEIGHBOR_ADVERTISEMENT = 136; - public static final int ICMPV6_NEIGHBOR_SOLICITATION = 135; - - public NeighborPacketForwarder(Handler h, InterfaceParams tetheredInterface, int type) { - super(h); - mTag = NeighborPacketForwarder.class.getSimpleName() + "-" - + tetheredInterface.name + "-" + type; - mType = type; - - if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) { - mSendIfaceParams = tetheredInterface; - } else { - mListenIfaceParams = tetheredInterface; - } - } - - /** Set new upstream iface and start/stop based on new params. */ - public void setUpstreamIface(InterfaceParams upstreamParams) { - final InterfaceParams oldUpstreamParams; - - if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) { - oldUpstreamParams = mListenIfaceParams; - mListenIfaceParams = upstreamParams; - } else { - oldUpstreamParams = mSendIfaceParams; - mSendIfaceParams = upstreamParams; - } - - if (oldUpstreamParams == null && upstreamParams != null) { - start(); - } else if (oldUpstreamParams != null && upstreamParams == null) { - stop(); - } else if (oldUpstreamParams != null && upstreamParams != null - && oldUpstreamParams.index != upstreamParams.index) { - stop(); - start(); - } - } - - // TODO: move NetworkStackUtils.closeSocketQuietly to - // frameworks/libs/net/common/device/com/android/net/module/util/[someclass]. - private void closeSocketQuietly(FileDescriptor fd) { - try { - SocketUtils.closeSocket(fd); - } catch (IOException ignored) { - } - } - - @Override - protected FileDescriptor createFd() { - try { - // ICMPv6 packets from modem do not have eth header, so RAW socket cannot be used. - // To keep uniformity in both directions PACKET socket can be used. - mFd = Os.socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0); - - // TODO: convert setup*Socket to setupICMPv6BpfFilter with filter type? - if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) { - TetheringUtils.setupNaSocket(mFd); - } else if (mType == ICMPV6_NEIGHBOR_SOLICITATION) { - TetheringUtils.setupNsSocket(mFd); - } - - SocketAddress bindAddress = SocketUtils.makePacketSocketAddress( - ETH_P_IPV6, mListenIfaceParams.index); - Os.bind(mFd, bindAddress); - } catch (ErrnoException | SocketException e) { - Log.wtf(mTag, "Failed to create socket", e); - closeSocketQuietly(mFd); - return null; - } - - return mFd; - } - - private Inet6Address getIpv6DestinationAddress(byte[] recvbuf) { - Inet6Address dstAddr; - try { - dstAddr = (Inet6Address) Inet6Address.getByAddress(Arrays.copyOfRange(recvbuf, - IPV6_DST_ADDR_OFFSET, IPV6_DST_ADDR_OFFSET + IPV6_ADDR_LEN)); - } catch (UnknownHostException | ClassCastException impossible) { - throw new AssertionError("16-byte array not valid IPv6 address?"); - } - return dstAddr; - } - - @Override - protected void handlePacket(byte[] recvbuf, int length) { - if (mSendIfaceParams == null) { - return; - } - - // The BPF filter should already have checked the length of the packet, but... - if (length < IPV6_HEADER_LEN) { - return; - } - Inet6Address destv6 = getIpv6DestinationAddress(recvbuf); - if (!destv6.isMulticastAddress()) { - return; - } - InetSocketAddress dest = new InetSocketAddress(destv6, 0); - - FileDescriptor fd = null; - try { - fd = Os.socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW); - SocketUtils.bindSocketToInterface(fd, mSendIfaceParams.name); - - int ret = Os.sendto(fd, recvbuf, 0, length, 0, dest); - } catch (ErrnoException | SocketException e) { - Log.e(mTag, "handlePacket error: " + e); - } finally { - closeSocketQuietly(fd); - } - } -} diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java deleted file mode 100644 index 7c0b7cc7515c..000000000000 --- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static android.net.util.NetworkConstants.IPV6_MIN_MTU; -import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; -import static android.net.util.TetheringUtils.getAllNodesForScopeId; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.IPPROTO_ICMPV6; -import static android.system.OsConstants.SOCK_RAW; -import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_SNDTIMEO; - -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.TrafficStats; -import android.net.util.InterfaceParams; -import android.net.util.SocketUtils; -import android.net.util.TetheringUtils; -import android.system.ErrnoException; -import android.system.Os; -import android.system.StructTimeval; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.TrafficStatsConstants; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketException; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * Basic IPv6 Router Advertisement Daemon. - * - * TODO: - * - * - Rewrite using Handler (and friends) so that AlarmManager can deliver - * "kick" messages when it's time to send a multicast RA. - * - * @hide - */ -public class RouterAdvertisementDaemon { - private static final String TAG = RouterAdvertisementDaemon.class.getSimpleName(); - private static final byte ICMPV6_ND_ROUTER_SOLICIT = asByte(133); - private static final byte ICMPV6_ND_ROUTER_ADVERT = asByte(134); - private static final int MIN_RA_HEADER_SIZE = 16; - - // Summary of various timers and lifetimes. - private static final int MIN_RTR_ADV_INTERVAL_SEC = 300; - private static final int MAX_RTR_ADV_INTERVAL_SEC = 600; - // In general, router, prefix, and DNS lifetimes are all advised to be - // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we double - // that to allow for multicast packet loss. - // - // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent - // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of - // "approximately 7 RAs per hour". - private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC; - // From https://tools.ietf.org/html/rfc4861#section-10 . - private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3; - // Both initial and final RAs, but also for changes in RA contents. - // From https://tools.ietf.org/html/rfc4861#section-10 . - private static final int MAX_URGENT_RTR_ADVERTISEMENTS = 5; - - private static final int DAY_IN_SECONDS = 86_400; - - private final InterfaceParams mInterface; - private final InetSocketAddress mAllNodes; - - // This lock is to protect the RA from being updated while being - // transmitted on another thread (multicast or unicast). - // - // TODO: This should be handled with a more RCU-like approach. - private final Object mLock = new Object(); - @GuardedBy("mLock") - private final byte[] mRA = new byte[IPV6_MIN_MTU]; - @GuardedBy("mLock") - private int mRaLength; - @GuardedBy("mLock") - private final DeprecatedInfoTracker mDeprecatedInfoTracker; - @GuardedBy("mLock") - private RaParams mRaParams; - - private volatile FileDescriptor mSocket; - private volatile MulticastTransmitter mMulticastTransmitter; - private volatile UnicastResponder mUnicastResponder; - - /** Encapsulate the RA parameters for RouterAdvertisementDaemon.*/ - public static class RaParams { - // Tethered traffic will have the hop limit properly decremented. - // Consequently, set the hoplimit greater by one than the upstream - // unicast hop limit. - // - // TODO: Dynamically pass down the IPV6_UNICAST_HOPS value from the - // upstream interface for more correct behaviour. - static final byte DEFAULT_HOPLIMIT = 65; - - public boolean hasDefaultRoute; - public byte hopLimit; - public int mtu; - public HashSet<IpPrefix> prefixes; - public HashSet<Inet6Address> dnses; - - public RaParams() { - hasDefaultRoute = false; - hopLimit = DEFAULT_HOPLIMIT; - mtu = IPV6_MIN_MTU; - prefixes = new HashSet<IpPrefix>(); - dnses = new HashSet<Inet6Address>(); - } - - public RaParams(RaParams other) { - hasDefaultRoute = other.hasDefaultRoute; - hopLimit = other.hopLimit; - mtu = other.mtu; - prefixes = (HashSet) other.prefixes.clone(); - dnses = (HashSet) other.dnses.clone(); - } - - /** - * Returns the subset of RA parameters that become deprecated when - * moving from announcing oldRa to announcing newRa. - * - * Currently only tracks differences in |prefixes| and |dnses|. - */ - public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) { - RaParams newlyDeprecated = new RaParams(); - - if (oldRa != null) { - for (IpPrefix ipp : oldRa.prefixes) { - if (newRa == null || !newRa.prefixes.contains(ipp)) { - newlyDeprecated.prefixes.add(ipp); - } - } - - for (Inet6Address dns : oldRa.dnses) { - if (newRa == null || !newRa.dnses.contains(dns)) { - newlyDeprecated.dnses.add(dns); - } - } - } - - return newlyDeprecated; - } - } - - private static class DeprecatedInfoTracker { - private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>(); - private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>(); - - Set<IpPrefix> getPrefixes() { - return mPrefixes.keySet(); - } - - void putPrefixes(Set<IpPrefix> prefixes) { - for (IpPrefix ipp : prefixes) { - mPrefixes.put(ipp, MAX_URGENT_RTR_ADVERTISEMENTS); - } - } - - void removePrefixes(Set<IpPrefix> prefixes) { - for (IpPrefix ipp : prefixes) { - mPrefixes.remove(ipp); - } - } - - Set<Inet6Address> getDnses() { - return mDnses.keySet(); - } - - void putDnses(Set<Inet6Address> dnses) { - for (Inet6Address dns : dnses) { - mDnses.put(dns, MAX_URGENT_RTR_ADVERTISEMENTS); - } - } - - void removeDnses(Set<Inet6Address> dnses) { - for (Inet6Address dns : dnses) { - mDnses.remove(dns); - } - } - - boolean isEmpty() { - return mPrefixes.isEmpty() && mDnses.isEmpty(); - } - - private boolean decrementCounters() { - boolean removed = decrementCounter(mPrefixes); - removed |= decrementCounter(mDnses); - return removed; - } - - private <T> boolean decrementCounter(HashMap<T, Integer> map) { - boolean removed = false; - - for (Iterator<Map.Entry<T, Integer>> it = map.entrySet().iterator(); - it.hasNext();) { - Map.Entry<T, Integer> kv = it.next(); - if (kv.getValue() == 0) { - it.remove(); - removed = true; - } else { - kv.setValue(kv.getValue() - 1); - } - } - - return removed; - } - } - - public RouterAdvertisementDaemon(InterfaceParams ifParams) { - mInterface = ifParams; - mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0); - mDeprecatedInfoTracker = new DeprecatedInfoTracker(); - } - - /** Build new RA.*/ - public void buildNewRa(RaParams deprecatedParams, RaParams newParams) { - synchronized (mLock) { - if (deprecatedParams != null) { - mDeprecatedInfoTracker.putPrefixes(deprecatedParams.prefixes); - mDeprecatedInfoTracker.putDnses(deprecatedParams.dnses); - } - - if (newParams != null) { - // Process information that is no longer deprecated. - mDeprecatedInfoTracker.removePrefixes(newParams.prefixes); - mDeprecatedInfoTracker.removeDnses(newParams.dnses); - } - - mRaParams = newParams; - assembleRaLocked(); - } - - maybeNotifyMulticastTransmitter(); - } - - /** Start router advertisement daemon. */ - public boolean start() { - if (!createSocket()) { - return false; - } - - mMulticastTransmitter = new MulticastTransmitter(); - mMulticastTransmitter.start(); - - mUnicastResponder = new UnicastResponder(); - mUnicastResponder.start(); - - return true; - } - - /** Stop router advertisement daemon. */ - public void stop() { - closeSocket(); - // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before - // the thread's termination. - maybeNotifyMulticastTransmitter(); - mMulticastTransmitter = null; - mUnicastResponder = null; - } - - @GuardedBy("mLock") - private void assembleRaLocked() { - final ByteBuffer ra = ByteBuffer.wrap(mRA); - ra.order(ByteOrder.BIG_ENDIAN); - - final boolean haveRaParams = (mRaParams != null); - boolean shouldSendRA = false; - - try { - putHeader(ra, haveRaParams && mRaParams.hasDefaultRoute, - haveRaParams ? mRaParams.hopLimit : RaParams.DEFAULT_HOPLIMIT); - putSlla(ra, mInterface.macAddr.toByteArray()); - mRaLength = ra.position(); - - // https://tools.ietf.org/html/rfc5175#section-4 says: - // - // "MUST NOT be added to a Router Advertisement message - // if no flags in the option are set." - // - // putExpandedFlagsOption(ra); - - if (haveRaParams) { - putMtu(ra, mRaParams.mtu); - mRaLength = ra.position(); - - for (IpPrefix ipp : mRaParams.prefixes) { - putPio(ra, ipp, DEFAULT_LIFETIME, DEFAULT_LIFETIME); - mRaLength = ra.position(); - shouldSendRA = true; - } - - if (mRaParams.dnses.size() > 0) { - putRdnss(ra, mRaParams.dnses, DEFAULT_LIFETIME); - mRaLength = ra.position(); - shouldSendRA = true; - } - } - - for (IpPrefix ipp : mDeprecatedInfoTracker.getPrefixes()) { - putPio(ra, ipp, 0, 0); - mRaLength = ra.position(); - shouldSendRA = true; - } - - final Set<Inet6Address> deprecatedDnses = mDeprecatedInfoTracker.getDnses(); - if (!deprecatedDnses.isEmpty()) { - putRdnss(ra, deprecatedDnses, 0); - mRaLength = ra.position(); - shouldSendRA = true; - } - } catch (BufferOverflowException e) { - // The packet up to mRaLength is valid, since it has been updated - // progressively as the RA was built. Log an error, and continue - // on as best as possible. - Log.e(TAG, "Could not construct new RA: " + e); - } - - // We have nothing worth announcing; indicate as much to maybeSendRA(). - if (!shouldSendRA) { - mRaLength = 0; - } - } - - private void maybeNotifyMulticastTransmitter() { - final MulticastTransmitter m = mMulticastTransmitter; - if (m != null) { - m.hup(); - } - } - - private static byte asByte(int value) { - return (byte) value; - } - private static short asShort(int value) { - return (short) value; - } - - private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) { - /** - Router Advertisement Message Format - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Code | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Cur Hop Limit |M|O|H|Prf|P|R|R| Router Lifetime | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reachable Time | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Retrans Timer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Options ... - +-+-+-+-+-+-+-+-+-+-+-+- - */ - ra.put(ICMPV6_ND_ROUTER_ADVERT) - .put(asByte(0)) - .putShort(asShort(0)) - .put(hopLimit) - // RFC 4191 "high" preference, iff. advertising a default route. - .put(hasDefaultRoute ? asByte(0x08) : asByte(0)) - .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0)) - .putInt(0) - .putInt(0); - } - - private static void putSlla(ByteBuffer ra, byte[] slla) { - /** - Source/Target Link-layer Address - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Link-Layer Address ... - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - if (slla == null || slla.length != 6) { - // Only IEEE 802.3 6-byte addresses are supported. - return; - } - - final byte nd_option_slla = 1; - final byte slla_num_8octets = 1; - ra.put(nd_option_slla) - .put(slla_num_8octets) - .put(slla); - } - - private static void putExpandedFlagsOption(ByteBuffer ra) { - /** - Router Advertisement Expanded Flags Option - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Bit fields available .. - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ... for assignment | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - final byte nd_option__efo = 26; - final byte efo_num_8octets = 1; - - ra.put(nd_option__efo) - .put(efo_num_8octets) - .putShort(asShort(0)) - .putInt(0); - } - - private static void putMtu(ByteBuffer ra, int mtu) { - /** - MTU - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | MTU | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - final byte nd_option_mtu = 5; - final byte mtu_num_8octs = 1; - ra.put(nd_option_mtu) - .put(mtu_num_8octs) - .putShort(asShort(0)) - .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu); - } - - private static void putPio(ByteBuffer ra, IpPrefix ipp, - int validTime, int preferredTime) { - /** - Prefix Information - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Prefix Length |L|A| Reserved1 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Valid Lifetime | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Preferred Lifetime | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reserved2 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | | - + Prefix + - | | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - final int prefixLength = ipp.getPrefixLength(); - if (prefixLength != 64) { - return; - } - final byte nd_option_pio = 3; - final byte pio_num_8octets = 4; - - if (validTime < 0) validTime = 0; - if (preferredTime < 0) preferredTime = 0; - if (preferredTime > validTime) preferredTime = validTime; - - final byte[] addr = ipp.getAddress().getAddress(); - ra.put(nd_option_pio) - .put(pio_num_8octets) - .put(asByte(prefixLength)) - .put(asByte(0xc0)) /* L & A set */ - .putInt(validTime) - .putInt(preferredTime) - .putInt(0) - .put(addr); - } - - private static void putRio(ByteBuffer ra, IpPrefix ipp) { - /** - Route Information Option - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Prefix Length |Resvd|Prf|Resvd| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Route Lifetime | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prefix (Variable Length) | - . . - . . - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - final int prefixLength = ipp.getPrefixLength(); - if (prefixLength > 64) { - return; - } - final byte nd_option_rio = 24; - final byte rio_num_8octets = asByte( - (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3); - - final byte[] addr = ipp.getAddress().getAddress(); - ra.put(nd_option_rio) - .put(rio_num_8octets) - .put(asByte(prefixLength)) - .put(asByte(0x18)) - .putInt(DEFAULT_LIFETIME); - - // Rely upon an IpPrefix's address being properly zeroed. - if (prefixLength > 0) { - ra.put(addr, 0, (prefixLength <= 64) ? 8 : 16); - } - } - - private static void putRdnss(ByteBuffer ra, Set<Inet6Address> dnses, int lifetime) { - /** - Recursive DNS Server (RDNSS) Option - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Lifetime | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - : Addresses of IPv6 Recursive DNS Servers : - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - final HashSet<Inet6Address> filteredDnses = new HashSet<>(); - for (Inet6Address dns : dnses) { - if ((new LinkAddress(dns, RFC7421_PREFIX_LENGTH)).isGlobalPreferred()) { - filteredDnses.add(dns); - } - } - if (filteredDnses.isEmpty()) return; - - final byte nd_option_rdnss = 25; - final byte rdnss_num_8octets = asByte(dnses.size() * 2 + 1); - ra.put(nd_option_rdnss) - .put(rdnss_num_8octets) - .putShort(asShort(0)) - .putInt(lifetime); - - for (Inet6Address dns : filteredDnses) { - // NOTE: If the full of list DNS servers doesn't fit in the packet, - // this code will cause a buffer overflow and the RA won't include - // this instance of the option at all. - // - // TODO: Consider looking at ra.remaining() to determine how many - // DNS servers will fit, and adding only those. - ra.put(dns.getAddress()); - } - } - - private boolean createSocket() { - final int send_timout_ms = 300; - - final int oldTag = TrafficStats.getAndSetThreadStatsTag( - TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR); - try { - mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); - // Setting SNDTIMEO is purely for defensive purposes. - Os.setsockoptTimeval( - mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms)); - SocketUtils.bindSocketToInterface(mSocket, mInterface.name); - TetheringUtils.setupRaSocket(mSocket, mInterface.index); - } catch (ErrnoException | IOException e) { - Log.e(TAG, "Failed to create RA daemon socket: " + e); - return false; - } finally { - TrafficStats.setThreadStatsTag(oldTag); - } - - return true; - } - - private void closeSocket() { - if (mSocket != null) { - try { - SocketUtils.closeSocket(mSocket); - } catch (IOException ignored) { } - } - mSocket = null; - } - - private boolean isSocketValid() { - final FileDescriptor s = mSocket; - return (s != null) && s.valid(); - } - - private boolean isSuitableDestination(InetSocketAddress dest) { - if (mAllNodes.equals(dest)) { - return true; - } - - final InetAddress destip = dest.getAddress(); - return (destip instanceof Inet6Address) - && destip.isLinkLocalAddress() - && (((Inet6Address) destip).getScopeId() == mInterface.index); - } - - private void maybeSendRA(InetSocketAddress dest) { - if (dest == null || !isSuitableDestination(dest)) { - dest = mAllNodes; - } - - try { - synchronized (mLock) { - if (mRaLength < MIN_RA_HEADER_SIZE) { - // No actual RA to send. - return; - } - Os.sendto(mSocket, mRA, 0, mRaLength, 0, dest); - } - Log.d(TAG, "RA sendto " + dest.getAddress().getHostAddress()); - } catch (ErrnoException | SocketException e) { - if (isSocketValid()) { - Log.e(TAG, "sendto error: " + e); - } - } - } - - private final class UnicastResponder extends Thread { - private final InetSocketAddress mSolicitor = new InetSocketAddress(0); - // The recycled buffer for receiving Router Solicitations from clients. - // If the RS is larger than IPV6_MIN_MTU the packets are truncated. - // This is fine since currently only byte 0 is examined anyway. - private final byte[] mSolicitation = new byte[IPV6_MIN_MTU]; - - @Override - public void run() { - while (isSocketValid()) { - try { - // Blocking receive. - final int rval = Os.recvfrom( - mSocket, mSolicitation, 0, mSolicitation.length, 0, mSolicitor); - // Do the least possible amount of validation. - if (rval < 1 || mSolicitation[0] != ICMPV6_ND_ROUTER_SOLICIT) { - continue; - } - } catch (ErrnoException | SocketException e) { - if (isSocketValid()) { - Log.e(TAG, "recvfrom error: " + e); - } - continue; - } - - maybeSendRA(mSolicitor); - } - } - } - - // TODO: Consider moving this to run on a provided Looper as a Handler, - // with WakeupMessage-style messages providing the timer driven input. - private final class MulticastTransmitter extends Thread { - private final Random mRandom = new Random(); - private final AtomicInteger mUrgentAnnouncements = new AtomicInteger(0); - - @Override - public void run() { - while (isSocketValid()) { - try { - Thread.sleep(getNextMulticastTransmitDelayMs()); - } catch (InterruptedException ignored) { - // Stop sleeping, immediately send an RA, and continue. - } - - maybeSendRA(mAllNodes); - synchronized (mLock) { - if (mDeprecatedInfoTracker.decrementCounters()) { - // At least one deprecated PIO has been removed; - // reassemble the RA. - assembleRaLocked(); - } - } - } - } - - public void hup() { - // Set to one fewer that the desired number, because as soon as - // the thread interrupt is processed we immediately send an RA - // and mUrgentAnnouncements is not examined until the subsequent - // sleep interval computation (i.e. this way we send 3 and not 4). - mUrgentAnnouncements.set(MAX_URGENT_RTR_ADVERTISEMENTS - 1); - interrupt(); - } - - private int getNextMulticastTransmitDelaySec() { - boolean deprecationInProgress = false; - synchronized (mLock) { - if (mRaLength < MIN_RA_HEADER_SIZE) { - // No actual RA to send; just sleep for 1 day. - return DAY_IN_SECONDS; - } - deprecationInProgress = !mDeprecatedInfoTracker.isEmpty(); - } - - final int urgentPending = mUrgentAnnouncements.getAndDecrement(); - if ((urgentPending > 0) || deprecationInProgress) { - return MIN_DELAY_BETWEEN_RAS_SEC; - } - - return MIN_RTR_ADV_INTERVAL_SEC + mRandom.nextInt( - MAX_RTR_ADV_INTERVAL_SEC - MIN_RTR_ADV_INTERVAL_SEC); - } - - private long getNextMulticastTransmitDelayMs() { - return 1000 * (long) getNextMulticastTransmitDelaySec(); - } - } -} diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java deleted file mode 100644 index b1ffdb01f5f3..000000000000 --- a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -import android.net.INetdUnsolicitedEventListener; - -import androidx.annotation.NonNull; - -/** - * Base {@link INetdUnsolicitedEventListener} that provides no-op implementations which can be - * overridden. - */ -public class BaseNetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub { - - @Override - public void onInterfaceClassActivityChanged(boolean isActive, int timerLabel, long timestampNs, - int uid) { } - - @Override - public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) { } - - @Override - public void onInterfaceDnsServerInfo(@NonNull String ifName, long lifetimeS, - @NonNull String[] servers) { } - - @Override - public void onInterfaceAddressUpdated(@NonNull String addr, String ifName, int flags, - int scope) { } - - @Override - public void onInterfaceAddressRemoved(@NonNull String addr, @NonNull String ifName, int flags, - int scope) { } - - @Override - public void onInterfaceAdded(@NonNull String ifName) { } - - @Override - public void onInterfaceRemoved(@NonNull String ifName) { } - - @Override - public void onInterfaceChanged(@NonNull String ifName, boolean up) { } - - @Override - public void onInterfaceLinkStateChanged(@NonNull String ifName, boolean up) { } - - @Override - public void onRouteChanged(boolean updated, @NonNull String route, @NonNull String gateway, - @NonNull String ifName) { } - - @Override - public void onStrictCleartextDetected(int uid, @NonNull String hex) { } - - @Override - public int getInterfaceVersion() { - return INetdUnsolicitedEventListener.VERSION; - } - - @Override - public String getInterfaceHash() { - return INetdUnsolicitedEventListener.HASH; - } -} diff --git a/packages/Tethering/src/android/net/util/InterfaceSet.java b/packages/Tethering/src/android/net/util/InterfaceSet.java deleted file mode 100644 index 758978711bd4..000000000000 --- a/packages/Tethering/src/android/net/util/InterfaceSet.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.StringJoiner; - - -/** - * @hide - */ -public class InterfaceSet { - public final Set<String> ifnames; - - public InterfaceSet(String... names) { - final Set<String> nameSet = new HashSet<>(); - for (String name : names) { - if (name != null) nameSet.add(name); - } - ifnames = Collections.unmodifiableSet(nameSet); - } - - @Override - public String toString() { - final StringJoiner sj = new StringJoiner(",", "[", "]"); - for (String ifname : ifnames) sj.add(ifname); - return sj.toString(); - } - - @Override - public boolean equals(Object obj) { - return obj != null - && obj instanceof InterfaceSet - && ifnames.equals(((InterfaceSet) obj).ifnames); - } -} diff --git a/packages/Tethering/src/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java deleted file mode 100644 index f203e9995f3d..000000000000 --- a/packages/Tethering/src/android/net/util/PrefixUtils.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - - -/** - * @hide - */ -public class PrefixUtils { - private static final IpPrefix[] MIN_NON_FORWARDABLE_PREFIXES = { - pfx("127.0.0.0/8"), // IPv4 loopback - pfx("169.254.0.0/16"), // IPv4 link-local, RFC3927#section-8 - pfx("::/3"), - pfx("fe80::/64"), // IPv6 link-local - pfx("fc00::/7"), // IPv6 ULA - pfx("ff02::/8"), // IPv6 link-local multicast - }; - - public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24"); - - /** Get non forwardable prefixes. */ - public static Set<IpPrefix> getNonForwardablePrefixes() { - final HashSet<IpPrefix> prefixes = new HashSet<>(); - addNonForwardablePrefixes(prefixes); - return prefixes; - } - - /** Add non forwardable prefixes. */ - public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) { - Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES); - } - - /** Get local prefixes from |lp|. */ - public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) { - final HashSet<IpPrefix> localPrefixes = new HashSet<>(); - if (lp == null) return localPrefixes; - - for (LinkAddress addr : lp.getAllLinkAddresses()) { - if (addr.getAddress().isLinkLocalAddress()) continue; - localPrefixes.add(asIpPrefix(addr)); - } - // TODO: Add directly-connected routes as well (ones from which we did - // not also form a LinkAddress)? - - return localPrefixes; - } - - /** Convert LinkAddress |addr| to IpPrefix. */ - public static IpPrefix asIpPrefix(LinkAddress addr) { - return new IpPrefix(addr.getAddress(), addr.getPrefixLength()); - } - - /** Convert InetAddress |ip| to IpPrefix. */ - public static IpPrefix ipAddressAsPrefix(InetAddress ip) { - final int bitLength = (ip instanceof Inet4Address) - ? NetworkConstants.IPV4_ADDR_BITS - : NetworkConstants.IPV6_ADDR_BITS; - return new IpPrefix(ip, bitLength); - } - - private static IpPrefix pfx(String prefixStr) { - return new IpPrefix(prefixStr); - } -} diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java deleted file mode 100644 index 53b54f7de05d..000000000000 --- a/packages/Tethering/src/android/net/util/TetheringUtils.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -import android.net.TetherStatsParcel; -import android.net.TetheringRequestParcel; -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.io.FileDescriptor; -import java.net.Inet6Address; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Objects; - -/** - * The classes and the methods for tethering utilization. - * - * {@hide} - */ -public class TetheringUtils { - public static final byte[] ALL_NODES = new byte[] { - (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 - }; - - /** - * Configures a socket for receiving and sending ICMPv6 neighbor advertisments. - * @param fd the socket's {@link FileDescriptor}. - */ - public static native void setupNaSocket(FileDescriptor fd) - throws SocketException; - - /** - * Configures a socket for receiving and sending ICMPv6 neighbor solicitations. - * @param fd the socket's {@link FileDescriptor}. - */ - public static native void setupNsSocket(FileDescriptor fd) - throws SocketException; - - /** - * The object which records offload Tx/Rx forwarded bytes/packets. - * TODO: Replace the inner class ForwardedStats of class OffloadHardwareInterface with - * this class as well. - */ - public static class ForwardedStats { - public final long rxBytes; - public final long rxPackets; - public final long txBytes; - public final long txPackets; - - public ForwardedStats() { - rxBytes = 0; - rxPackets = 0; - txBytes = 0; - txPackets = 0; - } - - public ForwardedStats(long rxBytes, long txBytes) { - this.rxBytes = rxBytes; - this.rxPackets = 0; - this.txBytes = txBytes; - this.txPackets = 0; - } - - public ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets) { - this.rxBytes = rxBytes; - this.rxPackets = rxPackets; - this.txBytes = txBytes; - this.txPackets = txPackets; - } - - public ForwardedStats(@NonNull TetherStatsParcel tetherStats) { - rxBytes = tetherStats.rxBytes; - rxPackets = tetherStats.rxPackets; - txBytes = tetherStats.txBytes; - txPackets = tetherStats.txPackets; - } - - public ForwardedStats(@NonNull ForwardedStats other) { - rxBytes = other.rxBytes; - rxPackets = other.rxPackets; - txBytes = other.txBytes; - txPackets = other.txPackets; - } - - /** Add Tx/Rx bytes/packets and return the result as a new object. */ - @NonNull - public ForwardedStats add(@NonNull ForwardedStats other) { - return new ForwardedStats(rxBytes + other.rxBytes, rxPackets + other.rxPackets, - txBytes + other.txBytes, txPackets + other.txPackets); - } - - /** Subtract Tx/Rx bytes/packets and return the result as a new object. */ - @NonNull - public ForwardedStats subtract(@NonNull ForwardedStats other) { - // TODO: Perhaps throw an exception if any negative difference value just in case. - final long rxBytesDiff = Math.max(rxBytes - other.rxBytes, 0); - final long rxPacketsDiff = Math.max(rxPackets - other.rxPackets, 0); - final long txBytesDiff = Math.max(txBytes - other.txBytes, 0); - final long txPacketsDiff = Math.max(txPackets - other.txPackets, 0); - return new ForwardedStats(rxBytesDiff, rxPacketsDiff, txBytesDiff, txPacketsDiff); - } - - /** Returns the string representation of this object. */ - @NonNull - public String toString() { - return String.format("ForwardedStats(rxb: %d, rxp: %d, txb: %d, txp: %d)", rxBytes, - rxPackets, txBytes, txPackets); - } - } - - /** - * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements. - * @param fd the socket's {@link FileDescriptor}. - * @param ifIndex the interface index. - */ - public static native void setupRaSocket(FileDescriptor fd, int ifIndex) - throws SocketException; - - /** - * Read s as an unsigned 16-bit integer. - */ - public static int uint16(short s) { - return s & 0xffff; - } - - /** Check whether two TetheringRequestParcels are the same. */ - public static boolean isTetheringRequestEquals(final TetheringRequestParcel request, - final TetheringRequestParcel otherRequest) { - if (request == otherRequest) return true; - - return request != null && otherRequest != null - && request.tetheringType == otherRequest.tetheringType - && Objects.equals(request.localIPv4Address, otherRequest.localIPv4Address) - && Objects.equals(request.staticClientAddress, otherRequest.staticClientAddress) - && request.exemptFromEntitlementCheck == otherRequest.exemptFromEntitlementCheck - && request.showProvisioningUi == otherRequest.showProvisioningUi; - } - - /** Get inet6 address for all nodes given scope ID. */ - public static Inet6Address getAllNodesForScopeId(int scopeId) { - try { - return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId); - } catch (UnknownHostException uhe) { - Log.wtf("TetheringUtils", "Failed to construct Inet6Address from " - + Arrays.toString(ALL_NODES) + " and scopedId " + scopeId); - return null; - } - } -} diff --git a/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java b/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java deleted file mode 100644 index e2804abd752b..000000000000 --- a/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.util.Log; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - - -/** - * A utility class that runs the provided callback on the provided handler when - * intents matching the provided filter arrive. Intents received by a stale - * receiver are safely ignored. - * - * Calls to startListening() and stopListening() must happen on the same thread. - * - * @hide - */ -public class VersionedBroadcastListener { - private static final boolean DBG = false; - - private final String mTag; - private final Context mContext; - private final Handler mHandler; - private final IntentFilter mFilter; - private final Consumer<Intent> mCallback; - private final AtomicInteger mGenerationNumber; - private BroadcastReceiver mReceiver; - - public VersionedBroadcastListener(String tag, Context ctx, Handler handler, - IntentFilter filter, Consumer<Intent> callback) { - mTag = tag; - mContext = ctx; - mHandler = handler; - mFilter = filter; - mCallback = callback; - mGenerationNumber = new AtomicInteger(0); - } - - /** Start listening to intent broadcast. */ - public void startListening() { - if (DBG) Log.d(mTag, "startListening"); - if (mReceiver != null) return; - - mReceiver = new Receiver(mTag, mGenerationNumber, mCallback); - mContext.registerReceiver(mReceiver, mFilter, null, mHandler); - } - - /** Stop listening to intent broadcast. */ - public void stopListening() { - if (DBG) Log.d(mTag, "stopListening"); - if (mReceiver == null) return; - - mGenerationNumber.incrementAndGet(); - mContext.unregisterReceiver(mReceiver); - mReceiver = null; - } - - private static class Receiver extends BroadcastReceiver { - public final String tag; - public final AtomicInteger atomicGenerationNumber; - public final Consumer<Intent> callback; - // Used to verify this receiver is still current. - public final int generationNumber; - - Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer<Intent> callback) { - this.tag = tag; - this.atomicGenerationNumber = atomicGenerationNumber; - this.callback = callback; - generationNumber = atomicGenerationNumber.incrementAndGet(); - } - - @Override - public void onReceive(Context context, Intent intent) { - final int currentGenerationNumber = atomicGenerationNumber.get(); - - if (DBG) { - Log.d(tag, "receiver generationNumber=" + generationNumber - + ", current generationNumber=" + currentGenerationNumber); - } - if (generationNumber != currentGenerationNumber) return; - - callback.accept(intent); - } - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java deleted file mode 100644 index 20f30ea7a460..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStats.UID_TETHERING; -import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; - -import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; - -import android.app.usage.NetworkStatsManager; -import android.net.INetd; -import android.net.MacAddress; -import android.net.NetworkStats; -import android.net.NetworkStats.Entry; -import android.net.TetherOffloadRuleParcel; -import android.net.TetherStatsParcel; -import android.net.ip.IpServer; -import android.net.netstats.provider.NetworkStatsProvider; -import android.net.util.SharedLog; -import android.net.util.TetheringUtils.ForwardedStats; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; - -import java.net.Inet6Address; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; - -/** - * This coordinator is responsible for providing BPF offload relevant functionality. - * - Get tethering stats. - * - Set data limit. - * - Set global alert. - * - Add/remove forwarding rules. - * - * @hide - */ -public class BpfCoordinator { - private static final String TAG = BpfCoordinator.class.getSimpleName(); - private static final int DUMP_TIMEOUT_MS = 10_000; - - @VisibleForTesting - enum StatsType { - STATS_PER_IFACE, - STATS_PER_UID, - } - - @NonNull - private final Handler mHandler; - @NonNull - private final INetd mNetd; - @NonNull - private final SharedLog mLog; - @NonNull - private final Dependencies mDeps; - @Nullable - private final BpfTetherStatsProvider mStatsProvider; - - // True if BPF offload is supported, false otherwise. The BPF offload could be disabled by - // a runtime resource overlay package or device configuration. This flag is only initialized - // in the constructor because it is hard to unwind all existing change once device - // configuration is changed. Especially the forwarding rules. Keep the same setting - // to make it simpler. See also TetheringConfiguration. - private final boolean mIsBpfEnabled; - - // Tracks whether BPF tethering is started or not. This is set by tethering before it - // starts the first IpServer and is cleared by tethering shortly before the last IpServer - // is stopped. Note that rule updates (especially deletions, but sometimes additions as - // well) may arrive when this is false. If they do, they must be communicated to netd. - // Changes in data limits may also arrive when this is false, and if they do, they must - // also be communicated to netd. - private boolean mPollingStarted = false; - - // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert - // quota is interface independent and global for tether offload. - private long mRemainingAlertQuota = QUOTA_UNLIMITED; - - // Maps upstream interface index to offloaded traffic statistics. - // Always contains the latest total bytes/packets, since each upstream was started, received - // from the BPF maps for each interface. - private final SparseArray<ForwardedStats> mStats = new SparseArray<>(); - - // Maps upstream interface names to interface quotas. - // Always contains the latest value received from the framework for each interface, regardless - // of whether offload is currently running (or is even supported) on that interface. Only - // includes interfaces that have a quota set. Note that this map is used for storing the quota - // which is set from the service. Because the service uses the interface name to present the - // interface, this map uses the interface name to be the mapping index. - private final HashMap<String, Long> mInterfaceQuotas = new HashMap<>(); - - // Maps upstream interface index to interface names. - // Store all interface name since boot. Used for lookup what interface name it is from the - // tether stats got from netd because netd reports interface index to present an interface. - // TODO: Remove the unused interface name. - private final SparseArray<String> mInterfaceNames = new SparseArray<>(); - - // Map of downstream rule maps. Each of these maps represents the IPv6 forwarding rules for a - // given downstream. Each map: - // - Is owned by the IpServer that is responsible for that downstream. - // - Must only be modified by that IpServer. - // - Is created when the IpServer adds its first rule, and deleted when the IpServer deletes - // its last rule (or clears its rules). - // TODO: Perhaps seal the map and rule operations which communicates with netd into a class. - // TODO: Does this need to be a LinkedHashMap or can it just be a HashMap? Also, could it be - // a ConcurrentHashMap, in order to avoid the copies in tetherOffloadRuleClear - // and tetherOffloadRuleUpdate? - // TODO: Perhaps use one-dimensional map and access specific downstream rules via downstream - // index. For doing that, IpServer must guarantee that it always has a valid IPv6 downstream - // interface index while calling function to clear all rules. IpServer may be calling clear - // rules function without a valid IPv6 downstream interface index even if it may have one - // before. IpServer would need to call getInterfaceParams() in the constructor instead of when - // startIpv6() is called, and make mInterfaceParams final. - private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> - mIpv6ForwardingRules = new LinkedHashMap<>(); - - // Runnable that used by scheduling next polling of stats. - private final Runnable mScheduledPollingTask = () -> { - updateForwardedStatsFromNetd(); - maybeSchedulePollingStats(); - }; - - @VisibleForTesting - public abstract static class Dependencies { - /** Get handler. */ - @NonNull public abstract Handler getHandler(); - - /** Get netd. */ - @NonNull public abstract INetd getNetd(); - - /** Get network stats manager. */ - @NonNull public abstract NetworkStatsManager getNetworkStatsManager(); - - /** Get shared log. */ - @NonNull public abstract SharedLog getSharedLog(); - - /** Get tethering configuration. */ - @Nullable public abstract TetheringConfiguration getTetherConfig(); - } - - @VisibleForTesting - public BpfCoordinator(@NonNull Dependencies deps) { - mDeps = deps; - mHandler = mDeps.getHandler(); - mNetd = mDeps.getNetd(); - mLog = mDeps.getSharedLog().forSubComponent(TAG); - mIsBpfEnabled = isBpfEnabled(); - BpfTetherStatsProvider provider = new BpfTetherStatsProvider(); - try { - mDeps.getNetworkStatsManager().registerNetworkStatsProvider( - getClass().getSimpleName(), provider); - } catch (RuntimeException e) { - // TODO: Perhaps not allow to use BPF offload because the reregistration failure - // implied that no data limit could be applies on a metered upstream if any. - Log.wtf(TAG, "Cannot register offload stats provider: " + e); - provider = null; - } - mStatsProvider = provider; - } - - /** - * Start BPF tethering offload stats polling when the first upstream is started. - * Note that this can be only called on handler thread. - * TODO: Perhaps check BPF support before starting. - * TODO: Start the stats polling only if there is any client on the downstream. - */ - public void startPolling() { - if (mPollingStarted) return; - - if (!mIsBpfEnabled) { - mLog.i("Offload disabled"); - return; - } - - mPollingStarted = true; - maybeSchedulePollingStats(); - - mLog.i("Polling started"); - } - - /** - * Stop BPF tethering offload stats polling. - * The data limit cleanup and the tether stats maps cleanup are not implemented here. - * These cleanups rely on all IpServers calling #tetherOffloadRuleRemove. After the - * last rule is removed from the upstream, #tetherOffloadRuleRemove does the cleanup - * functionality. - * Note that this can be only called on handler thread. - */ - public void stopPolling() { - if (!mPollingStarted) return; - - // Stop scheduled polling tasks and poll the latest stats from BPF maps. - if (mHandler.hasCallbacks(mScheduledPollingTask)) { - mHandler.removeCallbacks(mScheduledPollingTask); - } - updateForwardedStatsFromNetd(); - mPollingStarted = false; - - mLog.i("Polling stopped"); - } - - /** - * Add forwarding rule. After adding the first rule on a given upstream, must add the data - * limit on the given upstream. - * Note that this can be only called on handler thread. - */ - public void tetherOffloadRuleAdd( - @NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) { - if (!mIsBpfEnabled) return; - - try { - // TODO: Perhaps avoid to add a duplicate rule. - mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel()); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Could not add IPv6 forwarding rule: ", e); - return; - } - - if (!mIpv6ForwardingRules.containsKey(ipServer)) { - mIpv6ForwardingRules.put(ipServer, new LinkedHashMap<Inet6Address, - Ipv6ForwardingRule>()); - } - LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer); - - // Setup the data limit on the given upstream if the first rule is added. - final int upstreamIfindex = rule.upstreamIfindex; - if (!isAnyRuleOnUpstream(upstreamIfindex)) { - // If failed to set a data limit, probably should not use this upstream, because - // the upstream may not want to blow through the data limit that was told to apply. - // TODO: Perhaps stop the coordinator. - boolean success = updateDataLimit(upstreamIfindex); - if (!success) { - final String iface = mInterfaceNames.get(upstreamIfindex); - mLog.e("Setting data limit for " + iface + " failed."); - } - } - - // Must update the adding rule after calling #isAnyRuleOnUpstream because it needs to - // check if it is about adding a first rule for a given upstream. - rules.put(rule.address, rule); - } - - /** - * Remove forwarding rule. After removing the last rule on a given upstream, must clear - * data limit, update the last tether stats and remove the tether stats in the BPF maps. - * Note that this can be only called on handler thread. - */ - public void tetherOffloadRuleRemove( - @NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) { - if (!mIsBpfEnabled) return; - - try { - // TODO: Perhaps avoid to remove a non-existent rule. - mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel()); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Could not remove IPv6 forwarding rule: ", e); - return; - } - - LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer); - if (rules == null) return; - - // Must remove rules before calling #isAnyRuleOnUpstream because it needs to check if - // the last rule is removed for a given upstream. If no rule is removed, return early. - // Avoid unnecessary work on a non-existent rule which may have never been added or - // removed already. - if (rules.remove(rule.address) == null) return; - - // Remove the downstream entry if it has no more rule. - if (rules.isEmpty()) { - mIpv6ForwardingRules.remove(ipServer); - } - - // Do cleanup functionality if there is no more rule on the given upstream. - final int upstreamIfindex = rule.upstreamIfindex; - if (!isAnyRuleOnUpstream(upstreamIfindex)) { - try { - final TetherStatsParcel stats = - mNetd.tetherOffloadGetAndClearStats(upstreamIfindex); - // Update the last stats delta and delete the local cache for a given upstream. - updateQuotaAndStatsFromSnapshot(new TetherStatsParcel[] {stats}); - mStats.remove(upstreamIfindex); - } catch (RemoteException | ServiceSpecificException e) { - Log.wtf(TAG, "Exception when cleanup tether stats for upstream index " - + upstreamIfindex + ": ", e); - } - } - } - - /** - * Clear all forwarding rules for a given downstream. - * Note that this can be only called on handler thread. - */ - public void tetherOffloadRuleClear(@NonNull final IpServer ipServer) { - if (!mIsBpfEnabled) return; - - final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get( - ipServer); - if (rules == null) return; - - // Need to build a rule list because the rule map may be changed in the iteration. - for (final Ipv6ForwardingRule rule : new ArrayList<Ipv6ForwardingRule>(rules.values())) { - tetherOffloadRuleRemove(ipServer, rule); - } - } - - /** - * Update existing forwarding rules to new upstream for a given downstream. - * Note that this can be only called on handler thread. - */ - public void tetherOffloadRuleUpdate(@NonNull final IpServer ipServer, int newUpstreamIfindex) { - if (!mIsBpfEnabled) return; - - final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get( - ipServer); - if (rules == null) return; - - // Need to build a rule list because the rule map may be changed in the iteration. - for (final Ipv6ForwardingRule rule : new ArrayList<Ipv6ForwardingRule>(rules.values())) { - // Remove the old rule before adding the new one because the map uses the same key for - // both rules. Reversing the processing order causes that the new rule is removed as - // unexpected. - // TODO: Add new rule first to reduce the latency which has no rule. - tetherOffloadRuleRemove(ipServer, rule); - tetherOffloadRuleAdd(ipServer, rule.onNewUpstream(newUpstreamIfindex)); - } - } - - /** - * Add upstream name to lookup table. The lookup table is used for tether stats interface name - * lookup because the netd only reports interface index in BPF tether stats but the service - * expects the interface name in NetworkStats object. - * Note that this can be only called on handler thread. - */ - public void addUpstreamNameToLookupTable(int upstreamIfindex, @NonNull String upstreamIface) { - if (!mIsBpfEnabled) return; - - if (upstreamIfindex == 0 || TextUtils.isEmpty(upstreamIface)) return; - - // The same interface index to name mapping may be added by different IpServer objects or - // re-added by reconnection on the same upstream interface. Ignore the duplicate one. - final String iface = mInterfaceNames.get(upstreamIfindex); - if (iface == null) { - mInterfaceNames.put(upstreamIfindex, upstreamIface); - } else if (!TextUtils.equals(iface, upstreamIface)) { - Log.wtf(TAG, "The upstream interface name " + upstreamIface - + " is different from the existing interface name " - + iface + " for index " + upstreamIfindex); - } - } - - /** - * Dump information. - * Block the function until all the data are dumped on the handler thread or timed-out. The - * reason is that dumpsys invokes this function on the thread of caller and the data may only - * be allowed to be accessed on the handler thread. - */ - public void dump(@NonNull IndentingPrintWriter pw) { - final ConditionVariable dumpDone = new ConditionVariable(); - mHandler.post(() -> { - pw.println("mIsBpfEnabled: " + mIsBpfEnabled); - pw.println("Polling " + (mPollingStarted ? "started" : "not started")); - pw.println("Stats provider " + (mStatsProvider != null - ? "registered" : "not registered")); - pw.println("Upstream quota: " + mInterfaceQuotas.toString()); - pw.println("Polling interval: " + getPollingInterval() + " ms"); - - pw.println("Forwarding stats:"); - pw.increaseIndent(); - if (mStats.size() == 0) { - pw.println("<empty>"); - } else { - dumpStats(pw); - } - pw.decreaseIndent(); - - pw.println("Forwarding rules:"); - pw.increaseIndent(); - if (mIpv6ForwardingRules.size() == 0) { - pw.println("<empty>"); - } else { - dumpIpv6ForwardingRules(pw); - } - pw.decreaseIndent(); - - dumpDone.open(); - }); - if (!dumpDone.block(DUMP_TIMEOUT_MS)) { - pw.println("... dump timed-out after " + DUMP_TIMEOUT_MS + "ms"); - } - } - - private void dumpStats(@NonNull IndentingPrintWriter pw) { - for (int i = 0; i < mStats.size(); i++) { - final int upstreamIfindex = mStats.keyAt(i); - final ForwardedStats stats = mStats.get(upstreamIfindex); - pw.println(String.format("%d(%s) - %s", upstreamIfindex, mInterfaceNames.get( - upstreamIfindex), stats.toString())); - } - } - - private void dumpIpv6ForwardingRules(@NonNull IndentingPrintWriter pw) { - for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> entry : - mIpv6ForwardingRules.entrySet()) { - IpServer ipServer = entry.getKey(); - // The rule downstream interface index is paired with the interface name from - // IpServer#interfaceName. See #startIPv6, #updateIpv6ForwardingRules in IpServer. - final String downstreamIface = ipServer.interfaceName(); - pw.println("[" + downstreamIface + "]: iif(iface) oif(iface) v6addr srcmac dstmac"); - - pw.increaseIndent(); - LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = entry.getValue(); - for (Ipv6ForwardingRule rule : rules.values()) { - final int upstreamIfindex = rule.upstreamIfindex; - pw.println(String.format("%d(%s) %d(%s) %s %s %s", upstreamIfindex, - mInterfaceNames.get(upstreamIfindex), rule.downstreamIfindex, - downstreamIface, rule.address, rule.srcMac, rule.dstMac)); - } - pw.decreaseIndent(); - } - } - - /** IPv6 forwarding rule class. */ - public static class Ipv6ForwardingRule { - public final int upstreamIfindex; - public final int downstreamIfindex; - - @NonNull - public final Inet6Address address; - @NonNull - public final MacAddress srcMac; - @NonNull - public final MacAddress dstMac; - - public Ipv6ForwardingRule(int upstreamIfindex, int downstreamIfIndex, - @NonNull Inet6Address address, @NonNull MacAddress srcMac, - @NonNull MacAddress dstMac) { - this.upstreamIfindex = upstreamIfindex; - this.downstreamIfindex = downstreamIfIndex; - this.address = address; - this.srcMac = srcMac; - this.dstMac = dstMac; - } - - /** Return a new rule object which updates with new upstream index. */ - @NonNull - public Ipv6ForwardingRule onNewUpstream(int newUpstreamIfindex) { - return new Ipv6ForwardingRule(newUpstreamIfindex, downstreamIfindex, address, srcMac, - dstMac); - } - - /** - * Don't manipulate TetherOffloadRuleParcel directly because implementing onNewUpstream() - * would be error-prone due to generated stable AIDL classes not having a copy constructor. - */ - @NonNull - public TetherOffloadRuleParcel toTetherOffloadRuleParcel() { - final TetherOffloadRuleParcel parcel = new TetherOffloadRuleParcel(); - parcel.inputInterfaceIndex = upstreamIfindex; - parcel.outputInterfaceIndex = downstreamIfindex; - parcel.destination = address.getAddress(); - parcel.prefixLength = 128; - parcel.srcL2Address = srcMac.toByteArray(); - parcel.dstL2Address = dstMac.toByteArray(); - return parcel; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Ipv6ForwardingRule)) return false; - Ipv6ForwardingRule that = (Ipv6ForwardingRule) o; - return this.upstreamIfindex == that.upstreamIfindex - && this.downstreamIfindex == that.downstreamIfindex - && Objects.equals(this.address, that.address) - && Objects.equals(this.srcMac, that.srcMac) - && Objects.equals(this.dstMac, that.dstMac); - } - - @Override - public int hashCode() { - // TODO: if this is ever used in production code, don't pass ifindices - // to Objects.hash() to avoid autoboxing overhead. - return Objects.hash(upstreamIfindex, downstreamIfindex, address, srcMac, dstMac); - } - } - - /** - * A BPF tethering stats provider to provide network statistics to the system. - * Note that this class' data may only be accessed on the handler thread. - */ - @VisibleForTesting - class BpfTetherStatsProvider extends NetworkStatsProvider { - // The offloaded traffic statistics per interface that has not been reported since the - // last call to pushTetherStats. Only the interfaces that were ever tethering upstreams - // and has pending tether stats delta are included in this NetworkStats object. - private NetworkStats mIfaceStats = new NetworkStats(0L, 0); - - // The same stats as above, but counts network stats per uid. - private NetworkStats mUidStats = new NetworkStats(0L, 0); - - @Override - public void onRequestStatsUpdate(int token) { - mHandler.post(() -> pushTetherStats()); - } - - @Override - public void onSetAlert(long quotaBytes) { - mHandler.post(() -> updateAlertQuota(quotaBytes)); - } - - @Override - public void onSetLimit(@NonNull String iface, long quotaBytes) { - if (quotaBytes < QUOTA_UNLIMITED) { - throw new IllegalArgumentException("invalid quota value " + quotaBytes); - } - - mHandler.post(() -> { - final Long curIfaceQuota = mInterfaceQuotas.get(iface); - - if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return; - - if (quotaBytes == QUOTA_UNLIMITED) { - mInterfaceQuotas.remove(iface); - } else { - mInterfaceQuotas.put(iface, quotaBytes); - } - maybeUpdateDataLimit(iface); - }); - } - - @VisibleForTesting - void pushTetherStats() { - try { - // The token is not used for now. See b/153606961. - notifyStatsUpdated(0 /* token */, mIfaceStats, mUidStats); - - // Clear the accumulated tether stats delta after reported. Note that create a new - // empty object because NetworkStats#clear is @hide. - mIfaceStats = new NetworkStats(0L, 0); - mUidStats = new NetworkStats(0L, 0); - } catch (RuntimeException e) { - mLog.e("Cannot report network stats: ", e); - } - } - - private void accumulateDiff(@NonNull NetworkStats ifaceDiff, - @NonNull NetworkStats uidDiff) { - mIfaceStats = mIfaceStats.add(ifaceDiff); - mUidStats = mUidStats.add(uidDiff); - } - } - - private boolean isBpfEnabled() { - final TetheringConfiguration config = mDeps.getTetherConfig(); - return (config != null) ? config.isBpfOffloadEnabled() : true /* default value */; - } - - private int getInterfaceIndexFromRules(@NonNull String ifName) { - for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules - .values()) { - for (Ipv6ForwardingRule rule : rules.values()) { - final int upstreamIfindex = rule.upstreamIfindex; - if (TextUtils.equals(ifName, mInterfaceNames.get(upstreamIfindex))) { - return upstreamIfindex; - } - } - } - return 0; - } - - private long getQuotaBytes(@NonNull String iface) { - final Long limit = mInterfaceQuotas.get(iface); - final long quotaBytes = (limit != null) ? limit : QUOTA_UNLIMITED; - - return quotaBytes; - } - - private boolean sendDataLimitToNetd(int ifIndex, long quotaBytes) { - if (ifIndex == 0) { - Log.wtf(TAG, "Invalid interface index."); - return false; - } - - try { - mNetd.tetherOffloadSetInterfaceQuota(ifIndex, quotaBytes); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Exception when updating quota " + quotaBytes + ": ", e); - return false; - } - - return true; - } - - // Handle the data limit update from the service which is the stats provider registered for. - private void maybeUpdateDataLimit(@NonNull String iface) { - // Set data limit only on a given upstream which has at least one rule. If we can't get - // an interface index for a given interface name, it means either there is no rule for - // a given upstream or the interface name is not an upstream which is monitored by the - // coordinator. - final int ifIndex = getInterfaceIndexFromRules(iface); - if (ifIndex == 0) return; - - final long quotaBytes = getQuotaBytes(iface); - sendDataLimitToNetd(ifIndex, quotaBytes); - } - - // Handle the data limit update while adding forwarding rules. - private boolean updateDataLimit(int ifIndex) { - final String iface = mInterfaceNames.get(ifIndex); - if (iface == null) { - mLog.e("Fail to get the interface name for index " + ifIndex); - return false; - } - final long quotaBytes = getQuotaBytes(iface); - return sendDataLimitToNetd(ifIndex, quotaBytes); - } - - private boolean isAnyRuleOnUpstream(int upstreamIfindex) { - for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules - .values()) { - for (Ipv6ForwardingRule rule : rules.values()) { - if (upstreamIfindex == rule.upstreamIfindex) return true; - } - } - return false; - } - - @NonNull - private NetworkStats buildNetworkStats(@NonNull StatsType type, int ifIndex, - @NonNull final ForwardedStats diff) { - NetworkStats stats = new NetworkStats(0L, 0); - final String iface = mInterfaceNames.get(ifIndex); - if (iface == null) { - // TODO: Use Log.wtf once the coordinator owns full control of tether stats from netd. - // For now, netd may add the empty stats for the upstream which is not monitored by - // the coordinator. Silently ignore it. - return stats; - } - final int uid = (type == StatsType.STATS_PER_UID) ? UID_TETHERING : UID_ALL; - // Note that the argument 'metered', 'roaming' and 'defaultNetwork' are not recorded for - // network stats snapshot. See NetworkStatsRecorder#recordSnapshotLocked. - return stats.addEntry(new Entry(iface, uid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, diff.rxBytes, diff.rxPackets, - diff.txBytes, diff.txPackets, 0L /* operations */)); - } - - private void updateAlertQuota(long newQuota) { - if (newQuota < QUOTA_UNLIMITED) { - throw new IllegalArgumentException("invalid quota value " + newQuota); - } - if (mRemainingAlertQuota == newQuota) return; - - mRemainingAlertQuota = newQuota; - if (mRemainingAlertQuota == 0) { - mLog.i("onAlertReached"); - if (mStatsProvider != null) mStatsProvider.notifyAlertReached(); - } - } - - private void updateQuotaAndStatsFromSnapshot( - @NonNull final TetherStatsParcel[] tetherStatsList) { - long usedAlertQuota = 0; - for (TetherStatsParcel tetherStats : tetherStatsList) { - final Integer ifIndex = tetherStats.ifIndex; - final ForwardedStats curr = new ForwardedStats(tetherStats); - final ForwardedStats base = mStats.get(ifIndex); - final ForwardedStats diff = (base != null) ? curr.subtract(base) : curr; - usedAlertQuota += diff.rxBytes + diff.txBytes; - - // Update the local cache for counting tether stats delta. - mStats.put(ifIndex, curr); - - // Update the accumulated tether stats delta to the stats provider for the service - // querying. - if (mStatsProvider != null) { - try { - mStatsProvider.accumulateDiff( - buildNetworkStats(StatsType.STATS_PER_IFACE, ifIndex, diff), - buildNetworkStats(StatsType.STATS_PER_UID, ifIndex, diff)); - } catch (ArrayIndexOutOfBoundsException e) { - Log.wtf(TAG, "Fail to update the accumulated stats delta for interface index " - + ifIndex + " : ", e); - } - } - } - - if (mRemainingAlertQuota > 0 && usedAlertQuota > 0) { - // Trim to zero if overshoot. - final long newQuota = Math.max(mRemainingAlertQuota - usedAlertQuota, 0); - updateAlertQuota(newQuota); - } - - // TODO: Count the used limit quota for notifying data limit reached. - } - - private void updateForwardedStatsFromNetd() { - final TetherStatsParcel[] tetherStatsList; - try { - // The reported tether stats are total data usage for all currently-active upstream - // interfaces since tethering start. - tetherStatsList = mNetd.tetherOffloadGetStats(); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e("Problem fetching tethering stats: ", e); - return; - } - updateQuotaAndStatsFromSnapshot(tetherStatsList); - } - - @VisibleForTesting - int getPollingInterval() { - // The valid range of interval is DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long. - // Ignore the config value is less than the minimum polling interval. Note that the - // minimum interval definition is invoked as OffloadController#isPollingStatsNeeded does. - // TODO: Perhaps define a minimum polling interval constant. - final TetheringConfiguration config = mDeps.getTetherConfig(); - final int configInterval = (config != null) ? config.getOffloadPollInterval() : 0; - return Math.max(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, configInterval); - } - - private void maybeSchedulePollingStats() { - if (!mPollingStarted) return; - - if (mHandler.hasCallbacks(mScheduledPollingTask)) { - mHandler.removeCallbacks(mScheduledPollingTask); - } - - mHandler.postDelayed(mScheduledPollingTask, getPollingInterval()); - } - - // Return forwarding rule map. This is used for testing only. - // Note that this can be only called on handler thread. - @NonNull - @VisibleForTesting - final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> - getForwardingRulesForTesting() { - return mIpv6ForwardingRules; - } - - // Return upstream interface name map. This is used for testing only. - // Note that this can be only called on handler thread. - @NonNull - @VisibleForTesting - final SparseArray<String> getInterfaceNamesForTesting() { - return mInterfaceNames; - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java b/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java deleted file mode 100644 index 8a96988ae1d1..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.TetheringManager.TETHERING_WIFI; - -import android.net.MacAddress; -import android.net.TetheredClient; -import android.net.TetheredClient.AddressInfo; -import android.net.ip.IpServer; -import android.net.wifi.WifiClient; -import android.os.SystemClock; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Tracker for clients connected to downstreams. - * - * <p>This class is not thread safe, it is intended to be used only from the tethering handler - * thread. - */ -public class ConnectedClientsTracker { - private final Clock mClock; - - @NonNull - private List<WifiClient> mLastWifiClients = Collections.emptyList(); - @NonNull - private List<TetheredClient> mLastTetheredClients = Collections.emptyList(); - - @VisibleForTesting - static class Clock { - public long elapsedRealtime() { - return SystemClock.elapsedRealtime(); - } - } - - public ConnectedClientsTracker() { - this(new Clock()); - } - - @VisibleForTesting - ConnectedClientsTracker(Clock clock) { - mClock = clock; - } - - /** - * Update the tracker with new connected clients. - * - * <p>The new list can be obtained through {@link #getLastTetheredClients()}. - * @param ipServers The IpServers used to assign addresses to clients. - * @param wifiClients The list of L2-connected WiFi clients. Null for no change since last - * update. - * @return True if the list of clients changed since the last calculation. - */ - public boolean updateConnectedClients( - Iterable<IpServer> ipServers, @Nullable List<WifiClient> wifiClients) { - final long now = mClock.elapsedRealtime(); - - if (wifiClients != null) { - mLastWifiClients = wifiClients; - } - final Set<MacAddress> wifiClientMacs = getClientMacs(mLastWifiClients); - - // Build the list of non-expired leases from all IpServers, grouped by mac address - final Map<MacAddress, TetheredClient> clientsMap = new HashMap<>(); - for (IpServer server : ipServers) { - for (TetheredClient client : server.getAllLeases()) { - if (client.getTetheringType() == TETHERING_WIFI - && !wifiClientMacs.contains(client.getMacAddress())) { - // Skip leases of WiFi clients that are not (or no longer) L2-connected - continue; - } - final TetheredClient prunedClient = pruneExpired(client, now); - if (prunedClient == null) continue; // All addresses expired - - addLease(clientsMap, prunedClient); - } - } - - // TODO: add IPv6 addresses from netlink - - // Add connected WiFi clients that do not have any known address - for (MacAddress client : wifiClientMacs) { - if (clientsMap.containsKey(client)) continue; - clientsMap.put(client, new TetheredClient( - client, Collections.emptyList() /* addresses */, TETHERING_WIFI)); - } - - final HashSet<TetheredClient> clients = new HashSet<>(clientsMap.values()); - final boolean clientsChanged = clients.size() != mLastTetheredClients.size() - || !clients.containsAll(mLastTetheredClients); - mLastTetheredClients = Collections.unmodifiableList(new ArrayList<>(clients)); - return clientsChanged; - } - - private static void addLease(Map<MacAddress, TetheredClient> clientsMap, TetheredClient lease) { - final TetheredClient aggregateClient = clientsMap.getOrDefault( - lease.getMacAddress(), lease); - if (aggregateClient == lease) { - // This is the first lease with this mac address - clientsMap.put(lease.getMacAddress(), lease); - return; - } - - // Only add the address info; this assumes that the tethering type is the same when the mac - // address is the same. If a client is connected through different tethering types with the - // same mac address, connected clients callbacks will report all of its addresses under only - // one of these tethering types. This keeps the API simple considering that such a scenario - // would really be a rare edge case. - clientsMap.put(lease.getMacAddress(), aggregateClient.addAddresses(lease)); - } - - /** - * Get the last list of tethered clients, as calculated in {@link #updateConnectedClients}. - * - * <p>The returned list is immutable. - */ - @NonNull - public List<TetheredClient> getLastTetheredClients() { - return mLastTetheredClients; - } - - private static boolean hasExpiredAddress(List<AddressInfo> addresses, long now) { - for (AddressInfo info : addresses) { - if (info.getExpirationTime() <= now) { - return true; - } - } - return false; - } - - @Nullable - private static TetheredClient pruneExpired(TetheredClient client, long now) { - final List<AddressInfo> addresses = client.getAddresses(); - if (addresses.size() == 0) return null; - if (!hasExpiredAddress(addresses, now)) return client; - - final ArrayList<AddressInfo> newAddrs = new ArrayList<>(addresses.size() - 1); - for (AddressInfo info : addresses) { - if (info.getExpirationTime() > now) { - newAddrs.add(info); - } - } - - if (newAddrs.size() == 0) { - return null; - } - return new TetheredClient(client.getMacAddress(), newAddrs, client.getTetheringType()); - } - - @NonNull - private static Set<MacAddress> getClientMacs(@NonNull List<WifiClient> clients) { - final Set<MacAddress> macs = new HashSet<>(clients.size()); - for (WifiClient c : clients) { - macs.add(c.getMacAddress()); - } - return macs; - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java deleted file mode 100644 index bb7322f2a0d2..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE; -import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK; -import static android.net.TetheringConstants.EXTRA_RUN_PROVISION; -import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE; -import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION; -import static android.net.TetheringConstants.EXTRA_TETHER_SUBID; -import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME; -import static android.net.TetheringManager.TETHERING_BLUETOOTH; -import static android.net.TetheringManager.TETHERING_ETHERNET; -import static android.net.TetheringManager.TETHERING_INVALID; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.util.SharedLog; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.Parcel; -import android.os.PersistableBundle; -import android.os.ResultReceiver; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.provider.Settings; -import android.telephony.CarrierConfigManager; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.PrintWriter; -import java.util.BitSet; - -/** - * Re-check tethering provisioning for enabled downstream tether types. - * Reference TetheringManager.TETHERING_{@code *} for each tether type. - * - * All methods of this class must be accessed from the thread of tethering - * state machine. - * @hide - */ -public class EntitlementManager { - private static final String TAG = EntitlementManager.class.getSimpleName(); - private static final boolean DBG = false; - - @VisibleForTesting - protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning"; - private static final String ACTION_PROVISIONING_ALARM = - "com.android.networkstack.tethering.PROVISIONING_RECHECK_ALARM"; - - private final ComponentName mSilentProvisioningService; - private static final int MS_PER_HOUR = 60 * 60 * 1000; - private static final int DUMP_TIMEOUT = 10_000; - - // The BitSet is the bit map of each enabled downstream types, ex: - // {@link TetheringManager.TETHERING_WIFI} - // {@link TetheringManager.TETHERING_USB} - // {@link TetheringManager.TETHERING_BLUETOOTH} - private final BitSet mCurrentDownstreams; - private final BitSet mExemptedDownstreams; - private final Context mContext; - private final SharedLog mLog; - private final SparseIntArray mEntitlementCacheValue; - private final Handler mHandler; - // Key: TetheringManager.TETHERING_*(downstream). - // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). - private final SparseIntArray mCurrentEntitlementResults; - private final Runnable mPermissionChangeCallback; - private PendingIntent mProvisioningRecheckAlarm; - private boolean mLastCellularUpstreamPermitted = true; - private boolean mUsingCellularAsUpstream = false; - private boolean mNeedReRunProvisioningUi = false; - private OnUiEntitlementFailedListener mListener; - private TetheringConfigurationFetcher mFetcher; - - public EntitlementManager(Context ctx, Handler h, SharedLog log, - Runnable callback) { - mContext = ctx; - mLog = log.forSubComponent(TAG); - mCurrentDownstreams = new BitSet(); - mExemptedDownstreams = new BitSet(); - mCurrentEntitlementResults = new SparseIntArray(); - mEntitlementCacheValue = new SparseIntArray(); - mPermissionChangeCallback = callback; - mHandler = h; - mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM), - null, mHandler); - mSilentProvisioningService = ComponentName.unflattenFromString( - mContext.getResources().getString(R.string.config_wifi_tether_enable)); - } - - public void setOnUiEntitlementFailedListener(final OnUiEntitlementFailedListener listener) { - mListener = listener; - } - - /** Callback fired when UI entitlement failed. */ - public interface OnUiEntitlementFailedListener { - /** - * Ui entitlement check fails in |downstream|. - * - * @param downstream tethering type from TetheringManager.TETHERING_{@code *}. - */ - void onUiEntitlementFailed(int downstream); - } - - public void setTetheringConfigurationFetcher(final TetheringConfigurationFetcher fetcher) { - mFetcher = fetcher; - } - - /** Interface to fetch TetheringConfiguration. */ - public interface TetheringConfigurationFetcher { - /** - * Fetch current tethering configuration. This will be called to ensure whether entitlement - * check is needed. - * @return TetheringConfiguration instance. - */ - TetheringConfiguration fetchTetheringConfiguration(); - } - - /** - * Check if cellular upstream is permitted. - */ - public boolean isCellularUpstreamPermitted() { - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - - return isCellularUpstreamPermitted(config); - } - - private boolean isCellularUpstreamPermitted(final TetheringConfiguration config) { - if (!isTetherProvisioningRequired(config)) return true; - - // If provisioning is required and EntitlementManager doesn't know any downstreams, cellular - // upstream should not be enabled. Enable cellular upstream for exempted downstreams only - // when there is no non-exempted downstream. - if (mCurrentDownstreams.isEmpty()) return !mExemptedDownstreams.isEmpty(); - - return mCurrentEntitlementResults.indexOfValue(TETHER_ERROR_NO_ERROR) > -1; - } - - /** - * Set exempted downstream type. If there is only exempted downstream type active, - * corresponding entitlement check will not be run and cellular upstream will be permitted - * by default. If a privileged app enables tethering without a provisioning check, and then - * another app enables tethering of the same type but does not disable the provisioning check, - * then the downstream immediately loses exempt status and a provisioning check is run. - * If any non-exempted downstream type is active, the cellular upstream will be gated by the - * result of entitlement check from non-exempted downstreams. If entitlement check is still - * in progress on non-exempt downstreams, ceullar upstream would default be disabled. When any - * non-exempted downstream gets positive entitlement result, ceullar upstream will be enabled. - */ - public void setExemptedDownstreamType(final int type) { - mExemptedDownstreams.set(type, true); - } - - /** - * This is called when tethering starts. - * Launch provisioning app if upstream is cellular. - * - * @param downstreamType tethering type from TetheringManager.TETHERING_{@code *} - * @param showProvisioningUi a boolean indicating whether to show the - * provisioning app UI if there is one. - */ - public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) { - if (!isValidDownstreamType(downstreamType)) return; - - mCurrentDownstreams.set(downstreamType, true); - - mExemptedDownstreams.set(downstreamType, false); - - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (!isTetherProvisioningRequired(config)) return; - - // If upstream is not cellular, provisioning app would not be launched - // till upstream change to cellular. - if (mUsingCellularAsUpstream) { - if (showProvisioningUi) { - runUiTetherProvisioning(downstreamType, config); - } else { - runSilentTetherProvisioning(downstreamType, config); - } - mNeedReRunProvisioningUi = false; - } else { - mNeedReRunProvisioningUi |= showProvisioningUi; - } - } - - /** - * Tell EntitlementManager that a given type of tethering has been disabled - * - * @param type tethering type from TetheringManager.TETHERING_{@code *} - */ - public void stopProvisioningIfNeeded(int downstreamType) { - if (!isValidDownstreamType(downstreamType)) return; - - mCurrentDownstreams.set(downstreamType, false); - // There are lurking bugs where the notion of "provisioning required" or - // "tethering supported" may change without without tethering being notified properly. - // Remove the mapping all the time no matter provisioning is required or not. - removeDownstreamMapping(downstreamType); - mExemptedDownstreams.set(downstreamType, false); - } - - /** - * Notify EntitlementManager if upstream is cellular or not. - * - * @param isCellular whether tethering upstream is cellular. - */ - public void notifyUpstream(boolean isCellular) { - if (DBG) { - mLog.i("notifyUpstream: " + isCellular - + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted - + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi); - } - mUsingCellularAsUpstream = isCellular; - - if (mUsingCellularAsUpstream) { - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - maybeRunProvisioning(config); - } - } - - /** Run provisioning if needed */ - public void maybeRunProvisioning() { - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - maybeRunProvisioning(config); - } - - private void maybeRunProvisioning(final TetheringConfiguration config) { - if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) { - return; - } - - // Whenever any entitlement value changes, all downstreams will re-evaluate whether they - // are allowed. Therefore even if the silent check here ends in a failure and the UI later - // yields success, then the downstream that got a failure will re-evaluate as a result of - // the change and get the new correct value. - for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0; - downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) { - if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) { - if (mNeedReRunProvisioningUi) { - mNeedReRunProvisioningUi = false; - runUiTetherProvisioning(downstream, config); - } else { - runSilentTetherProvisioning(downstream, config); - } - } - } - } - - /** - * Check if the device requires a provisioning check in order to enable tethering. - * - * @param config an object that encapsulates the various tethering configuration elements. - * @return a boolean - {@code true} indicating tether provisioning is required by the carrier. - */ - @VisibleForTesting - protected boolean isTetherProvisioningRequired(final TetheringConfiguration config) { - if (SystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false) - || config.provisioningApp.length == 0) { - return false; - } - if (carrierConfigAffirmsEntitlementCheckNotRequired(config)) { - return false; - } - return (config.provisioningApp.length == 2); - } - - /** - * Re-check tethering provisioning for all enabled tether types. - * Reference TetheringManager.TETHERING_{@code *} for each tether type. - * - * @param config an object that encapsulates the various tethering configuration elements. - * Note: this method is only called from @{link Tethering.TetherMainSM} on the handler thread. - * If there are new callers from different threads, the logic should move to - * @{link Tethering.TetherMainSM} handler to avoid race conditions. - */ - public void reevaluateSimCardProvisioning(final TetheringConfiguration config) { - if (DBG) mLog.i("reevaluateSimCardProvisioning"); - - if (!mHandler.getLooper().isCurrentThread()) { - // Except for test, this log should not appear in normal flow. - mLog.log("reevaluateSimCardProvisioning() don't run in TetherMainSM thread"); - } - mEntitlementCacheValue.clear(); - mCurrentEntitlementResults.clear(); - - // TODO: refine provisioning check to isTetherProvisioningRequired() ?? - if (!config.hasMobileHotspotProvisionApp() - || carrierConfigAffirmsEntitlementCheckNotRequired(config)) { - evaluateCellularPermission(config); - return; - } - - if (mUsingCellularAsUpstream) { - maybeRunProvisioning(config); - } - } - - /** - * Get carrier configuration bundle. - * @param config an object that encapsulates the various tethering configuration elements. - * */ - public PersistableBundle getCarrierConfig(final TetheringConfiguration config) { - final CarrierConfigManager configManager = (CarrierConfigManager) mContext - .getSystemService(Context.CARRIER_CONFIG_SERVICE); - if (configManager == null) return null; - - final PersistableBundle carrierConfig = configManager.getConfigForSubId( - config.activeDataSubId); - - if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { - return carrierConfig; - } - - return null; - } - - // The logic here is aimed solely at confirming that a CarrierConfig exists - // and affirms that entitlement checks are not required. - // - // TODO: find a better way to express this, or alter the checking process - // entirely so that this is more intuitive. - private boolean carrierConfigAffirmsEntitlementCheckNotRequired( - final TetheringConfiguration config) { - // Check carrier config for entitlement checks - final PersistableBundle carrierConfig = getCarrierConfig(config); - if (carrierConfig == null) return false; - - // A CarrierConfigManager was found and it has a config. - final boolean isEntitlementCheckRequired = carrierConfig.getBoolean( - CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL); - return !isEntitlementCheckRequired; - } - - /** - * Run no UI tethering provisioning check. - * @param type tethering type from TetheringManager.TETHERING_{@code *} - * @param subId default data subscription ID. - */ - @VisibleForTesting - protected Intent runSilentTetherProvisioning(int type, final TetheringConfiguration config) { - if (DBG) mLog.i("runSilentTetherProvisioning: " + type); - // For silent provisioning, settings would stop tethering when entitlement fail. - ResultReceiver receiver = buildProxyReceiver(type, false/* notifyFail */, null); - - Intent intent = new Intent(); - intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); - intent.putExtra(EXTRA_RUN_PROVISION, true); - intent.putExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION, config.provisioningAppNoUi); - intent.putExtra(EXTRA_TETHER_PROVISIONING_RESPONSE, config.provisioningResponse); - intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); - intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId); - intent.setComponent(mSilentProvisioningService); - // Only admin user can change tethering and SilentTetherProvisioning don't need to - // show UI, it is fine to always start setting's background service as system user. - mContext.startService(intent); - return intent; - } - - private void runUiTetherProvisioning(int type, final TetheringConfiguration config) { - ResultReceiver receiver = buildProxyReceiver(type, true/* notifyFail */, null); - runUiTetherProvisioning(type, config, receiver); - } - - /** - * Run the UI-enabled tethering provisioning check. - * @param type tethering type from TetheringManager.TETHERING_{@code *} - * @param subId default data subscription ID. - * @param receiver to receive entitlement check result. - */ - @VisibleForTesting - protected Intent runUiTetherProvisioning(int type, final TetheringConfiguration config, - ResultReceiver receiver) { - if (DBG) mLog.i("runUiTetherProvisioning: " + type); - - Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING_UI); - intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); - intent.putExtra(EXTRA_TETHER_UI_PROVISIONING_APP_NAME, config.provisioningApp); - intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); - intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // Only launch entitlement UI for system user. Entitlement UI should not appear for other - // user because only admin user is allowed to change tethering. - mContext.startActivity(intent); - return intent; - } - - // Not needed to check if this don't run on the handler thread because it's private. - private void scheduleProvisioningRechecks(final TetheringConfiguration config) { - if (mProvisioningRecheckAlarm == null) { - final int period = config.provisioningCheckPeriod; - if (period <= 0) return; - - Intent intent = new Intent(ACTION_PROVISIONING_ALARM); - mProvisioningRecheckAlarm = PendingIntent.getBroadcast(mContext, 0, intent, 0); - AlarmManager alarmManager = (AlarmManager) mContext.getSystemService( - Context.ALARM_SERVICE); - long periodMs = period * MS_PER_HOUR; - long firstAlarmTime = SystemClock.elapsedRealtime() + periodMs; - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, firstAlarmTime, periodMs, - mProvisioningRecheckAlarm); - } - } - - private void cancelTetherProvisioningRechecks() { - if (mProvisioningRecheckAlarm != null) { - AlarmManager alarmManager = (AlarmManager) mContext.getSystemService( - Context.ALARM_SERVICE); - alarmManager.cancel(mProvisioningRecheckAlarm); - mProvisioningRecheckAlarm = null; - } - } - - private void evaluateCellularPermission(final TetheringConfiguration config) { - final boolean permitted = isCellularUpstreamPermitted(config); - - if (DBG) { - mLog.i("Cellular permission change from " + mLastCellularUpstreamPermitted - + " to " + permitted); - } - - if (mLastCellularUpstreamPermitted != permitted) { - mLog.log("Cellular permission change: " + permitted); - mPermissionChangeCallback.run(); - } - // Only schedule periodic re-check when tether is provisioned - // and the result is ok. - if (permitted && mCurrentEntitlementResults.size() > 0) { - scheduleProvisioningRechecks(config); - } else { - cancelTetherProvisioningRechecks(); - } - mLastCellularUpstreamPermitted = permitted; - } - - /** - * Add the mapping between provisioning result and tethering type. - * Notify UpstreamNetworkMonitor if Cellular permission changes. - * - * @param type tethering type from TetheringManager.TETHERING_{@code *} - * @param resultCode Provisioning result - */ - protected void addDownstreamMapping(int type, int resultCode) { - mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode - + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type)); - if (!mCurrentDownstreams.get(type)) return; - - mCurrentEntitlementResults.put(type, resultCode); - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - evaluateCellularPermission(config); - } - - /** - * Remove the mapping for input tethering type. - * @param type tethering type from TetheringManager.TETHERING_{@code *} - */ - protected void removeDownstreamMapping(int type) { - mLog.i("removeDownstreamMapping: " + type); - mCurrentEntitlementResults.delete(type); - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - evaluateCellularPermission(config); - } - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) { - mLog.log("Received provisioning alarm"); - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - reevaluateSimCardProvisioning(config); - } - } - }; - - private static boolean isValidDownstreamType(int type) { - switch (type) { - case TETHERING_BLUETOOTH: - case TETHERING_ETHERNET: - case TETHERING_USB: - case TETHERING_WIFI: - return true; - default: - return false; - } - } - - /** - * Dump the infromation of EntitlementManager. - * @param pw {@link PrintWriter} is used to print formatted - */ - public void dump(PrintWriter pw) { - final ConditionVariable mWaiting = new ConditionVariable(); - mHandler.post(() -> { - pw.print("isCellularUpstreamPermitted: "); - pw.println(isCellularUpstreamPermitted()); - for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0; - type = mCurrentDownstreams.nextSetBit(type + 1)) { - pw.print("Type: "); - pw.print(typeString(type)); - if (mCurrentEntitlementResults.indexOfKey(type) > -1) { - pw.print(", Value: "); - pw.println(errorString(mCurrentEntitlementResults.get(type))); - } else { - pw.println(", Value: empty"); - } - } - mWaiting.open(); - }); - if (!mWaiting.block(DUMP_TIMEOUT)) { - pw.println("... dump timed out after " + DUMP_TIMEOUT + "ms"); - } - pw.print("Exempted: ["); - for (int type = mExemptedDownstreams.nextSetBit(0); type >= 0; - type = mExemptedDownstreams.nextSetBit(type + 1)) { - pw.print(typeString(type)); - pw.print(", "); - } - pw.println("]"); - } - - private static String typeString(int type) { - switch (type) { - case TETHERING_BLUETOOTH: return "TETHERING_BLUETOOTH"; - case TETHERING_INVALID: return "TETHERING_INVALID"; - case TETHERING_USB: return "TETHERING_USB"; - case TETHERING_WIFI: return "TETHERING_WIFI"; - default: - return String.format("TETHERING UNKNOWN TYPE (%d)", type); - } - } - - private static String errorString(int value) { - switch (value) { - case TETHER_ERROR_ENTITLEMENT_UNKNOWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN"; - case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR"; - case TETHER_ERROR_PROVISIONING_FAILED: return "TETHER_ERROR_PROVISIONING_FAILED"; - default: - return String.format("UNKNOWN ERROR (%d)", value); - } - } - - private ResultReceiver buildProxyReceiver(int type, boolean notifyFail, - final ResultReceiver receiver) { - ResultReceiver rr = new ResultReceiver(mHandler) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - int updatedCacheValue = updateEntitlementCacheValue(type, resultCode); - addDownstreamMapping(type, updatedCacheValue); - if (updatedCacheValue == TETHER_ERROR_PROVISIONING_FAILED && notifyFail) { - mListener.onUiEntitlementFailed(type); - } - if (receiver != null) receiver.send(updatedCacheValue, null); - } - }; - - return writeToParcel(rr); - } - - // Instances of ResultReceiver need to be public classes for remote processes to be able - // to load them (otherwise, ClassNotFoundException). For private classes, this method - // performs a trick : round-trip parceling any instance of ResultReceiver will return a - // vanilla instance of ResultReceiver sharing the binder token with the original receiver. - // The binder token has a reference to the original instance of the private class and will - // still call its methods, and can be sent over. However it cannot be used for anything - // else than sending over a Binder call. - // While round-trip parceling is not great, there is currently no other way of generating - // a vanilla instance of ResultReceiver because all its fields are private. - private ResultReceiver writeToParcel(final ResultReceiver receiver) { - Parcel parcel = Parcel.obtain(); - receiver.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); - parcel.recycle(); - return receiverForSending; - } - - /** - * Update the last entitlement value to internal cache - * - * @param type tethering type from TetheringManager.TETHERING_{@code *} - * @param resultCode last entitlement value - * @return the last updated entitlement value - */ - private int updateEntitlementCacheValue(int type, int resultCode) { - if (DBG) { - mLog.i("updateEntitlementCacheValue: " + type + ", result: " + resultCode); - } - if (resultCode == TETHER_ERROR_NO_ERROR) { - mEntitlementCacheValue.put(type, resultCode); - return resultCode; - } else { - mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISIONING_FAILED); - return TETHER_ERROR_PROVISIONING_FAILED; - } - } - - /** Get the last value of the tethering entitlement check. */ - public void requestLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver, - boolean showEntitlementUi) { - if (!isValidDownstreamType(downstream)) { - receiver.send(TETHER_ERROR_ENTITLEMENT_UNKNOWN, null); - return; - } - - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (!isTetherProvisioningRequired(config)) { - receiver.send(TETHER_ERROR_NO_ERROR, null); - return; - } - - final int cacheValue = mEntitlementCacheValue.get( - downstream, TETHER_ERROR_ENTITLEMENT_UNKNOWN); - if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) { - receiver.send(cacheValue, null); - } else { - ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver); - runUiTetherProvisioning(downstream, config, proxy); - } - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java deleted file mode 100644 index f3dcaa2529e7..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.RouteInfo; -import android.net.ip.IpServer; -import android.net.util.NetworkConstants; -import android.net.util.SharedLog; -import android.util.Log; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.Random; - - -/** - * IPv6 tethering is rather different from IPv4 owing to the absence of NAT. - * This coordinator is responsible for evaluating the dedicated prefixes - * assigned to the device and deciding how to divvy them up among downstream - * interfaces. - * - * @hide - */ -public class IPv6TetheringCoordinator { - private static final String TAG = IPv6TetheringCoordinator.class.getSimpleName(); - private static final boolean DBG = false; - private static final boolean VDBG = false; - - private static class Downstream { - public final IpServer ipServer; - public final int mode; // IpServer.STATE_* - // Used to append to a ULA /48, constructing a ULA /64 for local use. - public final short subnetId; - - Downstream(IpServer ipServer, int mode, short subnetId) { - this.ipServer = ipServer; - this.mode = mode; - this.subnetId = subnetId; - } - } - - private final ArrayList<IpServer> mNotifyList; - private final SharedLog mLog; - // NOTE: mActiveDownstreams is a list and not a hash data structure because - // we keep active downstreams in arrival order. This is done so /64s can - // be parceled out on a "first come, first served" basis and a /64 used by - // a downstream that is no longer active can be redistributed to any next - // waiting active downstream (again, in arrival order). - private final LinkedList<Downstream> mActiveDownstreams; - private final byte[] mUniqueLocalPrefix; - private short mNextSubnetId; - private UpstreamNetworkState mUpstreamNetworkState; - - public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) { - mNotifyList = notifyList; - mLog = log.forSubComponent(TAG); - mActiveDownstreams = new LinkedList<>(); - mUniqueLocalPrefix = generateUniqueLocalPrefix(); - mNextSubnetId = 0; - } - - /** Add active downstream to ipv6 tethering candidate list. */ - public void addActiveDownstream(IpServer downstream, int mode) { - if (findDownstream(downstream) == null) { - // Adding a new downstream appends it to the list. Adding a - // downstream a second time without first removing it has no effect. - // We never change the mode of a downstream except by first removing - // it and then re-adding it (with its new mode specified); - if (mActiveDownstreams.offer(new Downstream(downstream, mode, mNextSubnetId))) { - // Make sure subnet IDs are always positive. They are appended - // to a ULA /48 to make a ULA /64 for local use. - mNextSubnetId = (short) Math.max(0, mNextSubnetId + 1); - } - updateIPv6TetheringInterfaces(); - } - } - - /** Remove downstream from ipv6 tethering candidate list. */ - public void removeActiveDownstream(IpServer downstream) { - stopIPv6TetheringOn(downstream); - if (mActiveDownstreams.remove(findDownstream(downstream))) { - updateIPv6TetheringInterfaces(); - } - - // When tethering is stopping we can reset the subnet counter. - if (mNotifyList.isEmpty()) { - if (!mActiveDownstreams.isEmpty()) { - Log.wtf(TAG, "Tethering notify list empty, IPv6 downstreams non-empty."); - } - mNextSubnetId = 0; - } - } - - /** - * Call when UpstreamNetworkState may be changed. - * If upstream has ipv6 for tethering, update this new UpstreamNetworkState - * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces. - */ - public void updateUpstreamNetworkState(UpstreamNetworkState ns) { - if (VDBG) { - Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns)); - } - if (TetheringInterfaceUtils.getIPv6Interface(ns) == null) { - stopIPv6TetheringOnAllInterfaces(); - setUpstreamNetworkState(null); - return; - } - - if (mUpstreamNetworkState != null - && !ns.network.equals(mUpstreamNetworkState.network)) { - stopIPv6TetheringOnAllInterfaces(); - } - - setUpstreamNetworkState(ns); - updateIPv6TetheringInterfaces(); - } - - private void stopIPv6TetheringOnAllInterfaces() { - for (IpServer ipServer : mNotifyList) { - stopIPv6TetheringOn(ipServer); - } - } - - private void setUpstreamNetworkState(UpstreamNetworkState ns) { - if (ns == null) { - mUpstreamNetworkState = null; - } else { - // Make a deep copy of the parts we need. - mUpstreamNetworkState = new UpstreamNetworkState( - new LinkProperties(ns.linkProperties), - new NetworkCapabilities(ns.networkCapabilities), - new Network(ns.network)); - } - - mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState)); - } - - private void updateIPv6TetheringInterfaces() { - for (IpServer ipServer : mNotifyList) { - final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer); - ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp); - break; - } - } - - private int getTtlAdjustment() { - if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) { - return 0; - } - - // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1 - // for carrier requirement. - if (mUpstreamNetworkState.networkCapabilities.hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR)) { - return -1; - } - - // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary - // distinction between tethered and untethered traffic. - return 1; - } - - private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) { - final Downstream ds = findDownstream(ipServer); - if (ds == null) return null; - - if (ds.mode == IpServer.STATE_LOCAL_ONLY) { - // Build a Unique Locally-assigned Prefix configuration. - return getUniqueLocalConfig(mUniqueLocalPrefix, ds.subnetId); - } - - // This downstream is in IpServer.STATE_TETHERED mode. - if (mUpstreamNetworkState == null || mUpstreamNetworkState.linkProperties == null) { - return null; - } - - // NOTE: Here, in future, we would have policies to decide how to divvy - // up the available dedicated prefixes among downstream interfaces. - // At this time we have no such mechanism--we only support tethering - // IPv6 toward the oldest (first requested) active downstream. - - final Downstream currentActive = mActiveDownstreams.peek(); - if (currentActive != null && currentActive.ipServer == ipServer) { - final LinkProperties lp = getIPv6OnlyLinkProperties( - mUpstreamNetworkState.linkProperties); - if (lp.hasIpv6DefaultRoute() && lp.hasGlobalIpv6Address()) { - return lp; - } - } - - return null; - } - - Downstream findDownstream(IpServer ipServer) { - for (Downstream ds : mActiveDownstreams) { - if (ds.ipServer == ipServer) return ds; - } - return null; - } - - private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) { - final LinkProperties v6only = new LinkProperties(); - if (lp == null) { - return v6only; - } - - // NOTE: At this time we don't copy over any information about any - // stacked links. No current stacked link configuration has IPv6. - - v6only.setInterfaceName(lp.getInterfaceName()); - - v6only.setMtu(lp.getMtu()); - - for (LinkAddress linkAddr : lp.getLinkAddresses()) { - if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) { - v6only.addLinkAddress(linkAddr); - } - } - - for (RouteInfo routeInfo : lp.getRoutes()) { - final IpPrefix destination = routeInfo.getDestination(); - if ((destination.getAddress() instanceof Inet6Address) - && (destination.getPrefixLength() <= 64)) { - v6only.addRoute(routeInfo); - } - } - - for (InetAddress dnsServer : lp.getDnsServers()) { - if (isIPv6GlobalAddress(dnsServer)) { - // For now we include ULAs. - v6only.addDnsServer(dnsServer); - } - } - - v6only.setDomains(lp.getDomains()); - - return v6only; - } - - // TODO: Delete this and switch to LinkAddress#isGlobalPreferred once we - // announce our own IPv6 address as DNS server. - private static boolean isIPv6GlobalAddress(InetAddress ip) { - return (ip instanceof Inet6Address) - && !ip.isAnyLocalAddress() - && !ip.isLoopbackAddress() - && !ip.isLinkLocalAddress() - && !ip.isSiteLocalAddress() - && !ip.isMulticastAddress(); - } - - private static LinkProperties getUniqueLocalConfig(byte[] ulp, short subnetId) { - final LinkProperties lp = new LinkProperties(); - - final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48); - lp.addRoute(new RouteInfo(local48, null, null, RouteInfo.RTN_UNICAST)); - - final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64); - // Because this is a locally-generated ULA, we don't have an upstream - // address. But because the downstream IP address management code gets - // its prefix from the upstream's IP address, we create a fake one here. - lp.addLinkAddress(new LinkAddress(local64.getAddress(), 64)); - - lp.setMtu(NetworkConstants.ETHER_MTU); - return lp; - } - - private static IpPrefix makeUniqueLocalPrefix(byte[] in6addr, short subnetId, int prefixlen) { - final byte[] bytes = Arrays.copyOf(in6addr, in6addr.length); - bytes[7] = (byte) (subnetId >> 8); - bytes[8] = (byte) subnetId; - final InetAddress addr; - try { - addr = InetAddress.getByAddress(bytes); - } catch (UnknownHostException e) { - throw new IllegalStateException("Invalid address length: " + bytes.length, e); - } - return new IpPrefix(addr, prefixlen); - } - - // Generates a Unique Locally-assigned Prefix: - // - // https://tools.ietf.org/html/rfc4193#section-3.1 - // - // The result is a /48 that can be used for local-only communications. - private static byte[] generateUniqueLocalPrefix() { - final byte[] ulp = new byte[6]; // 6 = 48bits / 8bits/byte - (new Random()).nextBytes(ulp); - - final byte[] in6addr = Arrays.copyOf(ulp, NetworkConstants.IPV6_ADDR_LEN); - in6addr[0] = (byte) 0xfd; // fc00::/7 and L=1 - - return in6addr; - } - - private static String toDebugString(UpstreamNetworkState ns) { - if (ns == null) { - return "UpstreamNetworkState{null}"; - } - return ns.toString(); - } - - private static void stopIPv6TetheringOn(IpServer ipServer) { - ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java deleted file mode 100644 index 88c77b07e7e3..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStats.UID_TETHERING; -import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; -import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; - -import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.usage.NetworkStatsManager; -import android.content.ContentResolver; -import android.net.InetAddresses; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.NetworkStats; -import android.net.NetworkStats.Entry; -import android.net.RouteInfo; -import android.net.netlink.ConntrackMessage; -import android.net.netlink.NetlinkConstants; -import android.net.netlink.NetlinkSocket; -import android.net.netstats.provider.NetworkStatsProvider; -import android.net.util.SharedLog; -import android.os.Handler; -import android.provider.Settings; -import android.system.ErrnoException; -import android.system.OsConstants; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; -import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * A class to encapsulate the business logic of programming the tethering - * hardware offload interface. - * - * @hide - */ -public class OffloadController { - private static final String TAG = OffloadController.class.getSimpleName(); - private static final boolean DBG = false; - private static final String ANYIP = "0.0.0.0"; - private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); - - @VisibleForTesting - enum StatsType { - STATS_PER_IFACE, - STATS_PER_UID, - } - - private enum UpdateType { IF_NEEDED, FORCE }; - - private final Handler mHandler; - private final OffloadHardwareInterface mHwInterface; - private final ContentResolver mContentResolver; - @Nullable - private final OffloadTetheringStatsProvider mStatsProvider; - private final SharedLog mLog; - private final HashMap<String, LinkProperties> mDownstreams; - private boolean mConfigInitialized; - private boolean mControlInitialized; - private LinkProperties mUpstreamLinkProperties; - // The complete set of offload-exempt prefixes passed in via Tethering from - // all upstream and downstream sources. - private Set<IpPrefix> mExemptPrefixes; - // A strictly "smaller" set of prefixes, wherein offload-approved prefixes - // (e.g. downstream on-link prefixes) have been removed and replaced with - // prefixes representing only the locally-assigned IP addresses. - private Set<String> mLastLocalPrefixStrs; - - // Maps upstream interface names to offloaded traffic statistics. - // Always contains the latest value received from the hardware for each interface, regardless of - // whether offload is currently running on that interface. - private ConcurrentHashMap<String, ForwardedStats> mForwardedStats = - new ConcurrentHashMap<>(16, 0.75F, 1); - - // Maps upstream interface names to interface quotas. - // Always contains the latest value received from the framework for each interface, regardless - // of whether offload is currently running (or is even supported) on that interface. Only - // includes upstream interfaces that have a quota set. - private HashMap<String, Long> mInterfaceQuotas = new HashMap<>(); - - // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert - // quota is interface independent and global for tether offload. Note that this is only - // accessed on the handler thread and in the constructor. - private long mRemainingAlertQuota = QUOTA_UNLIMITED; - // Runnable that used to schedule the next stats poll. - private final Runnable mScheduledPollingTask = () -> { - updateStatsForCurrentUpstream(); - maybeSchedulePollingStats(); - }; - - private int mNatUpdateCallbacksReceived; - private int mNatUpdateNetlinkErrors; - - @NonNull - private final Dependencies mDeps; - - // TODO: Put more parameters in constructor into dependency object. - interface Dependencies { - @NonNull - TetheringConfiguration getTetherConfig(); - } - - public OffloadController(Handler h, OffloadHardwareInterface hwi, - ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log, - @NonNull Dependencies deps) { - mHandler = h; - mHwInterface = hwi; - mContentResolver = contentResolver; - mLog = log.forSubComponent(TAG); - mDownstreams = new HashMap<>(); - mExemptPrefixes = new HashSet<>(); - mLastLocalPrefixStrs = new HashSet<>(); - OffloadTetheringStatsProvider provider = new OffloadTetheringStatsProvider(); - try { - nsm.registerNetworkStatsProvider(getClass().getSimpleName(), provider); - } catch (RuntimeException e) { - Log.wtf(TAG, "Cannot register offload stats provider: " + e); - provider = null; - } - mStatsProvider = provider; - mDeps = deps; - } - - /** Start hardware offload. */ - public boolean start() { - if (started()) return true; - - if (isOffloadDisabled()) { - mLog.i("tethering offload disabled"); - return false; - } - - if (!mConfigInitialized) { - mConfigInitialized = mHwInterface.initOffloadConfig(); - if (!mConfigInitialized) { - mLog.i("tethering offload config not supported"); - stop(); - return false; - } - } - - mControlInitialized = mHwInterface.initOffloadControl( - // OffloadHardwareInterface guarantees that these callback - // methods are called on the handler passed to it, which is the - // same as mHandler, as coordinated by the setup in Tethering. - new OffloadHardwareInterface.ControlCallback() { - @Override - public void onStarted() { - if (!started()) return; - mLog.log("onStarted"); - } - - @Override - public void onStoppedError() { - if (!started()) return; - mLog.log("onStoppedError"); - } - - @Override - public void onStoppedUnsupported() { - if (!started()) return; - mLog.log("onStoppedUnsupported"); - // Poll for statistics and trigger a sweep of tethering - // stats by observers. This might not succeed, but it's - // worth trying anyway. We need to do this because from - // this point on we continue with software forwarding, - // and we need to synchronize stats and limits between - // software and hardware forwarding. - updateStatsForAllUpstreams(); - if (mStatsProvider != null) mStatsProvider.pushTetherStats(); - } - - @Override - public void onSupportAvailable() { - if (!started()) return; - mLog.log("onSupportAvailable"); - - // [1] Poll for statistics and trigger a sweep of stats - // by observers. We need to do this to ensure that any - // limits set take into account any software tethering - // traffic that has been happening in the meantime. - updateStatsForAllUpstreams(); - if (mStatsProvider != null) mStatsProvider.pushTetherStats(); - // [2] (Re)Push all state. - computeAndPushLocalPrefixes(UpdateType.FORCE); - pushAllDownstreamState(); - pushUpstreamParameters(null); - } - - @Override - public void onStoppedLimitReached() { - if (!started()) return; - mLog.log("onStoppedLimitReached"); - - // We cannot reliably determine on which interface the limit was reached, - // because the HAL interface does not specify it. We cannot just use the - // current upstream, because that might have changed since the time that - // the HAL queued the callback. - // TODO: rev the HAL so that it provides an interface name. - - updateStatsForCurrentUpstream(); - if (mStatsProvider != null) { - mStatsProvider.pushTetherStats(); - // Push stats to service does not cause the service react to it - // immediately. Inform the service about limit reached. - mStatsProvider.notifyLimitReached(); - } - } - - @Override - public void onNatTimeoutUpdate(int proto, - String srcAddr, int srcPort, - String dstAddr, int dstPort) { - if (!started()) return; - updateNatTimeout(proto, srcAddr, srcPort, dstAddr, dstPort); - } - }); - - final boolean isStarted = started(); - if (!isStarted) { - mLog.i("tethering offload control not supported"); - stop(); - } else { - mLog.log("tethering offload started"); - mNatUpdateCallbacksReceived = 0; - mNatUpdateNetlinkErrors = 0; - maybeSchedulePollingStats(); - } - return isStarted; - } - - /** Stop hardware offload. */ - public void stop() { - // Completely stops tethering offload. After this method is called, it is no longer safe to - // call any HAL method, no callbacks from the hardware will be delivered, and any in-flight - // callbacks must be ignored. Offload may be started again by calling start(). - final boolean wasStarted = started(); - updateStatsForCurrentUpstream(); - mUpstreamLinkProperties = null; - mHwInterface.stopOffloadControl(); - mControlInitialized = false; - mConfigInitialized = false; - if (mHandler.hasCallbacks(mScheduledPollingTask)) { - mHandler.removeCallbacks(mScheduledPollingTask); - } - if (wasStarted) mLog.log("tethering offload stopped"); - } - - private boolean started() { - return mConfigInitialized && mControlInitialized; - } - - @VisibleForTesting - class OffloadTetheringStatsProvider extends NetworkStatsProvider { - // These stats must only ever be touched on the handler thread. - @NonNull - private NetworkStats mIfaceStats = new NetworkStats(0L, 0); - @NonNull - private NetworkStats mUidStats = new NetworkStats(0L, 0); - - /** - * A helper function that collect tether stats from local hashmap. Note that this does not - * invoke binder call. - */ - @VisibleForTesting - @NonNull - NetworkStats getTetherStats(@NonNull StatsType how) { - NetworkStats stats = new NetworkStats(0L, 0); - final int uid = (how == StatsType.STATS_PER_UID) ? UID_TETHERING : UID_ALL; - - for (final Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) { - final ForwardedStats value = kv.getValue(); - final Entry entry = new Entry(kv.getKey(), uid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, value.rxBytes, 0L, value.txBytes, 0L, 0L); - stats = stats.addEntry(entry); - } - - return stats; - } - - @Override - public void onSetLimit(String iface, long quotaBytes) { - // Listen for all iface is necessary since upstream might be changed after limit - // is set. - mHandler.post(() -> { - final Long curIfaceQuota = mInterfaceQuotas.get(iface); - - // If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE, - // which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not - // useful to set it multiple times. - // Otherwise, the quota needs to be updated to tell HAL to re-count from now even - // if the quota is the same as the existing one. - if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return; - - if (quotaBytes == QUOTA_UNLIMITED) { - mInterfaceQuotas.remove(iface); - } else { - mInterfaceQuotas.put(iface, quotaBytes); - } - maybeUpdateDataLimit(iface); - }); - } - - /** - * Push stats to service, but does not cause a force polling. Note that this can only be - * called on the handler thread. - */ - public void pushTetherStats() { - // TODO: remove the accumulated stats and report the diff from HAL directly. - final NetworkStats ifaceDiff = - getTetherStats(StatsType.STATS_PER_IFACE).subtract(mIfaceStats); - final NetworkStats uidDiff = - getTetherStats(StatsType.STATS_PER_UID).subtract(mUidStats); - try { - notifyStatsUpdated(0 /* token */, ifaceDiff, uidDiff); - mIfaceStats = mIfaceStats.add(ifaceDiff); - mUidStats = mUidStats.add(uidDiff); - } catch (RuntimeException e) { - mLog.e("Cannot report network stats: ", e); - } - } - - @Override - public void onRequestStatsUpdate(int token) { - // Do not attempt to update stats by querying the offload HAL - // synchronously from a different thread than the Handler thread. http://b/64771555. - mHandler.post(() -> { - updateStatsForCurrentUpstream(); - pushTetherStats(); - }); - } - - @Override - public void onSetAlert(long quotaBytes) { - // TODO: Ask offload HAL to notify alert without stopping traffic. - // Post it to handler thread since it access remaining quota bytes. - mHandler.post(() -> { - updateAlertQuota(quotaBytes); - maybeSchedulePollingStats(); - }); - } - } - - private String currentUpstreamInterface() { - return (mUpstreamLinkProperties != null) - ? mUpstreamLinkProperties.getInterfaceName() : null; - } - - private void maybeUpdateStats(String iface) { - if (TextUtils.isEmpty(iface)) { - return; - } - - // Always called on the handler thread. - // - // Use get()/put() instead of updating ForwardedStats in place because we can be called - // concurrently with getTetherStats. In combination with the guarantees provided by - // ConcurrentHashMap, this ensures that getTetherStats always gets the most recent copy of - // the stats for each interface, and does not observe partial writes where rxBytes is - // updated and txBytes is not. - ForwardedStats diff = mHwInterface.getForwardedStats(iface); - final long usedAlertQuota = diff.rxBytes + diff.txBytes; - ForwardedStats base = mForwardedStats.get(iface); - if (base != null) { - diff.add(base); - } - - // Update remaining alert quota if it is still positive. - if (mRemainingAlertQuota > 0 && usedAlertQuota > 0) { - // Trim to zero if overshoot. - final long newQuota = Math.max(mRemainingAlertQuota - usedAlertQuota, 0); - updateAlertQuota(newQuota); - } - - mForwardedStats.put(iface, diff); - // diff is a new object, just created by getForwardedStats(). Therefore, anyone reading from - // mForwardedStats (i.e., any caller of getTetherStats) will see the new stats immediately. - } - - /** - * Update remaining alert quota, fire the {@link NetworkStatsProvider#notifyAlertReached()} - * callback when it reaches zero. This can be invoked either from service setting the alert, or - * {@code maybeUpdateStats} when updating stats. Note that this can be only called on - * handler thread. - * - * @param newQuota non-negative value to indicate the new quota, or - * {@link NetworkStatsProvider#QUOTA_UNLIMITED} to indicate there is no - * quota. - */ - private void updateAlertQuota(long newQuota) { - if (newQuota < QUOTA_UNLIMITED) { - throw new IllegalArgumentException("invalid quota value " + newQuota); - } - if (mRemainingAlertQuota == newQuota) return; - - mRemainingAlertQuota = newQuota; - if (mRemainingAlertQuota == 0) { - mLog.i("notifyAlertReached"); - if (mStatsProvider != null) mStatsProvider.notifyAlertReached(); - } - } - - /** - * Schedule polling if needed, this will be stopped if offload has been - * stopped or remaining quota reaches zero or upstream is empty. - * Note that this can be only called on handler thread. - */ - private void maybeSchedulePollingStats() { - if (!isPollingStatsNeeded()) return; - - if (mHandler.hasCallbacks(mScheduledPollingTask)) { - mHandler.removeCallbacks(mScheduledPollingTask); - } - mHandler.postDelayed(mScheduledPollingTask, - mDeps.getTetherConfig().getOffloadPollInterval()); - } - - private boolean isPollingStatsNeeded() { - return started() && mRemainingAlertQuota > 0 - && !TextUtils.isEmpty(currentUpstreamInterface()) - && mDeps.getTetherConfig() != null - && mDeps.getTetherConfig().getOffloadPollInterval() - >= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; - } - - private boolean maybeUpdateDataLimit(String iface) { - // setDataLimit may only be called while offload is occurring on this upstream. - if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { - return true; - } - - Long limit = mInterfaceQuotas.get(iface); - if (limit == null) { - limit = Long.MAX_VALUE; - } - - return mHwInterface.setDataLimit(iface, limit); - } - - private void updateStatsForCurrentUpstream() { - maybeUpdateStats(currentUpstreamInterface()); - } - - private void updateStatsForAllUpstreams() { - // In practice, there should only ever be a single digit number of - // upstream interfaces over the lifetime of an active tethering session. - // Roughly speaking, imagine a very ambitious one or two of each of the - // following interface types: [ "rmnet_data", "wlan", "eth", "rndis" ]. - for (Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) { - maybeUpdateStats(kv.getKey()); - } - } - - /** Set current tethering upstream LinkProperties. */ - public void setUpstreamLinkProperties(LinkProperties lp) { - if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return; - - final String prevUpstream = currentUpstreamInterface(); - - mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null; - // Make sure we record this interface in the ForwardedStats map. - final String iface = currentUpstreamInterface(); - if (!TextUtils.isEmpty(iface)) mForwardedStats.putIfAbsent(iface, EMPTY_STATS); - - maybeSchedulePollingStats(); - - // TODO: examine return code and decide what to do if programming - // upstream parameters fails (probably just wait for a subsequent - // onOffloadEvent() callback to tell us offload is available again and - // then reapply all state). - computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); - pushUpstreamParameters(prevUpstream); - } - - /** Set local prefixes. */ - public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { - mExemptPrefixes = localPrefixes; - - if (!started()) return; - computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); - } - - /** Update current downstream LinkProperties. */ - public void notifyDownstreamLinkProperties(LinkProperties lp) { - final String ifname = lp.getInterfaceName(); - final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp)); - if (Objects.equals(oldLp, lp)) return; - - if (!started()) return; - pushDownstreamState(oldLp, lp); - } - - private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) { - final String ifname = newLp.getInterfaceName(); - final List<RouteInfo> oldRoutes = - (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST; - final List<RouteInfo> newRoutes = newLp.getRoutes(); - - // For each old route, if not in new routes: remove. - for (RouteInfo ri : oldRoutes) { - if (shouldIgnoreDownstreamRoute(ri)) continue; - if (!newRoutes.contains(ri)) { - mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString()); - } - } - - // For each new route, if not in old routes: add. - for (RouteInfo ri : newRoutes) { - if (shouldIgnoreDownstreamRoute(ri)) continue; - if (!oldRoutes.contains(ri)) { - mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString()); - } - } - } - - private void pushAllDownstreamState() { - for (LinkProperties lp : mDownstreams.values()) { - pushDownstreamState(null, lp); - } - } - - /** Remove downstream interface from offload hardware. */ - public void removeDownstreamInterface(String ifname) { - final LinkProperties lp = mDownstreams.remove(ifname); - if (lp == null) return; - - if (!started()) return; - - for (RouteInfo route : lp.getRoutes()) { - if (shouldIgnoreDownstreamRoute(route)) continue; - mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString()); - } - } - - private boolean isOffloadDisabled() { - final int defaultDisposition = mHwInterface.getDefaultTetherOffloadDisabled(); - return (Settings.Global.getInt( - mContentResolver, TETHER_OFFLOAD_DISABLED, defaultDisposition) != 0); - } - - private boolean pushUpstreamParameters(String prevUpstream) { - final String iface = currentUpstreamInterface(); - - if (TextUtils.isEmpty(iface)) { - final boolean rval = mHwInterface.setUpstreamParameters("", ANYIP, ANYIP, null); - // Update stats after we've told the hardware to stop forwarding so - // we don't miss packets. - maybeUpdateStats(prevUpstream); - return rval; - } - - // A stacked interface cannot be an upstream for hardware offload. - // Consequently, we examine only the primary interface name, look at - // getAddresses() rather than getAllAddresses(), and check getRoutes() - // rather than getAllRoutes(). - final ArrayList<String> v6gateways = new ArrayList<>(); - String v4addr = null; - String v4gateway = null; - - for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) { - if (ip instanceof Inet4Address) { - v4addr = ip.getHostAddress(); - break; - } - } - - // Find the gateway addresses of all default routes of either address family. - for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) { - if (!ri.hasGateway()) continue; - - final String gateway = ri.getGateway().getHostAddress(); - final InetAddress address = ri.getDestination().getAddress(); - if (ri.isDefaultRoute() && address instanceof Inet4Address) { - v4gateway = gateway; - } else if (ri.isDefaultRoute() && address instanceof Inet6Address) { - v6gateways.add(gateway); - } - } - - boolean success = mHwInterface.setUpstreamParameters( - iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways)); - - if (!success) { - return success; - } - - // Update stats after we've told the hardware to change routing so we don't miss packets. - maybeUpdateStats(prevUpstream); - - // Data limits can only be set once offload is running on the upstream. - success = maybeUpdateDataLimit(iface); - if (!success) { - // If we failed to set a data limit, don't use this upstream, because we don't want to - // blow through the data limit that we were told to apply. - mLog.log("Setting data limit for " + iface + " failed, disabling offload."); - stop(); - } - - return success; - } - - private boolean computeAndPushLocalPrefixes(UpdateType how) { - final boolean force = (how == UpdateType.FORCE); - final Set<String> localPrefixStrs = computeLocalPrefixStrings( - mExemptPrefixes, mUpstreamLinkProperties); - if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; - - mLastLocalPrefixStrs = localPrefixStrs; - return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs)); - } - - // TODO: Factor in downstream LinkProperties once that information is available. - private static Set<String> computeLocalPrefixStrings( - Set<IpPrefix> localPrefixes, LinkProperties upstreamLinkProperties) { - // Create an editable copy. - final Set<IpPrefix> prefixSet = new HashSet<>(localPrefixes); - - // TODO: If a downstream interface (not currently passed in) is reusing - // the /64 of the upstream (64share) then: - // - // [a] remove that /64 from the local prefixes - // [b] add in /128s for IP addresses on the downstream interface - // [c] add in /128s for IP addresses on the upstream interface - // - // Until downstream information is available here, simply add /128s from - // the upstream network; they'll just be redundant with their /64. - if (upstreamLinkProperties != null) { - for (LinkAddress linkAddr : upstreamLinkProperties.getLinkAddresses()) { - if (!linkAddr.isGlobalPreferred()) continue; - final InetAddress ip = linkAddr.getAddress(); - if (!(ip instanceof Inet6Address)) continue; - prefixSet.add(new IpPrefix(ip, 128)); - } - } - - final HashSet<String> localPrefixStrs = new HashSet<>(); - for (IpPrefix pfx : prefixSet) localPrefixStrs.add(pfx.toString()); - return localPrefixStrs; - } - - private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) { - // Ignore any link-local routes. - final IpPrefix destination = route.getDestination(); - final LinkAddress linkAddr = new LinkAddress(destination.getAddress(), - destination.getPrefixLength()); - if (!linkAddr.isGlobalPreferred()) return true; - - return false; - } - - /** Dump information. */ - public void dump(IndentingPrintWriter pw) { - if (isOffloadDisabled()) { - pw.println("Offload disabled"); - return; - } - final boolean isStarted = started(); - pw.println("Offload HALs " + (isStarted ? "started" : "not started")); - LinkProperties lp = mUpstreamLinkProperties; - String upstream = (lp != null) ? lp.getInterfaceName() : null; - pw.println("Current upstream: " + upstream); - pw.println("Exempt prefixes: " + mLastLocalPrefixStrs); - pw.println("NAT timeout update callbacks received during the " - + (isStarted ? "current" : "last") - + " offload session: " - + mNatUpdateCallbacksReceived); - pw.println("NAT timeout update netlink errors during the " - + (isStarted ? "current" : "last") - + " offload session: " - + mNatUpdateNetlinkErrors); - } - - private void updateNatTimeout( - int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) { - final String protoName = protoNameFor(proto); - if (protoName == null) { - mLog.e("Unknown NAT update callback protocol: " + proto); - return; - } - - final Inet4Address src = parseIPv4Address(srcAddr); - if (src == null) { - mLog.e("Failed to parse IPv4 address: " + srcAddr); - return; - } - - if (!isValidUdpOrTcpPort(srcPort)) { - mLog.e("Invalid src port: " + srcPort); - return; - } - - final Inet4Address dst = parseIPv4Address(dstAddr); - if (dst == null) { - mLog.e("Failed to parse IPv4 address: " + dstAddr); - return; - } - - if (!isValidUdpOrTcpPort(dstPort)) { - mLog.e("Invalid dst port: " + dstPort); - return; - } - - mNatUpdateCallbacksReceived++; - final String natDescription = String.format("%s (%s, %s) -> (%s, %s)", - protoName, srcAddr, srcPort, dstAddr, dstPort); - if (DBG) { - mLog.log("NAT timeout update: " + natDescription); - } - - final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto); - final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest( - proto, src, srcPort, dst, dstPort, timeoutSec); - - try { - NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg); - } catch (ErrnoException e) { - mNatUpdateNetlinkErrors++; - mLog.e("Error updating NAT conntrack entry >" + natDescription + "<: " + e - + ", msg: " + NetlinkConstants.hexify(msg)); - mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived); - mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors); - } - } - - private static Inet4Address parseIPv4Address(String addrString) { - try { - final InetAddress ip = InetAddresses.parseNumericAddress(addrString); - // TODO: Consider other sanitization steps here, including perhaps: - // not eql to 0.0.0.0 - // not within 169.254.0.0/16 - // not within ::ffff:0.0.0.0/96 - // not within ::/96 - // et cetera. - if (ip instanceof Inet4Address) { - return (Inet4Address) ip; - } - } catch (IllegalArgumentException iae) { } - return null; - } - - private static String protoNameFor(int proto) { - // OsConstants values are not constant expressions; no switch statement. - if (proto == OsConstants.IPPROTO_UDP) { - return "UDP"; - } else if (proto == OsConstants.IPPROTO_TCP) { - return "TCP"; - } - return null; - } - - private static int connectionTimeoutUpdateSecondsFor(int proto) { - // TODO: Replace this with more thoughtful work, perhaps reading from - // and maybe writing to any required - // - // /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_* - // /proc/sys/net/netfilter/nf_conntrack_udp_timeout{,_stream} - // - // entries. TBD. - if (proto == OsConstants.IPPROTO_TCP) { - // Cf. /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established - return 432000; - } else { - // Cf. /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream - return 180; - } - } - - private static boolean isValidUdpOrTcpPort(int port) { - return port > 0 && port < 65536; - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java deleted file mode 100644 index da5f25b2a596..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; -import static android.net.util.TetheringUtils.uint16; - -import android.annotation.NonNull; -import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; -import android.hardware.tetheroffload.control.V1_0.IOffloadControl; -import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; -import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; -import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; -import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; -import android.net.netlink.NetlinkSocket; -import android.net.netlink.StructNfGenMsg; -import android.net.netlink.StructNlMsgHdr; -import android.net.util.SharedLog; -import android.net.util.SocketUtils; -import android.os.Handler; -import android.os.NativeHandle; -import android.os.RemoteException; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.NoSuchElementException; - - -/** - * Capture tethering dependencies, for injection. - * - * @hide - */ -public class OffloadHardwareInterface { - private static final String TAG = OffloadHardwareInterface.class.getSimpleName(); - private static final String YIELDS = " -> "; - // Change this value to control whether tether offload is enabled or - // disabled by default in the absence of an explicit Settings value. - // See accompanying unittest to distinguish 0 from non-0 values. - private static final int DEFAULT_TETHER_OFFLOAD_DISABLED = 0; - private static final String NO_INTERFACE_NAME = ""; - private static final String NO_IPV4_ADDRESS = ""; - private static final String NO_IPV4_GATEWAY = ""; - // Reference kernel/uapi/linux/netfilter/nfnetlink_compat.h - public static final int NF_NETLINK_CONNTRACK_NEW = 1; - public static final int NF_NETLINK_CONNTRACK_UPDATE = 2; - public static final int NF_NETLINK_CONNTRACK_DESTROY = 4; - // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h - public static final short NFNL_SUBSYS_CTNETLINK = 1; - public static final short IPCTNL_MSG_CT_NEW = 0; - public static final short IPCTNL_MSG_CT_GET = 1; - - private final long NETLINK_MESSAGE_TIMEOUT_MS = 500; - - private final Handler mHandler; - private final SharedLog mLog; - private final Dependencies mDeps; - private IOffloadControl mOffloadControl; - private TetheringOffloadCallback mTetheringOffloadCallback; - private ControlCallback mControlCallback; - - /** The callback to notify status of offload management process. */ - public static class ControlCallback { - /** Offload started. */ - public void onStarted() {} - /** - * Offload stopped because an error has occurred in lower layer. - */ - public void onStoppedError() {} - /** - * Offload stopped because the device has moved to a bearer on which hardware offload is - * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will - * likely fail and cannot be presumed to be saved inside of the hardware management process. - * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin - * offload again. - */ - public void onStoppedUnsupported() {} - /** Indicate that offload is able to proivde support for this time. */ - public void onSupportAvailable() {} - /** Offload stopped because of usage limit reached. */ - public void onStoppedLimitReached() {} - - /** Indicate to update NAT timeout. */ - public void onNatTimeoutUpdate(int proto, - String srcAddr, int srcPort, - String dstAddr, int dstPort) {} - } - - /** The object which records Tx/Rx forwarded bytes. */ - public static class ForwardedStats { - public long rxBytes; - public long txBytes; - - public ForwardedStats() { - rxBytes = 0; - txBytes = 0; - } - - @VisibleForTesting - public ForwardedStats(long rxBytes, long txBytes) { - this.rxBytes = rxBytes; - this.txBytes = txBytes; - } - - /** Add Tx/Rx bytes. */ - public void add(ForwardedStats other) { - rxBytes += other.rxBytes; - txBytes += other.txBytes; - } - - /** Returns the string representation of this object. */ - public String toString() { - return String.format("rx:%s tx:%s", rxBytes, txBytes); - } - } - - public OffloadHardwareInterface(Handler h, SharedLog log) { - this(h, log, new Dependencies(log)); - } - - OffloadHardwareInterface(Handler h, SharedLog log, Dependencies deps) { - mHandler = h; - mLog = log.forSubComponent(TAG); - mDeps = deps; - } - - /** Capture OffloadHardwareInterface dependencies, for injection. */ - static class Dependencies { - private final SharedLog mLog; - - Dependencies(SharedLog log) { - mLog = log; - } - - public IOffloadConfig getOffloadConfig() { - try { - return IOffloadConfig.getService(true /*retry*/); - } catch (RemoteException | NoSuchElementException e) { - mLog.e("getIOffloadConfig error " + e); - return null; - } - } - - public IOffloadControl getOffloadControl() { - try { - return IOffloadControl.getService(true /*retry*/); - } catch (RemoteException | NoSuchElementException e) { - mLog.e("tethering offload control not supported: " + e); - return null; - } - } - - public NativeHandle createConntrackSocket(final int groups) { - final FileDescriptor fd; - try { - fd = NetlinkSocket.forProto(OsConstants.NETLINK_NETFILTER); - } catch (ErrnoException e) { - mLog.e("Unable to create conntrack socket " + e); - return null; - } - - final SocketAddress sockAddr = SocketUtils.makeNetlinkSocketAddress(0, groups); - try { - Os.bind(fd, sockAddr); - } catch (ErrnoException | SocketException e) { - mLog.e("Unable to bind conntrack socket for groups " + groups + " error: " + e); - try { - SocketUtils.closeSocket(fd); - } catch (IOException ie) { - // Nothing we can do here - } - return null; - } - try { - Os.connect(fd, sockAddr); - } catch (ErrnoException | SocketException e) { - mLog.e("connect to kernel fail for groups " + groups + " error: " + e); - try { - SocketUtils.closeSocket(fd); - } catch (IOException ie) { - // Nothing we can do here - } - return null; - } - - return new NativeHandle(fd, true); - } - } - - /** Get default value indicating whether offload is supported. */ - public int getDefaultTetherOffloadDisabled() { - return DEFAULT_TETHER_OFFLOAD_DISABLED; - } - - /** - * Offload management process need to know conntrack rules to support NAT, but it may not have - * permission to create netlink netfilter sockets. Create two netlink netfilter sockets and - * share them with offload management process. - */ - public boolean initOffloadConfig() { - final IOffloadConfig offloadConfig = mDeps.getOffloadConfig(); - if (offloadConfig == null) { - mLog.e("Could not find IOffloadConfig service"); - return false; - } - // Per the IConfigOffload definition: - // - // h1 provides a file descriptor bound to the following netlink groups - // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY). - // - // h2 provides a file descriptor bound to the following netlink groups - // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY). - final NativeHandle h1 = mDeps.createConntrackSocket( - NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); - if (h1 == null) return false; - - sendIpv4NfGenMsg(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET), - (short) (NLM_F_REQUEST | NLM_F_DUMP)); - - final NativeHandle h2 = mDeps.createConntrackSocket( - NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); - if (h2 == null) { - closeFdInNativeHandle(h1); - return false; - } - - final CbResults results = new CbResults(); - try { - offloadConfig.setHandles(h1, h2, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record("initOffloadConfig, setHandles fail", e); - return false; - } - // Explicitly close FDs. - closeFdInNativeHandle(h1); - closeFdInNativeHandle(h2); - - record("initOffloadConfig, setHandles results:", results); - return results.mSuccess; - } - - @VisibleForTesting - public void sendIpv4NfGenMsg(@NonNull NativeHandle handle, short type, short flags) { - final int length = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; - final byte[] msg = new byte[length]; - final ByteBuffer byteBuffer = ByteBuffer.wrap(msg); - byteBuffer.order(ByteOrder.nativeOrder()); - - final StructNlMsgHdr nlh = new StructNlMsgHdr(); - nlh.nlmsg_len = length; - nlh.nlmsg_type = type; - nlh.nlmsg_flags = flags; - nlh.nlmsg_seq = 0; - nlh.pack(byteBuffer); - - // Header needs to be added to buffer since a generic netlink request is being sent. - final StructNfGenMsg nfh = new StructNfGenMsg((byte) OsConstants.AF_INET); - nfh.pack(byteBuffer); - - try { - NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length, - NETLINK_MESSAGE_TIMEOUT_MS); - } catch (ErrnoException | InterruptedIOException e) { - mLog.e("Unable to send netfilter message, error: " + e); - } - } - - private void closeFdInNativeHandle(final NativeHandle h) { - try { - h.close(); - } catch (IOException | IllegalStateException e) { - // IllegalStateException means fd is already closed, do nothing here. - // Also nothing we can do if IOException. - } - } - - /** Initialize the tethering offload HAL. */ - public boolean initOffloadControl(ControlCallback controlCb) { - mControlCallback = controlCb; - - if (mOffloadControl == null) { - mOffloadControl = mDeps.getOffloadControl(); - if (mOffloadControl == null) { - mLog.e("tethering IOffloadControl.getService() returned null"); - return false; - } - } - - final String logmsg = String.format("initOffloadControl(%s)", - (controlCb == null) ? "null" - : "0x" + Integer.toHexString(System.identityHashCode(controlCb))); - - mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback, mLog); - final CbResults results = new CbResults(); - try { - mOffloadControl.initOffload( - mTetheringOffloadCallback, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - /** Stop IOffloadControl. */ - public void stopOffloadControl() { - if (mOffloadControl != null) { - try { - mOffloadControl.stopOffload( - (boolean success, String errMsg) -> { - if (!success) mLog.e("stopOffload failed: " + errMsg); - }); - } catch (RemoteException e) { - mLog.e("failed to stopOffload: " + e); - } - } - mOffloadControl = null; - mTetheringOffloadCallback = null; - mControlCallback = null; - mLog.log("stopOffloadControl()"); - } - - /** Get Tx/Rx usage from last query. */ - public ForwardedStats getForwardedStats(String upstream) { - final String logmsg = String.format("getForwardedStats(%s)", upstream); - - final ForwardedStats stats = new ForwardedStats(); - try { - mOffloadControl.getForwardedStats( - upstream, - (long rxBytes, long txBytes) -> { - stats.rxBytes = (rxBytes > 0) ? rxBytes : 0; - stats.txBytes = (txBytes > 0) ? txBytes : 0; - }); - } catch (RemoteException e) { - record(logmsg, e); - return stats; - } - - return stats; - } - - /** Set local prefixes to offload management process. */ - public boolean setLocalPrefixes(ArrayList<String> localPrefixes) { - final String logmsg = String.format("setLocalPrefixes([%s])", - String.join(",", localPrefixes)); - - final CbResults results = new CbResults(); - try { - mOffloadControl.setLocalPrefixes(localPrefixes, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - /** Set data limit value to offload management process. */ - public boolean setDataLimit(String iface, long limit) { - - final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit); - - final CbResults results = new CbResults(); - try { - mOffloadControl.setDataLimit( - iface, limit, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - /** Set upstream parameters to offload management process. */ - public boolean setUpstreamParameters( - String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) { - iface = (iface != null) ? iface : NO_INTERFACE_NAME; - v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS; - v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY; - v6gws = (v6gws != null) ? v6gws : new ArrayList<>(); - - final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])", - iface, v4addr, v4gateway, String.join(",", v6gws)); - - final CbResults results = new CbResults(); - try { - mOffloadControl.setUpstreamParameters( - iface, v4addr, v4gateway, v6gws, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - /** Add downstream prefix to offload management process. */ - public boolean addDownstreamPrefix(String ifname, String prefix) { - final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix); - - final CbResults results = new CbResults(); - try { - mOffloadControl.addDownstream(ifname, prefix, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - /** Remove downstream prefix from offload management process. */ - public boolean removeDownstreamPrefix(String ifname, String prefix) { - final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix); - - final CbResults results = new CbResults(); - try { - mOffloadControl.removeDownstream(ifname, prefix, - (boolean success, String errMsg) -> { - results.mSuccess = success; - results.mErrMsg = errMsg; - }); - } catch (RemoteException e) { - record(logmsg, e); - return false; - } - - record(logmsg, results); - return results.mSuccess; - } - - private void record(String msg, Throwable t) { - mLog.e(msg + YIELDS + "exception: " + t); - } - - private void record(String msg, CbResults results) { - final String logmsg = msg + YIELDS + results; - if (!results.mSuccess) { - mLog.e(logmsg); - } else { - mLog.log(logmsg); - } - } - - private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub { - public final Handler handler; - public final ControlCallback controlCb; - public final SharedLog log; - - TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) { - handler = h; - controlCb = cb; - log = sharedLog; - } - - @Override - public void onEvent(int event) { - handler.post(() -> { - switch (event) { - case OffloadCallbackEvent.OFFLOAD_STARTED: - controlCb.onStarted(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR: - controlCb.onStoppedError(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED: - controlCb.onStoppedUnsupported(); - break; - case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE: - controlCb.onSupportAvailable(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED: - controlCb.onStoppedLimitReached(); - break; - default: - log.e("Unsupported OffloadCallbackEvent: " + event); - } - }); - } - - @Override - public void updateTimeout(NatTimeoutUpdate params) { - handler.post(() -> { - controlCb.onNatTimeoutUpdate( - networkProtocolToOsConstant(params.proto), - params.src.addr, uint16(params.src.port), - params.dst.addr, uint16(params.dst.port)); - }); - } - } - - private static int networkProtocolToOsConstant(int proto) { - switch (proto) { - case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP; - case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP; - default: - // The caller checks this value and will log an error. Just make - // sure it won't collide with valid OsContants.IPPROTO_* values. - return -Math.abs(proto); - } - } - - private static class CbResults { - boolean mSuccess; - String mErrMsg; - - @Override - public String toString() { - if (mSuccess) { - return "ok"; - } else { - return "fail: " + mErrMsg; - } - } - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java deleted file mode 100644 index 4f616cdff086..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.networkstack.tethering; - -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.TetheringManager.TETHERING_BLUETOOTH; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.util.PrefixUtils.asIpPrefix; - -import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; -import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; -import static com.android.net.module.util.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH; - -import static java.util.Arrays.asList; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.Network; -import android.net.ip.IpServer; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.SparseArray; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -/** - * This class coordinate IP addresses conflict problem. - * - * Tethering downstream IP addresses may conflict with network assigned addresses. This - * coordinator is responsible for recording all of network assigned addresses and dispatched - * free address to downstream interfaces. - * - * This class is not thread-safe and should be accessed on the same tethering internal thread. - * @hide - */ -public class PrivateAddressCoordinator { - public static final int PREFIX_LENGTH = 24; - - // Upstream monitor would be stopped when tethering is down. When tethering restart, downstream - // address may be requested before coordinator get current upstream notification. To ensure - // coordinator do not select conflict downstream prefix, mUpstreamPrefixMap would not be cleared - // when tethering is down. Instead tethering would remove all deprecated upstreams from - // mUpstreamPrefixMap when tethering is starting. See #maybeRemoveDeprecatedUpstreams(). - private final ArrayMap<Network, List<IpPrefix>> mUpstreamPrefixMap; - private final ArraySet<IpServer> mDownstreams; - private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24"; - private static final String LEGACY_BLUETOOTH_IFACE_ADDRESS = "192.168.44.1/24"; - private final List<IpPrefix> mTetheringPrefixes; - private final ConnectivityManager mConnectivityMgr; - private final TetheringConfiguration mConfig; - // keyed by downstream type(TetheringManager.TETHERING_*). - private final SparseArray<LinkAddress> mCachedAddresses; - - public PrivateAddressCoordinator(Context context, TetheringConfiguration config) { - mDownstreams = new ArraySet<>(); - mUpstreamPrefixMap = new ArrayMap<>(); - mConnectivityMgr = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); - mConfig = config; - mCachedAddresses = new SparseArray<>(); - // Reserved static addresses for bluetooth and wifi p2p. - mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS)); - mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS)); - - mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))); - if (config.isSelectAllPrefixRangeEnabled()) { - mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12")); - mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8")); - } - } - - /** - * Record a new upstream IpPrefix which may conflict with tethering downstreams. - * The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called, - * UpstreamNetworkState must have an already populated LinkProperties. - */ - public void updateUpstreamPrefix(final UpstreamNetworkState ns) { - // Do not support VPN as upstream. Normally, networkCapabilities is not expected to be null, - // but just checking to be sure. - if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) { - removeUpstreamPrefix(ns.network); - return; - } - - final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes( - ns.linkProperties.getAllLinkAddresses()); - if (ipv4Prefixes.isEmpty()) { - removeUpstreamPrefix(ns.network); - return; - } - - mUpstreamPrefixMap.put(ns.network, ipv4Prefixes); - handleMaybePrefixConflict(ipv4Prefixes); - } - - private ArrayList<IpPrefix> getIpv4Prefixes(final List<LinkAddress> linkAddresses) { - final ArrayList<IpPrefix> list = new ArrayList<>(); - for (LinkAddress address : linkAddresses) { - if (!address.isIpv4()) continue; - - list.add(asIpPrefix(address)); - } - - return list; - } - - private void handleMaybePrefixConflict(final List<IpPrefix> prefixes) { - for (IpServer downstream : mDownstreams) { - final IpPrefix target = getDownstreamPrefix(downstream); - - for (IpPrefix source : prefixes) { - if (isConflictPrefix(source, target)) { - downstream.sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - break; - } - } - } - } - - /** Remove IpPrefix records corresponding to input network. */ - public void removeUpstreamPrefix(final Network network) { - mUpstreamPrefixMap.remove(network); - } - - /** - * Maybe remove deprecated upstream records, this would be called once tethering started without - * any exiting tethered downstream. - */ - public void maybeRemoveDeprecatedUpstreams() { - if (mUpstreamPrefixMap.isEmpty()) return; - - // Remove all upstreams that are no longer valid networks - final Set<Network> toBeRemoved = new HashSet<>(mUpstreamPrefixMap.keySet()); - toBeRemoved.removeAll(asList(mConnectivityMgr.getAllNetworks())); - - mUpstreamPrefixMap.removeAll(toBeRemoved); - } - - /** - * Pick a random available address and mark its prefix as in use for the provided IpServer, - * returns null if there is no available address. - */ - @Nullable - public LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) { - if (mConfig.shouldEnableWifiP2pDedicatedIp() - && ipServer.interfaceType() == TETHERING_WIFI_P2P) { - return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS); - } - - final LinkAddress cachedAddress = mCachedAddresses.get(ipServer.interfaceType()); - if (useLastAddress && cachedAddress != null - && !isConflictWithUpstream(asIpPrefix(cachedAddress))) { - mDownstreams.add(ipServer); - return cachedAddress; - } - - for (IpPrefix prefixRange : mTetheringPrefixes) { - final LinkAddress newAddress = chooseDownstreamAddress(prefixRange); - if (newAddress != null) { - mDownstreams.add(ipServer); - mCachedAddresses.put(ipServer.interfaceType(), newAddress); - return newAddress; - } - } - - // No available address. - return null; - } - - private int getPrefixBaseAddress(final IpPrefix prefix) { - return inet4AddressToIntHTH((Inet4Address) prefix.getAddress()); - } - - /** - * Check whether input prefix conflict with upstream prefixes or in-use downstream prefixes. - * If yes, return one of them. - */ - private IpPrefix getConflictPrefix(final IpPrefix prefix) { - final IpPrefix upstream = getConflictWithUpstream(prefix); - if (upstream != null) return upstream; - - return getInUseDownstreamPrefix(prefix); - } - - // Get the next non-conflict sub prefix. E.g: To get next sub prefix from 10.0.0.0/8, if the - // previously selected prefix is 10.20.42.0/24(subPrefix: 0.20.42.0) and the conflicting prefix - // is 10.16.0.0/20 (10.16.0.0 ~ 10.16.15.255), then the max address under subPrefix is - // 0.16.15.255 and the next subPrefix is 0.16.16.255/24 (0.16.15.255 + 0.0.1.0). - // Note: the sub address 0.0.0.255 here is fine to be any value that it will be replaced as - // selected random sub address later. - private int getNextSubPrefix(final IpPrefix conflictPrefix, final int prefixRangeMask) { - final int suffixMask = ~prefixLengthToV4NetmaskIntHTH(conflictPrefix.getPrefixLength()); - // The largest offset within the prefix assignment block that still conflicts with - // conflictPrefix. - final int maxConflict = - (getPrefixBaseAddress(conflictPrefix) | suffixMask) & ~prefixRangeMask; - - final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH); - // Pick a sub prefix a full prefix (1 << (32 - PREFIX_LENGTH) addresses) greater than - // maxConflict. This ensures that the selected prefix never overlaps with conflictPrefix. - // There is no need to mask the result with PREFIX_LENGTH bits because this is done by - // findAvailablePrefixFromRange when it constructs the prefix. - return maxConflict + (1 << (32 - PREFIX_LENGTH)); - } - - private LinkAddress chooseDownstreamAddress(final IpPrefix prefixRange) { - // The netmask of the prefix assignment block (e.g., 0xfff00000 for 172.16.0.0/12). - final int prefixRangeMask = prefixLengthToV4NetmaskIntHTH(prefixRange.getPrefixLength()); - - // The zero address in the block (e.g., 0xac100000 for 172.16.0.0/12). - final int baseAddress = getPrefixBaseAddress(prefixRange); - - // The subnet mask corresponding to PREFIX_LENGTH. - final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH); - - // The offset within prefixRange of a randomly-selected prefix of length PREFIX_LENGTH. - // This may not be the prefix of the address returned by this method: - // - If it is already in use, the method will return an address in another prefix. - // - If all prefixes within prefixRange are in use, the method will return null. For - // example, for a /24 prefix within 172.26.0.0/12, this will be a multiple of 256 in - // [0, 1048576). In other words, a random 32-bit number with mask 0x000fff00. - // - // prefixRangeMask is required to ensure no wrapping. For example, consider: - // - prefixRange 127.0.0.0/8 - // - randomPrefixStart 127.255.255.0 - // - A conflicting prefix of 127.255.254.0/23 - // In this case without prefixRangeMask, getNextSubPrefix would return 128.0.0.0, which - // means the "start < end" check in findAvailablePrefixFromRange would not reject the prefix - // because Java doesn't have unsigned integers, so 128.0.0.0 = 0x80000000 = -2147483648 - // is less than 127.0.0.0 = 0x7f000000 = 2130706432. - // - // Additionally, it makes debug output easier to read by making the numbers smaller. - final int randomPrefixStart = getRandomInt() & ~prefixRangeMask & prefixMask; - - // A random offset within the prefix. Used to determine the local address once the prefix - // is selected. It does not result in an IPv4 address ending in .0, .1, or .255 - // For a PREFIX_LENGTH of 255, this is a number between 2 and 254. - final int subAddress = getSanitizedSubAddr(~prefixMask); - - // Find a prefix length PREFIX_LENGTH between randomPrefixStart and the end of the block, - // such that the prefix does not conflict with any upstream. - IpPrefix downstreamPrefix = findAvailablePrefixFromRange( - randomPrefixStart, (~prefixRangeMask) + 1, baseAddress, prefixRangeMask); - if (downstreamPrefix != null) return getLinkAddress(downstreamPrefix, subAddress); - - // If that failed, do the same, but between 0 and randomPrefixStart. - downstreamPrefix = findAvailablePrefixFromRange( - 0, randomPrefixStart, baseAddress, prefixRangeMask); - - return getLinkAddress(downstreamPrefix, subAddress); - } - - private LinkAddress getLinkAddress(final IpPrefix prefix, final int subAddress) { - if (prefix == null) return null; - - final InetAddress address = intToInet4AddressHTH(getPrefixBaseAddress(prefix) | subAddress); - return new LinkAddress(address, PREFIX_LENGTH); - } - - private IpPrefix findAvailablePrefixFromRange(final int start, final int end, - final int baseAddress, final int prefixRangeMask) { - int newSubPrefix = start; - while (newSubPrefix < end) { - final InetAddress address = intToInet4AddressHTH(baseAddress | newSubPrefix); - final IpPrefix prefix = new IpPrefix(address, PREFIX_LENGTH); - - final IpPrefix conflictPrefix = getConflictPrefix(prefix); - - if (conflictPrefix == null) return prefix; - - newSubPrefix = getNextSubPrefix(conflictPrefix, prefixRangeMask); - } - - return null; - } - - /** Get random int which could be used to generate random address. */ - @VisibleForTesting - public int getRandomInt() { - return (new Random()).nextInt(); - } - - /** Get random subAddress and avoid selecting x.x.x.0, x.x.x.1 and x.x.x.255 address. */ - private int getSanitizedSubAddr(final int subAddrMask) { - final int randomSubAddr = getRandomInt() & subAddrMask; - // If prefix length > 30, the selecting speace would be less than 4 which may be hard to - // avoid 3 consecutive address. - if (PREFIX_LENGTH > 30) return randomSubAddr; - - // TODO: maybe it is not necessary to avoid .0, .1 and .255 address because tethering - // address would not be conflicted. This code only works because PREFIX_LENGTH is not longer - // than 24 - final int candidate = randomSubAddr & 0xff; - if (candidate == 0 || candidate == 1 || candidate == 255) { - return (randomSubAddr & 0xfffffffc) + 2; - } - - return randomSubAddr; - } - - /** Release downstream record for IpServer. */ - public void releaseDownstream(final IpServer ipServer) { - mDownstreams.remove(ipServer); - } - - /** Clear current upstream prefixes records. */ - public void clearUpstreamPrefixes() { - mUpstreamPrefixMap.clear(); - } - - private IpPrefix getConflictWithUpstream(final IpPrefix prefix) { - for (int i = 0; i < mUpstreamPrefixMap.size(); i++) { - final List<IpPrefix> list = mUpstreamPrefixMap.valueAt(i); - for (IpPrefix upstream : list) { - if (isConflictPrefix(prefix, upstream)) return upstream; - } - } - return null; - } - - private boolean isConflictWithUpstream(final IpPrefix prefix) { - return getConflictWithUpstream(prefix) != null; - } - - private boolean isConflictPrefix(final IpPrefix prefix1, final IpPrefix prefix2) { - if (prefix2.getPrefixLength() < prefix1.getPrefixLength()) { - return prefix2.contains(prefix1.getAddress()); - } - - return prefix1.contains(prefix2.getAddress()); - } - - // InUse Prefixes are prefixes of mCachedAddresses which are active downstream addresses, last - // downstream addresses(reserved for next time) and static addresses(e.g. bluetooth, wifi p2p). - private IpPrefix getInUseDownstreamPrefix(final IpPrefix prefix) { - for (int i = 0; i < mCachedAddresses.size(); i++) { - final IpPrefix downstream = asIpPrefix(mCachedAddresses.valueAt(i)); - if (isConflictPrefix(prefix, downstream)) return downstream; - } - - // IpServer may use manually-defined address (mStaticIpv4ServerAddr) which does not include - // in mCachedAddresses. - for (IpServer downstream : mDownstreams) { - final IpPrefix target = getDownstreamPrefix(downstream); - - if (isConflictPrefix(prefix, target)) return target; - } - - return null; - } - - @NonNull - private IpPrefix getDownstreamPrefix(final IpServer downstream) { - final LinkAddress address = downstream.getAddress(); - - return asIpPrefix(address); - } - - void dump(final IndentingPrintWriter pw) { - pw.println("mTetheringPrefixes:"); - pw.increaseIndent(); - for (IpPrefix prefix : mTetheringPrefixes) { - pw.println(prefix); - } - pw.decreaseIndent(); - - pw.println("mUpstreamPrefixMap:"); - pw.increaseIndent(); - for (int i = 0; i < mUpstreamPrefixMap.size(); i++) { - pw.println(mUpstreamPrefixMap.keyAt(i) + " - " + mUpstreamPrefixMap.valueAt(i)); - } - pw.decreaseIndent(); - - pw.println("mDownstreams:"); - pw.increaseIndent(); - for (IpServer ipServer : mDownstreams) { - pw.println(ipServer.interfaceType() + " - " + ipServer.getAddress()); - } - pw.decreaseIndent(); - - pw.println("mCachedAddresses:"); - pw.increaseIndent(); - for (int i = 0; i < mCachedAddresses.size(); i++) { - pw.println(mCachedAddresses.keyAt(i) + " - " + mCachedAddresses.valueAt(i)); - } - pw.decreaseIndent(); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java deleted file mode 100644 index 5a0c5b0cff5f..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ /dev/null @@ -1,2427 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.Manifest.permission.NETWORK_SETTINGS; -import static android.Manifest.permission.NETWORK_STACK; -import static android.content.pm.PackageManager.GET_ACTIVITIES; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.hardware.usb.UsbManager.USB_CONFIGURED; -import static android.hardware.usb.UsbManager.USB_CONNECTED; -import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; -import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; -import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; -import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; -import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER; -import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER; -import static android.net.TetheringManager.EXTRA_ERRORED_TETHER; -import static android.net.TetheringManager.TETHERING_BLUETOOTH; -import static android.net.TetheringManager.TETHERING_ETHERNET; -import static android.net.TetheringManager.TETHERING_INVALID; -import static android.net.TetheringManager.TETHERING_NCM; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.TetheringManager.TETHERING_WIGIG; -import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; -import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; -import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; -import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; -import static android.net.util.TetheringMessageBase.BASE_MAIN_SM; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; -import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - -import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; - -import android.app.usage.NetworkStatsManager; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothPan; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothProfile.ServiceListener; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.hardware.usb.UsbManager; -import android.net.ConnectivityManager; -import android.net.EthernetManager; -import android.net.IIntResultListener; -import android.net.INetd; -import android.net.ITetheringEventCallback; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.TetherStatesParcel; -import android.net.TetheredClient; -import android.net.TetheringCallbackStartedParcel; -import android.net.TetheringConfigurationParcel; -import android.net.TetheringRequestParcel; -import android.net.ip.IpServer; -import android.net.shared.NetdUtils; -import android.net.util.BaseNetdUnsolicitedEventListener; -import android.net.util.InterfaceSet; -import android.net.util.PrefixUtils; -import android.net.util.SharedLog; -import android.net.util.TetheringUtils; -import android.net.util.VersionedBroadcastListener; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiManager; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pInfo; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.ServiceSpecificException; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; -import android.util.SparseArray; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.MessageUtils; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -/** - * - * This class holds much of the business logic to allow Android devices - * to act as IP gateways via USB, BT, and WiFi interfaces. - */ -public class Tethering { - - private static final String TAG = Tethering.class.getSimpleName(); - private static final boolean DBG = false; - private static final boolean VDBG = false; - - private static final Class[] sMessageClasses = { - Tethering.class, TetherMainSM.class, IpServer.class - }; - private static final SparseArray<String> sMagicDecoderRing = - MessageUtils.findMessageNames(sMessageClasses); - // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h - private static final int NETID_UNSET = 0; - - private static class TetherState { - public final IpServer ipServer; - public int lastState; - public int lastError; - - TetherState(IpServer ipServer) { - this.ipServer = ipServer; - // Assume all state machines start out available and with no errors. - lastState = IpServer.STATE_AVAILABLE; - lastError = TETHER_ERROR_NO_ERROR; - } - - public boolean isCurrentlyServing() { - switch (lastState) { - case IpServer.STATE_TETHERED: - case IpServer.STATE_LOCAL_ONLY: - return true; - default: - return false; - } - } - } - - /** - * Cookie added when registering {@link android.net.TetheringManager.TetheringEventCallback}. - */ - private static class CallbackCookie { - public final boolean hasListClientsPermission; - - private CallbackCookie(boolean hasListClientsPermission) { - this.hasListClientsPermission = hasListClientsPermission; - } - } - - private final SharedLog mLog = new SharedLog(TAG); - private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks = - new RemoteCallbackList<>(); - // Currently active tethering requests per tethering type. Only one of each type can be - // requested at a time. After a tethering type is requested, the map keeps tethering parameters - // to be used after the interface comes up asynchronously. - private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests = - new SparseArray<>(); - - // used to synchronize public access to members - // TODO(b/153621704): remove mPublicSync to make Tethering lock free - private final Object mPublicSync; - private final Context mContext; - private final ArrayMap<String, TetherState> mTetherStates; - private final BroadcastReceiver mStateReceiver; - private final Looper mLooper; - private final StateMachine mTetherMainSM; - private final OffloadController mOffloadController; - private final UpstreamNetworkMonitor mUpstreamNetworkMonitor; - // TODO: Figure out how to merge this and other downstream-tracking objects - // into a single coherent structure. - // Use LinkedHashSet for predictable ordering order for ConnectedClientsTracker. - private final LinkedHashSet<IpServer> mForwardedDownstreams; - private final VersionedBroadcastListener mCarrierConfigChange; - private final TetheringDependencies mDeps; - private final EntitlementManager mEntitlementMgr; - private final Handler mHandler; - private final INetd mNetd; - private final NetdCallback mNetdCallback; - private final UserRestrictionActionListener mTetheringRestriction; - private final ActiveDataSubIdListener mActiveDataSubIdListener; - private final ConnectedClientsTracker mConnectedClientsTracker; - private final TetheringThreadExecutor mExecutor; - private final TetheringNotificationUpdater mNotificationUpdater; - private final UserManager mUserManager; - private final BpfCoordinator mBpfCoordinator; - private final PrivateAddressCoordinator mPrivateAddressCoordinator; - private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID; - // All the usage of mTetheringEventCallback should run in the same thread. - private ITetheringEventCallback mTetheringEventCallback = null; - - private volatile TetheringConfiguration mConfig; - private InterfaceSet mCurrentUpstreamIfaceSet; - - private boolean mRndisEnabled; // track the RNDIS function enabled state - // True iff. WiFi tethering should be started when soft AP is ready. - private boolean mWifiTetherRequested; - private Network mTetherUpstream; - private TetherStatesParcel mTetherStatesParcel; - private boolean mDataSaverEnabled = false; - private String mWifiP2pTetherInterface = null; - private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED; - - @GuardedBy("mPublicSync") - private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest; - @GuardedBy("mPublicSync") - private String mConfiguredEthernetIface; - @GuardedBy("mPublicSync") - private EthernetCallback mEthernetCallback; - - public Tethering(TetheringDependencies deps) { - mLog.mark("Tethering.constructed"); - mDeps = deps; - mContext = mDeps.getContext(); - mNetd = mDeps.getINetd(mContext); - mLooper = mDeps.getTetheringLooper(); - mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper); - - mPublicSync = new Object(); - - mTetherStates = new ArrayMap<>(); - mConnectedClientsTracker = new ConnectedClientsTracker(); - - mTetherMainSM = new TetherMainSM("TetherMain", mLooper, deps); - mTetherMainSM.start(); - - mHandler = mTetherMainSM.getHandler(); - mOffloadController = mDeps.getOffloadController(mHandler, mLog, - new OffloadController.Dependencies() { - - @Override - public TetheringConfiguration getTetherConfig() { - return mConfig; - } - }); - mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog, - TetherMainSM.EVENT_UPSTREAM_CALLBACK); - mForwardedDownstreams = new LinkedHashSet<>(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); - // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream - // permission is changed according to entitlement check result. - mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog, - () -> mTetherMainSM.sendMessage( - TetherMainSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); - mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { - mLog.log("OBSERVED UiEnitlementFailed"); - stopTethering(downstream); - }); - mEntitlementMgr.setTetheringConfigurationFetcher(() -> { - return mConfig; - }); - - mCarrierConfigChange = new VersionedBroadcastListener( - "CarrierConfigChangeListener", mContext, mHandler, filter, - (Intent ignored) -> { - mLog.log("OBSERVED carrier config change"); - updateConfiguration(); - mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); - }); - - mStateReceiver = new StateReceiver(); - - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - mTetheringRestriction = new UserRestrictionActionListener( - mUserManager, this, mNotificationUpdater); - mExecutor = new TetheringThreadExecutor(mHandler); - mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); - mNetdCallback = new NetdCallback(); - - // Load tethering configuration. - updateConfiguration(); - // It is OK for the configuration to be passed to the PrivateAddressCoordinator at - // construction time because the only part of the configuration it uses is - // shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that. - mPrivateAddressCoordinator = mDeps.getPrivateAddressCoordinator(mContext, mConfig); - - // Must be initialized after tethering configuration is loaded because BpfCoordinator - // constructor needs to use the configuration. - mBpfCoordinator = mDeps.getBpfCoordinator( - new BpfCoordinator.Dependencies() { - @NonNull - public Handler getHandler() { - return mHandler; - } - - @NonNull - public INetd getNetd() { - return mNetd; - } - - @NonNull - public NetworkStatsManager getNetworkStatsManager() { - return mContext.getSystemService(NetworkStatsManager.class); - } - - @NonNull - public SharedLog getSharedLog() { - return mLog; - } - - @Nullable - public TetheringConfiguration getTetherConfig() { - return mConfig; - } - }); - - startStateMachineUpdaters(); - } - - /** - * Start to register callbacks. - * Call this function when tethering is ready to handle callback events. - */ - private void startStateMachineUpdaters() { - try { - mNetd.registerUnsolicitedEventListener(mNetdCallback); - } catch (RemoteException e) { - mLog.e("Unable to register netd UnsolicitedEventListener"); - } - mCarrierConfigChange.startListening(); - mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, - PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); - - IntentFilter filter = new IntentFilter(); - filter.addAction(UsbManager.ACTION_USB_STATE); - filter.addAction(CONNECTIVITY_ACTION); - filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); - filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); - filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED); - mContext.registerReceiver(mStateReceiver, filter, null, mHandler); - - final IntentFilter noUpstreamFilter = new IntentFilter(); - noUpstreamFilter.addAction(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING); - mContext.registerReceiver( - mStateReceiver, noUpstreamFilter, PERMISSION_MAINLINE_NETWORK_STACK, mHandler); - - final WifiManager wifiManager = getWifiManager(); - if (wifiManager != null) { - wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); - } - - startTrackDefaultNetwork(); - } - - private class TetheringThreadExecutor implements Executor { - private final Handler mTetherHandler; - TetheringThreadExecutor(Handler handler) { - mTetherHandler = handler; - } - @Override - public void execute(Runnable command) { - if (!mTetherHandler.post(command)) { - throw new RejectedExecutionException(mTetherHandler + " is shutting down"); - } - } - } - - private class ActiveDataSubIdListener extends PhoneStateListener { - ActiveDataSubIdListener(Executor executor) { - super(executor); - } - - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId - + " to " + subId); - if (subId == mActiveDataSubId) return; - - mActiveDataSubId = subId; - updateConfiguration(); - mNotificationUpdater.onActiveDataSubscriptionIdChanged(subId); - // To avoid launching unexpected provisioning checks, ignore re-provisioning - // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() - // will be triggered again when CarrierConfig is loaded. - if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { - mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); - } else { - mLog.log("IGNORED reevaluate provisioning, no carrier config loaded"); - } - } - } - - private WifiManager getWifiManager() { - return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - } - - // NOTE: This is always invoked on the mLooper thread. - private void updateConfiguration() { - mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId); - mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired); - reportConfigurationChanged(mConfig.toStableParcelable()); - } - - private void maybeDunSettingChanged() { - final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext); - if (isDunRequired == mConfig.isDunRequired) return; - updateConfiguration(); - } - - private class NetdCallback extends BaseNetdUnsolicitedEventListener { - @Override - public void onInterfaceChanged(String ifName, boolean up) { - mHandler.post(() -> interfaceStatusChanged(ifName, up)); - } - - @Override - public void onInterfaceLinkStateChanged(String ifName, boolean up) { - mHandler.post(() -> interfaceLinkStateChanged(ifName, up)); - } - - @Override - public void onInterfaceAdded(String ifName) { - mHandler.post(() -> interfaceAdded(ifName)); - } - - @Override - public void onInterfaceRemoved(String ifName) { - mHandler.post(() -> interfaceRemoved(ifName)); - } - } - - private class TetheringSoftApCallback implements WifiManager.SoftApCallback { - // TODO: Remove onStateChanged override when this method has default on - // WifiManager#SoftApCallback interface. - // Wifi listener for state change of the soft AP - @Override - public void onStateChanged(final int state, final int failureReason) { - // Nothing - } - - // Called by wifi when the number of soft AP clients changed. - @Override - public void onConnectedClientsChanged(final List<WifiClient> clients) { - updateConnectedClients(clients); - } - } - - void interfaceStatusChanged(String iface, boolean up) { - // Never called directly: only called from interfaceLinkStateChanged. - // See NetlinkHandler.cpp: notifyInterfaceChanged. - if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); - synchronized (mPublicSync) { - if (up) { - maybeTrackNewInterfaceLocked(iface); - } else { - if (ifaceNameToType(iface) == TETHERING_BLUETOOTH - || ifaceNameToType(iface) == TETHERING_WIGIG) { - stopTrackingInterfaceLocked(iface); - } else { - // Ignore usb0 down after enabling RNDIS. - // We will handle disconnect in interfaceRemoved. - // Similarly, ignore interface down for WiFi. We monitor WiFi AP status - // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent. - if (VDBG) Log.d(TAG, "ignore interface down for " + iface); - } - } - } - } - - void interfaceLinkStateChanged(String iface, boolean up) { - interfaceStatusChanged(iface, up); - } - - private int ifaceNameToType(String iface) { - final TetheringConfiguration cfg = mConfig; - - if (cfg.isWifi(iface)) { - return TETHERING_WIFI; - } else if (cfg.isWigig(iface)) { - return TETHERING_WIGIG; - } else if (cfg.isWifiP2p(iface)) { - return TETHERING_WIFI_P2P; - } else if (cfg.isUsb(iface)) { - return TETHERING_USB; - } else if (cfg.isBluetooth(iface)) { - return TETHERING_BLUETOOTH; - } else if (cfg.isNcm(iface)) { - return TETHERING_NCM; - } - return TETHERING_INVALID; - } - - void interfaceAdded(String iface) { - if (VDBG) Log.d(TAG, "interfaceAdded " + iface); - synchronized (mPublicSync) { - maybeTrackNewInterfaceLocked(iface); - } - } - - void interfaceRemoved(String iface) { - if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); - synchronized (mPublicSync) { - stopTrackingInterfaceLocked(iface); - } - } - - void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) { - mHandler.post(() -> { - final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get( - request.tetheringType); - // If tethering is already enabled with a different request, - // disable before re-enabling. - if (unfinishedRequest != null - && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) { - enableTetheringInternal(request.tetheringType, false /* disabled */, null); - mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType); - } - mActiveTetheringRequests.put(request.tetheringType, request); - - if (request.exemptFromEntitlementCheck) { - mEntitlementMgr.setExemptedDownstreamType(request.tetheringType); - } else { - mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, - request.showProvisioningUi); - } - enableTetheringInternal(request.tetheringType, true /* enabled */, listener); - }); - } - - void stopTethering(int type) { - mHandler.post(() -> { - mActiveTetheringRequests.remove(type); - - enableTetheringInternal(type, false /* disabled */, null); - mEntitlementMgr.stopProvisioningIfNeeded(type); - }); - } - - /** - * Enables or disables tethering for the given type. If provisioning is required, it will - * schedule provisioning rechecks for the specified interface. - */ - private void enableTetheringInternal(int type, boolean enable, - final IIntResultListener listener) { - int result = TETHER_ERROR_NO_ERROR; - switch (type) { - case TETHERING_WIFI: - result = setWifiTethering(enable); - break; - case TETHERING_USB: - result = setUsbTethering(enable); - break; - case TETHERING_BLUETOOTH: - setBluetoothTethering(enable, listener); - break; - case TETHERING_NCM: - result = setNcmTethering(enable); - break; - case TETHERING_ETHERNET: - result = setEthernetTethering(enable); - break; - default: - Log.w(TAG, "Invalid tether type."); - result = TETHER_ERROR_UNKNOWN_TYPE; - } - - // The result of Bluetooth tethering will be sent by #setBluetoothTethering. - if (type != TETHERING_BLUETOOTH) { - sendTetherResult(listener, result, type); - } - } - - private void sendTetherResult(final IIntResultListener listener, final int result, - final int type) { - if (listener != null) { - try { - listener.onResult(result); - } catch (RemoteException e) { } - } - - // If changing tethering fail, remove corresponding request - // no matter who trigger the start/stop. - if (result != TETHER_ERROR_NO_ERROR) mActiveTetheringRequests.remove(type); - } - - private int setWifiTethering(final boolean enable) { - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mPublicSync) { - final WifiManager mgr = getWifiManager(); - if (mgr == null) { - mLog.e("setWifiTethering: failed to get WifiManager!"); - return TETHER_ERROR_SERVICE_UNAVAIL; - } - if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */)) - || (!enable && mgr.stopSoftAp())) { - mWifiTetherRequested = enable; - return TETHER_ERROR_NO_ERROR; - } - } - } finally { - Binder.restoreCallingIdentity(ident); - } - - return TETHER_ERROR_INTERNAL_ERROR; - } - - private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) { - final BluetoothAdapter adapter = mDeps.getBluetoothAdapter(); - if (adapter == null || !adapter.isEnabled()) { - Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " - + (adapter == null)); - sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL, TETHERING_BLUETOOTH); - return; - } - - adapter.getProfileProxy(mContext, new ServiceListener() { - @Override - public void onServiceDisconnected(int profile) { } - - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - // Clear identify is fine because caller already pass tethering permission at - // ConnectivityService#startTethering()(or stopTethering) before the control comes - // here. Bluetooth will check tethering permission again that there is - // Context#getOpPackageName() under BluetoothPan#setBluetoothTethering() to get - // caller's package name for permission check. - // Calling BluetoothPan#setBluetoothTethering() here means the package name always - // be system server. If calling identity is not cleared, that package's uid might - // not match calling uid and end up in permission denied. - final long identityToken = Binder.clearCallingIdentity(); - try { - ((BluetoothPan) proxy).setBluetoothTethering(enable); - } finally { - Binder.restoreCallingIdentity(identityToken); - } - // TODO: Enabling bluetooth tethering can fail asynchronously here. - // We should figure out a way to bubble up that failure instead of sending success. - final int result = (((BluetoothPan) proxy).isTetheringOn() == enable) - ? TETHER_ERROR_NO_ERROR - : TETHER_ERROR_INTERNAL_ERROR; - sendTetherResult(listener, result, TETHERING_BLUETOOTH); - adapter.closeProfileProxy(BluetoothProfile.PAN, proxy); - } - }, BluetoothProfile.PAN); - } - - private int setEthernetTethering(final boolean enable) { - final EthernetManager em = (EthernetManager) mContext.getSystemService( - Context.ETHERNET_SERVICE); - synchronized (mPublicSync) { - if (enable) { - if (mEthernetCallback != null) { - Log.d(TAG, "Ethernet tethering already started"); - return TETHER_ERROR_NO_ERROR; - } - - mEthernetCallback = new EthernetCallback(); - mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback); - } else { - stopEthernetTetheringLocked(); - } - } - return TETHER_ERROR_NO_ERROR; - } - - private void stopEthernetTetheringLocked() { - if (mConfiguredEthernetIface != null) { - stopTrackingInterfaceLocked(mConfiguredEthernetIface); - mConfiguredEthernetIface = null; - } - if (mEthernetCallback != null) { - mEthernetIfaceRequest.release(); - mEthernetCallback = null; - mEthernetIfaceRequest = null; - } - } - - private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback { - @Override - public void onAvailable(String iface) { - synchronized (mPublicSync) { - if (this != mEthernetCallback) { - // Ethernet callback arrived after Ethernet tethering stopped. Ignore. - return; - } - maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET); - changeInterfaceState(iface, IpServer.STATE_TETHERED); - mConfiguredEthernetIface = iface; - } - } - - @Override - public void onUnavailable() { - synchronized (mPublicSync) { - if (this != mEthernetCallback) { - // onAvailable called after stopping Ethernet tethering. - return; - } - stopEthernetTetheringLocked(); - } - } - } - - int tether(String iface) { - return tether(iface, IpServer.STATE_TETHERED); - } - - private int tether(String iface, int requestedState) { - if (DBG) Log.d(TAG, "Tethering " + iface); - synchronized (mPublicSync) { - TetherState tetherState = mTetherStates.get(iface); - if (tetherState == null) { - Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring"); - return TETHER_ERROR_UNKNOWN_IFACE; - } - // Ignore the error status of the interface. If the interface is available, - // the errors are referring to past tethering attempts anyway. - if (tetherState.lastState != IpServer.STATE_AVAILABLE) { - Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring"); - return TETHER_ERROR_UNAVAIL_IFACE; - } - // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet - // processed, this will be a no-op and it will not return an error. - // - // This code cannot race with untether() because they both synchronize on mPublicSync. - // TODO: reexamine the threading and messaging model to totally remove mPublicSync. - final int type = tetherState.ipServer.interfaceType(); - final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null); - if (request != null) { - mActiveTetheringRequests.delete(type); - } - tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState, 0, - request); - return TETHER_ERROR_NO_ERROR; - } - } - - int untether(String iface) { - if (DBG) Log.d(TAG, "Untethering " + iface); - synchronized (mPublicSync) { - TetherState tetherState = mTetherStates.get(iface); - if (tetherState == null) { - Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); - return TETHER_ERROR_UNKNOWN_IFACE; - } - if (!tetherState.isCurrentlyServing()) { - Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring"); - return TETHER_ERROR_UNAVAIL_IFACE; - } - tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED); - return TETHER_ERROR_NO_ERROR; - } - } - - void untetherAll() { - stopTethering(TETHERING_WIFI); - stopTethering(TETHERING_WIFI_P2P); - stopTethering(TETHERING_USB); - stopTethering(TETHERING_BLUETOOTH); - stopTethering(TETHERING_ETHERNET); - } - - int getLastTetherError(String iface) { - synchronized (mPublicSync) { - TetherState tetherState = mTetherStates.get(iface); - if (tetherState == null) { - Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface - + ", ignoring"); - return TETHER_ERROR_UNKNOWN_IFACE; - } - return tetherState.lastError; - } - } - - private boolean isProvisioningNeededButUnavailable() { - return isTetherProvisioningRequired() && !doesEntitlementPackageExist(); - } - - boolean isTetherProvisioningRequired() { - final TetheringConfiguration cfg = mConfig; - return mEntitlementMgr.isTetherProvisioningRequired(cfg); - } - - private boolean doesEntitlementPackageExist() { - // provisioningApp must contain package and class name. - if (mConfig.provisioningApp.length != 2) { - return false; - } - - final PackageManager pm = mContext.getPackageManager(); - try { - pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES); - } catch (PackageManager.NameNotFoundException e) { - return false; - } - return true; - } - - // TODO: Figure out how to update for local hotspot mode interfaces. - private void sendTetherStateChangedBroadcast() { - if (!isTetheringSupported()) return; - - final ArrayList<String> availableList = new ArrayList<>(); - final ArrayList<String> tetherList = new ArrayList<>(); - final ArrayList<String> localOnlyList = new ArrayList<>(); - final ArrayList<String> erroredList = new ArrayList<>(); - final ArrayList<Integer> lastErrorList = new ArrayList<>(); - - final TetheringConfiguration cfg = mConfig; - mTetherStatesParcel = new TetherStatesParcel(); - - int downstreamTypesMask = DOWNSTREAM_NONE; - synchronized (mPublicSync) { - for (int i = 0; i < mTetherStates.size(); i++) { - TetherState tetherState = mTetherStates.valueAt(i); - String iface = mTetherStates.keyAt(i); - if (tetherState.lastError != TETHER_ERROR_NO_ERROR) { - erroredList.add(iface); - lastErrorList.add(tetherState.lastError); - } else if (tetherState.lastState == IpServer.STATE_AVAILABLE) { - availableList.add(iface); - } else if (tetherState.lastState == IpServer.STATE_LOCAL_ONLY) { - localOnlyList.add(iface); - } else if (tetherState.lastState == IpServer.STATE_TETHERED) { - if (cfg.isUsb(iface)) { - downstreamTypesMask |= (1 << TETHERING_USB); - } else if (cfg.isWifi(iface)) { - downstreamTypesMask |= (1 << TETHERING_WIFI); - } else if (cfg.isBluetooth(iface)) { - downstreamTypesMask |= (1 << TETHERING_BLUETOOTH); - } - tetherList.add(iface); - } - } - } - - mTetherStatesParcel.availableList = availableList.toArray(new String[0]); - mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]); - mTetherStatesParcel.localOnlyList = localOnlyList.toArray(new String[0]); - mTetherStatesParcel.erroredIfaceList = erroredList.toArray(new String[0]); - mTetherStatesParcel.lastErrorList = new int[lastErrorList.size()]; - Iterator<Integer> iterator = lastErrorList.iterator(); - for (int i = 0; i < lastErrorList.size(); i++) { - mTetherStatesParcel.lastErrorList[i] = iterator.next().intValue(); - } - reportTetherStateChanged(mTetherStatesParcel); - - final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED); - bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList); - bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList); - bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList); - bcast.putStringArrayListExtra(EXTRA_ERRORED_TETHER, erroredList); - mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL); - if (DBG) { - Log.d(TAG, String.format( - "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]", - "avail", TextUtils.join(",", availableList), - "local_only", TextUtils.join(",", localOnlyList), - "tether", TextUtils.join(",", tetherList), - "error", TextUtils.join(",", erroredList))); - } - - mNotificationUpdater.onDownstreamChanged(downstreamTypesMask); - } - - private class StateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context content, Intent intent) { - final String action = intent.getAction(); - if (action == null) return; - - if (action.equals(UsbManager.ACTION_USB_STATE)) { - handleUsbAction(intent); - } else if (action.equals(CONNECTIVITY_ACTION)) { - handleConnectivityAction(intent); - } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { - handleWifiApAction(intent); - } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { - handleWifiP2pAction(intent); - } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { - mLog.log("OBSERVED configuration changed"); - updateConfiguration(); - } else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) { - mLog.log("OBSERVED user restrictions changed"); - handleUserRestrictionAction(); - } else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) { - mLog.log("OBSERVED data saver changed"); - handleDataSaverChanged(); - } else if (action.equals(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING)) { - untetherAll(); - } - } - - private void handleConnectivityAction(Intent intent) { - final NetworkInfo networkInfo = - (NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO); - if (networkInfo == null - || networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) { - return; - } - - if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString()); - mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED); - } - - private void handleUsbAction(Intent intent) { - final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false); - final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false); - final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false); - final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false); - - mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s", - usbConnected, usbConfigured, rndisEnabled)); - - // There are three types of ACTION_USB_STATE: - // - // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0) - // Meaning: USB connection has ended either because of - // software reset or hard unplug. - // - // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0) - // Meaning: the first stage of USB protocol handshake has - // occurred but it is not complete. - // - // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1) - // Meaning: the USB handshake is completely done and all the - // functions are ready to use. - // - // For more explanation, see b/62552150 . - synchronized (Tethering.this.mPublicSync) { - if (!usbConnected && mRndisEnabled) { - // Turn off tethering if it was enabled and there is a disconnect. - tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB); - mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_USB); - } else if (usbConfigured && rndisEnabled) { - // Tether if rndis is enabled and usb is configured. - tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB); - } else if (usbConnected && ncmEnabled) { - tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM); - } - mRndisEnabled = usbConfigured && rndisEnabled; - } - } - - private void handleWifiApAction(Intent intent) { - final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); - final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); - final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED); - - synchronized (Tethering.this.mPublicSync) { - switch (curState) { - case WifiManager.WIFI_AP_STATE_ENABLING: - // We can see this state on the way to both enabled and failure states. - break; - case WifiManager.WIFI_AP_STATE_ENABLED: - enableWifiIpServingLocked(ifname, ipmode); - break; - case WifiManager.WIFI_AP_STATE_DISABLING: - // We can see this state on the way to disabled. - break; - case WifiManager.WIFI_AP_STATE_DISABLED: - case WifiManager.WIFI_AP_STATE_FAILED: - default: - disableWifiIpServingLocked(ifname, curState); - break; - } - } - } - - private boolean isGroupOwner(WifiP2pGroup group) { - return group != null && group.isGroupOwner() - && !TextUtils.isEmpty(group.getInterface()); - } - - private void handleWifiP2pAction(Intent intent) { - if (mConfig.isWifiP2pLegacyTetheringMode()) return; - - final WifiP2pInfo p2pInfo = - (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); - final WifiP2pGroup group = - (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); - - if (VDBG) { - Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group); - } - - synchronized (Tethering.this.mPublicSync) { - // if no group is formed, bring it down if needed. - if (p2pInfo == null || !p2pInfo.groupFormed) { - disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface); - mWifiP2pTetherInterface = null; - return; - } - - // If there is a group but the device is not the owner, bail out. - if (!isGroupOwner(group)) return; - - // If already serving from the correct interface, nothing to do. - if (group.getInterface().equals(mWifiP2pTetherInterface)) return; - - // If already serving from another interface, turn it down first. - if (!TextUtils.isEmpty(mWifiP2pTetherInterface)) { - mLog.w("P2P tethered interface " + mWifiP2pTetherInterface - + "is different from current interface " - + group.getInterface() + ", re-tether it"); - disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface); - } - - // Finally bring up serving on the new interface - mWifiP2pTetherInterface = group.getInterface(); - enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY); - } - } - - private void handleUserRestrictionAction() { - mTetheringRestriction.onUserRestrictionsChanged(); - } - - private void handleDataSaverChanged() { - final ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - final boolean isDataSaverEnabled = connMgr.getRestrictBackgroundStatus() - != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; - - if (mDataSaverEnabled == isDataSaverEnabled) return; - - mDataSaverEnabled = isDataSaverEnabled; - if (mDataSaverEnabled) { - untetherAll(); - } - } - } - - @VisibleForTesting - boolean isTetheringActive() { - return mActiveTetheringRequests.size() > 0; - } - - @VisibleForTesting - protected static class UserRestrictionActionListener { - private final UserManager mUserMgr; - private final Tethering mWrapper; - private final TetheringNotificationUpdater mNotificationUpdater; - public boolean mDisallowTethering; - - public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper, - @NonNull TetheringNotificationUpdater updater) { - mUserMgr = um; - mWrapper = wrapper; - mNotificationUpdater = updater; - mDisallowTethering = false; - } - - public void onUserRestrictionsChanged() { - // getUserRestrictions gets restriction for this process' user, which is the primary - // user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary - // user. See UserManager.DISALLOW_CONFIG_TETHERING. - final Bundle restrictions = mUserMgr.getUserRestrictions(); - final boolean newlyDisallowed = - restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING); - final boolean prevDisallowed = mDisallowTethering; - mDisallowTethering = newlyDisallowed; - - final boolean tetheringDisallowedChanged = (newlyDisallowed != prevDisallowed); - if (!tetheringDisallowedChanged) { - return; - } - - if (!newlyDisallowed) { - // Clear the restricted notification when user is allowed to have tethering - // function. - mNotificationUpdater.tetheringRestrictionLifted(); - return; - } - - if (mWrapper.isTetheringActive()) { - // Restricted notification is shown when tethering function is disallowed on - // user's device. - mNotificationUpdater.notifyTetheringDisabledByRestriction(); - - // Untether from all downstreams since tethering is disallowed. - mWrapper.untetherAll(); - } - // TODO(b/148139325): send tetheringSupported on restriction change - } - } - - private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) { - mLog.log("Canceling WiFi tethering request -" - + " type=" + tetheringType - + " interface=" + ifname - + " state=" + apState); - - if (!TextUtils.isEmpty(ifname)) { - final TetherState ts = mTetherStates.get(ifname); - if (ts != null) { - ts.ipServer.unwanted(); - return; - } - } - - for (int i = 0; i < mTetherStates.size(); i++) { - final IpServer ipServer = mTetherStates.valueAt(i).ipServer; - if (ipServer.interfaceType() == tetheringType) { - ipServer.unwanted(); - return; - } - } - - mLog.log("Error disabling Wi-Fi IP serving; " - + (TextUtils.isEmpty(ifname) ? "no interface name specified" - : "specified interface: " + ifname)); - } - - private void disableWifiIpServingLocked(String ifname, int apState) { - // Regardless of whether we requested this transition, the AP has gone - // down. Don't try to tether again unless we're requested to do so. - // TODO: Remove this altogether, once Wi-Fi reliably gives us an - // interface name with every broadcast. - mWifiTetherRequested = false; - - disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState); - } - - private void disableWifiP2pIpServingLockedIfNeeded(String ifname) { - if (TextUtils.isEmpty(ifname)) return; - - disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0); - } - - private void enableWifiIpServingLocked(String ifname, int wifiIpMode) { - // Map wifiIpMode values to IpServer.Callback serving states, inferring - // from mWifiTetherRequested as a final "best guess". - final int ipServingMode; - switch (wifiIpMode) { - case IFACE_IP_MODE_TETHERED: - ipServingMode = IpServer.STATE_TETHERED; - break; - case IFACE_IP_MODE_LOCAL_ONLY: - ipServingMode = IpServer.STATE_LOCAL_ONLY; - break; - default: - mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode); - return; - } - - if (!TextUtils.isEmpty(ifname)) { - maybeTrackNewInterfaceLocked(ifname); - changeInterfaceState(ifname, ipServingMode); - } else { - mLog.e(String.format( - "Cannot enable IP serving in mode %s on missing interface name", - ipServingMode)); - } - } - - // TODO: Consider renaming to something more accurate in its description. - // This method: - // - allows requesting either tethering or local hotspot serving states - // - handles both enabling and disabling serving states - // - only tethers the first matching interface in listInterfaces() - // order of a given type - private void tetherMatchingInterfaces(int requestedState, int interfaceType) { - if (VDBG) { - Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")"); - } - - String[] ifaces = null; - try { - ifaces = mNetd.interfaceGetList(); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error listing Interfaces", e); - return; - } - String chosenIface = null; - if (ifaces != null) { - for (String iface : ifaces) { - if (ifaceNameToType(iface) == interfaceType) { - chosenIface = iface; - break; - } - } - } - if (chosenIface == null) { - Log.e(TAG, "could not find iface of type " + interfaceType); - return; - } - - changeInterfaceState(chosenIface, requestedState); - } - - private void changeInterfaceState(String ifname, int requestedState) { - final int result; - switch (requestedState) { - case IpServer.STATE_UNAVAILABLE: - case IpServer.STATE_AVAILABLE: - result = untether(ifname); - break; - case IpServer.STATE_TETHERED: - case IpServer.STATE_LOCAL_ONLY: - result = tether(ifname, requestedState); - break; - default: - Log.wtf(TAG, "Unknown interface state: " + requestedState); - return; - } - if (result != TETHER_ERROR_NO_ERROR) { - Log.e(TAG, "unable start or stop tethering on iface " + ifname); - return; - } - } - - TetheringConfiguration getTetheringConfiguration() { - return mConfig; - } - - boolean hasTetherableConfiguration() { - final TetheringConfiguration cfg = mConfig; - final boolean hasDownstreamConfiguration = - (cfg.tetherableUsbRegexs.length != 0) - || (cfg.tetherableWifiRegexs.length != 0) - || (cfg.tetherableBluetoothRegexs.length != 0); - final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty() - || cfg.chooseUpstreamAutomatically; - - return hasDownstreamConfiguration && hasUpstreamConfiguration; - } - - // TODO - update callers to use getTetheringConfiguration(), - // which has only final members. - String[] getTetherableUsbRegexs() { - return copy(mConfig.tetherableUsbRegexs); - } - - String[] getTetherableWifiRegexs() { - return copy(mConfig.tetherableWifiRegexs); - } - - String[] getTetherableBluetoothRegexs() { - return copy(mConfig.tetherableBluetoothRegexs); - } - - int setUsbTethering(boolean enable) { - if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); - UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); - if (usbManager == null) { - mLog.e("setUsbTethering: failed to get UsbManager!"); - return TETHER_ERROR_SERVICE_UNAVAIL; - } - - synchronized (mPublicSync) { - usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS - : UsbManager.FUNCTION_NONE); - } - return TETHER_ERROR_NO_ERROR; - } - - private int setNcmTethering(boolean enable) { - if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")"); - UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); - synchronized (mPublicSync) { - usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM - : UsbManager.FUNCTION_NONE); - } - return TETHER_ERROR_NO_ERROR; - } - - // TODO review API - figure out how to delete these entirely. - String[] getTetheredIfaces() { - ArrayList<String> list = new ArrayList<String>(); - synchronized (mPublicSync) { - for (int i = 0; i < mTetherStates.size(); i++) { - TetherState tetherState = mTetherStates.valueAt(i); - if (tetherState.lastState == IpServer.STATE_TETHERED) { - list.add(mTetherStates.keyAt(i)); - } - } - } - return list.toArray(new String[list.size()]); - } - - String[] getTetherableIfaces() { - ArrayList<String> list = new ArrayList<String>(); - synchronized (mPublicSync) { - for (int i = 0; i < mTetherStates.size(); i++) { - TetherState tetherState = mTetherStates.valueAt(i); - if (tetherState.lastState == IpServer.STATE_AVAILABLE) { - list.add(mTetherStates.keyAt(i)); - } - } - } - return list.toArray(new String[list.size()]); - } - - String[] getTetheredDhcpRanges() { - // TODO: this is only valid for the old DHCP server. Latest search suggests it is only used - // by WifiP2pServiceImpl to start dnsmasq: remove/deprecate after migrating callers. - return mConfig.legacyDhcpRanges; - } - - String[] getErroredIfaces() { - ArrayList<String> list = new ArrayList<String>(); - synchronized (mPublicSync) { - for (int i = 0; i < mTetherStates.size(); i++) { - TetherState tetherState = mTetherStates.valueAt(i); - if (tetherState.lastError != TETHER_ERROR_NO_ERROR) { - list.add(mTetherStates.keyAt(i)); - } - } - } - return list.toArray(new String[list.size()]); - } - - private void logMessage(State state, int what) { - mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what))); - } - - private boolean upstreamWanted() { - if (!mForwardedDownstreams.isEmpty()) return true; - - synchronized (mPublicSync) { - return mWifiTetherRequested; - } - } - - // Needed because the canonical source of upstream truth is just the - // upstream interface set, |mCurrentUpstreamIfaceSet|. - private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) { - if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) { - for (String ifname : ns.linkProperties.getAllInterfaceNames()) { - if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) { - return true; - } - } - } - return false; - } - - class TetherMainSM extends StateMachine { - // an interface SM has requested Tethering/Local Hotspot - static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MAIN_SM + 1; - // an interface SM has unrequested Tethering/Local Hotspot - static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MAIN_SM + 2; - // upstream connection change - do the right thing - static final int CMD_UPSTREAM_CHANGED = BASE_MAIN_SM + 3; - // we don't have a valid upstream conn, check again after a delay - static final int CMD_RETRY_UPSTREAM = BASE_MAIN_SM + 4; - // Events from NetworkCallbacks that we process on the main state - // machine thread on behalf of the UpstreamNetworkMonitor. - static final int EVENT_UPSTREAM_CALLBACK = BASE_MAIN_SM + 5; - // we treated the error and want now to clear it - static final int CMD_CLEAR_ERROR = BASE_MAIN_SM + 6; - static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MAIN_SM + 7; - // Events from EntitlementManager to choose upstream again. - static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MAIN_SM + 8; - private final State mInitialState; - private final State mTetherModeAliveState; - - private final State mSetIpForwardingEnabledErrorState; - private final State mSetIpForwardingDisabledErrorState; - private final State mStartTetheringErrorState; - private final State mStopTetheringErrorState; - private final State mSetDnsForwardersErrorState; - - // This list is a little subtle. It contains all the interfaces that currently are - // requesting tethering, regardless of whether these interfaces are still members of - // mTetherStates. This allows us to maintain the following predicates: - // - // 1) mTetherStates contains the set of all currently existing, tetherable, link state up - // interfaces. - // 2) mNotifyList contains all state machines that may have outstanding tethering state - // that needs to be torn down. - // - // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList - // so that the garbage collector does not clean up the state machine before it has a chance - // to tear itself down. - private final ArrayList<IpServer> mNotifyList; - private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; - private final OffloadWrapper mOffload; - - private static final int UPSTREAM_SETTLE_TIME_MS = 10000; - - TetherMainSM(String name, Looper looper, TetheringDependencies deps) { - super(name, looper); - - mInitialState = new InitialState(); - mTetherModeAliveState = new TetherModeAliveState(); - mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); - mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); - mStartTetheringErrorState = new StartTetheringErrorState(); - mStopTetheringErrorState = new StopTetheringErrorState(); - mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); - - addState(mInitialState); - addState(mTetherModeAliveState); - addState(mSetIpForwardingEnabledErrorState); - addState(mSetIpForwardingDisabledErrorState); - addState(mStartTetheringErrorState); - addState(mStopTetheringErrorState); - addState(mSetDnsForwardersErrorState); - - mNotifyList = new ArrayList<>(); - mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator(mNotifyList, mLog); - mOffload = new OffloadWrapper(); - - setInitialState(mInitialState); - } - - class InitialState extends State { - @Override - public boolean processMessage(Message message) { - logMessage(this, message.what); - switch (message.what) { - case EVENT_IFACE_SERVING_STATE_ACTIVE: { - final IpServer who = (IpServer) message.obj; - if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); - handleInterfaceServingStateActive(message.arg1, who); - transitionTo(mTetherModeAliveState); - break; - } - case EVENT_IFACE_SERVING_STATE_INACTIVE: { - final IpServer who = (IpServer) message.obj; - if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); - handleInterfaceServingStateInactive(who); - break; - } - case EVENT_IFACE_UPDATE_LINKPROPERTIES: - // Silently ignore these for now. - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - protected boolean turnOnMainTetherSettings() { - final TetheringConfiguration cfg = mConfig; - try { - mNetd.ipfwdEnableForwarding(TAG); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e(e); - transitionTo(mSetIpForwardingEnabledErrorState); - return false; - } - - // TODO: Randomize DHCPv4 ranges, especially in hotspot mode. - // Legacy DHCP server is disabled if passed an empty ranges array - final String[] dhcpRanges = cfg.enableLegacyDhcpServer - ? cfg.legacyDhcpRanges : new String[0]; - try { - NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); - } catch (RemoteException | ServiceSpecificException e) { - try { - // Stop and retry. - mNetd.tetherStop(); - NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); - } catch (RemoteException | ServiceSpecificException ee) { - mLog.e(ee); - transitionTo(mStartTetheringErrorState); - return false; - } - } - mLog.log("SET main tether settings: ON"); - return true; - } - - protected boolean turnOffMainTetherSettings() { - try { - mNetd.tetherStop(); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e(e); - transitionTo(mStopTetheringErrorState); - return false; - } - try { - mNetd.ipfwdDisableForwarding(TAG); - } catch (RemoteException | ServiceSpecificException e) { - mLog.e(e); - transitionTo(mSetIpForwardingDisabledErrorState); - return false; - } - transitionTo(mInitialState); - mLog.log("SET main tether settings: OFF"); - return true; - } - - protected void chooseUpstreamType(boolean tryCell) { - // We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we - // do not currently know how to watch for changes in DUN settings. - maybeDunSettingChanged(); - - final TetheringConfiguration config = mConfig; - final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically) - ? mUpstreamNetworkMonitor.getCurrentPreferredUpstream() - : mUpstreamNetworkMonitor.selectPreferredUpstreamType( - config.preferredUpstreamIfaceTypes); - if (ns == null) { - if (tryCell) { - mUpstreamNetworkMonitor.registerMobileNetworkRequest(); - // We think mobile should be coming up; don't set a retry. - } else { - sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); - } - } - setUpstreamNetwork(ns); - final Network newUpstream = (ns != null) ? ns.network : null; - if (mTetherUpstream != newUpstream) { - mTetherUpstream = newUpstream; - mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); - reportUpstreamChanged(ns); - } - } - - protected void setUpstreamNetwork(UpstreamNetworkState ns) { - InterfaceSet ifaces = null; - if (ns != null) { - // Find the interface with the default IPv4 route. It may be the - // interface described by linkProperties, or one of the interfaces - // stacked on top of it. - mLog.i("Looking for default routes on: " + ns.linkProperties); - ifaces = TetheringInterfaceUtils.getTetheringInterfaces(ns); - mLog.i("Found upstream interface(s): " + ifaces); - } - - if (ifaces != null) { - setDnsForwarders(ns.network, ns.linkProperties); - } - notifyDownstreamsOfNewUpstreamIface(ifaces); - if (ns != null && pertainsToCurrentUpstream(ns)) { - // If we already have UpstreamNetworkState for this network update it immediately. - handleNewUpstreamNetworkState(ns); - } else if (mCurrentUpstreamIfaceSet == null) { - // There are no available upstream networks. - handleNewUpstreamNetworkState(null); - } - } - - protected void setDnsForwarders(final Network network, final LinkProperties lp) { - // TODO: Set v4 and/or v6 DNS per available connectivity. - final Collection<InetAddress> dnses = lp.getDnsServers(); - // TODO: Properly support the absence of DNS servers. - final String[] dnsServers; - if (dnses != null && !dnses.isEmpty()) { - dnsServers = new String[dnses.size()]; - int i = 0; - for (InetAddress dns : dnses) { - dnsServers[i++] = dns.getHostAddress(); - } - } else { - dnsServers = mConfig.defaultIPv4DNS; - } - final int netId = (network != null) ? network.getNetId() : NETID_UNSET; - try { - mNetd.tetherDnsSet(netId, dnsServers); - mLog.log(String.format( - "SET DNS forwarders: network=%s dnsServers=%s", - network, Arrays.toString(dnsServers))); - } catch (RemoteException | ServiceSpecificException e) { - // TODO: Investigate how this can fail and what exactly - // happens if/when such failures occur. - mLog.e("setting DNS forwarders failed, " + e); - transitionTo(mSetDnsForwardersErrorState); - } - } - - protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) { - mCurrentUpstreamIfaceSet = ifaces; - for (IpServer ipServer : mNotifyList) { - ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifaces); - } - } - - protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) { - mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); - mOffload.updateUpstreamNetworkState(ns); - } - - private void handleInterfaceServingStateActive(int mode, IpServer who) { - if (mNotifyList.indexOf(who) < 0) { - mNotifyList.add(who); - mIPv6TetheringCoordinator.addActiveDownstream(who, mode); - } - - if (mode == IpServer.STATE_TETHERED) { - // No need to notify OffloadController just yet as there are no - // "offload-able" prefixes to pass along. This will handled - // when the TISM informs Tethering of its LinkProperties. - mForwardedDownstreams.add(who); - } else { - mOffload.excludeDownstreamInterface(who.interfaceName()); - mForwardedDownstreams.remove(who); - } - - // If this is a Wi-Fi interface, notify WifiManager of the active serving state. - if (who.interfaceType() == TETHERING_WIFI) { - final WifiManager mgr = getWifiManager(); - final String iface = who.interfaceName(); - switch (mode) { - case IpServer.STATE_TETHERED: - mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED); - break; - case IpServer.STATE_LOCAL_ONLY: - mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY); - break; - default: - Log.wtf(TAG, "Unknown active serving mode: " + mode); - break; - } - } - } - - private void handleInterfaceServingStateInactive(IpServer who) { - mNotifyList.remove(who); - mIPv6TetheringCoordinator.removeActiveDownstream(who); - mOffload.excludeDownstreamInterface(who.interfaceName()); - mForwardedDownstreams.remove(who); - updateConnectedClients(null /* wifiClients */); - - // If this is a Wi-Fi interface, tell WifiManager of any errors - // or the inactive serving state. - if (who.interfaceType() == TETHERING_WIFI) { - if (who.lastError() != TETHER_ERROR_NO_ERROR) { - getWifiManager().updateInterfaceIpState( - who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR); - } else { - getWifiManager().updateInterfaceIpState( - who.interfaceName(), IFACE_IP_MODE_UNSPECIFIED); - } - } - } - - @VisibleForTesting - void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { - if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { - mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); - return; - } - - final UpstreamNetworkState ns = (UpstreamNetworkState) o; - switch (arg1) { - case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: - mPrivateAddressCoordinator.updateUpstreamPrefix(ns); - break; - case UpstreamNetworkMonitor.EVENT_ON_LOST: - mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network); - break; - } - - if (ns == null || !pertainsToCurrentUpstream(ns)) { - // TODO: In future, this is where upstream evaluation and selection - // could be handled for notifications which include sufficient data. - // For example, after CONNECTIVITY_ACTION listening is removed, here - // is where we could observe a Wi-Fi network becoming available and - // passing validation. - if (mCurrentUpstreamIfaceSet == null) { - // If we have no upstream interface, try to run through upstream - // selection again. If, for example, IPv4 connectivity has shown up - // after IPv6 (e.g., 464xlat became available) we want the chance to - // notice and act accordingly. - chooseUpstreamType(false); - } - return; - } - - switch (arg1) { - case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: - if (ns.network.equals(mTetherUpstream)) { - mNotificationUpdater.onUpstreamCapabilitiesChanged(ns.networkCapabilities); - } - handleNewUpstreamNetworkState(ns); - break; - case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: - chooseUpstreamType(false); - break; - case UpstreamNetworkMonitor.EVENT_ON_LOST: - // TODO: Re-evaluate possible upstreams. Currently upstream - // reevaluation is triggered via received CONNECTIVITY_ACTION - // broadcasts that result in being passed a - // TetherMainSM.CMD_UPSTREAM_CHANGED. - handleNewUpstreamNetworkState(null); - break; - default: - mLog.e("Unknown arg1 value: " + arg1); - break; - } - } - - class TetherModeAliveState extends State { - boolean mUpstreamWanted = false; - boolean mTryCell = true; - - @Override - public void enter() { - // If turning on main tether settings fails, we have already - // transitioned to an error state; exit early. - if (!turnOnMainTetherSettings()) { - return; - } - - mPrivateAddressCoordinator.maybeRemoveDeprecatedUpstreams(); - mUpstreamNetworkMonitor.startObserveAllNetworks(); - - // TODO: De-duplicate with updateUpstreamWanted() below. - if (upstreamWanted()) { - mUpstreamWanted = true; - mOffload.start(); - chooseUpstreamType(true); - mTryCell = false; - } - - // TODO: Check the upstream interface if it is managed by BPF offload. - mBpfCoordinator.startPolling(); - } - - @Override - public void exit() { - mOffload.stop(); - mUpstreamNetworkMonitor.stop(); - notifyDownstreamsOfNewUpstreamIface(null); - handleNewUpstreamNetworkState(null); - if (mTetherUpstream != null) { - mTetherUpstream = null; - reportUpstreamChanged(null); - } - mBpfCoordinator.stopPolling(); - } - - private boolean updateUpstreamWanted() { - final boolean previousUpstreamWanted = mUpstreamWanted; - mUpstreamWanted = upstreamWanted(); - if (mUpstreamWanted != previousUpstreamWanted) { - if (mUpstreamWanted) { - mOffload.start(); - } else { - mOffload.stop(); - } - } - return previousUpstreamWanted; - } - - @Override - public boolean processMessage(Message message) { - logMessage(this, message.what); - boolean retValue = true; - switch (message.what) { - case EVENT_IFACE_SERVING_STATE_ACTIVE: { - IpServer who = (IpServer) message.obj; - if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); - handleInterfaceServingStateActive(message.arg1, who); - who.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, - mCurrentUpstreamIfaceSet); - // If there has been a change and an upstream is now - // desired, kick off the selection process. - final boolean previousUpstreamWanted = updateUpstreamWanted(); - if (!previousUpstreamWanted && mUpstreamWanted) { - chooseUpstreamType(true); - } - break; - } - case EVENT_IFACE_SERVING_STATE_INACTIVE: { - IpServer who = (IpServer) message.obj; - if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); - handleInterfaceServingStateInactive(who); - - if (mNotifyList.isEmpty()) { - // This transitions us out of TetherModeAliveState, - // either to InitialState or an error state. - turnOffMainTetherSettings(); - break; - } - - if (DBG) { - Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() - + " live requests:"); - for (IpServer o : mNotifyList) { - Log.d(TAG, " " + o); - } - } - // If there has been a change and an upstream is no - // longer desired, release any mobile requests. - final boolean previousUpstreamWanted = updateUpstreamWanted(); - if (previousUpstreamWanted && !mUpstreamWanted) { - mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); - } - break; - } - case EVENT_IFACE_UPDATE_LINKPROPERTIES: { - final LinkProperties newLp = (LinkProperties) message.obj; - if (message.arg1 == IpServer.STATE_TETHERED) { - mOffload.updateDownstreamLinkProperties(newLp); - } else { - mOffload.excludeDownstreamInterface(newLp.getInterfaceName()); - } - break; - } - case EVENT_UPSTREAM_PERMISSION_CHANGED: - case CMD_UPSTREAM_CHANGED: - updateUpstreamWanted(); - if (!mUpstreamWanted) break; - - // Need to try DUN immediately if Wi-Fi goes down. - chooseUpstreamType(true); - mTryCell = false; - break; - case CMD_RETRY_UPSTREAM: - updateUpstreamWanted(); - if (!mUpstreamWanted) break; - - chooseUpstreamType(mTryCell); - mTryCell = !mTryCell; - break; - case EVENT_UPSTREAM_CALLBACK: { - updateUpstreamWanted(); - if (mUpstreamWanted) { - handleUpstreamNetworkMonitorCallback(message.arg1, message.obj); - } - break; - } - default: - retValue = false; - break; - } - return retValue; - } - } - - class ErrorState extends State { - private int mErrorNotification; - - @Override - public boolean processMessage(Message message) { - boolean retValue = true; - switch (message.what) { - case EVENT_IFACE_SERVING_STATE_ACTIVE: - IpServer who = (IpServer) message.obj; - who.sendMessage(mErrorNotification); - break; - case CMD_CLEAR_ERROR: - mErrorNotification = TETHER_ERROR_NO_ERROR; - transitionTo(mInitialState); - break; - default: - retValue = false; - } - return retValue; - } - - void notify(int msgType) { - mErrorNotification = msgType; - for (IpServer ipServer : mNotifyList) { - ipServer.sendMessage(msgType); - } - } - - } - - class SetIpForwardingEnabledErrorState extends ErrorState { - @Override - public void enter() { - Log.e(TAG, "Error in setIpForwardingEnabled"); - notify(IpServer.CMD_IP_FORWARDING_ENABLE_ERROR); - } - } - - class SetIpForwardingDisabledErrorState extends ErrorState { - @Override - public void enter() { - Log.e(TAG, "Error in setIpForwardingDisabled"); - notify(IpServer.CMD_IP_FORWARDING_DISABLE_ERROR); - } - } - - class StartTetheringErrorState extends ErrorState { - @Override - public void enter() { - Log.e(TAG, "Error in startTethering"); - notify(IpServer.CMD_START_TETHERING_ERROR); - try { - mNetd.ipfwdDisableForwarding(TAG); - } catch (RemoteException | ServiceSpecificException e) { } - } - } - - class StopTetheringErrorState extends ErrorState { - @Override - public void enter() { - Log.e(TAG, "Error in stopTethering"); - notify(IpServer.CMD_STOP_TETHERING_ERROR); - try { - mNetd.ipfwdDisableForwarding(TAG); - } catch (RemoteException | ServiceSpecificException e) { } - } - } - - class SetDnsForwardersErrorState extends ErrorState { - @Override - public void enter() { - Log.e(TAG, "Error in setDnsForwarders"); - notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR); - try { - mNetd.tetherStop(); - } catch (RemoteException | ServiceSpecificException e) { } - try { - mNetd.ipfwdDisableForwarding(TAG); - } catch (RemoteException | ServiceSpecificException e) { } - } - } - - // A wrapper class to handle multiple situations where several calls to - // the OffloadController need to happen together. - // - // TODO: This suggests that the interface between OffloadController and - // Tethering is in need of improvement. Refactor these calls into the - // OffloadController implementation. - class OffloadWrapper { - public void start() { - final int status = mOffloadController.start() ? TETHER_HARDWARE_OFFLOAD_STARTED - : TETHER_HARDWARE_OFFLOAD_FAILED; - updateOffloadStatus(status); - sendOffloadExemptPrefixes(); - } - - public void stop() { - mOffloadController.stop(); - updateOffloadStatus(TETHER_HARDWARE_OFFLOAD_STOPPED); - } - - public void updateUpstreamNetworkState(UpstreamNetworkState ns) { - mOffloadController.setUpstreamLinkProperties( - (ns != null) ? ns.linkProperties : null); - } - - public void updateDownstreamLinkProperties(LinkProperties newLp) { - // Update the list of offload-exempt prefixes before adding - // new prefixes on downstream interfaces to the offload HAL. - sendOffloadExemptPrefixes(); - mOffloadController.notifyDownstreamLinkProperties(newLp); - } - - public void excludeDownstreamInterface(String ifname) { - // This and other interfaces may be in local-only hotspot mode; - // resend all local prefixes to the OffloadController. - sendOffloadExemptPrefixes(); - mOffloadController.removeDownstreamInterface(ifname); - } - - public void sendOffloadExemptPrefixes() { - sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); - } - - public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) { - // Add in well-known minimum set. - PrefixUtils.addNonForwardablePrefixes(localPrefixes); - // Add tragically hardcoded prefixes. - localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); - - // Maybe add prefixes or addresses for downstreams, depending on - // the IP serving mode of each. - for (IpServer ipServer : mNotifyList) { - final LinkProperties lp = ipServer.linkProperties(); - - switch (ipServer.servingMode()) { - case IpServer.STATE_UNAVAILABLE: - case IpServer.STATE_AVAILABLE: - // No usable LinkProperties in these states. - continue; - case IpServer.STATE_TETHERED: - // Only add IPv4 /32 and IPv6 /128 prefixes. The - // directly-connected prefixes will be sent as - // downstream "offload-able" prefixes. - for (LinkAddress addr : lp.getAllLinkAddresses()) { - final InetAddress ip = addr.getAddress(); - if (ip.isLinkLocalAddress()) continue; - localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip)); - } - break; - case IpServer.STATE_LOCAL_ONLY: - // Add prefixes covering all local IPs. - localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp)); - break; - } - } - - mOffloadController.setLocalPrefixes(localPrefixes); - } - - private void updateOffloadStatus(final int newStatus) { - if (newStatus == mOffloadStatus) return; - - mOffloadStatus = newStatus; - reportOffloadStatusChanged(mOffloadStatus); - } - } - } - - private void startTrackDefaultNetwork() { - mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(), - mEntitlementMgr); - } - - /** Get the latest value of the tethering entitlement check. */ - void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, - boolean showEntitlementUi) { - if (receiver == null) return; - - mHandler.post(() -> { - mEntitlementMgr.requestLatestTetheringEntitlementResult(type, receiver, - showEntitlementUi); - }); - } - - /** Register tethering event callback */ - void registerTetheringEventCallback(ITetheringEventCallback callback) { - final boolean hasListPermission = - hasCallingPermission(NETWORK_SETTINGS) - || hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK) - || hasCallingPermission(NETWORK_STACK); - mHandler.post(() -> { - mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission)); - final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel(); - parcel.tetheringSupported = isTetheringSupported(); - parcel.upstreamNetwork = mTetherUpstream; - parcel.config = mConfig.toStableParcelable(); - parcel.states = - mTetherStatesParcel != null ? mTetherStatesParcel : emptyTetherStatesParcel(); - parcel.tetheredClients = hasListPermission - ? mConnectedClientsTracker.getLastTetheredClients() - : Collections.emptyList(); - parcel.offloadStatus = mOffloadStatus; - try { - callback.onCallbackStarted(parcel); - } catch (RemoteException e) { - // Not really very much to do here. - } - }); - } - - private TetherStatesParcel emptyTetherStatesParcel() { - final TetherStatesParcel parcel = new TetherStatesParcel(); - parcel.availableList = new String[0]; - parcel.tetheredList = new String[0]; - parcel.localOnlyList = new String[0]; - parcel.erroredIfaceList = new String[0]; - parcel.lastErrorList = new int[0]; - - return parcel; - } - - private boolean hasCallingPermission(@NonNull String permission) { - return mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; - } - - /** Unregister tethering event callback */ - void unregisterTetheringEventCallback(ITetheringEventCallback callback) { - mHandler.post(() -> { - mTetheringEventCallbacks.unregister(callback); - }); - } - - private void reportUpstreamChanged(UpstreamNetworkState ns) { - final int length = mTetheringEventCallbacks.beginBroadcast(); - final Network network = (ns != null) ? ns.network : null; - final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null; - try { - for (int i = 0; i < length; i++) { - try { - mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network); - } catch (RemoteException e) { - // Not really very much to do here. - } - } - } finally { - mTetheringEventCallbacks.finishBroadcast(); - } - // Need to notify capabilities change after upstream network changed because new network's - // capabilities should be checked every time. - mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities); - } - - private void reportConfigurationChanged(TetheringConfigurationParcel config) { - final int length = mTetheringEventCallbacks.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - try { - mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config); - // TODO(b/148139325): send tetheringSupported on configuration change - } catch (RemoteException e) { - // Not really very much to do here. - } - } - } finally { - mTetheringEventCallbacks.finishBroadcast(); - } - } - - private void reportTetherStateChanged(TetherStatesParcel states) { - final int length = mTetheringEventCallbacks.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - try { - mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states); - } catch (RemoteException e) { - // Not really very much to do here. - } - } - } finally { - mTetheringEventCallbacks.finishBroadcast(); - } - } - - private void reportTetherClientsChanged(List<TetheredClient> clients) { - final int length = mTetheringEventCallbacks.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - try { - final CallbackCookie cookie = - (CallbackCookie) mTetheringEventCallbacks.getBroadcastCookie(i); - if (!cookie.hasListClientsPermission) continue; - mTetheringEventCallbacks.getBroadcastItem(i).onTetherClientsChanged(clients); - } catch (RemoteException e) { - // Not really very much to do here. - } - } - } finally { - mTetheringEventCallbacks.finishBroadcast(); - } - } - - private void reportOffloadStatusChanged(final int status) { - final int length = mTetheringEventCallbacks.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - try { - mTetheringEventCallbacks.getBroadcastItem(i).onOffloadStatusChanged(status); - } catch (RemoteException e) { - // Not really very much to do here. - } - } - } finally { - mTetheringEventCallbacks.finishBroadcast(); - } - } - - // if ro.tether.denied = true we default to no tethering - // gservices could set the secure setting to 1 though to enable it on a build where it - // had previously been turned off. - boolean isTetheringSupported() { - final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1; - final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TETHER_SUPPORTED, defaultVal) != 0; - final boolean tetherEnabledInSettings = tetherSupported - && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); - - return tetherEnabledInSettings && hasTetherableConfiguration() - && !isProvisioningNeededButUnavailable(); - } - - void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { - // Binder.java closes the resource for us. - @SuppressWarnings("resource") - final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump."); - return; - } - - pw.println("Tethering:"); - pw.increaseIndent(); - - pw.println("Configuration:"); - pw.increaseIndent(); - final TetheringConfiguration cfg = mConfig; - cfg.dump(pw); - pw.decreaseIndent(); - - pw.println("Entitlement:"); - pw.increaseIndent(); - mEntitlementMgr.dump(pw); - pw.decreaseIndent(); - - synchronized (mPublicSync) { - pw.println("Tether state:"); - pw.increaseIndent(); - for (int i = 0; i < mTetherStates.size(); i++) { - final String iface = mTetherStates.keyAt(i); - final TetherState tetherState = mTetherStates.valueAt(i); - pw.print(iface + " - "); - - switch (tetherState.lastState) { - case IpServer.STATE_UNAVAILABLE: - pw.print("UnavailableState"); - break; - case IpServer.STATE_AVAILABLE: - pw.print("AvailableState"); - break; - case IpServer.STATE_TETHERED: - pw.print("TetheredState"); - break; - case IpServer.STATE_LOCAL_ONLY: - pw.print("LocalHotspotState"); - break; - default: - pw.print("UnknownState"); - break; - } - pw.println(" - lastError = " + tetherState.lastError); - } - pw.println("Upstream wanted: " + upstreamWanted()); - pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet); - pw.decreaseIndent(); - } - - pw.println("Hardware offload:"); - pw.increaseIndent(); - mOffloadController.dump(pw); - pw.decreaseIndent(); - - pw.println("BPF offload:"); - pw.increaseIndent(); - mBpfCoordinator.dump(pw); - pw.decreaseIndent(); - - pw.println("Private address coordinator:"); - pw.increaseIndent(); - mPrivateAddressCoordinator.dump(pw); - pw.decreaseIndent(); - - pw.println("Log:"); - pw.increaseIndent(); - if (argsContain(args, "--short")) { - pw.println("<log removed for brevity>"); - } else { - mLog.dump(fd, pw, args); - } - pw.decreaseIndent(); - - pw.decreaseIndent(); - } - - private static boolean argsContain(String[] args, String target) { - for (String arg : args) { - if (target.equals(arg)) return true; - } - return false; - } - - private void updateConnectedClients(final List<WifiClient> wifiClients) { - if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, wifiClients)) { - reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients()); - } - } - - private IpServer.Callback makeControlCallback() { - return new IpServer.Callback() { - @Override - public void updateInterfaceState(IpServer who, int state, int lastError) { - notifyInterfaceStateChange(who, state, lastError); - } - - @Override - public void updateLinkProperties(IpServer who, LinkProperties newLp) { - notifyLinkPropertiesChanged(who, newLp); - } - - @Override - public void dhcpLeasesChanged() { - updateConnectedClients(null /* wifiClients */); - } - - @Override - public void requestEnableTethering(int tetheringType, boolean enabled) { - enableTetheringInternal(tetheringType, enabled, null); - } - }; - } - - // TODO: Move into TetherMainSM. - private void notifyInterfaceStateChange(IpServer who, int state, int error) { - final String iface = who.interfaceName(); - synchronized (mPublicSync) { - final TetherState tetherState = mTetherStates.get(iface); - if (tetherState != null && tetherState.ipServer.equals(who)) { - tetherState.lastState = state; - tetherState.lastError = error; - } else { - if (DBG) Log.d(TAG, "got notification from stale iface " + iface); - } - } - - mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error)); - - // If TetherMainSM is in ErrorState, TetherMainSM stays there. - // Thus we give a chance for TetherMainSM to recover to InitialState - // by sending CMD_CLEAR_ERROR - if (error == TETHER_ERROR_INTERNAL_ERROR) { - mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who); - } - int which; - switch (state) { - case IpServer.STATE_UNAVAILABLE: - case IpServer.STATE_AVAILABLE: - which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE; - break; - case IpServer.STATE_TETHERED: - case IpServer.STATE_LOCAL_ONLY: - which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE; - break; - default: - Log.wtf(TAG, "Unknown interface state: " + state); - return; - } - mTetherMainSM.sendMessage(which, state, 0, who); - sendTetherStateChangedBroadcast(); - } - - private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) { - final String iface = who.interfaceName(); - final int state; - synchronized (mPublicSync) { - final TetherState tetherState = mTetherStates.get(iface); - if (tetherState != null && tetherState.ipServer.equals(who)) { - state = tetherState.lastState; - } else { - mLog.log("got notification from stale iface " + iface); - return; - } - } - - mLog.log(String.format( - "OBSERVED LinkProperties update iface=%s state=%s lp=%s", - iface, IpServer.getStateString(state), newLp)); - final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; - mTetherMainSM.sendMessage(which, state, 0, newLp); - } - - private void maybeTrackNewInterfaceLocked(final String iface) { - // If we don't care about this type of interface, ignore. - final int interfaceType = ifaceNameToType(iface); - if (interfaceType == TETHERING_INVALID) { - mLog.log(iface + " is not a tetherable iface, ignoring"); - return; - } - maybeTrackNewInterfaceLocked(iface, interfaceType); - } - - private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) { - // If we have already started a TISM for this interface, skip. - if (mTetherStates.containsKey(iface)) { - mLog.log("active iface (" + iface + ") reported as added, ignoring"); - return; - } - - mLog.log("adding TetheringInterfaceStateMachine for: " + iface); - final TetherState tetherState = new TetherState( - new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator, - makeControlCallback(), mConfig.enableLegacyDhcpServer, - mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator, - mDeps.getIpServerDependencies())); - mTetherStates.put(iface, tetherState); - tetherState.ipServer.start(); - } - - private void stopTrackingInterfaceLocked(final String iface) { - final TetherState tetherState = mTetherStates.get(iface); - if (tetherState == null) { - mLog.log("attempting to remove unknown iface (" + iface + "), ignoring"); - return; - } - tetherState.ipServer.stop(); - mLog.log("removing TetheringInterfaceStateMachine for: " + iface); - mTetherStates.remove(iface); - } - - private static String[] copy(String[] strarray) { - return Arrays.copyOf(strarray, strarray.length); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java deleted file mode 100644 index 799637c9b1c5..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.content.Context.TELEPHONY_SERVICE; -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; -import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; -import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; - -import android.content.Context; -import android.content.res.Resources; -import android.net.TetheringConfigurationParcel; -import android.net.util.SharedLog; -import android.provider.DeviceConfig; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.StringJoiner; - -/** - * A utility class to encapsulate the various tethering configuration elements. - * - * This configuration data includes elements describing upstream properties - * (preferred and required types of upstream connectivity as well as default - * DNS servers to use if none are available) and downstream properties (such - * as regular expressions use to match suitable downstream interfaces and the - * DHCPv4 ranges to use). - * - * @hide - */ -public class TetheringConfiguration { - private static final String TAG = TetheringConfiguration.class.getSimpleName(); - - private static final String[] EMPTY_STRING_ARRAY = new String[0]; - - // Default ranges used for the legacy DHCP server. - // USB is 192.168.42.1 and 255.255.255.0 - // Wifi is 192.168.43.1 and 255.255.255.0 - // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 - // with 255.255.255.0 - // P2P is 192.168.49.1 and 255.255.255.0 - private static final String[] LEGACY_DHCP_DEFAULT_RANGE = { - "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254", - "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254", - "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254", - "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254", - }; - - private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"}; - - /** - * Override enabling BPF offload configuration for tethering. - */ - public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD = - "override_tether_enable_bpf_offload"; - - /** - * Use the old dnsmasq DHCP server for tethering instead of the framework implementation. - */ - public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER = - "tether_enable_legacy_dhcp_server"; - - public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP = - "use_legacy_wifi_p2p_dedicated_ip"; - - /** - * Flag use to enable select all prefix ranges feature. - * TODO: Remove this flag if there are no problems after M-2020-12 rolls out. - */ - public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES = - "tether_enable_select_all_prefix_ranges"; - - /** - * Default value that used to periodic polls tether offload stats from tethering offload HAL - * to make the data warnings work. - */ - public static final int DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS = 5000; - - public final String[] tetherableUsbRegexs; - public final String[] tetherableWifiRegexs; - public final String[] tetherableWigigRegexs; - public final String[] tetherableWifiP2pRegexs; - public final String[] tetherableBluetoothRegexs; - public final String[] tetherableNcmRegexs; - public final boolean isDunRequired; - public final boolean chooseUpstreamAutomatically; - public final Collection<Integer> preferredUpstreamIfaceTypes; - public final String[] legacyDhcpRanges; - public final String[] defaultIPv4DNS; - public final boolean enableLegacyDhcpServer; - - public final String[] provisioningApp; - public final String provisioningAppNoUi; - public final int provisioningCheckPeriod; - public final String provisioningResponse; - - public final int activeDataSubId; - - private final int mOffloadPollInterval; - // TODO: Add to TetheringConfigurationParcel if required. - private final boolean mEnableBpfOffload; - private final boolean mEnableWifiP2pDedicatedIp; - - private final boolean mEnableSelectAllPrefixRange; - - public TetheringConfiguration(Context ctx, SharedLog log, int id) { - final SharedLog configLog = log.forSubComponent("config"); - - activeDataSubId = id; - Resources res = getResources(ctx, activeDataSubId); - - tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs); - tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs); - // TODO: Evaluate deleting this altogether now that Wi-Fi always passes - // us an interface name. Careful consideration needs to be given to - // implications for Settings and for provisioning checks. - tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs); - tetherableWigigRegexs = getResourceStringArray(res, R.array.config_tether_wigig_regexs); - tetherableWifiP2pRegexs = getResourceStringArray( - res, R.array.config_tether_wifi_p2p_regexs); - tetherableBluetoothRegexs = getResourceStringArray( - res, R.array.config_tether_bluetooth_regexs); - - isDunRequired = checkDunRequired(ctx); - - chooseUpstreamAutomatically = getResourceBoolean( - res, R.bool.config_tether_upstream_automatic, false /** defaultValue */); - preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired); - - legacyDhcpRanges = getLegacyDhcpRanges(res); - defaultIPv4DNS = copy(DEFAULT_IPV4_DNS); - mEnableBpfOffload = getEnableBpfOffload(res); - enableLegacyDhcpServer = getEnableLegacyDhcpServer(res); - - provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app); - provisioningAppNoUi = getResourceString(res, - R.string.config_mobile_hotspot_provision_app_no_ui); - provisioningCheckPeriod = getResourceInteger(res, - R.integer.config_mobile_hotspot_provision_check_period, - 0 /* No periodic re-check */); - provisioningResponse = getResourceString(res, - R.string.config_mobile_hotspot_provision_response); - - mOffloadPollInterval = getResourceInteger(res, - R.integer.config_tether_offload_poll_interval, - DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - - mEnableWifiP2pDedicatedIp = getResourceBoolean(res, - R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip, - false /* defaultValue */); - - // Flags should normally not be booleans, but this is a kill-switch flag that is only used - // to turn off the feature, so binary rollback problems do not apply. - mEnableSelectAllPrefixRange = getDeviceConfigBoolean( - TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */); - - configLog.log(toString()); - } - - /** Check whether input interface belong to usb.*/ - public boolean isUsb(String iface) { - return matchesDownstreamRegexs(iface, tetherableUsbRegexs); - } - - /** Check whether input interface belong to wifi.*/ - public boolean isWifi(String iface) { - return matchesDownstreamRegexs(iface, tetherableWifiRegexs); - } - - /** Check whether input interface belong to wigig.*/ - public boolean isWigig(String iface) { - return matchesDownstreamRegexs(iface, tetherableWigigRegexs); - } - - /** Check whether this interface is Wifi P2P interface. */ - public boolean isWifiP2p(String iface) { - return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs); - } - - /** Check whether using legacy mode for wifi P2P. */ - public boolean isWifiP2pLegacyTetheringMode() { - return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0); - } - - /** Check whether input interface belong to bluetooth.*/ - public boolean isBluetooth(String iface) { - return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs); - } - - /** Check if interface is ncm */ - public boolean isNcm(String iface) { - return matchesDownstreamRegexs(iface, tetherableNcmRegexs); - } - - /** Check whether no ui entitlement application is available.*/ - public boolean hasMobileHotspotProvisionApp() { - return !TextUtils.isEmpty(provisioningAppNoUi); - } - - /** Check whether dedicated wifi p2p address is enabled. */ - public boolean shouldEnableWifiP2pDedicatedIp() { - return mEnableWifiP2pDedicatedIp; - } - - /** Does the dumping.*/ - public void dump(PrintWriter pw) { - pw.print("activeDataSubId: "); - pw.println(activeDataSubId); - - dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs); - dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); - dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs); - dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs); - dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs); - - pw.print("isDunRequired: "); - pw.println(isDunRequired); - - pw.print("chooseUpstreamAutomatically: "); - pw.println(chooseUpstreamAutomatically); - pw.print("legacyPreredUpstreamIfaceTypes: "); - pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes))); - - dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges); - dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS); - - pw.print("offloadPollInterval: "); - pw.println(mOffloadPollInterval); - - dumpStringArray(pw, "provisioningApp", provisioningApp); - pw.print("provisioningAppNoUi: "); - pw.println(provisioningAppNoUi); - - pw.print("enableBpfOffload: "); - pw.println(mEnableBpfOffload); - - pw.print("enableLegacyDhcpServer: "); - pw.println(enableLegacyDhcpServer); - - pw.print("enableWifiP2pDedicatedIp: "); - pw.println(mEnableWifiP2pDedicatedIp); - - pw.print("mEnableSelectAllPrefixRange: "); - pw.println(mEnableSelectAllPrefixRange); - } - - /** Returns the string representation of this object.*/ - public String toString() { - final StringJoiner sj = new StringJoiner(" "); - sj.add(String.format("activeDataSubId:%d", activeDataSubId)); - sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs))); - sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs))); - sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs))); - sj.add(String.format("tetherableBluetoothRegexs:%s", - makeString(tetherableBluetoothRegexs))); - sj.add(String.format("isDunRequired:%s", isDunRequired)); - sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically)); - sj.add(String.format("offloadPollInterval:%d", mOffloadPollInterval)); - sj.add(String.format("preferredUpstreamIfaceTypes:%s", - toIntArray(preferredUpstreamIfaceTypes))); - sj.add(String.format("provisioningApp:%s", makeString(provisioningApp))); - sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi)); - sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload)); - sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer)); - return String.format("TetheringConfiguration{%s}", sj.toString()); - } - - private static void dumpStringArray(PrintWriter pw, String label, String[] values) { - pw.print(label); - pw.print(": "); - - if (values != null) { - final StringJoiner sj = new StringJoiner(", ", "[", "]"); - for (String value : values) sj.add(value); - pw.print(sj.toString()); - } else { - pw.print("null"); - } - - pw.println(); - } - - private static String makeString(String[] strings) { - if (strings == null) return "null"; - final StringJoiner sj = new StringJoiner(",", "[", "]"); - for (String s : strings) sj.add(s); - return sj.toString(); - } - - /** Check whether dun is required. */ - public static boolean checkDunRequired(Context ctx) { - final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); - // TelephonyManager would uses the active data subscription, which should be the one used - // by tethering. - return (tm != null) ? tm.isTetheringApnRequired() : false; - } - - public int getOffloadPollInterval() { - return mOffloadPollInterval; - } - - public boolean isBpfOffloadEnabled() { - return mEnableBpfOffload; - } - - public boolean isSelectAllPrefixRangeEnabled() { - return mEnableSelectAllPrefixRange; - } - - private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { - final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types); - final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length); - for (int i : ifaceTypes) { - switch (i) { - case TYPE_MOBILE: - case TYPE_MOBILE_HIPRI: - if (dunRequired) continue; - break; - case TYPE_MOBILE_DUN: - if (!dunRequired) continue; - break; - } - upstreamIfaceTypes.add(i); - } - - // Fix up upstream interface types for DUN or mobile. NOTE: independent - // of the value of |dunRequired|, cell data of one form or another is - // *always* an upstream, regardless of the upstream interface types - // specified by configuration resources. - if (dunRequired) { - appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN); - } else { - // Do not modify if a cellular interface type is already present in the - // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no - // cellular interface types are found in the upstream interface types. - // This preserves backwards compatibility and prevents the DUN and default - // mobile types incorrectly appearing together, which could happen on - // previous releases in the common case where checkDunRequired returned - // DUN_UNSPECIFIED. - if (!containsOneOf(upstreamIfaceTypes, TYPE_MOBILE, TYPE_MOBILE_HIPRI)) { - upstreamIfaceTypes.add(TYPE_MOBILE); - upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI); - } - } - - // Always make sure our good friend Ethernet is present. - // TODO: consider unilaterally forcing this at the front. - prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET); - - return upstreamIfaceTypes; - } - - private static boolean matchesDownstreamRegexs(String iface, String[] regexs) { - for (String regex : regexs) { - if (iface.matches(regex)) return true; - } - return false; - } - - private static String[] getLegacyDhcpRanges(Resources res) { - final String[] fromResource = getResourceStringArray(res, R.array.config_tether_dhcp_range); - if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) { - return fromResource; - } - return copy(LEGACY_DHCP_DEFAULT_RANGE); - } - - private static String getResourceString(Resources res, final int resId) { - try { - return res.getString(resId); - } catch (Resources.NotFoundException e) { - return ""; - } - } - - private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) { - try { - return res.getBoolean(resId); - } catch (Resources.NotFoundException e404) { - return defaultValue; - } - } - - private static String[] getResourceStringArray(Resources res, int resId) { - try { - final String[] strArray = res.getStringArray(resId); - return (strArray != null) ? strArray : EMPTY_STRING_ARRAY; - } catch (Resources.NotFoundException e404) { - return EMPTY_STRING_ARRAY; - } - } - - private static int getResourceInteger(Resources res, int resId, int defaultValue) { - try { - return res.getInteger(resId); - } catch (Resources.NotFoundException e404) { - return defaultValue; - } - } - - private boolean getEnableBpfOffload(final Resources res) { - // Get BPF offload config - // Priority 1: Device config - // Priority 2: Resource config - // Priority 3: Default value - final boolean defaultValue = getResourceBoolean( - res, R.bool.config_tether_enable_bpf_offload, true /** default value */); - - return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue); - } - - private boolean getEnableLegacyDhcpServer(final Resources res) { - return getResourceBoolean( - res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */) - || getDeviceConfigBoolean( - TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */); - } - - private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) { - // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead - // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the - // returned boolean value comes from device config or default value (because of null - // property string). See the test case testBpfOffload{*} in TetheringConfigurationTest.java. - final String value = getDeviceConfigProperty(name); - return value != null ? Boolean.parseBoolean(value) : defaultValue; - } - - @VisibleForTesting - protected String getDeviceConfigProperty(String name) { - return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name); - } - - private Resources getResources(Context ctx, int subId) { - if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - return getResourcesForSubIdWrapper(ctx, subId); - } else { - return ctx.getResources(); - } - } - - @VisibleForTesting - protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) { - return SubscriptionManager.getResourcesForSubId(ctx, subId); - } - - private static String[] copy(String[] strarray) { - return Arrays.copyOf(strarray, strarray.length); - } - - private static void prependIfNotPresent(ArrayList<Integer> list, int value) { - if (list.contains(value)) return; - list.add(0, value); - } - - private static void appendIfNotPresent(ArrayList<Integer> list, int value) { - if (list.contains(value)) return; - list.add(value); - } - - private static boolean containsOneOf(ArrayList<Integer> list, Integer... values) { - for (Integer value : values) { - if (list.contains(value)) return true; - } - return false; - } - - private static int[] toIntArray(Collection<Integer> values) { - final int[] result = new int[values.size()]; - int index = 0; - for (Integer value : values) { - result[index++] = value; - } - return result; - } - - /** - * Convert this TetheringConfiguration to a TetheringConfigurationParcel. - */ - public TetheringConfigurationParcel toStableParcelable() { - final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel(); - parcel.subId = activeDataSubId; - parcel.tetherableUsbRegexs = tetherableUsbRegexs; - parcel.tetherableWifiRegexs = tetherableWifiRegexs; - parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs; - parcel.isDunRequired = isDunRequired; - parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically; - - parcel.preferredUpstreamIfaceTypes = toIntArray(preferredUpstreamIfaceTypes); - - parcel.legacyDhcpRanges = legacyDhcpRanges; - parcel.defaultIPv4DNS = defaultIPv4DNS; - parcel.enableLegacyDhcpServer = enableLegacyDhcpServer; - parcel.provisioningApp = provisioningApp; - parcel.provisioningAppNoUi = provisioningAppNoUi; - parcel.provisioningCheckPeriod = provisioningCheckPeriod; - return parcel; - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java deleted file mode 100644 index 45b914178e97..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import android.app.usage.NetworkStatsManager; -import android.bluetooth.BluetoothAdapter; -import android.content.Context; -import android.net.INetd; -import android.net.NetworkRequest; -import android.net.ip.IpServer; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.SystemProperties; -import android.text.TextUtils; - -import androidx.annotation.NonNull; - -import com.android.internal.util.StateMachine; - -import java.util.ArrayList; - - -/** - * Capture tethering dependencies, for injection. - * - * @hide - */ -public abstract class TetheringDependencies { - /** - * Get a reference to the BpfCoordinator to be used by tethering. - */ - public @NonNull BpfCoordinator getBpfCoordinator( - @NonNull BpfCoordinator.Dependencies deps) { - return new BpfCoordinator(deps); - } - - /** - * Get a reference to the offload hardware interface to be used by tethering. - */ - public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) { - return new OffloadHardwareInterface(h, log); - } - - /** - * Get a reference to the offload controller to be used by tethering. - */ - @NonNull - public OffloadController getOffloadController(@NonNull Handler h, - @NonNull SharedLog log, @NonNull OffloadController.Dependencies deps) { - final NetworkStatsManager statsManager = - (NetworkStatsManager) getContext().getSystemService(Context.NETWORK_STATS_SERVICE); - return new OffloadController(h, getOffloadHardwareInterface(h, log), - getContext().getContentResolver(), statsManager, log, deps); - } - - - /** - * Get a reference to the UpstreamNetworkMonitor to be used by tethering. - */ - public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target, - SharedLog log, int what) { - return new UpstreamNetworkMonitor(ctx, target, log, what); - } - - /** - * Get a reference to the IPv6TetheringCoordinator to be used by tethering. - */ - public IPv6TetheringCoordinator getIPv6TetheringCoordinator( - ArrayList<IpServer> notifyList, SharedLog log) { - return new IPv6TetheringCoordinator(notifyList, log); - } - - /** - * Get dependencies to be used by IpServer. - */ - public abstract IpServer.Dependencies getIpServerDependencies(); - - /** - * Indicates whether tethering is supported on the device. - */ - public boolean isTetheringSupported() { - return true; - } - - /** - * Get the NetworkRequest that should be fulfilled by the default network. - */ - public abstract NetworkRequest getDefaultNetworkRequest(); - - /** - * Get a reference to the EntitlementManager to be used by tethering. - */ - public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log, - Runnable callback) { - return new EntitlementManager(ctx, h, log, callback); - } - - /** - * Generate a new TetheringConfiguration according to input sub Id. - */ - public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log, - int subId) { - return new TetheringConfiguration(ctx, log, subId); - } - - /** - * Get a reference to INetd to be used by tethering. - */ - public INetd getINetd(Context context) { - return INetd.Stub.asInterface( - (IBinder) context.getSystemService(Context.NETD_SERVICE)); - } - - /** - * Get a reference to the TetheringNotificationUpdater to be used by tethering. - */ - public TetheringNotificationUpdater getNotificationUpdater(@NonNull final Context ctx, - @NonNull final Looper looper) { - return new TetheringNotificationUpdater(ctx, looper); - } - - /** - * Get tethering thread looper. - */ - public abstract Looper getTetheringLooper(); - - /** - * Get Context of TetheringSerice. - */ - public abstract Context getContext(); - - /** - * Get a reference to BluetoothAdapter to be used by tethering. - */ - public abstract BluetoothAdapter getBluetoothAdapter(); - - /** - * Get SystemProperties which indicate whether tethering is denied. - */ - public boolean isTetheringDenied() { - return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true"); - } - - /** - * Get a reference to PrivateAddressCoordinator to be used by Tethering. - */ - public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx, - TetheringConfiguration cfg) { - return new PrivateAddressCoordinator(ctx, cfg); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java deleted file mode 100644 index ff38f717a121..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import android.annotation.Nullable; -import android.net.LinkProperties; -import android.net.NetworkCapabilities; -import android.net.RouteInfo; -import android.net.util.InterfaceSet; - -import com.android.net.module.util.NetUtils; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * @hide - */ -public final class TetheringInterfaceUtils { - private static final InetAddress IN6ADDR_ANY = getByAddress( - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - private static final InetAddress INADDR_ANY = getByAddress(new byte[] {0, 0, 0, 0}); - - /** - * Get upstream interfaces for tethering based on default routes for IPv4/IPv6. - * @return null if there is no usable interface, or a set of at least one interface otherwise. - */ - public static @Nullable InterfaceSet getTetheringInterfaces(UpstreamNetworkState ns) { - if (ns == null) { - return null; - } - - final LinkProperties lp = ns.linkProperties; - final String if4 = getInterfaceForDestination(lp, INADDR_ANY); - final String if6 = getIPv6Interface(ns); - - return (if4 == null && if6 == null) ? null : new InterfaceSet(if4, if6); - } - - /** - * Get the upstream interface for IPv6 tethering. - * @return null if there is no usable interface, or the interface name otherwise. - */ - public static @Nullable String getIPv6Interface(UpstreamNetworkState ns) { - // Broadly speaking: - // - // [1] does the upstream have an IPv6 default route? - // - // and - // - // [2] does the upstream have one or more global IPv6 /64s - // dedicated to this device? - // - // In lieu of Prefix Delegation and other evaluation of whether a - // prefix may or may not be dedicated to this device, for now just - // check whether the upstream is TRANSPORT_CELLULAR. This works - // because "[t]he 3GPP network allocates each default bearer a unique - // /64 prefix", per RFC 6459, Section 5.2. - final boolean canTether = - (ns != null) && (ns.network != null) - && (ns.linkProperties != null) && (ns.networkCapabilities != null) - // At least one upstream DNS server: - && ns.linkProperties.hasIpv6DnsServer() - // Minimal amount of IPv6 provisioning: - && ns.linkProperties.hasGlobalIpv6Address() - // Temporary approximation of "dedicated prefix": - && ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR); - - return canTether - ? getInterfaceForDestination(ns.linkProperties, IN6ADDR_ANY) - : null; - } - - private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) { - final RouteInfo ri = (lp != null) - ? NetUtils.selectBestRoute(lp.getAllRoutes(), dst) - : null; - return (ri != null) ? ri.getInterface() : null; - } - - private static InetAddress getByAddress(final byte[] addr) { - try { - return InetAddress.getByAddress(null, addr); - } catch (UnknownHostException e) { - throw new AssertionError("illegal address length" + addr.length); - } - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java deleted file mode 100644 index a0198cc9c126..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; -import static android.text.TextUtils.isEmpty; - -import android.app.Notification; -import android.app.Notification.Action; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.net.NetworkCapabilities; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.UserHandle; -import android.provider.Settings; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.SparseArray; - -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.IntRange; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * A class to display tethering-related notifications. - * - * <p>This class is not thread safe, it is intended to be used only from the tethering handler - * thread. However the constructor is an exception, as it is called on another thread ; - * therefore for thread safety all members of this class MUST either be final or initialized - * to their default value (0, false or null). - * - * @hide - */ -public class TetheringNotificationUpdater { - private static final String TAG = TetheringNotificationUpdater.class.getSimpleName(); - private static final String CHANNEL_ID = "TETHERING_STATUS"; - private static final String WIFI_DOWNSTREAM = "WIFI"; - private static final String USB_DOWNSTREAM = "USB"; - private static final String BLUETOOTH_DOWNSTREAM = "BT"; - @VisibleForTesting - static final String ACTION_DISABLE_TETHERING = - "com.android.server.connectivity.tethering.DISABLE_TETHERING"; - private static final boolean NOTIFY_DONE = true; - private static final boolean NO_NOTIFY = false; - @VisibleForTesting - static final int EVENT_SHOW_NO_UPSTREAM = 1; - // Id to update and cancel restricted notification. Must be unique within the tethering app. - @VisibleForTesting - static final int RESTRICTED_NOTIFICATION_ID = 1001; - // Id to update and cancel no upstream notification. Must be unique within the tethering app. - @VisibleForTesting - static final int NO_UPSTREAM_NOTIFICATION_ID = 1002; - // Id to update and cancel roaming notification. Must be unique within the tethering app. - @VisibleForTesting - static final int ROAMING_NOTIFICATION_ID = 1003; - @VisibleForTesting - static final int NO_ICON_ID = 0; - @VisibleForTesting - static final int DOWNSTREAM_NONE = 0; - // Refer to TelephonyManager#getSimCarrierId for more details about carrier id. - @VisibleForTesting - static final int VERIZON_CARRIER_ID = 1839; - private final Context mContext; - private final NotificationManager mNotificationManager; - private final NotificationChannel mChannel; - private final Handler mHandler; - - // WARNING : the constructor is called on a different thread. Thread safety therefore - // relies on these values being initialized to 0, false or null, and not any other value. If you - // need to change this, you will need to change the thread where the constructor is invoked, or - // to introduce synchronization. - // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. - // This value has to be made 1 2 and 4, and OR'd with the others. - private int mDownstreamTypesMask = DOWNSTREAM_NONE; - private boolean mNoUpstream = false; - private boolean mRoaming = false; - - // WARNING : this value is not able to being initialized to 0 and must have volatile because - // telephony service is not guaranteed that is up before tethering service starts. If telephony - // is up later than tethering, TetheringNotificationUpdater will use incorrect and valid - // subscription id(0) to query resources. Therefore, initialized subscription id must be - // INVALID_SUBSCRIPTION_ID. - private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - RESTRICTED_NOTIFICATION_ID, - NO_UPSTREAM_NOTIFICATION_ID, - ROAMING_NOTIFICATION_ID - }) - @interface NotificationId {} - - private static final class MccMncOverrideInfo { - public final String visitedMccMnc; - public final int homeMcc; - public final int homeMnc; - MccMncOverrideInfo(String visitedMccMnc, int mcc, int mnc) { - this.visitedMccMnc = visitedMccMnc; - this.homeMcc = mcc; - this.homeMnc = mnc; - } - } - - private static final SparseArray<MccMncOverrideInfo> sCarrierIdToMccMnc = new SparseArray<>(); - - static { - sCarrierIdToMccMnc.put(VERIZON_CARRIER_ID, new MccMncOverrideInfo("20404", 311, 480)); - } - - public TetheringNotificationUpdater(@NonNull final Context context, - @NonNull final Looper looper) { - mContext = context; - mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0) - .getSystemService(Context.NOTIFICATION_SERVICE); - mChannel = new NotificationChannel( - CHANNEL_ID, - context.getResources().getString(R.string.notification_channel_tethering_status), - NotificationManager.IMPORTANCE_LOW); - mNotificationManager.createNotificationChannel(mChannel); - mHandler = new NotificationHandler(looper); - } - - private class NotificationHandler extends Handler { - NotificationHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch(msg.what) { - case EVENT_SHOW_NO_UPSTREAM: - notifyTetheringNoUpstream(); - break; - } - } - } - - /** Called when downstream has changed */ - public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { - updateActiveNotifications( - mActiveDataSubId, downstreamTypesMask, mNoUpstream, mRoaming); - } - - /** Called when active data subscription id changed */ - public void onActiveDataSubscriptionIdChanged(final int subId) { - updateActiveNotifications(subId, mDownstreamTypesMask, mNoUpstream, mRoaming); - } - - /** Called when upstream network capabilities changed */ - public void onUpstreamCapabilitiesChanged(@Nullable final NetworkCapabilities capabilities) { - final boolean isNoUpstream = (capabilities == null); - final boolean isRoaming = capabilities != null - && !capabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING); - updateActiveNotifications( - mActiveDataSubId, mDownstreamTypesMask, isNoUpstream, isRoaming); - } - - @NonNull - @VisibleForTesting - final Handler getHandler() { - return mHandler; - } - - @NonNull - @VisibleForTesting - Resources getResourcesForSubId(@NonNull final Context context, final int subId) { - final Resources res = SubscriptionManager.getResourcesForSubId(context, subId); - final TelephonyManager tm = - ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)) - .createForSubscriptionId(mActiveDataSubId); - final int carrierId = tm.getSimCarrierId(); - final String mccmnc = tm.getSimOperator(); - final MccMncOverrideInfo overrideInfo = sCarrierIdToMccMnc.get(carrierId); - if (overrideInfo != null && overrideInfo.visitedMccMnc.equals(mccmnc)) { - // Re-configure MCC/MNC value to specific carrier to get right resources. - final Configuration config = res.getConfiguration(); - config.mcc = overrideInfo.homeMcc; - config.mnc = overrideInfo.homeMnc; - return context.createConfigurationContext(config).getResources(); - } - return res; - } - - private void updateActiveNotifications(final int subId, final int downstreamTypes, - final boolean noUpstream, final boolean isRoaming) { - final boolean tetheringActiveChanged = - (downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE); - final boolean subIdChanged = subId != mActiveDataSubId; - final boolean upstreamChanged = noUpstream != mNoUpstream; - final boolean roamingChanged = isRoaming != mRoaming; - final boolean updateAll = tetheringActiveChanged || subIdChanged; - mActiveDataSubId = subId; - mDownstreamTypesMask = downstreamTypes; - mNoUpstream = noUpstream; - mRoaming = isRoaming; - - if (updateAll || upstreamChanged) updateNoUpstreamNotification(); - if (updateAll || roamingChanged) updateRoamingNotification(); - } - - private void updateNoUpstreamNotification() { - final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; - - if (tetheringInactive || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) { - clearNotification(NO_UPSTREAM_NOTIFICATION_ID); - mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM); - } - } - - private void updateRoamingNotification() { - final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; - - if (tetheringInactive || !mRoaming || setupRoamingNotification() == NO_NOTIFY) { - clearNotification(ROAMING_NOTIFICATION_ID); - } - } - - @VisibleForTesting - void tetheringRestrictionLifted() { - clearNotification(RESTRICTED_NOTIFICATION_ID); - } - - private void clearNotification(@NotificationId final int id) { - mNotificationManager.cancel(null /* tag */, id); - } - - @VisibleForTesting - static String getSettingsPackageName(@NonNull final PackageManager pm) { - final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS); - final ComponentName settingsComponent = settingsIntent.resolveActivity(pm); - return settingsComponent != null - ? settingsComponent.getPackageName() : "com.android.settings"; - } - - @VisibleForTesting - void notifyTetheringDisabledByRestriction() { - final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); - final String title = res.getString(R.string.disable_tether_notification_title); - final String message = res.getString(R.string.disable_tether_notification_message); - if (isEmpty(title) || isEmpty(message)) return; - - final PendingIntent pi = PendingIntent.getActivity( - mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - new Intent(Settings.ACTION_TETHER_SETTINGS) - .setPackage(getSettingsPackageName(mContext.getPackageManager())) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), - PendingIntent.FLAG_IMMUTABLE, - null /* options */); - - showNotification(R.drawable.stat_sys_tether_general, title, message, - RESTRICTED_NOTIFICATION_ID, false /* ongoing */, pi, new Action[0]); - } - - private void notifyTetheringNoUpstream() { - final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); - final String title = res.getString(R.string.no_upstream_notification_title); - final String message = res.getString(R.string.no_upstream_notification_message); - final String disableButton = - res.getString(R.string.no_upstream_notification_disable_button); - if (isEmpty(title) || isEmpty(message) || isEmpty(disableButton)) return; - - final Intent intent = new Intent(ACTION_DISABLE_TETHERING); - intent.setPackage(mContext.getPackageName()); - final PendingIntent pi = PendingIntent.getBroadcast( - mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - intent, - PendingIntent.FLAG_IMMUTABLE); - final Action action = new Action.Builder(NO_ICON_ID, disableButton, pi).build(); - - showNotification(R.drawable.stat_sys_tether_general, title, message, - NO_UPSTREAM_NOTIFICATION_ID, true /* ongoing */, null /* pendingIntent */, action); - } - - private boolean setupRoamingNotification() { - final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); - final boolean upstreamRoamingNotification = - res.getBoolean(R.bool.config_upstream_roaming_notification); - - if (!upstreamRoamingNotification) return NO_NOTIFY; - - final String title = res.getString(R.string.upstream_roaming_notification_title); - final String message = res.getString(R.string.upstream_roaming_notification_message); - if (isEmpty(title) || isEmpty(message)) return NO_NOTIFY; - - final PendingIntent pi = PendingIntent.getActivity( - mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - new Intent(Settings.ACTION_TETHER_SETTINGS) - .setPackage(getSettingsPackageName(mContext.getPackageManager())) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), - PendingIntent.FLAG_IMMUTABLE, - null /* options */); - - showNotification(R.drawable.stat_sys_tether_general, title, message, - ROAMING_NOTIFICATION_ID, true /* ongoing */, pi, new Action[0]); - return NOTIFY_DONE; - } - - private boolean setupNoUpstreamNotification() { - final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); - final int delayToShowUpstreamNotification = - res.getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul); - - if (delayToShowUpstreamNotification < 0) return NO_NOTIFY; - - mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_SHOW_NO_UPSTREAM), - delayToShowUpstreamNotification); - return NOTIFY_DONE; - } - - private void showNotification(@DrawableRes final int iconId, @NonNull final String title, - @NonNull final String message, @NotificationId final int id, final boolean ongoing, - @Nullable PendingIntent pi, @NonNull final Action... actions) { - final Notification notification = - new Notification.Builder(mContext, mChannel.getId()) - .setSmallIcon(iconId) - .setContentTitle(title) - .setContentText(message) - .setOngoing(ongoing) - .setColor(mContext.getColor( - android.R.color.system_notification_accent_color)) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setCategory(Notification.CATEGORY_STATUS) - .setContentIntent(pi) - .setActions(actions) - .build(); - - mNotificationManager.notify(null /* tag */, id, notification); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java deleted file mode 100644 index 613328d1c148..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.Manifest.permission.ACCESS_NETWORK_STATE; -import static android.Manifest.permission.NETWORK_STACK; -import static android.Manifest.permission.TETHER_PRIVILEGED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; -import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; -import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; - -import android.app.Service; -import android.bluetooth.BluetoothAdapter; -import android.content.Context; -import android.content.Intent; -import android.net.IIntResultListener; -import android.net.INetworkStackConnector; -import android.net.ITetheringConnector; -import android.net.ITetheringEventCallback; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.NetworkStack; -import android.net.TetheringRequestParcel; -import android.net.dhcp.DhcpServerCallbacks; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.ip.IpServer; -import android.os.Binder; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.provider.Settings; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Android service used to manage tethering. - * - * <p>The service returns a binder for the system server to communicate with the tethering. - */ -public class TetheringService extends Service { - private static final String TAG = TetheringService.class.getSimpleName(); - - private TetheringConnector mConnector; - - @Override - public void onCreate() { - final TetheringDependencies deps = makeTetheringDependencies(); - // The Tethering object needs a fully functional context to start, so this can't be done - // in the constructor. - mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this); - } - - /** - * Make a reference to Tethering object. - */ - @VisibleForTesting - public Tethering makeTethering(TetheringDependencies deps) { - System.loadLibrary("tetherutilsjni"); - return new Tethering(deps); - } - - @NonNull - @Override - public IBinder onBind(Intent intent) { - return mConnector; - } - - private static class TetheringConnector extends ITetheringConnector.Stub { - private final TetheringService mService; - private final Tethering mTethering; - - TetheringConnector(Tethering tether, TetheringService service) { - mTethering = tether; - mService = service; - } - - @Override - public void tether(String iface, String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - listener.onResult(mTethering.tether(iface)); - } catch (RemoteException e) { } - } - - @Override - public void untether(String iface, String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - listener.onResult(mTethering.untether(iface)); - } catch (RemoteException e) { } - } - - @Override - public void setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - listener.onResult(mTethering.setUsbTethering(enable)); - } catch (RemoteException e) { } - } - - @Override - public void startTethering(TetheringRequestParcel request, String callerPkg, - String callingAttributionTag, IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, - callingAttributionTag, - request.exemptFromEntitlementCheck /* onlyAllowPrivileged */, - listener)) { - return; - } - - mTethering.startTethering(request, listener); - } - - @Override - public void stopTethering(int type, String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - mTethering.stopTethering(type); - listener.onResult(TETHER_ERROR_NO_ERROR); - } catch (RemoteException e) { } - } - - @Override - public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, - boolean showEntitlementUi, String callerPkg, String callingAttributionTag) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, receiver)) return; - - mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi); - } - - @Override - public void registerTetheringEventCallback(ITetheringEventCallback callback, - String callerPkg) { - try { - if (!hasTetherAccessPermission()) { - callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); - return; - } - mTethering.registerTetheringEventCallback(callback); - } catch (RemoteException e) { } - } - - @Override - public void unregisterTetheringEventCallback(ITetheringEventCallback callback, - String callerPkg) { - try { - if (!hasTetherAccessPermission()) { - callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); - return; - } - mTethering.unregisterTetheringEventCallback(callback); - } catch (RemoteException e) { } - } - - @Override - public void stopAllTethering(String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - mTethering.untetherAll(); - listener.onResult(TETHER_ERROR_NO_ERROR); - } catch (RemoteException e) { } - } - - @Override - public void isTetheringSupported(String callerPkg, String callingAttributionTag, - IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; - - try { - listener.onResult(TETHER_ERROR_NO_ERROR); - } catch (RemoteException e) { } - } - - @Override - protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, - @Nullable String[] args) { - mTethering.dump(fd, writer, args); - } - - private boolean checkAndNotifyCommonError(final String callerPkg, - final String callingAttributionTag, final IIntResultListener listener) { - return checkAndNotifyCommonError(callerPkg, callingAttributionTag, - false /* onlyAllowPrivileged */, listener); - } - - private boolean checkAndNotifyCommonError(final String callerPkg, - final String callingAttributionTag, final boolean onlyAllowPrivileged, - final IIntResultListener listener) { - try { - if (!hasTetherChangePermission(callerPkg, callingAttributionTag, - onlyAllowPrivileged)) { - listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - return true; - } - if (!mTethering.isTetheringSupported()) { - listener.onResult(TETHER_ERROR_UNSUPPORTED); - return true; - } - } catch (RemoteException e) { - return true; - } - - return false; - } - - private boolean checkAndNotifyCommonError(final String callerPkg, - final String callingAttributionTag, final ResultReceiver receiver) { - if (!hasTetherChangePermission(callerPkg, callingAttributionTag, - false /* onlyAllowPrivileged */)) { - receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null); - return true; - } - if (!mTethering.isTetheringSupported()) { - receiver.send(TETHER_ERROR_UNSUPPORTED, null); - return true; - } - - return false; - } - - private boolean hasNetworkStackPermission() { - return checkCallingOrSelfPermission(NETWORK_STACK) - || checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK); - } - - private boolean hasTetherPrivilegedPermission() { - return checkCallingOrSelfPermission(TETHER_PRIVILEGED); - } - - private boolean checkCallingOrSelfPermission(final String permission) { - return mService.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; - } - - private boolean hasTetherChangePermission(final String callerPkg, - final String callingAttributionTag, final boolean onlyAllowPrivileged) { - if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false; - - if (hasTetherPrivilegedPermission()) return true; - - if (mTethering.isTetherProvisioningRequired()) return false; - - int uid = Binder.getCallingUid(); - - // If callerPkg's uid is not same as Binder.getCallingUid(), - // checkAndNoteWriteSettingsOperation will return false and the operation will be - // denied. - return mService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg, - callingAttributionTag, false /* throwException */); - } - - private boolean hasTetherAccessPermission() { - if (hasTetherPrivilegedPermission()) return true; - - return mService.checkCallingOrSelfPermission( - ACCESS_NETWORK_STATE) == PERMISSION_GRANTED; - } - } - - /** - * Check if the package is a allowed to write settings. This also accounts that such an access - * happened. - * - * @return {@code true} iff the package is allowed to write settings. - */ - @VisibleForTesting - boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, - @NonNull String callingPackage, @Nullable String callingAttributionTag, - boolean throwException) { - return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, - throwException); - } - - /** - * An injection method for testing. - */ - @VisibleForTesting - public TetheringDependencies makeTetheringDependencies() { - return new TetheringDependencies() { - @Override - public NetworkRequest getDefaultNetworkRequest() { - // TODO: b/147280869, add a proper system API to replace this. - final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder() - .clearCapabilities() - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); - return trackDefaultRequest; - } - - @Override - public Looper getTetheringLooper() { - final HandlerThread tetherThread = new HandlerThread("android.tethering"); - tetherThread.start(); - return tetherThread.getLooper(); - } - - @Override - public Context getContext() { - return TetheringService.this; - } - - @Override - public IpServer.Dependencies getIpServerDependencies() { - return new IpServer.Dependencies() { - @Override - public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, - DhcpServerCallbacks cb) { - try { - final INetworkStackConnector service = getNetworkStackConnector(); - if (service == null) return; - - service.makeDhcpServer(ifName, params, cb); - } catch (RemoteException e) { - Log.e(TAG, "Fail to make dhcp server"); - try { - cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); - } catch (RemoteException re) { } - } - } - }; - } - - // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring - // networkStackClient. - static final int NETWORKSTACK_TIMEOUT_MS = 60_000; - private INetworkStackConnector getNetworkStackConnector() { - IBinder connector; - try { - final long before = System.currentTimeMillis(); - while ((connector = NetworkStack.getService()) == null) { - if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { - Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector"); - return null; - } - Thread.sleep(200); - } - } catch (InterruptedException e) { - Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector"); - return null; - } - return INetworkStackConnector.Stub.asInterface(connector); - } - - @Override - public BluetoothAdapter getBluetoothAdapter() { - return BluetoothAdapter.getDefaultAdapter(); - } - }; - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java deleted file mode 100644 index b17065cb7804..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.ConnectivityManager.TYPE_BLUETOOTH; -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; -import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.IpPrefix; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.util.PrefixUtils; -import android.net.util.SharedLog; -import android.os.Handler; -import android.util.Log; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.StateMachine; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - - -/** - * A class to centralize all the network and link properties information - * pertaining to the current and any potential upstream network. - * - * The owner of UNM gets it to register network callbacks by calling the - * following methods : - * Calling #startTrackDefaultNetwork() to track the system default network. - * Calling #startObserveAllNetworks() to observe all networks. Listening all - * networks is necessary while the expression of preferred upstreams remains - * a list of legacy connectivity types. In future, this can be revisited. - * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network. - * - * The methods and data members of this class are only to be accessed and - * modified from the tethering main state machine thread. Any other - * access semantics would necessitate the addition of locking. - * - * TODO: Move upstream selection logic here. - * - * All callback methods are run on the same thread as the specified target - * state machine. This class does not require locking when accessed from this - * thread. Access from other threads is not advised. - * - * @hide - */ -public class UpstreamNetworkMonitor { - private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName(); - private static final boolean DBG = false; - private static final boolean VDBG = false; - - public static final int EVENT_ON_CAPABILITIES = 1; - public static final int EVENT_ON_LINKPROPERTIES = 2; - public static final int EVENT_ON_LOST = 3; - public static final int NOTIFY_LOCAL_PREFIXES = 10; - // This value is used by deprecated preferredUpstreamIfaceTypes selection which is default - // disabled. - @VisibleForTesting - public static final int TYPE_NONE = -1; - - private static final int CALLBACK_LISTEN_ALL = 1; - private static final int CALLBACK_DEFAULT_INTERNET = 2; - private static final int CALLBACK_MOBILE_REQUEST = 3; - - private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray(); - static { - sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI); - sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH); - sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET); - } - - private final Context mContext; - private final SharedLog mLog; - private final StateMachine mTarget; - private final Handler mHandler; - private final int mWhat; - private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>(); - private HashSet<IpPrefix> mLocalPrefixes; - private ConnectivityManager mCM; - private EntitlementManager mEntitlementMgr; - private NetworkCallback mListenAllCallback; - private NetworkCallback mDefaultNetworkCallback; - private NetworkCallback mMobileNetworkCallback; - private boolean mDunRequired; - // Whether the current default upstream is mobile or not. - private boolean mIsDefaultCellularUpstream; - // The current system default network (not really used yet). - private Network mDefaultInternetNetwork; - // The current upstream network used for tethering. - private Network mTetheringUpstreamNetwork; - - public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) { - mContext = ctx; - mTarget = tgt; - mHandler = mTarget.getHandler(); - mLog = log.forSubComponent(TAG); - mWhat = what; - mLocalPrefixes = new HashSet<>(); - mIsDefaultCellularUpstream = false; - } - - @VisibleForTesting - public UpstreamNetworkMonitor( - ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) { - this((Context) null, tgt, log, what); - mCM = cm; - } - - /** - * Tracking the system default network. This method should be called when system is ready. - * - * @param defaultNetworkRequest should be the same as ConnectivityService default request - * @param entitle a EntitlementManager object to communicate between EntitlementManager and - * UpstreamNetworkMonitor - */ - public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest, - EntitlementManager entitle) { - - // defaultNetworkRequest is not really a "request", just a way of tracking the system - // default network. It's guaranteed not to actually bring up any networks because it's - // the should be the same request as the ConnectivityService default request, and thus - // shares fate with it. We can't use registerDefaultNetworkCallback because it will not - // track the system default network if there is a VPN that applies to our UID. - if (mDefaultNetworkCallback == null) { - mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET); - cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler); - } - if (mEntitlementMgr == null) { - mEntitlementMgr = entitle; - } - } - - /** Listen all networks. */ - public void startObserveAllNetworks() { - stop(); - - final NetworkRequest listenAllRequest = new NetworkRequest.Builder() - .clearCapabilities().build(); - mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL); - cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); - } - - /** - * Stop tracking candidate tethering upstreams and release mobile network request. - * Note: this function is used when tethering is stopped because tethering do not need to - * choose upstream anymore. But it would not stop default network tracking because - * EntitlementManager may need to know default network to decide whether to request entitlement - * check even tethering is not active yet. - */ - public void stop() { - releaseMobileNetworkRequest(); - - releaseCallback(mListenAllCallback); - mListenAllCallback = null; - - mTetheringUpstreamNetwork = null; - mNetworkMap.clear(); - } - - /** Setup or teardown DUN connection according to |dunRequired|. */ - public void updateMobileRequiresDun(boolean dunRequired) { - final boolean valueChanged = (mDunRequired != dunRequired); - mDunRequired = dunRequired; - if (valueChanged && mobileNetworkRequested()) { - releaseMobileNetworkRequest(); - registerMobileNetworkRequest(); - } - } - - /** Whether mobile network is requested. */ - public boolean mobileNetworkRequested() { - return (mMobileNetworkCallback != null); - } - - /** Request mobile network if mobile upstream is permitted. */ - public void registerMobileNetworkRequest() { - if (!isCellularUpstreamPermitted()) { - mLog.i("registerMobileNetworkRequest() is not permitted"); - releaseMobileNetworkRequest(); - return; - } - if (mMobileNetworkCallback != null) { - mLog.e("registerMobileNetworkRequest() already registered"); - return; - } - - final NetworkRequest mobileUpstreamRequest; - if (mDunRequired) { - mobileUpstreamRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_DUN) - .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) - .addTransportType(TRANSPORT_CELLULAR).build(); - } else { - mobileUpstreamRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_CELLULAR).build(); - } - - // The existing default network and DUN callbacks will be notified. - // Therefore, to avoid duplicate notifications, we only register a no-op. - mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST); - - // The following use of the legacy type system cannot be removed until - // upstream selection no longer finds networks by legacy type. - // See also http://b/34364553 . - final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI; - - // TODO: Change the timeout from 0 (no onUnavailable callback) to some - // moderate callback timeout. This might be useful for updating some UI. - // Additionally, we log a message to aid in any subsequent debugging. - mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest); - - cm().requestNetwork(mobileUpstreamRequest, 0, legacyType, mHandler, - mMobileNetworkCallback); - } - - /** Release mobile network request. */ - public void releaseMobileNetworkRequest() { - if (mMobileNetworkCallback == null) return; - - cm().unregisterNetworkCallback(mMobileNetworkCallback); - mMobileNetworkCallback = null; - } - - // So many TODOs here, but chief among them is: make this functionality an - // integral part of this class such that whenever a higher priority network - // becomes available and useful we (a) file a request to keep it up as - // necessary and (b) change all upstream tracking state accordingly (by - // passing LinkProperties up to Tethering). - /** - * Select the first available network from |perferredTypes|. - */ - public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { - final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( - mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); - - mLog.log("preferred upstream type: " + typeStatePair.type); - - switch (typeStatePair.type) { - case TYPE_MOBILE_DUN: - case TYPE_MOBILE_HIPRI: - // Tethering just selected mobile upstream in spite of the default network being - // not mobile. This can happen because of the priority list. - // Notify EntitlementManager to check permission for using mobile upstream. - if (!mIsDefaultCellularUpstream) { - mEntitlementMgr.maybeRunProvisioning(); - } - // If we're on DUN, put our own grab on it. - registerMobileNetworkRequest(); - break; - case TYPE_NONE: - // If we found NONE and mobile upstream is permitted we don't want to do this - // as we want any previous requests to keep trying to bring up something we can use. - if (!isCellularUpstreamPermitted()) releaseMobileNetworkRequest(); - break; - default: - // If we've found an active upstream connection that's not DUN/HIPRI - // we should stop any outstanding DUN/HIPRI requests. - releaseMobileNetworkRequest(); - break; - } - - return typeStatePair.ns; - } - - /** - * Get current preferred upstream network. If default network is cellular and DUN is required, - * preferred upstream would be DUN otherwise preferred upstream is the same as default network. - * Returns null if no current upstream is available. - */ - public UpstreamNetworkState getCurrentPreferredUpstream() { - final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null) - ? mNetworkMap.get(mDefaultInternetNetwork) - : null; - if (isNetworkUsableAndNotCellular(dfltState)) return dfltState; - - if (!isCellularUpstreamPermitted()) return null; - - if (!mDunRequired) return dfltState; - - // Find a DUN network. Note that code in Tethering causes a DUN request - // to be filed, but this might be moved into this class in future. - return findFirstDunNetwork(mNetworkMap.values()); - } - - /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */ - public void setCurrentUpstream(Network upstream) { - mTetheringUpstreamNetwork = upstream; - } - - /** Return local prefixes. */ - public Set<IpPrefix> getLocalPrefixes() { - return (Set<IpPrefix>) mLocalPrefixes.clone(); - } - - private boolean isCellularUpstreamPermitted() { - if (mEntitlementMgr != null) { - return mEntitlementMgr.isCellularUpstreamPermitted(); - } else { - // This flow should only happens in testing. - return true; - } - } - - private void handleAvailable(Network network) { - if (mNetworkMap.containsKey(network)) return; - - if (VDBG) Log.d(TAG, "onAvailable for " + network); - mNetworkMap.put(network, new UpstreamNetworkState(null, null, network)); - } - - private void handleNetCap(Network network, NetworkCapabilities newNc) { - final UpstreamNetworkState prev = mNetworkMap.get(network); - if (prev == null || newNc.equals(prev.networkCapabilities)) { - // Ignore notifications about networks for which we have not yet - // received onAvailable() (should never happen) and any duplicate - // notifications (e.g. matching more than one of our callbacks). - return; - } - - if (VDBG) { - Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s", - network, newNc)); - } - - mNetworkMap.put(network, new UpstreamNetworkState( - prev.linkProperties, newNc, network)); - // TODO: If sufficient information is available to select a more - // preferable upstream, do so now and notify the target. - notifyTarget(EVENT_ON_CAPABILITIES, network); - } - - private void handleLinkProp(Network network, LinkProperties newLp) { - final UpstreamNetworkState prev = mNetworkMap.get(network); - if (prev == null || newLp.equals(prev.linkProperties)) { - // Ignore notifications about networks for which we have not yet - // received onAvailable() (should never happen) and any duplicate - // notifications (e.g. matching more than one of our callbacks). - return; - } - - if (VDBG) { - Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s", - network, newLp)); - } - - mNetworkMap.put(network, new UpstreamNetworkState( - newLp, prev.networkCapabilities, network)); - // TODO: If sufficient information is available to select a more - // preferable upstream, do so now and notify the target. - notifyTarget(EVENT_ON_LINKPROPERTIES, network); - } - - private void handleLost(Network network) { - // There are few TODOs within ConnectivityService's rematching code - // pertaining to spurious onLost() notifications. - // - // TODO: simplify this, probably if favor of code that: - // - selects a new upstream if mTetheringUpstreamNetwork has - // been lost (by any callback) - // - deletes the entry from the map only when the LISTEN_ALL - // callback gets notified. - - if (!mNetworkMap.containsKey(network)) { - // Ignore loss of networks about which we had not previously - // learned any information or for which we have already processed - // an onLost() notification. - return; - } - - if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network); - - // TODO: If sufficient information is available to select a more - // preferable upstream, do so now and notify the target. Likewise, - // if the current upstream network is gone, notify the target of the - // fact that we now have no upstream at all. - notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network)); - } - - private void recomputeLocalPrefixes() { - final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values()); - if (!mLocalPrefixes.equals(localPrefixes)) { - mLocalPrefixes = localPrefixes; - notifyTarget(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone()); - } - } - - // Fetch (and cache) a ConnectivityManager only if and when we need one. - private ConnectivityManager cm() { - if (mCM == null) { - // MUST call the String variant to be able to write unittests. - mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - } - return mCM; - } - - /** - * A NetworkCallback class that handles information of interest directly - * in the thread on which it is invoked. To avoid locking, this MUST be - * run on the same thread as the target state machine's handler. - */ - private class UpstreamNetworkCallback extends NetworkCallback { - private final int mCallbackType; - - UpstreamNetworkCallback(int callbackType) { - mCallbackType = callbackType; - } - - @Override - public void onAvailable(Network network) { - handleAvailable(network); - } - - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { - if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { - mDefaultInternetNetwork = network; - final boolean newIsCellular = isCellular(newNc); - if (mIsDefaultCellularUpstream != newIsCellular) { - mIsDefaultCellularUpstream = newIsCellular; - mEntitlementMgr.notifyUpstream(newIsCellular); - } - return; - } - - handleNetCap(network, newNc); - } - - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { - if (mCallbackType == CALLBACK_DEFAULT_INTERNET) return; - - handleLinkProp(network, newLp); - // Any non-LISTEN_ALL callback will necessarily concern a network that will - // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback. - // So it's not useful to do this work for non-LISTEN_ALL callbacks. - if (mCallbackType == CALLBACK_LISTEN_ALL) { - recomputeLocalPrefixes(); - } - } - - @Override - public void onLost(Network network) { - if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { - mDefaultInternetNetwork = null; - mIsDefaultCellularUpstream = false; - mEntitlementMgr.notifyUpstream(false); - return; - } - - handleLost(network); - // Any non-LISTEN_ALL callback will necessarily concern a network that will - // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback. - // So it's not useful to do this work for non-LISTEN_ALL callbacks. - if (mCallbackType == CALLBACK_LISTEN_ALL) { - recomputeLocalPrefixes(); - } - } - } - - private void releaseCallback(NetworkCallback cb) { - if (cb != null) cm().unregisterNetworkCallback(cb); - } - - private void notifyTarget(int which, Network network) { - notifyTarget(which, mNetworkMap.get(network)); - } - - private void notifyTarget(int which, Object obj) { - mTarget.sendMessage(mWhat, which, 0, obj); - } - - private static class TypeStatePair { - public int type = TYPE_NONE; - public UpstreamNetworkState ns = null; - } - - private static TypeStatePair findFirstAvailableUpstreamByType( - Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes, - boolean isCellularUpstreamPermitted) { - final TypeStatePair result = new TypeStatePair(); - - for (int type : preferredTypes) { - NetworkCapabilities nc; - try { - nc = networkCapabilitiesForType(type); - } catch (IllegalArgumentException iae) { - Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + type); - continue; - } - if (!isCellularUpstreamPermitted && isCellular(nc)) { - continue; - } - - for (UpstreamNetworkState value : netStates) { - if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { - continue; - } - - result.type = type; - result.ns = value; - return result; - } - } - - return result; - } - - private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) { - final HashSet<IpPrefix> prefixSet = new HashSet<>(); - - for (UpstreamNetworkState ns : netStates) { - final LinkProperties lp = ns.linkProperties; - if (lp == null) continue; - prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp)); - } - - return prefixSet; - } - - private static boolean isCellular(UpstreamNetworkState ns) { - return (ns != null) && isCellular(ns.networkCapabilities); - } - - private static boolean isCellular(NetworkCapabilities nc) { - return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) - && nc.hasCapability(NET_CAPABILITY_NOT_VPN); - } - - private static boolean hasCapability(UpstreamNetworkState ns, int netCap) { - return (ns != null) && (ns.networkCapabilities != null) - && ns.networkCapabilities.hasCapability(netCap); - } - - private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) { - return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) - && !isCellular(ns.networkCapabilities); - } - - private static UpstreamNetworkState findFirstDunNetwork( - Iterable<UpstreamNetworkState> netStates) { - for (UpstreamNetworkState ns : netStates) { - if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns; - } - - return null; - } - - /** - * Given a legacy type (TYPE_WIFI, ...) returns the corresponding NetworkCapabilities instance. - * This function is used for deprecated legacy type and be disabled by default. - */ - @VisibleForTesting - public static NetworkCapabilities networkCapabilitiesForType(int type) { - final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); - - // Map from type to transports. - final int notFound = -1; - final int transport = sLegacyTypeToTransport.get(type, notFound); - if (transport == notFound) { - throw new IllegalArgumentException("unknown legacy type: " + type); - } - builder.addTransportType(transport); - - if (type == TYPE_MOBILE_DUN) { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); - // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES. - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - } else { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - } - return builder.build(); - } -} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java deleted file mode 100644 index bab9f84cf762..000000000000 --- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.networkstack.tethering; - -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; - -import androidx.annotation.NonNull; - -/** - * Snapshot of tethering upstream network state. - */ -public class UpstreamNetworkState { - /** {@link LinkProperties}. */ - public final LinkProperties linkProperties; - /** {@link NetworkCapabilities}. */ - public final NetworkCapabilities networkCapabilities; - /** {@link Network}. */ - public final Network network; - - /** Constructs a new UpstreamNetworkState. */ - public UpstreamNetworkState(LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, Network network) { - this.linkProperties = linkProperties; - this.networkCapabilities = networkCapabilities; - this.network = network; - } - - @NonNull - @Override - public String toString() { - return String.format("UpstreamNetworkState{%s, %s, %s}", - network == null ? "null" : network, - networkCapabilities == null ? "null" : networkCapabilities, - linkProperties == null ? "null" : linkProperties); - } -} diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp deleted file mode 100644 index 02bab9ba353e..000000000000 --- a/packages/Tethering/tests/integration/Android.bp +++ /dev/null @@ -1,84 +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. -// -java_defaults { - name: "TetheringIntegrationTestsDefaults", - srcs: [ - "src/**/*.java", - "src/**/*.kt", - ], - static_libs: [ - "NetworkStackApiStableLib", - "androidx.test.rules", - "mockito-target-extended-minus-junit4", - "net-tests-utils", - "testables", - ], - libs: [ - "android.test.runner", - "android.test.base", - "android.test.mock", - ], - jni_libs: [ - // For mockito extended - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - ], - jarjar_rules: ":NetworkStackJarJarRules", -} - -android_library { - name: "TetheringIntegrationTestsLib", - platform_apis: true, - defaults: ["TetheringIntegrationTestsDefaults"], - visibility: ["//cts/tests/tests/tethering"] -} - -android_test { - name: "TetheringIntegrationTests", - platform_apis: true, - defaults: ["TetheringIntegrationTestsDefaults"], - test_suites: [ - "device-tests", - "mts", - ], - compile_multilib: "both", -} - -// Special version of the tethering tests that includes all tests necessary for code coverage -// purposes. This is currently the union of TetheringTests, TetheringIntegrationTests and -// NetworkStackTests. -android_test { - name: "TetheringCoverageTests", - platform_apis: true, - test_suites: ["device-tests", "mts"], - test_config: "AndroidTest_Coverage.xml", - defaults: ["libnetworkstackutilsjni_deps"], - static_libs: [ - "NetworkStaticLibTestsLib", - "NetworkStackTestsLib", - "TetheringTestsLib", - "TetheringIntegrationTestsLib", - ], - jni_libs: [ - // For mockito extended - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - // For NetworkStackUtils included in NetworkStackBase - "libnetworkstackutilsjni", - ], - compile_multilib: "both", - manifest: "AndroidManifest_coverage.xml", -}
\ No newline at end of file diff --git a/packages/Tethering/tests/integration/AndroidManifest_coverage.xml b/packages/Tethering/tests/integration/AndroidManifest_coverage.xml deleted file mode 100644 index 06de00d78558..000000000000 --- a/packages/Tethering/tests/integration/AndroidManifest_coverage.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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" - xmlns:tools="http://schemas.android.com/tools" - package="com.android.networkstack.tethering.tests.coverage"> - - <application tools:replace="android:label" - android:debuggable="true" - android:label="Tethering coverage tests"> - <uses-library android:name="android.test.runner" /> - </application> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.networkstack.tethering.tests.coverage" - android:label="Tethering coverage tests"> - </instrumentation> -</manifest> diff --git a/packages/Tethering/tests/integration/AndroidTest_Coverage.xml b/packages/Tethering/tests/integration/AndroidTest_Coverage.xml deleted file mode 100644 index 3def2099e45f..000000000000 --- a/packages/Tethering/tests/integration/AndroidTest_Coverage.xml +++ /dev/null @@ -1,12 +0,0 @@ -<configuration description="Runs coverage tests for Tethering"> - <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> - <option name="test-file-name" value="TetheringCoverageTests.apk" /> - </target_preparer> - - <option name="test-tag" value="TetheringCoverageTests" /> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.networkstack.tethering.tests.coverage" /> - <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - <option name="hidden-api-checks" value="false"/> - </test> -</configuration>
\ No newline at end of file diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java deleted file mode 100644 index d206ea0b4d45..000000000000 --- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.Manifest.permission.MANAGE_TEST_NETWORKS; -import static android.Manifest.permission.NETWORK_SETTINGS; -import static android.Manifest.permission.TETHER_PRIVILEGED; -import static android.net.TetheringManager.TETHERING_ETHERNET; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeFalse; -import static org.junit.Assume.assumeTrue; - -import android.app.UiAutomation; -import android.content.Context; -import android.net.EthernetManager.TetheredInterfaceCallback; -import android.net.EthernetManager.TetheredInterfaceRequest; -import android.net.TetheringManager.StartTetheringCallback; -import android.net.TetheringManager.TetheringEventCallback; -import android.net.TetheringManager.TetheringRequest; -import android.net.dhcp.DhcpAckPacket; -import android.net.dhcp.DhcpOfferPacket; -import android.net.dhcp.DhcpPacket; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.system.Os; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.MediumTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.HandlerUtils; -import com.android.testutils.TapPacketReader; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.FileDescriptor; -import java.net.Inet4Address; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.List; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class EthernetTetheringTest { - - private static final String TAG = EthernetTetheringTest.class.getSimpleName(); - private static final int TIMEOUT_MS = 5000; - private static final int PACKET_READ_TIMEOUT_MS = 100; - private static final int DHCP_DISCOVER_ATTEMPTS = 10; - private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] { - DhcpPacket.DHCP_SUBNET_MASK, - DhcpPacket.DHCP_ROUTER, - DhcpPacket.DHCP_DNS_SERVER, - DhcpPacket.DHCP_LEASE_TIME, - }; - private static final String DHCP_HOSTNAME = "testhostname"; - - private final Context mContext = InstrumentationRegistry.getContext(); - private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class); - private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class); - - private TestNetworkInterface mTestIface; - private HandlerThread mHandlerThread; - private Handler mHandler; - private TapPacketReader mTapPacketReader; - - private TetheredInterfaceRequester mTetheredInterfaceRequester; - private MyTetheringEventCallback mTetheringEventCallback; - - private UiAutomation mUiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - private boolean mRunTests; - - @Before - public void setUp() throws Exception { - // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive - // tethered client callbacks. - mUiAutomation.adoptShellPermissionIdentity( - MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED); - mRunTests = mTm.isTetheringSupported() && mEm != null; - assumeTrue(mRunTests); - - mHandlerThread = new HandlerThread(getClass().getSimpleName()); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); - mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm); - } - - private void cleanUp() throws Exception { - mTm.stopTethering(TETHERING_ETHERNET); - if (mTetheringEventCallback != null) { - mTetheringEventCallback.awaitInterfaceUntethered(); - mTetheringEventCallback.unregister(); - mTetheringEventCallback = null; - } - if (mTapPacketReader != null) { - TapPacketReader reader = mTapPacketReader; - mHandler.post(() -> reader.stop()); - mTapPacketReader = null; - } - mHandlerThread.quitSafely(); - mTetheredInterfaceRequester.release(); - mEm.setIncludeTestInterfaces(false); - maybeDeleteTestInterface(); - } - - @After - public void tearDown() throws Exception { - try { - if (mRunTests) cleanUp(); - } finally { - mUiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - public void testVirtualEthernetAlreadyExists() throws Exception { - // This test requires manipulating packets. Skip if there is a physical Ethernet connected. - assumeFalse(mEm.isAvailable()); - - mTestIface = createTestInterface(); - // This must be done now because as soon as setIncludeTestInterfaces(true) is called, the - // interface will be placed in client mode, which will delete the link-local address. - // At that point NetworkInterface.getByName() will cease to work on the interface, because - // starting in R NetworkInterface can no longer see interfaces without IP addresses. - int mtu = getMTU(mTestIface); - - Log.d(TAG, "Including test interfaces"); - mEm.setIncludeTestInterfaces(true); - - final String iface = mTetheredInterfaceRequester.getInterface(); - assertEquals("TetheredInterfaceCallback for unexpected interface", - mTestIface.getInterfaceName(), iface); - - checkVirtualEthernet(mTestIface, mtu); - } - - @Test - public void testVirtualEthernet() throws Exception { - // This test requires manipulating packets. Skip if there is a physical Ethernet connected. - assumeFalse(mEm.isAvailable()); - - CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface(); - - mEm.setIncludeTestInterfaces(true); - - mTestIface = createTestInterface(); - - final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertEquals("TetheredInterfaceCallback for unexpected interface", - mTestIface.getInterfaceName(), iface); - - checkVirtualEthernet(mTestIface, getMTU(mTestIface)); - } - - @Test - public void testStaticIpv4() throws Exception { - assumeFalse(mEm.isAvailable()); - - mEm.setIncludeTestInterfaces(true); - - mTestIface = createTestInterface(); - - final String iface = mTetheredInterfaceRequester.getInterface(); - assertEquals("TetheredInterfaceCallback for unexpected interface", - mTestIface.getInterfaceName(), iface); - - assertInvalidStaticIpv4Request(iface, null, null); - assertInvalidStaticIpv4Request(iface, "2001:db8::1/64", "2001:db8:2::/64"); - assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", "2001:db8:2::/28"); - assertInvalidStaticIpv4Request(iface, "2001:db8:2::/28", "192.0.2.2/28"); - assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", null); - assertInvalidStaticIpv4Request(iface, null, "192.0.2.2/28"); - assertInvalidStaticIpv4Request(iface, "192.0.2.3/27", "192.0.2.2/28"); - - final String localAddr = "192.0.2.3/28"; - final String clientAddr = "192.0.2.2/28"; - mTetheringEventCallback = enableEthernetTethering(iface, - requestWithStaticIpv4(localAddr, clientAddr)); - - mTetheringEventCallback.awaitInterfaceTethered(); - assertInterfaceHasIpAddress(iface, localAddr); - - byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray(); - byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray(); - - FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor(); - mTapPacketReader = makePacketReader(fd, getMTU(mTestIface)); - DhcpResults dhcpResults = runDhcp(fd, client1); - assertEquals(new LinkAddress(clientAddr), dhcpResults.ipAddress); - - try { - runDhcp(fd, client2); - fail("Only one client should get an IP address"); - } catch (TimeoutException expected) { } - - } - - private boolean isAdbOverNetwork() { - // If adb TCP port opened, this test may running by adb over network. - return (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1) - || (SystemProperties.getInt("service.adb.tcp.port", -1) > -1); - } - - @Test - public void testPhysicalEthernet() throws Exception { - assumeTrue(mEm.isAvailable()); - // Do not run this test if adb is over network and ethernet is connected. - // It is likely the adb run over ethernet, the adb would break when ethernet is switching - // from client mode to server mode. See b/160389275. - assumeFalse(isAdbOverNetwork()); - - // Get an interface to use. - final String iface = mTetheredInterfaceRequester.getInterface(); - - // Enable Ethernet tethering and check that it starts. - mTetheringEventCallback = enableEthernetTethering(iface); - - // There is nothing more we can do on a physical interface without connecting an actual - // client, which is not possible in this test. - } - - private static final class MyTetheringEventCallback implements TetheringEventCallback { - private final TetheringManager mTm; - private final CountDownLatch mTetheringStartedLatch = new CountDownLatch(1); - private final CountDownLatch mTetheringStoppedLatch = new CountDownLatch(1); - private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1); - private final String mIface; - - private volatile boolean mInterfaceWasTethered = false; - private volatile boolean mUnregistered = false; - private volatile Collection<TetheredClient> mClients = null; - - MyTetheringEventCallback(TetheringManager tm, String iface) { - mTm = tm; - mIface = iface; - } - - public void unregister() { - mTm.unregisterTetheringEventCallback(this); - mUnregistered = true; - } - - @Override - public void onTetheredInterfacesChanged(List<String> interfaces) { - // Ignore stale callbacks registered by previous test cases. - if (mUnregistered) return; - - final boolean wasTethered = mTetheringStartedLatch.getCount() == 0; - if (!mInterfaceWasTethered && (mIface == null || interfaces.contains(mIface))) { - // This interface is being tethered for the first time. - Log.d(TAG, "Tethering started: " + interfaces); - mInterfaceWasTethered = true; - mTetheringStartedLatch.countDown(); - } else if (mInterfaceWasTethered && !interfaces.contains(mIface)) { - Log.d(TAG, "Tethering stopped: " + interfaces); - mTetheringStoppedLatch.countDown(); - } - } - - public void awaitInterfaceTethered() throws Exception { - assertTrue("Ethernet not tethered after " + TIMEOUT_MS + "ms", - mTetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } - - public void awaitInterfaceUntethered() throws Exception { - // Don't block teardown if the interface was never tethered. - // This is racy because the interface might become tethered right after this check, but - // that can only happen in tearDown if startTethering timed out, which likely means - // the test has already failed. - if (!mInterfaceWasTethered) return; - - assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms", - mTetheringStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } - - @Override - public void onError(String ifName, int error) { - // Ignore stale callbacks registered by previous test cases. - if (mUnregistered) return; - - fail("TetheringEventCallback got error:" + error + " on iface " + ifName); - } - - @Override - public void onClientsChanged(Collection<TetheredClient> clients) { - // Ignore stale callbacks registered by previous test cases. - if (mUnregistered) return; - - Log.d(TAG, "Got clients changed: " + clients); - mClients = clients; - if (clients.size() > 0) { - mClientConnectedLatch.countDown(); - } - } - - public Collection<TetheredClient> awaitClientConnected() throws Exception { - assertTrue("Did not receive client connected callback after " + TIMEOUT_MS + "ms", - mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - return mClients; - } - } - - private MyTetheringEventCallback enableEthernetTethering(String iface, - TetheringRequest request) throws Exception { - MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface); - mTm.registerTetheringEventCallback(mHandler::post, callback); - - StartTetheringCallback startTetheringCallback = new StartTetheringCallback() { - @Override - public void onTetheringFailed(int resultCode) { - fail("Unexpectedly got onTetheringFailed"); - } - }; - Log.d(TAG, "Starting Ethernet tethering"); - mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback); - callback.awaitInterfaceTethered(); - return callback; - } - - private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception { - return enableEthernetTethering(iface, - new TetheringRequest.Builder(TETHERING_ETHERNET) - .setShouldShowEntitlementUi(false).build()); - } - - private int getMTU(TestNetworkInterface iface) throws SocketException { - NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName()); - assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif); - return nif.getMTU(); - } - - private TapPacketReader makePacketReader(FileDescriptor fd, int mtu) { - final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu); - mHandler.post(() -> reader.start()); - HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); - return reader; - } - - private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception { - FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor(); - mTapPacketReader = makePacketReader(fd, mtu); - mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName()); - checkTetheredClientCallbacks(fd); - } - - private DhcpResults runDhcp(FileDescriptor fd, byte[] clientMacAddr) throws Exception { - // We have to retransmit DHCP requests because IpServer declares itself to be ready before - // its DhcpServer is actually started. TODO: fix this race and remove this loop. - DhcpPacket offerPacket = null; - for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) { - Log.d(TAG, "Sending DHCP discover"); - sendDhcpDiscover(fd, clientMacAddr); - offerPacket = getNextDhcpPacket(); - if (offerPacket instanceof DhcpOfferPacket) break; - } - if (!(offerPacket instanceof DhcpOfferPacket)) { - throw new TimeoutException("No DHCPOFFER received on interface within timeout"); - } - - sendDhcpRequest(fd, offerPacket, clientMacAddr); - DhcpPacket ackPacket = getNextDhcpPacket(); - if (!(ackPacket instanceof DhcpAckPacket)) { - throw new TimeoutException("No DHCPACK received on interface within timeout"); - } - - return ackPacket.toDhcpResults(); - } - - private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception { - // Create a fake client. - byte[] clientMacAddr = new byte[6]; - new Random().nextBytes(clientMacAddr); - - DhcpResults dhcpResults = runDhcp(fd, clientMacAddr); - - final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected(); - assertEquals(1, clients.size()); - final TetheredClient client = clients.iterator().next(); - - // Check the MAC address. - assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress()); - assertEquals(TETHERING_ETHERNET, client.getTetheringType()); - - // Check the hostname. - assertEquals(1, client.getAddresses().size()); - TetheredClient.AddressInfo info = client.getAddresses().get(0); - assertEquals(DHCP_HOSTNAME, info.getHostname()); - - // Check the address is the one that was handed out in the DHCP ACK. - assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress()); - - // Check that the lifetime is correct +/- 10s. - final long now = SystemClock.elapsedRealtime(); - final long actualLeaseDuration = (info.getAddress().getExpirationTime() - now) / 1000; - final String msg = String.format("IP address should have lifetime of %d, got %d", - dhcpResults.leaseDuration, actualLeaseDuration); - assertTrue(msg, Math.abs(dhcpResults.leaseDuration - actualLeaseDuration) < 10); - } - - private DhcpPacket getNextDhcpPacket() throws ParseException { - byte[] packet; - while ((packet = mTapPacketReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) { - try { - return DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2); - } catch (DhcpPacket.ParseException e) { - // Not a DHCP packet. Continue. - } - } - return null; - } - - private static final class TetheredInterfaceRequester implements TetheredInterfaceCallback { - private final CountDownLatch mInterfaceAvailableLatch = new CountDownLatch(1); - private final Handler mHandler; - private final EthernetManager mEm; - - private TetheredInterfaceRequest mRequest; - private final CompletableFuture<String> mFuture = new CompletableFuture<>(); - - TetheredInterfaceRequester(Handler handler, EthernetManager em) { - mHandler = handler; - mEm = em; - } - - @Override - public void onAvailable(String iface) { - Log.d(TAG, "Ethernet interface available: " + iface); - mFuture.complete(iface); - } - - @Override - public void onUnavailable() { - mFuture.completeExceptionally(new IllegalStateException("onUnavailable received")); - } - - public CompletableFuture<String> requestInterface() { - assertNull("BUG: more than one tethered interface request", mRequest); - Log.d(TAG, "Requesting tethered interface"); - mRequest = mEm.requestTetheredInterface(mHandler::post, this); - return mFuture; - } - - public String getInterface() throws Exception { - return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - public void release() { - if (mRequest != null) { - mFuture.obtrudeException(new IllegalStateException("Request already released")); - mRequest.release(); - mRequest = null; - } - } - } - - private void sendDhcpDiscover(FileDescriptor fd, byte[] macAddress) throws Exception { - ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2, - new Random().nextInt() /* transactionId */, (short) 0 /* secs */, - macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS, - false /* rapid commit */, DHCP_HOSTNAME); - sendPacket(fd, packet); - } - - private void sendDhcpRequest(FileDescriptor fd, DhcpPacket offerPacket, byte[] macAddress) - throws Exception { - DhcpResults results = offerPacket.toDhcpResults(); - Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress(); - Inet4Address serverIdentifier = results.serverAddress; - ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2, - 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */, - false /* broadcast */, macAddress, clientIp /* requestedIpAddress */, - serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME); - sendPacket(fd, packet); - } - - private void sendPacket(FileDescriptor fd, ByteBuffer packet) throws Exception { - assertNotNull("Only tests on virtual interfaces can send packets", fd); - Os.write(fd, packet); - } - - public void assertLinkAddressMatches(LinkAddress l1, LinkAddress l2) { - // Check all fields except the deprecation and expiry times. - String msg = String.format("LinkAddresses do not match. expected: %s actual: %s", l1, l2); - assertTrue(msg, l1.isSameAddressAs(l2)); - assertEquals("LinkAddress flags do not match", l1.getFlags(), l2.getFlags()); - assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope()); - } - - private TetheringRequest requestWithStaticIpv4(String local, String client) { - LinkAddress localAddr = local == null ? null : new LinkAddress(local); - LinkAddress clientAddr = client == null ? null : new LinkAddress(client); - return new TetheringRequest.Builder(TETHERING_ETHERNET) - .setStaticIpv4Addresses(localAddr, clientAddr) - .setShouldShowEntitlementUi(false).build(); - } - - private void assertInvalidStaticIpv4Request(String iface, String local, String client) - throws Exception { - try { - enableEthernetTethering(iface, requestWithStaticIpv4(local, client)); - fail("Unexpectedly accepted invalid IPv4 configuration: " + local + ", " + client); - } catch (IllegalArgumentException | NullPointerException expected) { } - } - - private void assertInterfaceHasIpAddress(String iface, String expected) throws Exception { - LinkAddress expectedAddr = new LinkAddress(expected); - NetworkInterface nif = NetworkInterface.getByName(iface); - for (InterfaceAddress ia : nif.getInterfaceAddresses()) { - final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength()); - if (expectedAddr.equals(addr)) { - return; - } - } - fail("Expected " + iface + " to have IP address " + expected + ", found " - + nif.getInterfaceAddresses()); - } - - private TestNetworkInterface createTestInterface() throws Exception { - TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); - TestNetworkInterface iface = tnm.createTapInterface(); - Log.d(TAG, "Created test interface " + iface.getInterfaceName()); - return iface; - } - - private void maybeDeleteTestInterface() throws Exception { - if (mTestIface != null) { - mTestIface.getFileDescriptor().close(); - Log.d(TAG, "Deleted test interface " + mTestIface.getInterfaceName()); - mTestIface = null; - } - } -} diff --git a/packages/Tethering/tests/mts/Android.bp b/packages/Tethering/tests/mts/Android.bp deleted file mode 100644 index f925b0a53f32..000000000000 --- a/packages/Tethering/tests/mts/Android.bp +++ /dev/null @@ -1,56 +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. - -android_test { - // This tests for functionality that is not required for devices that - // don't use Tethering mainline module. - name: "MtsTetheringTest", - - libs: [ - "android.test.base", - ], - - srcs: [ - "src/**/*.java", - ], - - static_libs: [ - "androidx.test.rules", - // mockito-target-extended-minus-junit4 used in this lib have dependency with - // jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent. - "cts-net-utils", - // This is needed for androidx.test.runner.AndroidJUnitRunner. - "ctstestrunner-axt", - "junit", - "junit-params", - ], - - jni_libs: [ - // For mockito extended which is pulled in from -net-utils -> net-tests-utils - // (mockito-target-extended-minus-junit4). - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - ], - - platform_apis: true, - - // Tag this module as a mts test artifact - test_suites: [ - "general-tests", - "mts", - ], - - // Include both the 32 and 64 bit versions - compile_multilib: "both", -} diff --git a/packages/Tethering/tests/mts/AndroidManifest.xml b/packages/Tethering/tests/mts/AndroidManifest.xml deleted file mode 100644 index 6d2abcad42a3..000000000000 --- a/packages/Tethering/tests/mts/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?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="android.tethering.mts"> - - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <uses-permission android:name="android.permission.INTERNET"/> - - <application android:debuggable="true"> - <uses-library android:name="android.test.runner" /> - </application> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.tethering.mts" - android:label="MTS tests of android.tethering"> - <meta-data android:name="listener" - android:value="com.android.cts.runner.CtsTestRunListener" /> - </instrumentation> - -</manifest> diff --git a/packages/Tethering/tests/mts/AndroidTest.xml b/packages/Tethering/tests/mts/AndroidTest.xml deleted file mode 100644 index 80788dfa6f40..000000000000 --- a/packages/Tethering/tests/mts/AndroidTest.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<configuration description="Config for MTS Tethering test cases"> - <option name="test-suite-tag" value="mts" /> - <option name="config-descriptor:metadata" key="component" value="networking" /> - <!-- Instant app do not have INTERNET permission. --> - <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" /> - <!-- Feature is not backed by native code. --> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <!-- Allow running this against a secondary user. --> - <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="MtsTetheringTest.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.tethering.mts" /> - </test> - - <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.tethering" /> - </object> -</configuration> diff --git a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java deleted file mode 100644 index 7ffe37ad648d..000000000000 --- a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.tethering.mts; - -import static android.Manifest.permission.MANAGE_TEST_NETWORKS; -import static android.Manifest.permission.NETWORK_SETTINGS; -import static android.Manifest.permission.READ_DEVICE_CONFIG; -import static android.Manifest.permission.TETHER_PRIVILEGED; -import static android.Manifest.permission.WRITE_SETTINGS; -import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported; -import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; - -import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.app.UiAutomation; -import android.content.Context; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.TetheringManager; -import android.net.cts.util.CtsTetheringUtils; -import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; -import android.provider.DeviceConfig; - -import androidx.annotation.NonNull; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.TestNetworkTracker; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -public class TetheringModuleTest { - private Context mContext; - private TetheringManager mTm; - private CtsTetheringUtils mCtsTetheringUtils; - - private UiAutomation mUiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - - @Before - public void setUp() throws Exception { - mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, - WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED); - mContext = InstrumentationRegistry.getContext(); - mTm = mContext.getSystemService(TetheringManager.class); - mCtsTetheringUtils = new CtsTetheringUtils(mContext); - } - - @After - public void tearDown() throws Exception { - mUiAutomation.dropShellPermissionIdentity(); - } - - private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES = - "tether_enable_select_all_prefix_ranges"; - @Test - public void testSwitchBasePrefixRangeWhenConflict() throws Exception { - assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true)); - - addressConflictTest(true); - } - - @Test - public void testSwitchPrefixRangeWhenConflict() throws Exception { - addressConflictTest(false); - } - - private void addressConflictTest(final boolean wholeRangeConflict) throws Exception { - final TestTetheringEventCallback tetherEventCallback = - mCtsTetheringUtils.registerTetheringEventCallback(); - - TestNetworkTracker tnt = null; - try { - tetherEventCallback.assumeTetheringSupported(); - assumeTrue(isWifiTetheringSupported(tetherEventCallback)); - - mCtsTetheringUtils.startWifiTethering(tetherEventCallback); - - final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces(); - assertEquals(1, tetheredIfaces.size()); - final String wifiTetheringIface = tetheredIfaces.get(0); - - NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface); - // Tethering downstream only have one ipv4 address. - final LinkAddress hotspotAddr = getFirstIpv4Address(nif); - assertNotNull(hotspotAddr); - - final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict); - assertNotNull(testPrefix); - - tnt = setUpTestNetwork( - new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength())); - - tetherEventCallback.expectTetheredInterfacesChanged(null); - final List<String> wifiRegexs = - tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs(); - - tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs); - nif = NetworkInterface.getByName(wifiTetheringIface); - final LinkAddress newHotspotAddr = getFirstIpv4Address(nif); - assertNotNull(newHotspotAddr); - - assertFalse(testPrefix.containsPrefix( - new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength()))); - - mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); - } finally { - if (tnt != null) { - tnt.teardown(); - } - mTm.stopAllTethering(); - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - } - } - - private LinkAddress getFirstIpv4Address(final NetworkInterface nif) { - for (InterfaceAddress ia : nif.getInterfaceAddresses()) { - final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength()); - if (addr.isIpv4()) return addr; - } - return null; - } - - @NonNull - private IpPrefix getConflictingPrefix(final LinkAddress address, - final boolean wholeRangeConflict) { - if (!wholeRangeConflict) { - return new IpPrefix(address.getAddress(), address.getPrefixLength()); - } - - final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList( - new IpPrefix("192.168.0.0/16"), - new IpPrefix("172.16.0.0/12"), - new IpPrefix("10.0.0.0/8"))); - - for (IpPrefix prefix : prefixPool) { - if (prefix.contains(address.getAddress())) return prefix; - } - - fail("Could not find sutiable conflict prefix"); - - // Never go here. - return null; - } - - private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception { - return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/); - - } - - public static boolean isFeatureEnabled(final String name, final boolean defaultValue) { - return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue); - } -} diff --git a/packages/Tethering/tests/privileged/Android.bp b/packages/Tethering/tests/privileged/Android.bp deleted file mode 100644 index 9217345dc2f5..000000000000 --- a/packages/Tethering/tests/privileged/Android.bp +++ /dev/null @@ -1,49 +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. -// - -java_defaults { - name: "TetheringPrivilegedTestsJniDefaults", - jni_libs: [ - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - "libtetherutilsjni", - ], - jni_uses_sdk_apis: true, - visibility: ["//visibility:private"], -} - -android_test { - name: "TetheringPrivilegedTests", - defaults: [ - "TetheringPrivilegedTestsJniDefaults", - ], - srcs: [ - "src/**/*.java", - "src/**/*.kt", - ], - certificate: "networkstack", - platform_apis: true, - test_suites: [ - "device-tests", - "mts", - ], - static_libs: [ - "androidx.test.rules", - "net-tests-utils", - "TetheringApiCurrentLib", - ], - compile_multilib: "both", -} diff --git a/packages/Tethering/tests/privileged/AndroidManifest.xml b/packages/Tethering/tests/privileged/AndroidManifest.xml deleted file mode 100644 index 49eba15d13d4..000000000000 --- a/packages/Tethering/tests/privileged/AndroidManifest.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?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.networkstack.tethering.tests.privileged" - android:sharedUserId="android.uid.networkstack"> - - <!-- Note: do not add any privileged or signature permissions that are granted - to the network stack and its shared uid apps. Otherwise, the test APK will - install, but when the device is rebooted, it will bootloop because this - test APK is not in the privileged permission allow list --> - - <application android:debuggable="true"> - <uses-library android:name="android.test.runner" /> - </application> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.networkstack.tethering.tests.privileged" - android:label="Tethering privileged tests"> - </instrumentation> -</manifest> diff --git a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java deleted file mode 100644 index 42a91aa9acd5..000000000000 --- a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static android.system.OsConstants.IPPROTO_ICMPV6; - -import static com.android.net.module.util.IpUtils.icmpv6Checksum; -import static com.android.net.module.util.NetworkStackConstants.ETHER_SRC_ADDR_OFFSET; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.app.Instrumentation; -import android.content.Context; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.MacAddress; -import android.net.util.InterfaceParams; -import android.net.util.TetheringUtils; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.TapPacketReader; -import com.android.testutils.TapPacketReaderRule; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; - -import java.nio.ByteBuffer; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DadProxyTest { - private static final int DATA_BUFFER_LEN = 4096; - private static final int PACKET_TIMEOUT_MS = 5_000; - - // Start the readers manually on a common handler shared with DadProxy, for simplicity - @Rule - public final TapPacketReaderRule mUpstreamReader = new TapPacketReaderRule( - DATA_BUFFER_LEN, false /* autoStart */); - @Rule - public final TapPacketReaderRule mTetheredReader = new TapPacketReaderRule( - DATA_BUFFER_LEN, false /* autoStart */); - - private InterfaceParams mUpstreamParams, mTetheredParams; - private HandlerThread mHandlerThread; - private Handler mHandler; - private TapPacketReader mUpstreamPacketReader, mTetheredPacketReader; - - private static INetd sNetd; - - @BeforeClass - public static void setupOnce() { - System.loadLibrary("tetherutilsjni"); - - final Instrumentation inst = InstrumentationRegistry.getInstrumentation(); - final IBinder netdIBinder = - (IBinder) inst.getContext().getSystemService(Context.NETD_SERVICE); - sNetd = INetd.Stub.asInterface(netdIBinder); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mHandlerThread = new HandlerThread(getClass().getSimpleName()); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); - - setupTapInterfaces(); - - // Looper must be prepared here since AndroidJUnitRunner runs tests on separate threads. - if (Looper.myLooper() == null) Looper.prepare(); - - DadProxy mProxy = setupProxy(); - } - - @After - public void tearDown() throws Exception { - mUpstreamReader.stop(); - mTetheredReader.stop(); - - if (mHandlerThread != null) { - mHandlerThread.quitSafely(); - mHandlerThread.join(PACKET_TIMEOUT_MS); - } - - if (mTetheredParams != null) { - sNetd.networkRemoveInterface(INetd.LOCAL_NET_ID, mTetheredParams.name); - } - if (mUpstreamParams != null) { - sNetd.networkRemoveInterface(INetd.LOCAL_NET_ID, mUpstreamParams.name); - } - } - - private void setupTapInterfaces() { - // Create upstream test iface. - mUpstreamReader.start(mHandler); - mUpstreamParams = InterfaceParams.getByName(mUpstreamReader.iface.getInterfaceName()); - assertNotNull(mUpstreamParams); - mUpstreamPacketReader = mUpstreamReader.getReader(); - - // Create tethered test iface. - mTetheredReader.start(mHandler); - mTetheredParams = InterfaceParams.getByName(mTetheredReader.getIface().getInterfaceName()); - assertNotNull(mTetheredParams); - mTetheredPacketReader = mTetheredReader.getReader(); - } - - private static final int IPV6_HEADER_LEN = 40; - private static final int ETH_HEADER_LEN = 14; - private static final int ICMPV6_NA_NS_LEN = 24; - private static final int LL_TARGET_OPTION_LEN = 8; - private static final int ICMPV6_CHECKSUM_OFFSET = 2; - private static final int ETHER_TYPE_IPV6 = 0x86dd; - - private static ByteBuffer createDadPacket(int type) { - // Refer to buildArpPacket() - int icmpLen = ICMPV6_NA_NS_LEN - + (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT - ? LL_TARGET_OPTION_LEN : 0); - final ByteBuffer buf = ByteBuffer.allocate(icmpLen + IPV6_HEADER_LEN + ETH_HEADER_LEN); - - // Ethernet header. - final MacAddress srcMac = MacAddress.fromString("33:33:ff:66:77:88"); - buf.put(srcMac.toByteArray()); - final MacAddress dstMac = MacAddress.fromString("01:02:03:04:05:06"); - buf.put(dstMac.toByteArray()); - buf.putShort((short) ETHER_TYPE_IPV6); - - // IPv6 header - byte[] version = {(byte) 0x60, 0x00, 0x00, 0x00}; - buf.put(version); // Version - buf.putShort((byte) icmpLen); // Length - buf.put((byte) IPPROTO_ICMPV6); // Next header - buf.put((byte) 0xff); // Hop limit - - final byte[] target = - InetAddresses.parseNumericAddress("fe80::1122:3344:5566:7788").getAddress(); - final byte[] src; - final byte[] dst; - if (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION) { - src = InetAddresses.parseNumericAddress("::").getAddress(); - dst = InetAddresses.parseNumericAddress("ff02::1:ff66:7788").getAddress(); - } else { - src = target; - dst = TetheringUtils.ALL_NODES; - } - buf.put(src); - buf.put(dst); - - // ICMPv6 Header - buf.put((byte) type); // Type - buf.put((byte) 0x00); // Code - buf.putShort((short) 0); // Checksum - buf.putInt(0); // Reserved - buf.put(target); - - if (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT) { - //NA packet has LL target address - //ICMPv6 Option - buf.put((byte) 0x02); // Type - buf.put((byte) 0x01); // Length - byte[] ll_target = MacAddress.fromString("01:02:03:04:05:06").toByteArray(); - buf.put(ll_target); - } - - // Populate checksum field - final int transportOffset = ETH_HEADER_LEN + IPV6_HEADER_LEN; - final short checksum = icmpv6Checksum(buf, ETH_HEADER_LEN, transportOffset, icmpLen); - buf.putShort(transportOffset + ICMPV6_CHECKSUM_OFFSET, checksum); - - buf.flip(); - return buf; - } - - private DadProxy setupProxy() throws Exception { - DadProxy proxy = new DadProxy(mHandler, mTetheredParams); - mHandler.post(() -> proxy.setUpstreamIface(mUpstreamParams)); - - // Upstream iface is added to local network to simplify test case. - // Otherwise the test needs to create and destroy a network for the upstream iface. - sNetd.networkAddInterface(INetd.LOCAL_NET_ID, mUpstreamParams.name); - sNetd.networkAddInterface(INetd.LOCAL_NET_ID, mTetheredParams.name); - - return proxy; - } - - // TODO: change to assert. - private boolean waitForPacket(ByteBuffer packet, TapPacketReader reader) { - byte[] p; - - while ((p = reader.popPacket(PACKET_TIMEOUT_MS)) != null) { - final ByteBuffer buffer = ByteBuffer.wrap(p); - - if (buffer.compareTo(packet) == 0) return true; - } - return false; - } - - private void updateDstMac(ByteBuffer buf, MacAddress mac) { - buf.put(mac.toByteArray()); - buf.rewind(); - } - private void updateSrcMac(ByteBuffer buf, InterfaceParams ifaceParams) { - buf.position(ETHER_SRC_ADDR_OFFSET); - buf.put(ifaceParams.macAddr.toByteArray()); - buf.rewind(); - } - - @Test - public void testNaForwardingFromUpstreamToTether() throws Exception { - ByteBuffer na = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT); - - mUpstreamPacketReader.sendResponse(na); - updateDstMac(na, MacAddress.fromString("33:33:00:00:00:01")); - updateSrcMac(na, mTetheredParams); - assertTrue(waitForPacket(na, mTetheredPacketReader)); - } - - @Test - // TODO: remove test once DAD works in both directions. - public void testNaForwardingFromTetherToUpstream() throws Exception { - ByteBuffer na = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT); - - mTetheredPacketReader.sendResponse(na); - updateDstMac(na, MacAddress.fromString("33:33:00:00:00:01")); - updateSrcMac(na, mTetheredParams); - assertFalse(waitForPacket(na, mUpstreamPacketReader)); - } - - @Test - public void testNsForwardingFromTetherToUpstream() throws Exception { - ByteBuffer ns = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION); - - mTetheredPacketReader.sendResponse(ns); - updateSrcMac(ns, mUpstreamParams); - assertTrue(waitForPacket(ns, mUpstreamPacketReader)); - } - - @Test - // TODO: remove test once DAD works in both directions. - public void testNsForwardingFromUpstreamToTether() throws Exception { - ByteBuffer ns = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION); - - mUpstreamPacketReader.sendResponse(ns); - updateSrcMac(ns, mUpstreamParams); - assertFalse(waitForPacket(ns, mTetheredPacketReader)); - } -} diff --git a/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java deleted file mode 100644 index 57c28fc67cc3..000000000000 --- a/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE; -import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; - -import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_GET; -import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_NEW; -import static com.android.networkstack.tethering.OffloadHardwareInterface.NFNL_SUBSYS_CTNETLINK; -import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_DESTROY; -import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_NEW; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.net.netlink.StructNlMsgHdr; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.NativeHandle; -import android.system.Os; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ConntrackSocketTest { - private static final long TIMEOUT = 500; - - private HandlerThread mHandlerThread; - private Handler mHandler; - private final SharedLog mLog = new SharedLog("privileged-test"); - - private OffloadHardwareInterface mOffloadHw; - private OffloadHardwareInterface.Dependencies mDeps; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mHandlerThread = new HandlerThread(getClass().getSimpleName()); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); - - // Looper must be prepared here since AndroidJUnitRunner runs tests on separate threads. - if (Looper.myLooper() == null) Looper.prepare(); - - mDeps = new OffloadHardwareInterface.Dependencies(mLog); - mOffloadHw = new OffloadHardwareInterface(mHandler, mLog, mDeps); - } - - @Test - public void testIpv4ConntrackSocket() throws Exception { - // Set up server and connect. - final InetSocketAddress anyAddress = new InetSocketAddress( - InetAddress.getByName("127.0.0.1"), 0); - final ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(anyAddress); - final SocketAddress theAddress = serverSocket.getLocalSocketAddress(); - - // Make a connection to the server. - final Socket socket = new Socket(); - socket.connect(theAddress); - final Socket acceptedSocket = serverSocket.accept(); - - final NativeHandle handle = mDeps.createConntrackSocket( - NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); - mOffloadHw.sendIpv4NfGenMsg(handle, - (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET), - (short) (NLM_F_REQUEST | NLM_F_DUMP)); - - boolean foundConntrackEntry = false; - ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_RECV_BUFSIZE); - buffer.order(ByteOrder.nativeOrder()); - - try { - while (Os.read(handle.getFileDescriptor(), buffer) > 0) { - buffer.flip(); - - // TODO: ConntrackMessage should get a parse API like StructNlMsgHdr - // so we can confirm that the conntrack added is for the TCP connection above. - final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(buffer); - assertNotNull(nlmsghdr); - - // As long as 1 conntrack entry is found test case will pass, even if it's not - // the from the TCP connection above. - if (nlmsghdr.nlmsg_type == ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW)) { - foundConntrackEntry = true; - break; - } - } - } finally { - socket.close(); - serverSocket.close(); - } - assertTrue("Did not receive any NFNL_SUBSYS_CTNETLINK/IPCTNL_MSG_CT_NEW message", - foundConntrackEntry); - } -} diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp deleted file mode 100644 index 45c7b656e28f..000000000000 --- a/packages/Tethering/tests/unit/Android.bp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -// Tests in this folder are included both in unit tests and CTS. -java_library { - name: "TetheringCommonTests", - srcs: [ - "common/**/*.java", - "common/**/*.kt" - ], - static_libs: [ - "androidx.test.rules", - "net-tests-utils", - ], - // TODO(b/147200698) change sdk_version to module-current and remove framework-minus-apex - sdk_version: "core_platform", - libs: [ - "framework-minus-apex", - "framework-tethering.impl", - ], - visibility: ["//cts/tests/tests/tethering"], -} - -java_defaults { - name: "TetheringTestsDefaults", - srcs: [ - "src/**/*.java", - "src/**/*.kt", - ], - static_libs: [ - "TetheringApiCurrentLib", - "TetheringCommonTests", - "androidx.test.rules", - "frameworks-base-testutils", - "mockito-target-extended-minus-junit4", - "net-tests-utils", - "testables", - ], - // TODO(b/147200698) change sdk_version to module-current and - // remove framework-minus-apex, ext, and framework-res - sdk_version: "core_platform", - libs: [ - "android.test.runner", - "android.test.base", - "android.test.mock", - "ext", - "framework-minus-apex", - "framework-res", - "framework-tethering.impl", - "framework-wifi.stubs.module_lib", - ], - jni_libs: [ - // For mockito extended - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - ], - jarjar_rules: "jarjar-rules.txt", -} - -// Library containing the unit tests. This is used by the coverage test target to pull in the -// unit test code. It is not currently used by the tests themselves because all the build -// configuration needed by the tests is in the TetheringTestsDefaults rule. -android_library { - name: "TetheringTestsLib", - defaults: ["TetheringTestsDefaults"], - visibility: [ - "//frameworks/base/packages/Tethering/tests/integration", - ] -} - -android_test { - name: "TetheringTests", - platform_apis: true, - test_suites: [ - "device-tests", - "mts", - ], - defaults: ["TetheringTestsDefaults"], - compile_multilib: "both", -} diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml deleted file mode 100644 index 355342f64371..000000000000 --- a/packages/Tethering/tests/unit/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.networkstack.tethering.tests.unit"> - - <application android:debuggable="true"> - <uses-library android:name="android.test.runner" /> - <service - android:name="com.android.networkstack.tethering.MockTetheringService" - android:permission="android.permission.TETHER_PRIVILEGED" - android:exported="true"> - <intent-filter> - <action android:name="com.android.networkstack.tethering.TetheringService"/> - </intent-filter> - </service> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.networkstack.tethering.tests.unit" - android:label="Tethering service tests"> - </instrumentation> -</manifest> diff --git a/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt b/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt deleted file mode 100644 index 55c59dd08f41..000000000000 --- a/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.InetAddresses.parseNumericAddress -import android.net.TetheredClient.AddressInfo -import android.net.TetheringManager.TETHERING_BLUETOOTH -import android.net.TetheringManager.TETHERING_USB -import android.system.OsConstants.RT_SCOPE_UNIVERSE -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -private val TEST_MACADDR = MacAddress.fromBytes(byteArrayOf(12, 23, 34, 45, 56, 67)) -private val TEST_OTHER_MACADDR = MacAddress.fromBytes(byteArrayOf(23, 34, 45, 56, 67, 78)) -private val TEST_ADDR1 = makeLinkAddress("192.168.113.3", prefixLength = 24, expTime = 123L) -private val TEST_ADDR2 = makeLinkAddress("fe80::1:2:3", prefixLength = 64, expTime = 456L) -private val TEST_HOSTNAME = "test_hostname" -private val TEST_OTHER_HOSTNAME = "test_other_hostname" -private val TEST_ADDRINFO1 = AddressInfo(TEST_ADDR1, TEST_HOSTNAME) -private val TEST_ADDRINFO2 = AddressInfo(TEST_ADDR2, null) - -private fun makeLinkAddress(addr: String, prefixLength: Int, expTime: Long) = LinkAddress( - parseNumericAddress(addr), - prefixLength, - 0 /* flags */, - RT_SCOPE_UNIVERSE, - expTime /* deprecationTime */, - expTime /* expirationTime */) - -@RunWith(AndroidJUnit4::class) -@SmallTest -class TetheredClientTest { - @Test - fun testParceling() { - assertParcelSane(TEST_ADDRINFO1, fieldCount = 2) - assertParcelSane(makeTestClient(), fieldCount = 3) - } - - @Test - fun testEquals() { - assertEquals(makeTestClient(), makeTestClient()) - - // Different mac address - assertNotEquals(makeTestClient(), TetheredClient( - TEST_OTHER_MACADDR, - listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), - TETHERING_BLUETOOTH)) - - // Different hostname - assertNotEquals(makeTestClient(), TetheredClient( - TEST_MACADDR, - listOf(AddressInfo(TEST_ADDR1, TEST_OTHER_HOSTNAME), TEST_ADDRINFO2), - TETHERING_BLUETOOTH)) - - // Null hostname - assertNotEquals(makeTestClient(), TetheredClient( - TEST_MACADDR, - listOf(AddressInfo(TEST_ADDR1, null), TEST_ADDRINFO2), - TETHERING_BLUETOOTH)) - - // Missing address - assertNotEquals(makeTestClient(), TetheredClient( - TEST_MACADDR, - listOf(TEST_ADDRINFO2), - TETHERING_BLUETOOTH)) - - // Different type - assertNotEquals(makeTestClient(), TetheredClient( - TEST_MACADDR, - listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), - TETHERING_USB)) - } - - @Test - fun testAddAddresses() { - val client1 = TetheredClient(TEST_MACADDR, listOf(TEST_ADDRINFO1), TETHERING_USB) - val client2 = TetheredClient(TEST_OTHER_MACADDR, listOf(TEST_ADDRINFO2), TETHERING_USB) - assertEquals(TetheredClient( - TEST_MACADDR, - listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), - TETHERING_USB), client1.addAddresses(client2)) - } - - @Test - fun testGetters() { - assertEquals(TEST_MACADDR, makeTestClient().macAddress) - assertEquals(listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), makeTestClient().addresses) - assertEquals(TETHERING_BLUETOOTH, makeTestClient().tetheringType) - } - - @Test - fun testAddressInfo_Getters() { - assertEquals(TEST_ADDR1, TEST_ADDRINFO1.address) - assertEquals(TEST_ADDR2, TEST_ADDRINFO2.address) - assertEquals(TEST_HOSTNAME, TEST_ADDRINFO1.hostname) - assertEquals(null, TEST_ADDRINFO2.hostname) - } - - private fun makeTestClient() = TetheredClient( - TEST_MACADDR, - listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), - TETHERING_BLUETOOTH) -}
\ No newline at end of file diff --git a/packages/Tethering/tests/unit/jarjar-rules.txt b/packages/Tethering/tests/unit/jarjar-rules.txt deleted file mode 100644 index 7ed89632a861..000000000000 --- a/packages/Tethering/tests/unit/jarjar-rules.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Don't jar-jar the entire package because this test use some -# internal classes (like ArrayUtils in com.android.internal.util) -rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1 -rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1 -rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1 -rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1 -rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1 -rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1 -rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1 - -rule android.util.LocalLog* com.android.networkstack.tethering.util.LocalLog@1 - -# TODO: either stop using frameworks-base-testutils or remove the unit test classes it contains. -# TestableLooper from "testables" can be used instead of TestLooper from frameworks-base-testutils. -zap android.os.test.TestLooperTest* -zap com.android.test.filters.SelectTestTests*
\ No newline at end of file diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java deleted file mode 100644 index a8857b2e5cb0..000000000000 --- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.dhcp; - -import static android.net.InetAddresses.parseNumericAddress; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.LinkAddress; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DhcpServingParamsParcelExtTest { - private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123"); - private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42"); - private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b; - private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a; - private static final int TEST_PREFIX_LENGTH = 17; - private static final int TEST_LEASE_TIME_SECS = 120; - private static final int TEST_MTU = 1000; - private static final Set<Inet4Address> TEST_ADDRESS_SET = - new HashSet<Inet4Address>(Arrays.asList( - new Inet4Address[] {inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")})); - private static final Set<Integer> TEST_ADDRESS_SET_PARCELED = - new HashSet<Integer>(Arrays.asList(new Integer[] {0xc0a8017b, 0xc0a8017c})); - - private DhcpServingParamsParcelExt mParcel; - - @Before - public void setUp() { - mParcel = new DhcpServingParamsParcelExt(); - } - - @Test - public void testSetServerAddr() { - mParcel.setServerAddr(new LinkAddress(TEST_ADDRESS, TEST_PREFIX_LENGTH)); - - assertEquals(TEST_ADDRESS_PARCELED, mParcel.serverAddr); - assertEquals(TEST_PREFIX_LENGTH, mParcel.serverAddrPrefixLength); - } - - @Test - public void testSetDefaultRouters() { - mParcel.setDefaultRouters(TEST_ADDRESS_SET); - assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.defaultRouters)); - } - - @Test - public void testSetDnsServers() { - mParcel.setDnsServers(TEST_ADDRESS_SET); - assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.dnsServers)); - } - - @Test - public void testSetExcludedAddrs() { - mParcel.setExcludedAddrs(TEST_ADDRESS_SET); - assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.excludedAddrs)); - } - - @Test - public void testSetDhcpLeaseTimeSecs() { - mParcel.setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS); - assertEquals(TEST_LEASE_TIME_SECS, mParcel.dhcpLeaseTimeSecs); - } - - @Test - public void testSetLinkMtu() { - mParcel.setLinkMtu(TEST_MTU); - assertEquals(TEST_MTU, mParcel.linkMtu); - } - - @Test - public void testSetMetered() { - mParcel.setMetered(true); - assertTrue(mParcel.metered); - mParcel.setMetered(false); - assertFalse(mParcel.metered); - } - - @Test - public void testSetClientAddr() { - mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS); - assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.singleClientAddr); - } - - private static Inet4Address inet4Addr(String addr) { - return (Inet4Address) parseNumericAddress(addr); - } - - private static Set<Integer> asSet(int[] ints) { - return IntStream.of(ints).boxed().collect(Collectors.toSet()); - } -} diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java deleted file mode 100644 index 2eb75895ac3e..000000000000 --- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ /dev/null @@ -1,1201 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static android.net.INetd.IF_STATE_UP; -import static android.net.RouteInfo.RTN_UNICAST; -import static android.net.TetheringManager.TETHERING_BLUETOOTH; -import static android.net.TetheringManager.TETHERING_NCM; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; -import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.ip.IpServer.STATE_AVAILABLE; -import static android.net.ip.IpServer.STATE_LOCAL_ONLY; -import static android.net.ip.IpServer.STATE_TETHERED; -import static android.net.ip.IpServer.STATE_UNAVAILABLE; -import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH; -import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH; -import static android.net.netlink.StructNdMsg.NUD_FAILED; -import static android.net.netlink.StructNdMsg.NUD_REACHABLE; -import static android.net.netlink.StructNdMsg.NUD_STALE; - -import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.usage.NetworkStatsManager; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.RouteInfo; -import android.net.TetherOffloadRuleParcel; -import android.net.TetherStatsParcel; -import android.net.dhcp.DhcpServerCallbacks; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.IDhcpEventCallbacks; -import android.net.dhcp.IDhcpServer; -import android.net.dhcp.IDhcpServerCallbacks; -import android.net.ip.IpNeighborMonitor.NeighborEvent; -import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; -import android.net.ip.RouterAdvertisementDaemon.RaParams; -import android.net.util.InterfaceParams; -import android.net.util.InterfaceSet; -import android.net.util.PrefixUtils; -import android.net.util.SharedLog; -import android.os.Build; -import android.os.Handler; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.text.TextUtils; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.networkstack.tethering.BpfCoordinator; -import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; -import com.android.networkstack.tethering.PrivateAddressCoordinator; -import com.android.networkstack.tethering.TetheringConfiguration; -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpServerTest { - @Rule - public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); - - private static final String IFACE_NAME = "testnet1"; - private static final String UPSTREAM_IFACE = "upstream0"; - private static final String UPSTREAM_IFACE2 = "upstream1"; - private static final int UPSTREAM_IFINDEX = 101; - private static final int UPSTREAM_IFINDEX2 = 102; - private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; - private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24; - private static final int DHCP_LEASE_TIME_SECS = 3600; - private static final boolean DEFAULT_USING_BPF_OFFLOAD = true; - - private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams( - IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); - private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams( - UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); - private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams( - UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS, - 1500 /* defaultMtu */); - - private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000; - - private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24"); - private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24"); - - @Mock private INetd mNetd; - @Mock private IpServer.Callback mCallback; - @Mock private SharedLog mSharedLog; - @Mock private IDhcpServer mDhcpServer; - @Mock private DadProxy mDadProxy; - @Mock private RouterAdvertisementDaemon mRaDaemon; - @Mock private IpNeighborMonitor mIpNeighborMonitor; - @Mock private IpServer.Dependencies mDependencies; - @Mock private PrivateAddressCoordinator mAddressCoordinator; - @Mock private NetworkStatsManager mStatsManager; - @Mock private TetheringConfiguration mTetherConfig; - - @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor; - - private final TestLooper mLooper = new TestLooper(); - private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor = - ArgumentCaptor.forClass(LinkProperties.class); - private IpServer mIpServer; - private InterfaceConfigurationParcel mInterfaceConfiguration; - private NeighborEventConsumer mNeighborEventConsumer; - private BpfCoordinator mBpfCoordinator; - - private void initStateMachine(int interfaceType) throws Exception { - initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); - } - - private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, - boolean usingBpfOffload) throws Exception { - when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy); - when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); - when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS); - when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS); - when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2); - - when(mDependencies.getIfindex(eq(UPSTREAM_IFACE))).thenReturn(UPSTREAM_IFINDEX); - when(mDependencies.getIfindex(eq(UPSTREAM_IFACE2))).thenReturn(UPSTREAM_IFINDEX2); - - mInterfaceConfiguration = new InterfaceConfigurationParcel(); - mInterfaceConfiguration.flags = new String[0]; - if (interfaceType == TETHERING_BLUETOOTH) { - mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR; - mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH; - } - - ArgumentCaptor<NeighborEventConsumer> neighborCaptor = - ArgumentCaptor.forClass(NeighborEventConsumer.class); - doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(), - neighborCaptor.capture()); - - mIpServer = new IpServer( - IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator, - mCallback, usingLegacyDhcp, usingBpfOffload, mAddressCoordinator, mDependencies); - mIpServer.start(); - mNeighborEventConsumer = neighborCaptor.getValue(); - - // Starting the state machine always puts us in a consistent state and notifies - // the rest of the world that we've changed from an unknown to available state. - mLooper.dispatchAll(); - reset(mNetd, mCallback); - - when(mRaDaemon.start()).thenReturn(true); - } - - private void initTetheredStateMachine(int interfaceType, String upstreamIface) - throws Exception { - initTetheredStateMachine(interfaceType, upstreamIface, false, - DEFAULT_USING_BPF_OFFLOAD); - } - - private void initTetheredStateMachine(int interfaceType, String upstreamIface, - boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception { - initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload); - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - if (upstreamIface != null) { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(upstreamIface); - dispatchTetherConnectionChanged(upstreamIface, lp, 0); - } - reset(mNetd, mCallback, mAddressCoordinator); - when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( - mTestAddress); - } - - private void setUpDhcpServer() throws Exception { - doAnswer(inv -> { - final IDhcpServerCallbacks cb = inv.getArgument(2); - new Thread(() -> { - try { - cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); - } catch (RemoteException e) { - fail(e.getMessage()); - } - }).run(); - return null; - }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); - } - - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog); - when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( - mTestAddress); - when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */); - - mBpfCoordinator = spy(new BpfCoordinator( - new BpfCoordinator.Dependencies() { - @NonNull - public Handler getHandler() { - return new Handler(mLooper.getLooper()); - } - - @NonNull - public INetd getNetd() { - return mNetd; - } - - @NonNull - public NetworkStatsManager getNetworkStatsManager() { - return mStatsManager; - } - - @NonNull - public SharedLog getSharedLog() { - return mSharedLog; - } - - @Nullable - public TetheringConfiguration getTetherConfig() { - return mTetherConfig; - } - })); - - setUpDhcpServer(); - } - - @Test - public void startsOutAvailable() { - when(mDependencies.getIpNeighborMonitor(any(), any(), any())) - .thenReturn(mIpNeighborMonitor); - mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog, - mNetd, mBpfCoordinator, mCallback, false /* usingLegacyDhcp */, - DEFAULT_USING_BPF_OFFLOAD, mAddressCoordinator, mDependencies); - mIpServer.start(); - mLooper.dispatchAll(); - verify(mCallback).updateInterfaceState( - mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); - verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); - verifyNoMoreInteractions(mCallback, mNetd); - } - - @Test - public void shouldDoNothingUntilRequested() throws Exception { - initStateMachine(TETHERING_BLUETOOTH); - final int [] noOp_commands = { - IpServer.CMD_TETHER_UNREQUESTED, - IpServer.CMD_IP_FORWARDING_ENABLE_ERROR, - IpServer.CMD_IP_FORWARDING_DISABLE_ERROR, - IpServer.CMD_START_TETHERING_ERROR, - IpServer.CMD_STOP_TETHERING_ERROR, - IpServer.CMD_SET_DNS_FORWARDERS_ERROR, - IpServer.CMD_TETHER_CONNECTION_CHANGED - }; - for (int command : noOp_commands) { - // None of these commands should trigger us to request action from - // the rest of the system. - dispatchCommand(command); - verifyNoMoreInteractions(mNetd, mCallback); - } - } - - @Test - public void handlesImmediateInterfaceDown() throws Exception { - initStateMachine(TETHERING_BLUETOOTH); - - dispatchCommand(IpServer.CMD_INTERFACE_DOWN); - verify(mCallback).updateInterfaceState( - mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); - verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); - verifyNoMoreInteractions(mNetd, mCallback); - } - - @Test - public void canBeTethered() throws Exception { - initStateMachine(TETHERING_BLUETOOTH); - - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - InOrder inOrder = inOrder(mCallback, mNetd); - inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); - inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - // One for ipv4 route, one for ipv6 link local route. - inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), - any(), any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), any(LinkProperties.class)); - verifyNoMoreInteractions(mNetd, mCallback); - } - - @Test - public void canUnrequestTethering() throws Exception { - initTetheredStateMachine(TETHERING_BLUETOOTH, null); - - dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); - InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); - inOrder.verify(mNetd).tetherApplyDnsInterfaces(); - inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); - inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - inOrder.verify(mAddressCoordinator).releaseDownstream(any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), any(LinkProperties.class)); - verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); - } - - @Test - public void canBeTetheredAsUsb() throws Exception { - initStateMachine(TETHERING_USB); - - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); - inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); - inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> - IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP))); - inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); - inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), - any(), any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), mLinkPropertiesCaptor.capture()); - assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); - verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); - } - - @Test - public void canBeTetheredAsWifiP2p() throws Exception { - initStateMachine(TETHERING_WIFI_P2P); - - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); - InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); - inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); - inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> - IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP))); - inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); - inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), - any(), any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), mLinkPropertiesCaptor.capture()); - assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); - verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); - } - - @Test - public void handlesFirstUpstreamChange() throws Exception { - initTetheredStateMachine(TETHERING_BLUETOOTH, null); - - // Telling the state machine about its upstream interface triggers - // a little more configuration. - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - InOrder inOrder = inOrder(mNetd); - inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); - verifyNoMoreInteractions(mNetd, mCallback); - } - - @Test - public void handlesChangingUpstream() throws Exception { - initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); - - dispatchTetherConnectionChanged(UPSTREAM_IFACE2); - InOrder inOrder = inOrder(mNetd); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); - verifyNoMoreInteractions(mNetd, mCallback); - } - - @Test - public void handlesChangingUpstreamNatFailure() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - - doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); - - dispatchTetherConnectionChanged(UPSTREAM_IFACE2); - InOrder inOrder = inOrder(mNetd); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2); - } - - @Test - public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - - doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward( - IFACE_NAME, UPSTREAM_IFACE2); - - dispatchTetherConnectionChanged(UPSTREAM_IFACE2); - InOrder inOrder = inOrder(mNetd); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2); - } - - @Test - public void canUnrequestTetheringWithUpstream() throws Exception { - initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); - - dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); - InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator); - inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); - inOrder.verify(mNetd).tetherApplyDnsInterfaces(); - inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); - inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - inOrder.verify(mAddressCoordinator).releaseDownstream(any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), any(LinkProperties.class)); - verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); - } - - @Test - public void interfaceDownLeadsToUnavailable() throws Exception { - for (boolean shouldThrow : new boolean[]{true, false}) { - initTetheredStateMachine(TETHERING_USB, null); - - if (shouldThrow) { - doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME); - } - dispatchCommand(IpServer.CMD_INTERFACE_DOWN); - InOrder usbTeardownOrder = inOrder(mNetd, mCallback); - // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down - // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address. - usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( - argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - usbTeardownOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); - usbTeardownOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), mLinkPropertiesCaptor.capture()); - assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); - } - } - - @Test - public void usbShouldBeTornDownOnTetherError() throws Exception { - initStateMachine(TETHERING_USB); - - doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME); - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - InOrder usbTeardownOrder = inOrder(mNetd, mCallback); - usbTeardownOrder.verify(mNetd).interfaceSetCfg( - argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); - - usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( - argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - usbTeardownOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR); - usbTeardownOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), mLinkPropertiesCaptor.capture()); - assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); - } - - @Test - public void shouldTearDownUsbOnUpstreamError() throws Exception { - initTetheredStateMachine(TETHERING_USB, null); - - doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString()); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - InOrder usbTeardownOrder = inOrder(mNetd, mCallback); - usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE); - - usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( - argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); - usbTeardownOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR); - usbTeardownOrder.verify(mCallback).updateLinkProperties( - eq(mIpServer), mLinkPropertiesCaptor.capture()); - assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); - } - - @Test - public void ignoresDuplicateUpstreamNotifications() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - - verifyNoMoreInteractions(mNetd, mCallback); - - for (int i = 0; i < 5; i++) { - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - verifyNoMoreInteractions(mNetd, mCallback); - } - } - - @Test - public void startsDhcpServer() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - - assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); - } - - @Test - public void startsDhcpServerOnBluetooth() throws Exception { - initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - - assertDhcpStarted(mBluetoothPrefix); - } - - @Test - public void startsDhcpServerOnWifiP2p() throws Exception { - initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - - assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); - } - - @Test - public void startsDhcpServerOnNcm() throws Exception { - initStateMachine(TETHERING_NCM); - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - - assertDhcpStarted(new IpPrefix("192.168.42.0/24")); - } - - @Test - public void testOnNewPrefixRequest() throws Exception { - initStateMachine(TETHERING_NCM); - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); - - final IDhcpEventCallbacks eventCallbacks; - final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor = - ArgumentCaptor.forClass(IDhcpEventCallbacks.class); - verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), dhcpEventCbsCaptor.capture()); - eventCallbacks = dhcpEventCbsCaptor.getValue(); - assertDhcpStarted(new IpPrefix("192.168.42.0/24")); - - final ArgumentCaptor<LinkProperties> lpCaptor = - ArgumentCaptor.forClass(LinkProperties.class); - InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator); - inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); - inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); - // One for ipv4 route, one for ipv6 link local route. - inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), - any(), any()); - inOrder.verify(mCallback).updateInterfaceState( - mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); - inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); - verifyNoMoreInteractions(mCallback, mAddressCoordinator); - - // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals - // onNewPrefixRequest callback. - final LinkAddress newAddress = new LinkAddress("192.168.100.125/24"); - when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( - newAddress); - eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24")); - mLooper.dispatchAll(); - - inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(false)); - inOrder.verify(mNetd).tetherApplyDnsInterfaces(); - inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); - verifyNoMoreInteractions(mCallback); - - final LinkProperties linkProperties = lpCaptor.getValue(); - final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses(); - assertEquals(1, linkProperties.getLinkAddresses().size()); - assertEquals(1, linkProperties.getRoutes().size()); - final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(), - linkAddresses.get(0).getPrefixLength()); - assertNotEquals(prefix, new IpPrefix("192.168.42.0/24")); - - verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any()); - assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix); - } - - @Test - public void doesNotStartDhcpServerIfDisabled() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */, - DEFAULT_USING_BPF_OFFLOAD); - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - - verify(mDependencies, never()).makeDhcpServer(any(), any(), any()); - } - - private InetAddress addr(String addr) throws Exception { - return InetAddresses.parseNumericAddress(addr); - } - - private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { - mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr, - nudState, mac)); - mLooper.dispatchAll(); - } - - private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { - mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr, - nudState, mac)); - mLooper.dispatchAll(); - } - - /** - * Custom ArgumentMatcher for TetherOffloadRuleParcel. This is needed because generated stable - * AIDL classes don't have equals(), so we cannot just use eq(). A custom assert, such as: - * - * private void checkFooCalled(StableParcelable p, ...) { - * ArgumentCaptor<FooParam> captor = ArgumentCaptor.forClass(FooParam.class); - * verify(mMock).foo(captor.capture()); - * Foo foo = captor.getValue(); - * assertFooMatchesExpectations(foo); - * } - * - * almost works, but not quite. This is because if the code under test calls foo() twice, the - * first call to checkFooCalled() matches both the calls, putting both calls into the captor, - * and then fails with TooManyActualInvocations. It also makes it harder to use other mockito - * features such as never(), inOrder(), etc. - * - * This approach isn't great because if the match fails, the error message is unhelpful - * (actual: "android.net.TetherOffloadRuleParcel@8c827b0" or some such), but at least it does - * work. - * - * TODO: consider making the error message more readable by adding a method that catching the - * AssertionFailedError and throwing a new assertion with more details. See - * NetworkMonitorTest#verifyNetworkTested. - * - * See ConnectivityServiceTest#assertRoutesAdded for an alternative approach which solves the - * TooManyActualInvocations problem described above by forcing the caller of the custom assert - * method to specify all expected invocations in one call. This is useful when the stable - * parcelable class being asserted on has a corresponding Java object (eg., RouteInfo and - * RouteInfoParcelable), and the caller can just pass in a list of them. It not useful here - * because there is no such object. - */ - private static class TetherOffloadRuleParcelMatcher implements - ArgumentMatcher<TetherOffloadRuleParcel> { - public final int upstreamIfindex; - public final InetAddress dst; - public final MacAddress dstMac; - - TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac) { - this.upstreamIfindex = upstreamIfindex; - this.dst = dst; - this.dstMac = dstMac; - } - - public boolean matches(TetherOffloadRuleParcel parcel) { - return upstreamIfindex == parcel.inputInterfaceIndex - && (TEST_IFACE_PARAMS.index == parcel.outputInterfaceIndex) - && Arrays.equals(dst.getAddress(), parcel.destination) - && (128 == parcel.prefixLength) - && Arrays.equals(TEST_IFACE_PARAMS.macAddr.toByteArray(), parcel.srcL2Address) - && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address); - } - - public String toString() { - return String.format("TetherOffloadRuleParcelMatcher(%d, %s, %s", - upstreamIfindex, dst.getHostAddress(), dstMac); - } - } - - @NonNull - private static TetherOffloadRuleParcel matches( - int upstreamIfindex, InetAddress dst, MacAddress dstMac) { - return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac)); - } - - @NonNull - private static Ipv6ForwardingRule makeForwardingRule( - int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) { - return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index, - (Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac); - } - - @NonNull - private static TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) { - TetherStatsParcel parcel = new TetherStatsParcel(); - parcel.ifIndex = ifIndex; - return parcel; - } - - private void resetNetdAndBpfCoordinator() throws Exception { - reset(mNetd, mBpfCoordinator); - when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]); - when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX)) - .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX)); - when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX2)) - .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX2)); - } - - @Test - public void addRemoveipv6ForwardingRules() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, - DEFAULT_USING_BPF_OFFLOAD); - - final int myIfindex = TEST_IFACE_PARAMS.index; - final int notMyIfindex = myIfindex - 1; - - final MacAddress myMac = TEST_IFACE_PARAMS.macAddr; - final InetAddress neighA = InetAddresses.parseNumericAddress("2001:db8::1"); - final InetAddress neighB = InetAddresses.parseNumericAddress("2001:db8::2"); - final InetAddress neighLL = InetAddresses.parseNumericAddress("fe80::1"); - final InetAddress neighMC = InetAddresses.parseNumericAddress("ff02::1234"); - final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00"); - final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a"); - final MacAddress macB = MacAddress.fromString("11:22:33:00:00:0b"); - - resetNetdAndBpfCoordinator(); - verifyNoMoreInteractions(mBpfCoordinator, mNetd); - - // TODO: Perhaps verify the interaction of tetherOffloadSetInterfaceQuota and - // tetherOffloadGetAndClearStats in netd while the rules are changed. - - // Events on other interfaces are ignored. - recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, macA); - verifyNoMoreInteractions(mBpfCoordinator, mNetd); - - // Events on this interface are received and sent to netd. - recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); - resetNetdAndBpfCoordinator(); - - recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); - resetNetdAndBpfCoordinator(); - - // Link-local and multicast neighbors are ignored. - recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, macA); - verifyNoMoreInteractions(mBpfCoordinator, mNetd); - recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, macA); - verifyNoMoreInteractions(mBpfCoordinator, mNetd); - - // A neighbor that is no longer valid causes the rule to be removed. - // NUD_FAILED events do not have a MAC address. - recvNewNeigh(myIfindex, neighA, NUD_FAILED, null); - verify(mBpfCoordinator).tetherOffloadRuleRemove( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull)); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macNull)); - resetNetdAndBpfCoordinator(); - - // A neighbor that is deleted causes the rule to be removed. - recvDelNeigh(myIfindex, neighB, NUD_STALE, macB); - verify(mBpfCoordinator).tetherOffloadRuleRemove( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull)); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macNull)); - resetNetdAndBpfCoordinator(); - - // Upstream changes result in updating the rules. - recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); - recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); - resetNetdAndBpfCoordinator(); - - InOrder inOrder = inOrder(mNetd); - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE2); - dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); - verify(mBpfCoordinator).tetherOffloadRuleUpdate(mIpServer, UPSTREAM_IFINDEX2); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA)); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA)); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB)); - resetNetdAndBpfCoordinator(); - - // When the upstream is lost, rules are removed. - dispatchTetherConnectionChanged(null, null, 0); - // Clear function is called two times by: - // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost. - // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost. - // See dispatchTetherConnectionChanged. - verify(mBpfCoordinator, times(2)).tetherOffloadRuleClear(mIpServer); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA)); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB)); - resetNetdAndBpfCoordinator(); - - // If the upstream is IPv4-only, no rules are added. - dispatchTetherConnectionChanged(UPSTREAM_IFACE); - resetNetdAndBpfCoordinator(); - recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); - // Clear function is called by #updateIpv6ForwardingRules for the IPv6 upstream is lost. - verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); - verifyNoMoreInteractions(mBpfCoordinator, mNetd); - - // Rules can be added again once upstream IPv6 connectivity is available. - lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); - recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); - verify(mBpfCoordinator, never()).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); - verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); - - // If upstream IPv6 connectivity is lost, rules are removed. - resetNetdAndBpfCoordinator(); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); - verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); - - // When the interface goes down, rules are removed. - lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); - recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); - recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); - resetNetdAndBpfCoordinator(); - - mIpServer.stop(); - mLooper.dispatchAll(); - verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA)); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); - verify(mIpNeighborMonitor).stop(); - resetNetdAndBpfCoordinator(); - } - - @Test - public void enableDisableUsingBpfOffload() throws Exception { - final int myIfindex = TEST_IFACE_PARAMS.index; - final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1"); - final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a"); - final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00"); - - // Expect that rules can be only added/removed when the BPF offload config is enabled. - // Note that the BPF offload disabled case is not a realistic test case. Because IP - // neighbor monitor doesn't start if BPF offload is disabled, there should have no - // neighbor event listening. This is used for testing the protection check just in case. - // TODO: Perhaps remove the BPF offload disabled case test once this check isn't needed - // anymore. - - // [1] Enable BPF offload. - // A neighbor that is added or deleted causes the rule to be added or removed. - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, - true /* usingBpfOffload */); - resetNetdAndBpfCoordinator(); - - recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA); - verify(mBpfCoordinator).tetherOffloadRuleAdd( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA)); - verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neigh, macA)); - resetNetdAndBpfCoordinator(); - - recvDelNeigh(myIfindex, neigh, NUD_STALE, macA); - verify(mBpfCoordinator).tetherOffloadRuleRemove( - mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macNull)); - verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neigh, macNull)); - resetNetdAndBpfCoordinator(); - - // [2] Disable BPF offload. - // A neighbor that is added or deleted doesn’t cause the rule to be added or removed. - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, - false /* usingBpfOffload */); - resetNetdAndBpfCoordinator(); - - recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA); - verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(any(), any()); - verify(mNetd, never()).tetherOffloadRuleAdd(any()); - resetNetdAndBpfCoordinator(); - - recvDelNeigh(myIfindex, neigh, NUD_STALE, macA); - verify(mBpfCoordinator, never()).tetherOffloadRuleRemove(any(), any()); - verify(mNetd, never()).tetherOffloadRuleRemove(any()); - resetNetdAndBpfCoordinator(); - } - - @Test - public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, - false /* usingBpfOffload */); - - // IP neighbor monitor doesn't start if BPF offload is disabled. - verify(mIpNeighborMonitor, never()).start(); - } - - private LinkProperties buildIpv6OnlyLinkProperties(final String iface) { - final LinkProperties linkProp = new LinkProperties(); - linkProp.setInterfaceName(iface); - linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64")); - linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST)); - final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888"); - linkProp.addDnsServer(dns); - - return linkProp; - } - - @Test - public void testAdjustTtlValue() throws Exception { - final ArgumentCaptor<RaParams> raParamsCaptor = - ArgumentCaptor.forClass(RaParams.class); - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); - final RaParams noV6Params = raParamsCaptor.getValue(); - assertEquals(65, noV6Params.hopLimit); - reset(mRaDaemon); - - when(mNetd.getProcSysNet( - INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64"); - final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1); - verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); - final RaParams nonCellularParams = raParamsCaptor.getValue(); - assertEquals(65, nonCellularParams.hopLimit); - reset(mRaDaemon); - - dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); - verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); - final RaParams noUpstream = raParamsCaptor.getValue(); - assertEquals(65, nonCellularParams.hopLimit); - reset(mRaDaemon); - - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); - verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); - final RaParams cellularParams = raParamsCaptor.getValue(); - assertEquals(63, cellularParams.hopLimit); - reset(mRaDaemon); - } - - @Test - public void testStopObsoleteDhcpServer() throws Exception { - final ArgumentCaptor<DhcpServerCallbacks> cbCaptor = - ArgumentCaptor.forClass(DhcpServerCallbacks.class); - doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), - cbCaptor.capture()); - initStateMachine(TETHERING_WIFI); - dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - verify(mDhcpServer, never()).startWithCallbacks(any(), any()); - - // No stop dhcp server because dhcp server is not created yet. - dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); - verify(mDhcpServer, never()).stop(any()); - - // Stop obsolete dhcp server. - try { - final DhcpServerCallbacks cb = cbCaptor.getValue(); - cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); - mLooper.dispatchAll(); - } catch (RemoteException e) { - fail(e.getMessage()); - } - verify(mDhcpServer).stop(any()); - } - - private void assertDhcpServingParams(final DhcpServingParamsParcel params, - final IpPrefix prefix) { - // Last address byte is random - assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr))); - assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength); - assertEquals(1, params.defaultRouters.length); - assertEquals(params.serverAddr, params.defaultRouters[0]); - assertEquals(1, params.dnsServers.length); - assertEquals(params.serverAddr, params.dnsServers[0]); - assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs); - if (mIpServer.interfaceType() == TETHERING_NCM) { - assertTrue(params.changePrefixOnDecline); - } - } - - private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception { - verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any()); - verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix); - } - - /** - * Send a command to the state machine under test, and run the event loop to idle. - * - * @param command One of the IpServer.CMD_* constants. - * @param arg1 An additional argument to pass. - */ - private void dispatchCommand(int command, int arg1) { - mIpServer.sendMessage(command, arg1); - mLooper.dispatchAll(); - } - - /** - * Send a command to the state machine under test, and run the event loop to idle. - * - * @param command One of the IpServer.CMD_* constants. - */ - private void dispatchCommand(int command) { - mIpServer.sendMessage(command); - mLooper.dispatchAll(); - } - - /** - * Special override to tell the state machine that the upstream interface has changed. - * - * @see #dispatchCommand(int) - * @param upstreamIface String name of upstream interface (or null) - * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream. - */ - private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, - int ttlAdjustment) { - dispatchTetherConnectionChanged(upstreamIface); - mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); - mLooper.dispatchAll(); - } - - private void dispatchTetherConnectionChanged(String upstreamIface) { - final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null; - mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs); - mLooper.dispatchAll(); - } - - private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) { - // Find the first IPv4 LinkAddress. - LinkAddress addr4 = null; - for (LinkAddress addr : lp.getLinkAddresses()) { - if (!(addr.getAddress() instanceof Inet4Address)) continue; - addr4 = addr; - break; - } - assertNotNull("missing IPv4 address", addr4); - - final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength()); - // Assert the presence of the associated directly connected route. - final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(), - RouteInfo.RTN_UNICAST); - assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'", - lp.getRoutes().contains(directlyConnected)); - } - - private void assertNoAddressesNorRoutes(LinkProperties lp) { - assertTrue(lp.getLinkAddresses().isEmpty()); - assertTrue(lp.getRoutes().isEmpty()); - // We also check that interface name is non-empty, because we should - // never see an empty interface name in any LinkProperties update. - assertFalse(TextUtils.isEmpty(lp.getInterfaceName())); - } - - private boolean assertContainsFlag(String[] flags, String match) { - for (String flag : flags) { - if (flag.equals(match)) return true; - } - fail("Missing flag: " + match); - return false; - } - - private boolean assertNotContainsFlag(String[] flags, String match) { - for (String flag : flags) { - if (flag.equals(match)) { - fail("Unexpected flag: " + match); - return false; - } - } - return true; - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void dadProxyUpdates() throws Exception { - InOrder inOrder = inOrder(mDadProxy); - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); - - // Add an upstream without IPv6. - dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); - inOrder.verify(mDadProxy).setUpstreamIface(null); - - // Add IPv6 to the upstream. - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); - - // Change upstream. - // New linkproperties is needed, otherwise changing the iface has no impact. - LinkProperties lp2 = new LinkProperties(); - lp2.setInterfaceName(UPSTREAM_IFACE2); - dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0); - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2); - - // Lose IPv6 on the upstream... - dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0); - inOrder.verify(mDadProxy).setUpstreamIface(null); - - // ... and regain it on a different upstream. - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); - - // Lose upstream. - dispatchTetherConnectionChanged(null, null, 0); - inOrder.verify(mDadProxy).setUpstreamIface(null); - - // Regain upstream. - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); - - // Stop tethering. - mIpServer.stop(); - mLooper.dispatchAll(); - } - - private void checkDadProxyEnabled(boolean expectEnabled) throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); - InOrder inOrder = inOrder(mDadProxy); - // Add IPv6 to the upstream. - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE); - if (expectEnabled) { - inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); - } else { - inOrder.verifyNoMoreInteractions(); - } - // Stop tethering. - mIpServer.stop(); - mLooper.dispatchAll(); - if (expectEnabled) { - inOrder.verify(mDadProxy).stop(); - } - else { - verify(mDependencies, never()).getDadProxy(any(), any()); - } - } - @Test @IgnoreAfter(Build.VERSION_CODES.R) - public void testDadProxyUpdates_DisabledUpToR() throws Exception { - checkDadProxyEnabled(false); - } - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testDadProxyUpdates_EnabledAfterR() throws Exception { - checkDadProxyEnabled(true); - } -} diff --git a/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java b/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java deleted file mode 100644 index ea084b607868..000000000000 --- a/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class InterfaceSetTest { - @Test - public void testNullNamesIgnored() { - final InterfaceSet set = new InterfaceSet(null, "if1", null, "if2", null); - assertEquals(2, set.ifnames.size()); - assertTrue(set.ifnames.contains("if1")); - assertTrue(set.ifnames.contains("if2")); - } - - @Test - public void testToString() { - final InterfaceSet set = new InterfaceSet("if1", "if2"); - final String setString = set.toString(); - assertTrue(setString.equals("[if1,if2]") || setString.equals("[if2,if1]")); - } - - @Test - public void testToString_Empty() { - final InterfaceSet set = new InterfaceSet(null, null); - assertEquals("[]", set.toString()); - } - - @Test - public void testEquals() { - assertEquals(new InterfaceSet(null, "if1", "if2"), new InterfaceSet("if2", "if1")); - assertEquals(new InterfaceSet(null, null), new InterfaceSet()); - assertFalse(new InterfaceSet("if1", "if3").equals(new InterfaceSet("if1", "if2"))); - assertFalse(new InterfaceSet("if1", "if2").equals(new InterfaceSet("if1"))); - assertFalse(new InterfaceSet().equals(null)); - } -} diff --git a/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java b/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java deleted file mode 100644 index 91c7771cc7fe..000000000000 --- a/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import android.net.LinkAddress; -import android.net.TetheringRequestParcel; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.MiscAsserts; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class TetheringUtilsTest { - private static final LinkAddress TEST_SERVER_ADDR = new LinkAddress("192.168.43.1/24"); - private static final LinkAddress TEST_CLIENT_ADDR = new LinkAddress("192.168.43.5/24"); - private TetheringRequestParcel mTetheringRequest; - - @Before - public void setUp() { - mTetheringRequest = makeTetheringRequestParcel(); - } - - public TetheringRequestParcel makeTetheringRequestParcel() { - final TetheringRequestParcel request = new TetheringRequestParcel(); - request.tetheringType = TETHERING_WIFI; - request.localIPv4Address = TEST_SERVER_ADDR; - request.staticClientAddress = TEST_CLIENT_ADDR; - request.exemptFromEntitlementCheck = false; - request.showProvisioningUi = true; - return request; - } - - @Test - public void testIsTetheringRequestEquals() throws Exception { - TetheringRequestParcel request = makeTetheringRequestParcel(); - - assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, mTetheringRequest)); - assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request)); - assertTrue(TetheringUtils.isTetheringRequestEquals(null, null)); - assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, null)); - assertFalse(TetheringUtils.isTetheringRequestEquals(null, mTetheringRequest)); - - request = makeTetheringRequestParcel(); - request.tetheringType = TETHERING_USB; - assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request)); - - request = makeTetheringRequestParcel(); - request.localIPv4Address = null; - request.staticClientAddress = null; - assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request)); - - request = makeTetheringRequestParcel(); - request.exemptFromEntitlementCheck = true; - assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request)); - - request = makeTetheringRequestParcel(); - request.showProvisioningUi = false; - assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request)); - - MiscAsserts.assertFieldCountEquals(5, TetheringRequestParcel.class); - } -} diff --git a/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java b/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java deleted file mode 100644 index 5a9b6e380ea9..000000000000 --- a/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.reset; - -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.test.BroadcastInterceptingContext; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class VersionedBroadcastListenerTest { - private static final String TAG = VersionedBroadcastListenerTest.class.getSimpleName(); - private static final String ACTION_TEST = "action.test.happy.broadcasts"; - - @Mock private Context mContext; - private BroadcastInterceptingContext mServiceContext; - private Handler mHandler; - private VersionedBroadcastListener mListener; - private int mCallbackCount; - - private void doCallback() { - mCallbackCount++; - } - - private class MockContext extends BroadcastInterceptingContext { - MockContext(Context base) { - super(base); - } - } - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - if (Looper.myLooper() == null) { - Looper.prepare(); - } - } - - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - reset(mContext); - mServiceContext = new MockContext(mContext); - mHandler = new Handler(Looper.myLooper()); - mCallbackCount = 0; - final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_TEST); - mListener = new VersionedBroadcastListener( - TAG, mServiceContext, mHandler, filter, (Intent intent) -> doCallback()); - } - - @After public void tearDown() throws Exception { - if (mListener != null) { - mListener.stopListening(); - mListener = null; - } - } - - private void sendBroadcast() { - final Intent intent = new Intent(ACTION_TEST); - mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - @Test - public void testBasicListening() { - assertEquals(0, mCallbackCount); - mListener.startListening(); - for (int i = 0; i < 5; i++) { - sendBroadcast(); - assertEquals(i + 1, mCallbackCount); - } - mListener.stopListening(); - } - - @Test - public void testBroadcastsBeforeStartAreIgnored() { - assertEquals(0, mCallbackCount); - for (int i = 0; i < 5; i++) { - sendBroadcast(); - assertEquals(0, mCallbackCount); - } - - mListener.startListening(); - sendBroadcast(); - assertEquals(1, mCallbackCount); - } - - @Test - public void testBroadcastsAfterStopAreIgnored() { - mListener.startListening(); - sendBroadcast(); - assertEquals(1, mCallbackCount); - mListener.stopListening(); - - for (int i = 0; i < 5; i++) { - sendBroadcast(); - assertEquals(1, mCallbackCount); - } - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java deleted file mode 100644 index 64242ae8255f..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStats.UID_TETHERING; -import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; - -import static com.android.networkstack.tethering.BpfCoordinator.StatsType; -import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_IFACE; -import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_UID; -import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.argThat; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.usage.NetworkStatsManager; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.MacAddress; -import android.net.NetworkStats; -import android.net.TetherOffloadRuleParcel; -import android.net.TetherStatsParcel; -import android.net.ip.IpServer; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; -import com.android.testutils.TestableNetworkStatsProviderCbBinder; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class BpfCoordinatorTest { - private static final int DOWNSTREAM_IFINDEX = 10; - private static final MacAddress DOWNSTREAM_MAC = MacAddress.ALL_ZEROS_ADDRESS; - private static final InetAddress NEIGH_A = InetAddresses.parseNumericAddress("2001:db8::1"); - private static final InetAddress NEIGH_B = InetAddresses.parseNumericAddress("2001:db8::2"); - private static final MacAddress MAC_A = MacAddress.fromString("00:00:00:00:00:0a"); - private static final MacAddress MAC_B = MacAddress.fromString("11:22:33:00:00:0b"); - - @Mock private NetworkStatsManager mStatsManager; - @Mock private INetd mNetd; - @Mock private IpServer mIpServer; - @Mock private TetheringConfiguration mTetherConfig; - - // Late init since methods must be called by the thread that created this object. - private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb; - private BpfCoordinator.BpfTetherStatsProvider mTetherStatsProvider; - private final ArgumentCaptor<ArrayList> mStringArrayCaptor = - ArgumentCaptor.forClass(ArrayList.class); - private final TestLooper mTestLooper = new TestLooper(); - private BpfCoordinator.Dependencies mDeps = - new BpfCoordinator.Dependencies() { - @NonNull - public Handler getHandler() { - return new Handler(mTestLooper.getLooper()); - } - - @NonNull - public INetd getNetd() { - return mNetd; - } - - @NonNull - public NetworkStatsManager getNetworkStatsManager() { - return mStatsManager; - } - - @NonNull - public SharedLog getSharedLog() { - return new SharedLog("test"); - } - - @Nullable - public TetheringConfiguration getTetherConfig() { - return mTetherConfig; - } - }; - - @Before public void setUp() { - MockitoAnnotations.initMocks(this); - when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */); - } - - private void waitForIdle() { - mTestLooper.dispatchAll(); - } - - private void setupFunctioningNetdInterface() throws Exception { - when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]); - } - - @NonNull - private BpfCoordinator makeBpfCoordinator() throws Exception { - final BpfCoordinator coordinator = new BpfCoordinator(mDeps); - final ArgumentCaptor<BpfCoordinator.BpfTetherStatsProvider> - tetherStatsProviderCaptor = - ArgumentCaptor.forClass(BpfCoordinator.BpfTetherStatsProvider.class); - verify(mStatsManager).registerNetworkStatsProvider(anyString(), - tetherStatsProviderCaptor.capture()); - mTetherStatsProvider = tetherStatsProviderCaptor.getValue(); - assertNotNull(mTetherStatsProvider); - mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder(); - mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb); - return coordinator; - } - - @NonNull - private static NetworkStats.Entry buildTestEntry(@NonNull StatsType how, - @NonNull String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { - return new NetworkStats.Entry(iface, how == STATS_PER_IFACE ? UID_ALL : UID_TETHERING, - SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, - rxPackets, txBytes, txPackets, 0L); - } - - @NonNull - private static TetherStatsParcel buildTestTetherStatsParcel(@NonNull Integer ifIndex, - long rxBytes, long rxPackets, long txBytes, long txPackets) { - final TetherStatsParcel parcel = new TetherStatsParcel(); - parcel.ifIndex = ifIndex; - parcel.rxBytes = rxBytes; - parcel.rxPackets = rxPackets; - parcel.txBytes = txBytes; - parcel.txPackets = txPackets; - return parcel; - } - - // Set up specific tether stats list and wait for the stats cache is updated by polling thread - // in the coordinator. Beware of that it is only used for the default polling interval. - private void setTetherOffloadStatsList(TetherStatsParcel[] tetherStatsList) throws Exception { - when(mNetd.tetherOffloadGetStats()).thenReturn(tetherStatsList); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - } - - @Test - public void testGetForwardedStats() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - coordinator.startPolling(); - - final String wlanIface = "wlan0"; - final Integer wlanIfIndex = 100; - final String mobileIface = "rmnet_data0"; - final Integer mobileIfIndex = 101; - - // Add interface name to lookup table. In realistic case, the upstream interface name will - // be added by IpServer when IpServer has received with a new IPv6 upstream update event. - coordinator.addUpstreamNameToLookupTable(wlanIfIndex, wlanIface); - coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface); - - // [1] Both interface stats are changed. - // Setup the tether stats of wlan and mobile interface. Note that move forward the time of - // the looper to make sure the new tether stats has been updated by polling update thread. - setTetherOffloadStatsList(new TetherStatsParcel[] { - buildTestTetherStatsParcel(wlanIfIndex, 1000, 100, 2000, 200), - buildTestTetherStatsParcel(mobileIfIndex, 3000, 300, 4000, 400)}); - - final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, wlanIface, 1000, 100, 2000, 200)) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 3000, 300, 4000, 400)); - - final NetworkStats expectedUidStats = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, wlanIface, 1000, 100, 2000, 200)) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 3000, 300, 4000, 400)); - - // Force pushing stats update to verify the stats reported. - // TODO: Perhaps make #expectNotifyStatsUpdated to use test TetherStatsParcel object for - // verifying the notification. - mTetherStatsProvider.pushTetherStats(); - mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats); - - // [2] Only one interface stats is changed. - // The tether stats of mobile interface is accumulated and The tether stats of wlan - // interface is the same. - setTetherOffloadStatsList(new TetherStatsParcel[] { - buildTestTetherStatsParcel(wlanIfIndex, 1000, 100, 2000, 200), - buildTestTetherStatsParcel(mobileIfIndex, 3010, 320, 4030, 440)}); - - final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, wlanIface, 0, 0, 0, 0)) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 10, 20, 30, 40)); - - final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, wlanIface, 0, 0, 0, 0)) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 10, 20, 30, 40)); - - // Force pushing stats update to verify that only diff of stats is reported. - mTetherStatsProvider.pushTetherStats(); - mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff, - expectedUidStatsDiff); - - // [3] Stop coordinator. - // Shutdown the coordinator and clear the invocation history, especially the - // tetherOffloadGetStats() calls. - coordinator.stopPolling(); - clearInvocations(mNetd); - - // Verify the polling update thread stopped. - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - verify(mNetd, never()).tetherOffloadGetStats(); - } - - @Test - public void testOnSetAlert() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - coordinator.startPolling(); - - final String mobileIface = "rmnet_data0"; - final Integer mobileIfIndex = 100; - coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface); - - // Verify that set quota to 0 will immediately triggers a callback. - mTetherStatsProvider.onSetAlert(0); - waitForIdle(); - mTetherStatsProviderCb.expectNotifyAlertReached(); - - // Verify that notifyAlertReached never fired if quota is not yet reached. - when(mNetd.tetherOffloadGetStats()).thenReturn( - new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0)}); - mTetherStatsProvider.onSetAlert(100); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.assertNoCallback(); - - // Verify that notifyAlertReached fired when quota is reached. - when(mNetd.tetherOffloadGetStats()).thenReturn( - new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 50, 0, 50, 0)}); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.expectNotifyAlertReached(); - - // Verify that set quota with UNLIMITED won't trigger any callback. - mTetherStatsProvider.onSetAlert(QUOTA_UNLIMITED); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.assertNoCallback(); - } - - // The custom ArgumentMatcher simply comes from IpServerTest. - // TODO: move both of them into a common utility class for reusing the code. - private static class TetherOffloadRuleParcelMatcher implements - ArgumentMatcher<TetherOffloadRuleParcel> { - public final int upstreamIfindex; - public final int downstreamIfindex; - public final Inet6Address address; - public final MacAddress srcMac; - public final MacAddress dstMac; - - TetherOffloadRuleParcelMatcher(@NonNull Ipv6ForwardingRule rule) { - upstreamIfindex = rule.upstreamIfindex; - downstreamIfindex = rule.downstreamIfindex; - address = rule.address; - srcMac = rule.srcMac; - dstMac = rule.dstMac; - } - - public boolean matches(@NonNull TetherOffloadRuleParcel parcel) { - return upstreamIfindex == parcel.inputInterfaceIndex - && (downstreamIfindex == parcel.outputInterfaceIndex) - && Arrays.equals(address.getAddress(), parcel.destination) - && (128 == parcel.prefixLength) - && Arrays.equals(srcMac.toByteArray(), parcel.srcL2Address) - && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address); - } - - public String toString() { - return String.format("TetherOffloadRuleParcelMatcher(%d, %d, %s, %s, %s", - upstreamIfindex, downstreamIfindex, address.getHostAddress(), srcMac, dstMac); - } - } - - @NonNull - private TetherOffloadRuleParcel matches(@NonNull Ipv6ForwardingRule rule) { - return argThat(new TetherOffloadRuleParcelMatcher(rule)); - } - - @NonNull - private static Ipv6ForwardingRule buildTestForwardingRule( - int upstreamIfindex, @NonNull InetAddress address, @NonNull MacAddress dstMac) { - return new Ipv6ForwardingRule(upstreamIfindex, DOWNSTREAM_IFINDEX, (Inet6Address) address, - DOWNSTREAM_MAC, dstMac); - } - - @Test - public void testSetDataLimit() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - - final String mobileIface = "rmnet_data0"; - final Integer mobileIfIndex = 100; - coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface); - - // [1] Default limit. - // Set the unlimited quota as default if the service has never applied a data limit for a - // given upstream. Note that the data limit only be applied on an upstream which has rules. - final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A); - final InOrder inOrder = inOrder(mNetd); - coordinator.tetherOffloadRuleAdd(mIpServer, rule); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(rule)); - inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED); - inOrder.verifyNoMoreInteractions(); - - // [2] Specific limit. - // Applying the data limit boundary {min, 1gb, max, infinity} on current upstream. - for (final long quota : new long[] {0, 1048576000, Long.MAX_VALUE, QUOTA_UNLIMITED}) { - mTetherStatsProvider.onSetLimit(mobileIface, quota); - waitForIdle(); - inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, quota); - inOrder.verifyNoMoreInteractions(); - } - - // [3] Invalid limit. - // The valid range of quota is 0..max_int64 or -1 (unlimited). - final long invalidLimit = Long.MIN_VALUE; - try { - mTetherStatsProvider.onSetLimit(mobileIface, invalidLimit); - waitForIdle(); - fail("No exception thrown for invalid limit " + invalidLimit + "."); - } catch (IllegalArgumentException expected) { - assertEquals(expected.getMessage(), "invalid quota value " + invalidLimit); - } - } - - // TODO: Test the case in which the rules are changed from different IpServer objects. - @Test - public void testSetDataLimitOnRuleChange() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - - final String mobileIface = "rmnet_data0"; - final Integer mobileIfIndex = 100; - coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface); - - // Applying a data limit to the current upstream does not take any immediate action. - // The data limit could be only set on an upstream which has rules. - final long limit = 12345; - final InOrder inOrder = inOrder(mNetd); - mTetherStatsProvider.onSetLimit(mobileIface, limit); - waitForIdle(); - inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong()); - - // Adding the first rule on current upstream immediately sends the quota to netd. - final Ipv6ForwardingRule ruleA = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A); - coordinator.tetherOffloadRuleAdd(mIpServer, ruleA); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleA)); - inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, limit); - inOrder.verifyNoMoreInteractions(); - - // Adding the second rule on current upstream does not send the quota to netd. - final Ipv6ForwardingRule ruleB = buildTestForwardingRule(mobileIfIndex, NEIGH_B, MAC_B); - coordinator.tetherOffloadRuleAdd(mIpServer, ruleB); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleB)); - inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong()); - - // Removing the second rule on current upstream does not send the quota to netd. - coordinator.tetherOffloadRuleRemove(mIpServer, ruleB); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleB)); - inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong()); - - // Removing the last rule on current upstream immediately sends the cleanup stuff to netd. - when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex)) - .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0)); - coordinator.tetherOffloadRuleRemove(mIpServer, ruleA); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleA)); - inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testTetherOffloadRuleUpdateAndClear() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - - final String ethIface = "eth1"; - final String mobileIface = "rmnet_data0"; - final Integer ethIfIndex = 100; - final Integer mobileIfIndex = 101; - coordinator.addUpstreamNameToLookupTable(ethIfIndex, ethIface); - coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface); - - final InOrder inOrder = inOrder(mNetd); - - // Before the rule test, here are the additional actions while the rules are changed. - // - After adding the first rule on a given upstream, the coordinator adds a data limit. - // If the service has never applied the data limit, set an unlimited quota as default. - // - After removing the last rule on a given upstream, the coordinator gets the last stats. - // Then, it clears the stats and the limit entry from BPF maps. - // See tetherOffloadRule{Add, Remove, Clear, Clean}. - - // [1] Adding rules on the upstream Ethernet. - // Note that the default data limit is applied after the first rule is added. - final Ipv6ForwardingRule ethernetRuleA = buildTestForwardingRule( - ethIfIndex, NEIGH_A, MAC_A); - final Ipv6ForwardingRule ethernetRuleB = buildTestForwardingRule( - ethIfIndex, NEIGH_B, MAC_B); - - coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleA); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleA)); - inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(ethIfIndex, QUOTA_UNLIMITED); - - coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleB); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleB)); - - // [2] Update the existing rules from Ethernet to cellular. - final Ipv6ForwardingRule mobileRuleA = buildTestForwardingRule( - mobileIfIndex, NEIGH_A, MAC_A); - final Ipv6ForwardingRule mobileRuleB = buildTestForwardingRule( - mobileIfIndex, NEIGH_B, MAC_B); - when(mNetd.tetherOffloadGetAndClearStats(ethIfIndex)) - .thenReturn(buildTestTetherStatsParcel(ethIfIndex, 10, 20, 30, 40)); - - // Update the existing rules for upstream changes. The rules are removed and re-added one - // by one for updating upstream interface index by #tetherOffloadRuleUpdate. - coordinator.tetherOffloadRuleUpdate(mIpServer, mobileIfIndex); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleA)); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleA)); - inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleB)); - inOrder.verify(mNetd).tetherOffloadGetAndClearStats(ethIfIndex); - inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleB)); - - // [3] Clear all rules for a given IpServer. - when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex)) - .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 50, 60, 70, 80)); - coordinator.tetherOffloadRuleClear(mIpServer); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleA)); - inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleB)); - inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex); - - // [4] Force pushing stats update to verify that the last diff of stats is reported on all - // upstreams. - mTetherStatsProvider.pushTetherStats(); - mTetherStatsProviderCb.expectNotifyStatsUpdated( - new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, ethIface, 10, 20, 30, 40)) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 50, 60, 70, 80)), - new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, ethIface, 10, 20, 30, 40)) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 50, 60, 70, 80))); - } - - @Test - public void testTetheringConfigDisable() throws Exception { - setupFunctioningNetdInterface(); - when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(false); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - coordinator.startPolling(); - - // The tether stats polling task should not be scheduled. - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - verify(mNetd, never()).tetherOffloadGetStats(); - - // The interface name lookup table can't be added. - final String iface = "rmnet_data0"; - final Integer ifIndex = 100; - coordinator.addUpstreamNameToLookupTable(ifIndex, iface); - assertEquals(0, coordinator.getInterfaceNamesForTesting().size()); - - // The rule can't be added. - final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1"); - final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a"); - final Ipv6ForwardingRule rule = buildTestForwardingRule(ifIndex, neigh, mac); - coordinator.tetherOffloadRuleAdd(mIpServer, rule); - verify(mNetd, never()).tetherOffloadRuleAdd(any()); - LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = - coordinator.getForwardingRulesForTesting().get(mIpServer); - assertNull(rules); - - // The rule can't be removed. This is not a realistic case because adding rule is not - // allowed. That implies no rule could be removed, cleared or updated. Verify these - // cases just in case. - rules = new LinkedHashMap<Inet6Address, Ipv6ForwardingRule>(); - rules.put(rule.address, rule); - coordinator.getForwardingRulesForTesting().put(mIpServer, rules); - coordinator.tetherOffloadRuleRemove(mIpServer, rule); - verify(mNetd, never()).tetherOffloadRuleRemove(any()); - rules = coordinator.getForwardingRulesForTesting().get(mIpServer); - assertNotNull(rules); - assertEquals(1, rules.size()); - - // The rule can't be cleared. - coordinator.tetherOffloadRuleClear(mIpServer); - verify(mNetd, never()).tetherOffloadRuleRemove(any()); - rules = coordinator.getForwardingRulesForTesting().get(mIpServer); - assertNotNull(rules); - assertEquals(1, rules.size()); - - // The rule can't be updated. - coordinator.tetherOffloadRuleUpdate(mIpServer, rule.upstreamIfindex + 1 /* new */); - verify(mNetd, never()).tetherOffloadRuleRemove(any()); - verify(mNetd, never()).tetherOffloadRuleAdd(any()); - rules = coordinator.getForwardingRulesForTesting().get(mIpServer); - assertNotNull(rules); - assertEquals(1, rules.size()); - } - - @Test - public void testTetheringConfigSetPollingInterval() throws Exception { - setupFunctioningNetdInterface(); - - final BpfCoordinator coordinator = makeBpfCoordinator(); - - // [1] The default polling interval. - coordinator.startPolling(); - assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval()); - coordinator.stopPolling(); - - // [2] Expect the invalid polling interval isn't applied. The valid range of interval is - // DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long. - for (final int interval - : new int[] {0, 100, DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS - 1}) { - when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval); - coordinator.startPolling(); - assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval()); - coordinator.stopPolling(); - } - - // [3] Set a specific polling interval which is larger than default value. - // Use a large polling interval to avoid flaky test because the time forwarding - // approximation is used to verify the scheduled time of the polling thread. - final int pollingInterval = 100_000; - when(mTetherConfig.getOffloadPollInterval()).thenReturn(pollingInterval); - coordinator.startPolling(); - - // Expect the specific polling interval to be applied. - assertEquals(pollingInterval, coordinator.getPollingInterval()); - - // Start on a new polling time slot. - mTestLooper.moveTimeForward(pollingInterval); - waitForIdle(); - clearInvocations(mNetd); - - // Move time forward to 90% polling interval time. Expect that the polling thread has not - // scheduled yet. - mTestLooper.moveTimeForward((long) (pollingInterval * 0.9)); - waitForIdle(); - verify(mNetd, never()).tetherOffloadGetStats(); - - // Move time forward to the remaining 10% polling interval time. Expect that the polling - // thread has scheduled. - mTestLooper.moveTimeForward((long) (pollingInterval * 0.1)); - waitForIdle(); - verify(mNetd).tetherOffloadGetStats(); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt deleted file mode 100644 index d915354b0c37..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering - -import android.net.LinkAddress -import android.net.MacAddress -import android.net.TetheredClient -import android.net.TetheredClient.AddressInfo -import android.net.TetheringManager.TETHERING_USB -import android.net.TetheringManager.TETHERING_WIFI -import android.net.ip.IpServer -import android.net.wifi.WifiClient -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -@RunWith(AndroidJUnit4::class) -@SmallTest -class ConnectedClientsTrackerTest { - - private val server1 = mock(IpServer::class.java) - private val server2 = mock(IpServer::class.java) - private val servers = listOf(server1, server2) - - private val clock = TestClock(1324L) - - private val client1Addr = MacAddress.fromString("01:23:45:67:89:0A") - private val client1 = TetheredClient(client1Addr, listOf( - makeAddrInfo("192.168.43.44/32", null /* hostname */, clock.time + 20)), - TETHERING_WIFI) - private val wifiClient1 = makeWifiClient(client1Addr) - private val client2Addr = MacAddress.fromString("02:34:56:78:90:AB") - private val client2Exp30AddrInfo = makeAddrInfo( - "192.168.43.45/32", "my_hostname", clock.time + 30) - private val client2 = TetheredClient(client2Addr, listOf( - client2Exp30AddrInfo, - makeAddrInfo("2001:db8:12::34/72", "other_hostname", clock.time + 10)), - TETHERING_WIFI) - private val wifiClient2 = makeWifiClient(client2Addr) - private val client3Addr = MacAddress.fromString("03:45:67:89:0A:BC") - private val client3 = TetheredClient(client3Addr, - listOf(makeAddrInfo("2001:db8:34::34/72", "other_other_hostname", clock.time + 10)), - TETHERING_USB) - - private fun makeAddrInfo(addr: String, hostname: String?, expTime: Long) = - LinkAddress(addr).let { - AddressInfo(LinkAddress(it.address, it.prefixLength, it.flags, it.scope, - expTime /* deprecationTime */, expTime /* expirationTime */), hostname) - } - - @Test - fun testUpdateConnectedClients() { - doReturn(emptyList<TetheredClient>()).`when`(server1).allLeases - doReturn(emptyList<TetheredClient>()).`when`(server2).allLeases - - val tracker = ConnectedClientsTracker(clock) - assertFalse(tracker.updateConnectedClients(servers, null)) - - // Obtain a lease for client 1 - doReturn(listOf(client1)).`when`(server1).allLeases - assertSameClients(listOf(client1), assertNewClients(tracker, servers, listOf(wifiClient1))) - - // Client 2 L2-connected, no lease yet - val client2WithoutAddr = TetheredClient(client2Addr, emptyList(), TETHERING_WIFI) - assertSameClients(listOf(client1, client2WithoutAddr), - assertNewClients(tracker, servers, listOf(wifiClient1, wifiClient2))) - - // Client 2 lease obtained - doReturn(listOf(client1, client2)).`when`(server1).allLeases - assertSameClients(listOf(client1, client2), assertNewClients(tracker, servers, null)) - - // Client 3 lease obtained - doReturn(listOf(client3)).`when`(server2).allLeases - assertSameClients(listOf(client1, client2, client3), - assertNewClients(tracker, servers, null)) - - // Client 2 L2-disconnected - assertSameClients(listOf(client1, client3), - assertNewClients(tracker, servers, listOf(wifiClient1))) - - // Client 1 L2-disconnected - assertSameClients(listOf(client3), assertNewClients(tracker, servers, emptyList())) - - // Client 1 comes back - assertSameClients(listOf(client1, client3), - assertNewClients(tracker, servers, listOf(wifiClient1))) - - // Leases lost, client 1 still L2-connected - doReturn(emptyList<TetheredClient>()).`when`(server1).allLeases - doReturn(emptyList<TetheredClient>()).`when`(server2).allLeases - assertSameClients(listOf(TetheredClient(client1Addr, emptyList(), TETHERING_WIFI)), - assertNewClients(tracker, servers, null)) - } - - @Test - fun testUpdateConnectedClients_LeaseExpiration() { - val tracker = ConnectedClientsTracker(clock) - doReturn(listOf(client1, client2)).`when`(server1).allLeases - doReturn(listOf(client3)).`when`(server2).allLeases - assertSameClients(listOf(client1, client2, client3), assertNewClients( - tracker, servers, listOf(wifiClient1, wifiClient2))) - - clock.time += 20 - // Client 3 has no remaining lease: removed - val expectedClients = listOf( - // Client 1 has no remaining lease but is L2-connected - TetheredClient(client1Addr, emptyList(), TETHERING_WIFI), - // Client 2 has some expired leases - TetheredClient( - client2Addr, - // Only the "t + 30" address is left, the "t + 10" address expired - listOf(client2Exp30AddrInfo), - TETHERING_WIFI)) - assertSameClients(expectedClients, assertNewClients(tracker, servers, null)) - } - - private fun assertNewClients( - tracker: ConnectedClientsTracker, - ipServers: Iterable<IpServer>, - wifiClients: List<WifiClient>? - ): List<TetheredClient> { - assertTrue(tracker.updateConnectedClients(ipServers, wifiClients)) - return tracker.lastTetheredClients - } - - private fun assertSameClients(expected: List<TetheredClient>, actual: List<TetheredClient>) { - val expectedSet = HashSet(expected) - assertEquals(expected.size, expectedSet.size) - assertEquals(expectedSet, HashSet(actual)) - } - - private fun makeWifiClient(macAddr: MacAddress): WifiClient { - // Use a mock WifiClient as the constructor is not part of the WiFi module exported API. - return mock(WifiClient::class.java).apply { doReturn(macAddr).`when`(this).macAddress } - } - - private class TestClock(var time: Long) : ConnectedClientsTracker.Clock() { - override fun elapsedRealtime(): Long { - return time - } - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java deleted file mode 100644 index 354e75356e9f..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE; -import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK; -import static android.net.TetheringConstants.EXTRA_RUN_PROVISION; -import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE; -import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION; -import static android.net.TetheringConstants.EXTRA_TETHER_SUBID; -import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME; -import static android.net.TetheringManager.TETHERING_BLUETOOTH; -import static android.net.TetheringManager.TETHERING_ETHERNET; -import static android.net.TetheringManager.TETHERING_INVALID; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; -import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.util.SharedLog; -import android.os.Bundle; -import android.os.Handler; -import android.os.PersistableBundle; -import android.os.ResultReceiver; -import android.os.SystemProperties; -import android.os.test.TestLooper; -import android.provider.DeviceConfig; -import android.provider.Settings; -import android.telephony.CarrierConfigManager; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.test.BroadcastInterceptingContext; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public final class EntitlementManagerTest { - - private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; - private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; - private static final String PROVISIONING_APP_RESPONSE = "app_response"; - - @Mock private CarrierConfigManager mCarrierConfigManager; - @Mock private Context mContext; - @Mock private Resources mResources; - @Mock private SharedLog mLog; - @Mock private EntitlementManager.OnUiEntitlementFailedListener mEntitlementFailedListener; - - // Like so many Android system APIs, these cannot be mocked because it is marked final. - // We have to use the real versions. - private final PersistableBundle mCarrierConfig = new PersistableBundle(); - private final TestLooper mLooper = new TestLooper(); - private Context mMockContext; - private Runnable mPermissionChangeCallback; - - private WrappedEntitlementManager mEnMgr; - private TetheringConfiguration mConfig; - private MockitoSession mMockingSession; - - private class MockContext extends BroadcastInterceptingContext { - MockContext(Context base) { - super(base); - } - - @Override - public Resources getResources() { - return mResources; - } - } - - public class WrappedEntitlementManager extends EntitlementManager { - public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN; - public int uiProvisionCount = 0; - public int silentProvisionCount = 0; - - public WrappedEntitlementManager(Context ctx, Handler h, SharedLog log, - Runnable callback) { - super(ctx, h, log, callback); - } - - public void reset() { - fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN; - uiProvisionCount = 0; - silentProvisionCount = 0; - } - - @Override - protected Intent runUiTetherProvisioning(int type, - final TetheringConfiguration config, final ResultReceiver receiver) { - Intent intent = super.runUiTetherProvisioning(type, config, receiver); - assertUiTetherProvisioningIntent(type, config, receiver, intent); - uiProvisionCount++; - receiver.send(fakeEntitlementResult, null); - return intent; - } - - private void assertUiTetherProvisioningIntent(int type, final TetheringConfiguration config, - final ResultReceiver receiver, final Intent intent) { - assertEquals(Settings.ACTION_TETHER_PROVISIONING_UI, intent.getAction()); - assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID)); - final String[] appName = intent.getStringArrayExtra( - EXTRA_TETHER_UI_PROVISIONING_APP_NAME); - assertEquals(PROVISIONING_APP_NAME.length, appName.length); - for (int i = 0; i < PROVISIONING_APP_NAME.length; i++) { - assertEquals(PROVISIONING_APP_NAME[i], appName[i]); - } - assertEquals(receiver, intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK)); - assertEquals(config.activeDataSubId, - intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID)); - } - - @Override - protected Intent runSilentTetherProvisioning(int type, - final TetheringConfiguration config) { - Intent intent = super.runSilentTetherProvisioning(type, config); - assertSilentTetherProvisioning(type, config, intent); - silentProvisionCount++; - addDownstreamMapping(type, fakeEntitlementResult); - return intent; - } - - private void assertSilentTetherProvisioning(int type, final TetheringConfiguration config, - final Intent intent) { - assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID)); - assertEquals(true, intent.getBooleanExtra(EXTRA_RUN_PROVISION, false)); - assertEquals(PROVISIONING_NO_UI_APP_NAME, - intent.getStringExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION)); - assertEquals(PROVISIONING_APP_RESPONSE, - intent.getStringExtra(EXTRA_TETHER_PROVISIONING_RESPONSE)); - assertTrue(intent.hasExtra(EXTRA_PROVISION_CALLBACK)); - assertEquals(config.activeDataSubId, - intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID)); - } - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mMockingSession = mockitoSession() - .initMocks(this) - .mockStatic(SystemProperties.class) - .mockStatic(DeviceConfig.class) - .strictness(Strictness.WARN) - .startMocking(); - // Don't disable tethering provisioning unless requested. - doReturn(false).when( - () -> SystemProperties.getBoolean( - eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean())); - doReturn(null).when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), anyString())); - - when(mResources.getStringArray(R.array.config_tether_dhcp_range)) - .thenReturn(new String[0]); - when(mResources.getStringArray(R.array.config_tether_usb_regexs)) - .thenReturn(new String[0]); - when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) - .thenReturn(new String[0]); - when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) - .thenReturn(new String[0]); - when(mResources.getIntArray(R.array.config_tether_upstream_types)) - .thenReturn(new int[0]); - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - false); - when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn(""); - when(mLog.forSubComponent(anyString())).thenReturn(mLog); - - mMockContext = new MockContext(mContext); - mPermissionChangeCallback = spy(() -> { }); - mEnMgr = new WrappedEntitlementManager(mMockContext, new Handler(mLooper.getLooper()), mLog, - mPermissionChangeCallback); - mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - mEnMgr.setTetheringConfigurationFetcher(() -> { - return mConfig; - }); - } - - @After - public void tearDown() throws Exception { - mMockingSession.finishMocking(); - } - - private void setupForRequiredProvisioning() { - // Produce some acceptable looking provision app setting if requested. - when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) - .thenReturn(PROVISIONING_APP_NAME); - when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui)) - .thenReturn(PROVISIONING_NO_UI_APP_NAME); - when(mResources.getString(R.string.config_mobile_hotspot_provision_response)).thenReturn( - PROVISIONING_APP_RESPONSE); - // Act like the CarrierConfigManager is present and ready unless told otherwise. - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(mCarrierConfigManager); - when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig); - mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); - mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - } - - @Test - public void canRequireProvisioning() { - setupForRequiredProvisioning(); - assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig)); - } - - @Test - public void toleratesCarrierConfigManagerMissing() { - setupForRequiredProvisioning(); - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(null); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - // Couldn't get the CarrierConfigManager, but still had a declared provisioning app. - // Therefore provisioning still be required. - assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig)); - } - - @Test - public void toleratesCarrierConfigMissing() { - setupForRequiredProvisioning(); - when(mCarrierConfigManager.getConfig()).thenReturn(null); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - // We still have a provisioning app configured, so still require provisioning. - assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig)); - } - - @Test - public void toleratesCarrierConfigNotLoaded() { - setupForRequiredProvisioning(); - mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false); - // We still have a provisioning app configured, so still require provisioning. - assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig)); - } - - @Test - public void provisioningNotRequiredWhenAppNotFound() { - setupForRequiredProvisioning(); - when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) - .thenReturn(null); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig)); - when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) - .thenReturn(new String[] {"malformedApp"}); - mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig)); - } - - @Test - public void testRequestLastEntitlementCacheValue() throws Exception { - // 1. Entitlement check is not required. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - ResultReceiver receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_NO_ERROR, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - - setupForRequiredProvisioning(); - // 2. No cache value and don't need to run entitlement check. - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 3. No cache value and ui entitlement check is needed. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 4. Cache value is TETHER_ERROR_PROVISIONING_FAILED and don't need to run entitlement - // check. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 5. Cache value is TETHER_ERROR_PROVISIONING_FAILED and ui entitlement check is needed. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_NO_ERROR, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 6. Cache value is TETHER_ERROR_NO_ERROR. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_NO_ERROR, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 7. Test get value for other downstream type. - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_USB, receiver, false); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - // 8. Test get value for invalid downstream type. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode); - } - }; - mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI_P2P, receiver, true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - mEnMgr.reset(); - } - - private void assertPermissionChangeCallback(InOrder inOrder) { - inOrder.verify(mPermissionChangeCallback, times(1)).run(); - } - - private void assertNoPermissionChange(InOrder inOrder) { - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void verifyPermissionResult() { - final InOrder inOrder = inOrder(mPermissionChangeCallback); - setupForRequiredProvisioning(); - mEnMgr.notifyUpstream(true); - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); - mLooper.dispatchAll(); - // Permitted: true -> false - assertPermissionChangeCallback(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); - mLooper.dispatchAll(); - // Permitted: false -> false - assertNoPermissionChange(inOrder); - - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); - mLooper.dispatchAll(); - // Permitted: false -> true - assertPermissionChangeCallback(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - } - - @Test - public void verifyPermissionIfAllNotApproved() { - final InOrder inOrder = inOrder(mPermissionChangeCallback); - setupForRequiredProvisioning(); - mEnMgr.notifyUpstream(true); - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); - mLooper.dispatchAll(); - // Permitted: true -> false - assertPermissionChangeCallback(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); - mLooper.dispatchAll(); - // Permitted: false -> false - assertNoPermissionChange(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); - mLooper.dispatchAll(); - // Permitted: false -> false - assertNoPermissionChange(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - } - - @Test - public void verifyPermissionIfAnyApproved() { - final InOrder inOrder = inOrder(mPermissionChangeCallback); - setupForRequiredProvisioning(); - mEnMgr.notifyUpstream(true); - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); - mLooper.dispatchAll(); - // Permitted: true -> true - assertNoPermissionChange(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); - mLooper.dispatchAll(); - // Permitted: true -> true - assertNoPermissionChange(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); - mLooper.dispatchAll(); - // Permitted: true -> false - assertPermissionChangeCallback(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - } - - @Test - public void verifyPermissionWhenProvisioningNotStarted() { - final InOrder inOrder = inOrder(mPermissionChangeCallback); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - assertNoPermissionChange(inOrder); - setupForRequiredProvisioning(); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - assertNoPermissionChange(inOrder); - } - - @Test - public void testRunTetherProvisioning() { - final InOrder inOrder = inOrder(mPermissionChangeCallback); - setupForRequiredProvisioning(); - // 1. start ui provisioning, upstream is mobile - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.notifyUpstream(true); - mLooper.dispatchAll(); - mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - // Permitted: true -> true - assertNoPermissionChange(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - mEnMgr.reset(); - - // 2. start no-ui provisioning - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - assertEquals(1, mEnMgr.silentProvisionCount); - // Permitted: true -> true - assertNoPermissionChange(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - mEnMgr.reset(); - - // 3. tear down mobile, then start ui provisioning - mEnMgr.notifyUpstream(false); - mLooper.dispatchAll(); - mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - assertNoPermissionChange(inOrder); - mEnMgr.reset(); - - // 4. switch upstream back to mobile - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.notifyUpstream(true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - // Permitted: true -> true - assertNoPermissionChange(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - mEnMgr.reset(); - - // 5. tear down mobile, then switch SIM - mEnMgr.notifyUpstream(false); - mLooper.dispatchAll(); - mEnMgr.reevaluateSimCardProvisioning(mConfig); - assertEquals(0, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - assertNoPermissionChange(inOrder); - mEnMgr.reset(); - - // 6. switch upstream back to mobile again - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.notifyUpstream(true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - assertEquals(3, mEnMgr.silentProvisionCount); - // Permitted: true -> false - assertPermissionChangeCallback(inOrder); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - mEnMgr.reset(); - - // 7. start ui provisioning, upstream is mobile, downstream is ethernet - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - // Permitted: false -> true - assertPermissionChangeCallback(inOrder); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - mEnMgr.reset(); - - // 8. downstream is invalid - mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true); - mLooper.dispatchAll(); - assertEquals(0, mEnMgr.uiProvisionCount); - assertEquals(0, mEnMgr.silentProvisionCount); - assertNoPermissionChange(inOrder); - mEnMgr.reset(); - } - - @Test - public void testCallStopTetheringWhenUiProvisioningFail() { - setupForRequiredProvisioning(); - verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI); - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.notifyUpstream(true); - mLooper.dispatchAll(); - mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); - mLooper.dispatchAll(); - assertEquals(1, mEnMgr.uiProvisionCount); - verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); - } - - @Test - public void testsetExemptedDownstreamType() throws Exception { - setupForRequiredProvisioning(); - // Cellular upstream is not permitted when no entitlement result. - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - - // If there is exempted downstream and no other non-exempted downstreams, cellular is - // permitted. - mEnMgr.setExemptedDownstreamType(TETHERING_WIFI); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - - // If second downstream run entitlement check fail, cellular upstream is not permitted. - mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; - mEnMgr.notifyUpstream(true); - mLooper.dispatchAll(); - mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); - mLooper.dispatchAll(); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - - // When second downstream is down, exempted downstream can use cellular upstream. - assertEquals(1, mEnMgr.uiProvisionCount); - verify(mEntitlementFailedListener).onUiEntitlementFailed(TETHERING_USB); - mEnMgr.stopProvisioningIfNeeded(TETHERING_USB); - assertTrue(mEnMgr.isCellularUpstreamPermitted()); - - mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); - assertFalse(mEnMgr.isCellularUpstreamPermitted()); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java deleted file mode 100644 index f2b5314e5a17..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.RouteInfo.RTN_UNICAST; -import static android.net.ip.IpServer.STATE_LOCAL_ONLY; -import static android.net.ip.IpServer.STATE_TETHERED; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.net.InetAddresses; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.RouteInfo; -import android.net.ip.IpServer; -import android.net.util.SharedLog; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IPv6TetheringCoordinatorTest { - private static final String TEST_DNS_SERVER = "2001:4860:4860::8888"; - private static final String TEST_INTERFACE = "test_rmnet0"; - private static final String TEST_IPV6_ADDRESS = "2001:db8::1/64"; - private static final String TEST_IPV4_ADDRESS = "192.168.100.1/24"; - - private IPv6TetheringCoordinator mIPv6TetheringCoordinator; - private ArrayList<IpServer> mNotifyList; - - @Mock private SharedLog mSharedLog; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog); - mNotifyList = new ArrayList<IpServer>(); - mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mSharedLog); - } - - private UpstreamNetworkState createDualStackUpstream(final int transportType) { - final Network network = mock(Network.class); - final NetworkCapabilities netCap = - new NetworkCapabilities.Builder().addTransportType(transportType).build(); - final InetAddress dns = InetAddresses.parseNumericAddress(TEST_DNS_SERVER); - final LinkProperties linkProp = new LinkProperties(); - linkProp.setInterfaceName(TEST_INTERFACE); - linkProp.addLinkAddress(new LinkAddress(TEST_IPV6_ADDRESS)); - linkProp.addLinkAddress(new LinkAddress(TEST_IPV4_ADDRESS)); - linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, TEST_INTERFACE, RTN_UNICAST)); - linkProp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, TEST_INTERFACE, - RTN_UNICAST)); - linkProp.addDnsServer(dns); - return new UpstreamNetworkState(linkProp, netCap, network); - } - - private void assertOnlyOneV6AddressAndNoV4(LinkProperties lp) { - assertEquals(lp.getInterfaceName(), TEST_INTERFACE); - assertFalse(lp.hasIpv4Address()); - final List<LinkAddress> addresses = lp.getLinkAddresses(); - assertEquals(addresses.size(), 1); - final LinkAddress v6Address = addresses.get(0); - assertEquals(v6Address, new LinkAddress(TEST_IPV6_ADDRESS)); - } - - @Test - public void testUpdateIpv6Upstream() throws Exception { - // 1. Add first IpServer. - final IpServer firstServer = mock(IpServer.class); - mNotifyList.add(firstServer); - mIPv6TetheringCoordinator.addActiveDownstream(firstServer, STATE_TETHERED); - verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); - verifyNoMoreInteractions(firstServer); - - // 2. Add second IpServer and it would not have ipv6 tethering. - final IpServer secondServer = mock(IpServer.class); - mNotifyList.add(secondServer); - mIPv6TetheringCoordinator.addActiveDownstream(secondServer, STATE_LOCAL_ONLY); - verifyNoMoreInteractions(secondServer); - reset(firstServer, secondServer); - - // 3. No upstream. - mIPv6TetheringCoordinator.updateUpstreamNetworkState(null); - verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); - reset(firstServer, secondServer); - - // 4. Update ipv6 mobile upstream. - final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR); - final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class); - mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream); - verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), - lp.capture()); - final LinkProperties v6OnlyLink = lp.getValue(); - assertOnlyOneV6AddressAndNoV4(v6OnlyLink); - verifyNoMoreInteractions(firstServer); - verifyNoMoreInteractions(secondServer); - reset(firstServer, secondServer); - - // 5. Remove first IpServer. - mNotifyList.remove(firstServer); - mIPv6TetheringCoordinator.removeActiveDownstream(firstServer); - verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); - verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), - lp.capture()); - final LinkProperties localOnlyLink = lp.getValue(); - assertNotNull(localOnlyLink); - assertNotEquals(localOnlyLink, v6OnlyLink); - reset(firstServer, secondServer); - - // 6. Remove second IpServer. - mNotifyList.remove(secondServer); - mIPv6TetheringCoordinator.removeActiveDownstream(secondServer); - verifyNoMoreInteractions(firstServer); - verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java deleted file mode 100644 index 071a290e657b..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.networkstack.tethering; - -import static android.Manifest.permission.WRITE_SETTINGS; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - -import static org.mockito.Mockito.mock; - -import android.content.Context; -import android.content.Intent; -import android.net.ITetheringConnector; -import android.os.Binder; -import android.os.IBinder; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -public class MockTetheringService extends TetheringService { - private final Tethering mTethering = mock(Tethering.class); - - @Override - public IBinder onBind(Intent intent) { - return new MockTetheringConnector(super.onBind(intent)); - } - - @Override - public Tethering makeTethering(TetheringDependencies deps) { - return mTethering; - } - - @Override - boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, - @NonNull String callingPackage, @Nullable String callingAttributionTag, - boolean throwException) { - // Test this does not verify the calling package / UID, as calling package could be shell - // and not match the UID. - return context.checkCallingOrSelfPermission(WRITE_SETTINGS) == PERMISSION_GRANTED; - } - - public Tethering getTethering() { - return mTethering; - } - - public class MockTetheringConnector extends Binder { - final IBinder mBase; - MockTetheringConnector(IBinder base) { - mBase = base; - } - - public ITetheringConnector getTetheringConnector() { - return ITetheringConnector.Stub.asInterface(mBase); - } - - public MockTetheringService getService() { - return MockTetheringService.this; - } - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java deleted file mode 100644 index ce52ae22ece8..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStats.UID_TETHERING; -import static android.net.RouteInfo.RTN_UNICAST; -import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; - -import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE; -import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID; -import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats; -import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; -import static com.android.testutils.MiscAsserts.assertContainsAll; -import static com.android.testutils.MiscAsserts.assertThrows; -import static com.android.testutils.NetworkStatsUtilsKt.assertNetworkStatsEquals; - -import static junit.framework.Assert.assertNotNull; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.app.usage.NetworkStatsManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.net.ITetheringStatsProvider; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.NetworkStats; -import android.net.NetworkStats.Entry; -import android.net.RouteInfo; -import android.net.netstats.provider.NetworkStatsProvider; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.test.TestLooper; -import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; -import android.test.mock.MockContentResolver; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.testutils.TestableNetworkStatsProviderCbBinder; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class OffloadControllerTest { - private static final String RNDIS0 = "test_rndis0"; - private static final String RMNET0 = "test_rmnet_data0"; - private static final String WLAN0 = "test_wlan0"; - - private static final String IPV6_LINKLOCAL = "fe80::/64"; - private static final String IPV6_DOC_PREFIX = "2001:db8::/64"; - private static final String IPV6_DISCARD_PREFIX = "100::/64"; - private static final String USB_PREFIX = "192.168.42.0/24"; - private static final String WIFI_PREFIX = "192.168.43.0/24"; - private static final long WAIT_FOR_IDLE_TIMEOUT = 2 * 1000; - - @Mock private OffloadHardwareInterface mHardware; - @Mock private ApplicationInfo mApplicationInfo; - @Mock private Context mContext; - @Mock private NetworkStatsManager mStatsManager; - @Mock private TetheringConfiguration mTetherConfig; - // Late init since methods must be called by the thread that created this object. - private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb; - private OffloadController.OffloadTetheringStatsProvider mTetherStatsProvider; - private final ArgumentCaptor<ArrayList> mStringArrayCaptor = - ArgumentCaptor.forClass(ArrayList.class); - private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor = - ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class); - private MockContentResolver mContentResolver; - private final TestLooper mTestLooper = new TestLooper(); - private OffloadController.Dependencies mDeps = new OffloadController.Dependencies() { - @Override - public TetheringConfiguration getTetherConfig() { - return mTetherConfig; - } - }; - - @Before public void setUp() { - MockitoAnnotations.initMocks(this); - when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); - when(mContext.getPackageName()).thenReturn("OffloadControllerTest"); - mContentResolver = new MockContentResolver(mContext); - mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); - when(mContext.getContentResolver()).thenReturn(mContentResolver); - FakeSettingsProvider.clearSettingsProvider(); - when(mTetherConfig.getOffloadPollInterval()).thenReturn(-1); // Disabled. - } - - @After public void tearDown() throws Exception { - FakeSettingsProvider.clearSettingsProvider(); - } - - private void setupFunctioningHardwareInterface() { - when(mHardware.initOffloadConfig()).thenReturn(true); - when(mHardware.initOffloadControl(mControlCallbackCaptor.capture())) - .thenReturn(true); - when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true); - when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats()); - when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true); - } - - private void enableOffload() { - Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); - } - - private void setOffloadPollInterval(int interval) { - when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval); - } - - private void waitForIdle() { - mTestLooper.dispatchAll(); - } - - private OffloadController makeOffloadController() throws Exception { - OffloadController offload = new OffloadController(new Handler(mTestLooper.getLooper()), - mHardware, mContentResolver, mStatsManager, new SharedLog("test"), mDeps); - final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider> - tetherStatsProviderCaptor = - ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class); - verify(mStatsManager).registerNetworkStatsProvider(anyString(), - tetherStatsProviderCaptor.capture()); - mTetherStatsProvider = tetherStatsProviderCaptor.getValue(); - assertNotNull(mTetherStatsProvider); - mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder(); - mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb); - return offload; - } - - @Test - public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception { - setupFunctioningHardwareInterface(); - when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1); - assertThrows(SettingNotFoundException.class, () -> - Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled(); - inOrder.verify(mHardware, never()).initOffloadConfig(); - inOrder.verify(mHardware, never()).initOffloadControl( - any(OffloadHardwareInterface.ControlCallback.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception { - setupFunctioningHardwareInterface(); - when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0); - assertThrows(SettingNotFoundException.class, () -> - Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled(); - inOrder.verify(mHardware, times(1)).initOffloadConfig(); - inOrder.verify(mHardware, times(1)).initOffloadControl( - any(OffloadHardwareInterface.ControlCallback.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testSettingsAllowsStart() throws Exception { - setupFunctioningHardwareInterface(); - Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled(); - inOrder.verify(mHardware, times(1)).initOffloadConfig(); - inOrder.verify(mHardware, times(1)).initOffloadControl( - any(OffloadHardwareInterface.ControlCallback.class)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testSettingsDisablesStart() throws Exception { - setupFunctioningHardwareInterface(); - Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled(); - inOrder.verify(mHardware, never()).initOffloadConfig(); - inOrder.verify(mHardware, never()).initOffloadControl(anyObject()); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testSetUpstreamLinkPropertiesWorking() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled(); - inOrder.verify(mHardware, times(1)).initOffloadConfig(); - inOrder.verify(mHardware, times(1)).initOffloadControl( - any(OffloadHardwareInterface.ControlCallback.class)); - inOrder.verifyNoMoreInteractions(); - - // In reality, the UpstreamNetworkMonitor would have passed down to us - // a covering set of local prefixes representing a minimum essential - // set plus all the prefixes on networks with network agents. - // - // We simulate that there, and then add upstream elements one by one - // and watch what happens. - final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>(); - for (String s : new String[]{ - "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) { - minimumLocalPrefixes.add(new IpPrefix(s)); - } - offload.setLocalPrefixes(minimumLocalPrefixes); - inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); - ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); - assertEquals(4, localPrefixes.size()); - assertContainsAll(localPrefixes, - "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); - inOrder.verifyNoMoreInteractions(); - - offload.setUpstreamLinkProperties(null); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - // This LinkProperties value does not differ from the default upstream. - // There should be no extraneous call to setUpstreamParameters(). - inOrder.verify(mHardware, never()).setUpstreamParameters( - anyObject(), anyObject(), anyObject(), anyObject()); - inOrder.verifyNoMoreInteractions(); - - final LinkProperties lp = new LinkProperties(); - - final String testIfName = "rmnet_data17"; - lp.setInterfaceName(testIfName); - offload.setUpstreamLinkProperties(lp); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(null), eq(null), eq(null)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - final String ipv4Addr = "192.0.2.5"; - final String linkAddr = ipv4Addr + "/24"; - lp.addLinkAddress(new LinkAddress(linkAddr)); - lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, null, RTN_UNICAST)); - offload.setUpstreamLinkProperties(lp); - // IPv4 prefixes and addresses on the upstream are simply left as whole - // prefixes (already passed in from UpstreamNetworkMonitor code). If a - // tethering client sends traffic to the IPv4 default router or other - // clients on the upstream this will not be hardware-forwarded, and that - // should be fine for now. Ergo: no change in local addresses, no call - // to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(null), eq(null)); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - final String ipv4Gateway = "192.0.2.1"; - lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv4Gateway), null, RTN_UNICAST)); - offload.setUpstreamLinkProperties(lp); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), eq(null)); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - final String ipv6Gw1 = "fe80::cafe"; - lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw1), null, RTN_UNICAST)); - offload.setUpstreamLinkProperties(lp); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - ArrayList<String> v6gws = mStringArrayCaptor.getValue(); - assertEquals(1, v6gws.size()); - assertTrue(v6gws.contains(ipv6Gw1)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - final String ipv6Gw2 = "fe80::d00d"; - lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw2), null, RTN_UNICAST)); - offload.setUpstreamLinkProperties(lp); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - v6gws = mStringArrayCaptor.getValue(); - assertEquals(2, v6gws.size()); - assertTrue(v6gws.contains(ipv6Gw1)); - assertTrue(v6gws.contains(ipv6Gw2)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - final LinkProperties stacked = new LinkProperties(); - stacked.setInterfaceName("stacked"); - stacked.addLinkAddress(new LinkAddress("192.0.2.129/25")); - stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null, - RTN_UNICAST)); - stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null, - RTN_UNICAST)); - assertTrue(lp.addStackedLink(stacked)); - offload.setUpstreamLinkProperties(lp); - // No change in local addresses means no call to setLocalPrefixes(). - inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - v6gws = mStringArrayCaptor.getValue(); - assertEquals(2, v6gws.size()); - assertTrue(v6gws.contains(ipv6Gw1)); - assertTrue(v6gws.contains(ipv6Gw2)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - // Add in some IPv6 upstream info. When there is a tethered downstream - // making use of the IPv6 prefix we would expect to see the /64 route - // removed from "local prefixes" and /128s added for the upstream IPv6 - // addresses. This is not yet implemented, and for now we simply - // expect to see these /128s. - lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null, RTN_UNICAST)); - // "2001:db8::/64" plus "assigned" ASCII in hex - lp.addLinkAddress(new LinkAddress("2001:db8::6173:7369:676e:6564/64")); - // "2001:db8::/64" plus "random" ASCII in hex - lp.addLinkAddress(new LinkAddress("2001:db8::7261:6e64:6f6d/64")); - offload.setUpstreamLinkProperties(lp); - inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); - localPrefixes = mStringArrayCaptor.getValue(); - assertEquals(6, localPrefixes.size()); - assertContainsAll(localPrefixes, - "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64", - "2001:db8::6173:7369:676e:6564/128", "2001:db8::7261:6e64:6f6d/128"); - // The relevant parts of the LinkProperties have not changed, but at the - // moment we do not de-dup upstream LinkProperties this carefully. - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); - v6gws = mStringArrayCaptor.getValue(); - assertEquals(2, v6gws.size()); - assertTrue(v6gws.contains(ipv6Gw1)); - assertTrue(v6gws.contains(ipv6Gw2)); - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); - inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); - inOrder.verifyNoMoreInteractions(); - - // Completely identical LinkProperties updates are de-duped. - offload.setUpstreamLinkProperties(lp); - // This LinkProperties value does not differ from the default upstream. - // There should be no extraneous call to setUpstreamParameters(). - inOrder.verify(mHardware, never()).setUpstreamParameters( - anyObject(), anyObject(), anyObject(), anyObject()); - inOrder.verifyNoMoreInteractions(); - } - - private static @NonNull Entry buildTestEntry(@NonNull OffloadController.StatsType how, - @NonNull String iface, long rxBytes, long txBytes) { - return new Entry(iface, how == STATS_PER_IFACE ? UID_ALL : UID_TETHERING, SET_DEFAULT, - TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, 0L, - txBytes, 0L, 0L); - } - - @Test - public void testGetForwardedStats() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final String ethernetIface = "eth1"; - final String mobileIface = "rmnet_data0"; - - when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( - new ForwardedStats(12345, 54321)); - when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn( - new ForwardedStats(999, 99999)); - - InOrder inOrder = inOrder(mHardware); - - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(ethernetIface); - offload.setUpstreamLinkProperties(lp); - // Previous upstream was null, so no stats are fetched. - inOrder.verify(mHardware, never()).getForwardedStats(any()); - - lp.setInterfaceName(mobileIface); - offload.setUpstreamLinkProperties(lp); - // Expect that we fetch stats from the previous upstream. - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface)); - - lp.setInterfaceName(ethernetIface); - offload.setUpstreamLinkProperties(lp); - // Expect that we fetch stats from the previous upstream. - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(mobileIface)); - - // Verify that the fetched stats are stored. - final NetworkStats ifaceStats = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE); - final NetworkStats uidStats = mTetherStatsProvider.getTetherStats(STATS_PER_UID); - final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999)) - .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321)); - - final NetworkStats expectedUidStats = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) - .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321)); - - assertNetworkStatsEquals(expectedIfaceStats, ifaceStats); - assertNetworkStatsEquals(expectedUidStats, uidStats); - - // Force pushing stats update to verify the stats reported. - mTetherStatsProvider.pushTetherStats(); - mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats); - - when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( - new ForwardedStats(100000, 100000)); - offload.setUpstreamLinkProperties(null); - // Expect that we first clear the HAL's upstream parameters. - inOrder.verify(mHardware, times(1)).setUpstreamParameters( - eq(""), eq("0.0.0.0"), eq("0.0.0.0"), eq(null)); - // Expect that we fetch stats from the previous upstream. - inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface)); - - // There is no current upstream, so no stats are fetched. - inOrder.verify(mHardware, never()).getForwardedStats(any()); - inOrder.verifyNoMoreInteractions(); - - // Verify that the stored stats is accumulated. - final NetworkStats ifaceStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE); - final NetworkStats uidStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_UID); - final NetworkStats expectedIfaceStatsAccu = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999)) - .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321)); - - final NetworkStats expectedUidStatsAccu = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) - .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321)); - - assertNetworkStatsEquals(expectedIfaceStatsAccu, ifaceStatsAccu); - assertNetworkStatsEquals(expectedUidStatsAccu, uidStatsAccu); - - // Verify that only diff of stats is reported. - mTetherStatsProvider.pushTetherStats(); - final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0)) - .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000)); - - final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2) - .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0)) - .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000)); - mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff, - expectedUidStatsDiff); - } - - @Test - public void testSetInterfaceQuota() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final String ethernetIface = "eth1"; - final String mobileIface = "rmnet_data0"; - final long ethernetLimit = 12345; - final long mobileLimit = 12345678; - - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(ethernetIface); - offload.setUpstreamLinkProperties(lp); - - final InOrder inOrder = inOrder(mHardware); - when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true); - when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true); - - // Applying an interface quota to the current upstream immediately sends it to the hardware. - mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit); - waitForIdle(); - inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit); - inOrder.verifyNoMoreInteractions(); - - // Applying an interface quota to another upstream does not take any immediate action. - mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit); - waitForIdle(); - inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong()); - - // Switching to that upstream causes the quota to be applied if the parameters were applied - // correctly. - lp.setInterfaceName(mobileIface); - offload.setUpstreamLinkProperties(lp); - waitForIdle(); - inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit); - - // Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set - // to Long.MAX_VALUE. - mTetherStatsProvider.onSetLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED); - waitForIdle(); - inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE); - - // If setting upstream parameters fails, then the data limit is not set. - when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false); - lp.setInterfaceName(ethernetIface); - offload.setUpstreamLinkProperties(lp); - mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit); - waitForIdle(); - inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong()); - - // If setting the data limit fails while changing upstreams, offload is stopped. - when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true); - when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false); - lp.setInterfaceName(mobileIface); - offload.setUpstreamLinkProperties(lp); - mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit); - waitForIdle(); - inOrder.verify(mHardware).getForwardedStats(ethernetIface); - inOrder.verify(mHardware).stopOffloadControl(); - } - - @Test - public void testDataLimitCallback() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); - callback.onStoppedLimitReached(); - mTetherStatsProviderCb.expectNotifyStatsUpdated(); - } - - @Test - public void testAddRemoveDownstreams() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - final InOrder inOrder = inOrder(mHardware); - inOrder.verify(mHardware, times(1)).initOffloadConfig(); - inOrder.verify(mHardware, times(1)).initOffloadControl( - any(OffloadHardwareInterface.ControlCallback.class)); - inOrder.verifyNoMoreInteractions(); - - // Tethering makes several calls to setLocalPrefixes() before add/remove - // downstream calls are made. This is not tested here; only the behavior - // of notifyDownstreamLinkProperties() and removeDownstreamInterface() - // are tested. - - // [1] USB tethering is started. - final LinkProperties usbLinkProperties = new LinkProperties(); - usbLinkProperties.setInterfaceName(RNDIS0); - usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); - usbLinkProperties.addRoute( - new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX); - inOrder.verifyNoMoreInteractions(); - - // [2] Routes for IPv6 link-local prefixes should never be added. - usbLinkProperties.addRoute( - new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString()); - inOrder.verifyNoMoreInteractions(); - - // [3] Add an IPv6 prefix for good measure. Only new offload-able - // prefixes should be passed to the HAL. - usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); - usbLinkProperties.addRoute( - new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); - inOrder.verifyNoMoreInteractions(); - - // [4] Adding addresses doesn't affect notifyDownstreamLinkProperties(). - // The address is passed in by a separate setLocalPrefixes() invocation. - usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::2/64")); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString()); - - // [5] Differences in local routes are converted into addDownstream() - // and removeDownstream() invocations accordingly. - usbLinkProperties.removeRoute( - new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0, RTN_UNICAST)); - usbLinkProperties.addRoute( - new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); - inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX); - inOrder.verifyNoMoreInteractions(); - - // [6] Removing a downstream interface which was never added causes no - // interactions with the HAL. - offload.removeDownstreamInterface(WLAN0); - inOrder.verifyNoMoreInteractions(); - - // [7] Removing an active downstream removes all remaining prefixes. - offload.removeDownstreamInterface(RNDIS0); - inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, USB_PREFIX); - inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - // Pretend to set a few different upstreams (only the interface name - // matters for this test; we're ignoring IP and route information). - final LinkProperties upstreamLp = new LinkProperties(); - for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) { - upstreamLp.setInterfaceName(ifname); - offload.setUpstreamLinkProperties(upstreamLp); - } - - // Clear invocation history, especially the getForwardedStats() calls - // that happen with setUpstreamParameters(). - clearInvocations(mHardware); - - OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); - callback.onStoppedUnsupported(); - - // Verify forwarded stats behaviour. - verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); - verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); - // TODO: verify the exact stats reported. - mTetherStatsProviderCb.expectNotifyStatsUpdated(); - mTetherStatsProviderCb.assertNoCallback(); - verifyNoMoreInteractions(mHardware); - } - - @Test - public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters() - throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - - final OffloadController offload = makeOffloadController(); - offload.start(); - - // Pretend to set a few different upstreams (only the interface name - // matters for this test; we're ignoring IP and route information). - final LinkProperties upstreamLp = new LinkProperties(); - for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) { - upstreamLp.setInterfaceName(ifname); - offload.setUpstreamLinkProperties(upstreamLp); - } - - // Pretend that some local prefixes and downstreams have been added - // (and removed, for good measure). - final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>(); - for (String s : new String[]{ - "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) { - minimumLocalPrefixes.add(new IpPrefix(s)); - } - offload.setLocalPrefixes(minimumLocalPrefixes); - - final LinkProperties usbLinkProperties = new LinkProperties(); - usbLinkProperties.setInterfaceName(RNDIS0); - usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); - usbLinkProperties.addRoute( - new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(usbLinkProperties); - - final LinkProperties wifiLinkProperties = new LinkProperties(); - wifiLinkProperties.setInterfaceName(WLAN0); - wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24")); - wifiLinkProperties.addRoute( - new RouteInfo(new IpPrefix(WIFI_PREFIX), null, null, RTN_UNICAST)); - wifiLinkProperties.addRoute( - new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST)); - // Use a benchmark prefix (RFC 5180 + erratum), since the documentation - // prefix is included in the excluded prefix list. - wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64")); - wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64")); - wifiLinkProperties.addRoute( - new RouteInfo(new IpPrefix("2001:2::/64"), null, null, RTN_UNICAST)); - offload.notifyDownstreamLinkProperties(wifiLinkProperties); - - offload.removeDownstreamInterface(RNDIS0); - - // Clear invocation history, especially the getForwardedStats() calls - // that happen with setUpstreamParameters(). - clearInvocations(mHardware); - - OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); - callback.onSupportAvailable(); - - // Verify forwarded stats behaviour. - verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); - verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); - mTetherStatsProviderCb.expectNotifyStatsUpdated(); - mTetherStatsProviderCb.assertNoCallback(); - - // TODO: verify local prefixes and downstreams are also pushed to the HAL. - verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); - ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); - assertEquals(4, localPrefixes.size()); - assertContainsAll(localPrefixes, - // TODO: The logic to find and exclude downstream IP prefixes - // is currently in Tethering's OffloadWrapper but must be moved - // into OffloadController proper. After this, also check for: - // "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128" - "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); - verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24"); - verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64"); - verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any()); - verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong()); - verifyNoMoreInteractions(mHardware); - } - - @Test - public void testOnSetAlert() throws Exception { - setupFunctioningHardwareInterface(); - enableOffload(); - setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - final OffloadController offload = makeOffloadController(); - offload.start(); - - // Initialize with fake eth upstream. - final String ethernetIface = "eth1"; - InOrder inOrder = inOrder(mHardware); - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(ethernetIface); - offload.setUpstreamLinkProperties(lp); - // Previous upstream was null, so no stats are fetched. - inOrder.verify(mHardware, never()).getForwardedStats(any()); - - // Verify that set quota to 0 will immediately triggers an callback. - mTetherStatsProvider.onSetAlert(0); - waitForIdle(); - mTetherStatsProviderCb.expectNotifyAlertReached(); - - // Verify that notifyAlertReached never fired if quota is not yet reached. - when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( - new ForwardedStats(0, 0)); - mTetherStatsProvider.onSetAlert(100); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.assertNoCallback(); - - // Verify that notifyAlertReached fired when quota is reached. - when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( - new ForwardedStats(50, 50)); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.expectNotifyAlertReached(); - - // Verify that set quota with UNLIMITED won't trigger any callback, and won't fetch - // any stats since the polling is stopped. - reset(mHardware); - mTetherStatsProvider.onSetAlert(NetworkStatsProvider.QUOTA_UNLIMITED); - mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - waitForIdle(); - mTetherStatsProviderCb.assertNoCallback(); - verify(mHardware, never()).getForwardedStats(any()); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java deleted file mode 100644 index 38b19dd3da5c..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.util.TetheringUtils.uint16; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_UNIX; -import static android.system.OsConstants.SOCK_STREAM; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; -import android.hardware.tetheroffload.control.V1_0.IOffloadControl; -import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; -import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; -import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; -import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; -import android.net.netlink.StructNfGenMsg; -import android.net.netlink.StructNlMsgHdr; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.NativeHandle; -import android.os.test.TestLooper; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.FileDescriptor; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public final class OffloadHardwareInterfaceTest { - private static final String RMNET0 = "test_rmnet_data0"; - - private final TestLooper mTestLooper = new TestLooper(); - - private OffloadHardwareInterface mOffloadHw; - private ITetheringOffloadCallback mTetheringOffloadCallback; - private OffloadHardwareInterface.ControlCallback mControlCallback; - - @Mock private IOffloadConfig mIOffloadConfig; - @Mock private IOffloadControl mIOffloadControl; - @Mock private NativeHandle mNativeHandle; - - // Random values to test Netlink message. - private static final short TEST_TYPE = 184; - private static final short TEST_FLAGS = 263; - - class MyDependencies extends OffloadHardwareInterface.Dependencies { - MyDependencies(SharedLog log) { - super(log); - } - - @Override - public IOffloadConfig getOffloadConfig() { - return mIOffloadConfig; - } - - @Override - public IOffloadControl getOffloadControl() { - return mIOffloadControl; - } - - @Override - public NativeHandle createConntrackSocket(final int groups) { - return mNativeHandle; - } - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - final SharedLog log = new SharedLog("test"); - mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log, - new MyDependencies(log)); - mControlCallback = spy(new OffloadHardwareInterface.ControlCallback()); - } - - private void startOffloadHardwareInterface() throws Exception { - mOffloadHw.initOffloadConfig(); - mOffloadHw.initOffloadControl(mControlCallback); - final ArgumentCaptor<ITetheringOffloadCallback> mOffloadCallbackCaptor = - ArgumentCaptor.forClass(ITetheringOffloadCallback.class); - verify(mIOffloadControl).initOffload(mOffloadCallbackCaptor.capture(), any()); - mTetheringOffloadCallback = mOffloadCallbackCaptor.getValue(); - } - - @Test - public void testGetForwardedStats() throws Exception { - startOffloadHardwareInterface(); - final OffloadHardwareInterface.ForwardedStats stats = mOffloadHw.getForwardedStats(RMNET0); - verify(mIOffloadControl).getForwardedStats(eq(RMNET0), any()); - assertNotNull(stats); - } - - @Test - public void testSetLocalPrefixes() throws Exception { - startOffloadHardwareInterface(); - final ArrayList<String> localPrefixes = new ArrayList<>(); - localPrefixes.add("127.0.0.0/8"); - localPrefixes.add("fe80::/64"); - mOffloadHw.setLocalPrefixes(localPrefixes); - verify(mIOffloadControl).setLocalPrefixes(eq(localPrefixes), any()); - } - - @Test - public void testSetDataLimit() throws Exception { - startOffloadHardwareInterface(); - final long limit = 12345; - mOffloadHw.setDataLimit(RMNET0, limit); - verify(mIOffloadControl).setDataLimit(eq(RMNET0), eq(limit), any()); - } - - @Test - public void testSetUpstreamParameters() throws Exception { - startOffloadHardwareInterface(); - final String v4addr = "192.168.10.1"; - final String v4gateway = "192.168.10.255"; - final ArrayList<String> v6gws = new ArrayList<>(0); - v6gws.add("2001:db8::1"); - mOffloadHw.setUpstreamParameters(RMNET0, v4addr, v4gateway, v6gws); - verify(mIOffloadControl).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway), - eq(v6gws), any()); - - final ArgumentCaptor<ArrayList<String>> mArrayListCaptor = - ArgumentCaptor.forClass(ArrayList.class); - mOffloadHw.setUpstreamParameters(null, null, null, null); - verify(mIOffloadControl).setUpstreamParameters(eq(""), eq(""), eq(""), - mArrayListCaptor.capture(), any()); - assertEquals(mArrayListCaptor.getValue().size(), 0); - } - - @Test - public void testUpdateDownstreamPrefix() throws Exception { - startOffloadHardwareInterface(); - final String ifName = "wlan1"; - final String prefix = "192.168.43.0/24"; - mOffloadHw.addDownstreamPrefix(ifName, prefix); - verify(mIOffloadControl).addDownstream(eq(ifName), eq(prefix), any()); - - mOffloadHw.removeDownstreamPrefix(ifName, prefix); - verify(mIOffloadControl).removeDownstream(eq(ifName), eq(prefix), any()); - } - - @Test - public void testTetheringOffloadCallback() throws Exception { - startOffloadHardwareInterface(); - - mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED); - mTestLooper.dispatchAll(); - verify(mControlCallback).onStarted(); - - mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR); - mTestLooper.dispatchAll(); - verify(mControlCallback).onStoppedError(); - - mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED); - mTestLooper.dispatchAll(); - verify(mControlCallback).onStoppedUnsupported(); - - mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE); - mTestLooper.dispatchAll(); - verify(mControlCallback).onSupportAvailable(); - - mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED); - mTestLooper.dispatchAll(); - verify(mControlCallback).onStoppedLimitReached(); - - final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP); - mTetheringOffloadCallback.updateTimeout(tcpParams); - mTestLooper.dispatchAll(); - verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP), - eq(tcpParams.src.addr), - eq(uint16(tcpParams.src.port)), - eq(tcpParams.dst.addr), - eq(uint16(tcpParams.dst.port))); - - final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP); - mTetheringOffloadCallback.updateTimeout(udpParams); - mTestLooper.dispatchAll(); - verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP), - eq(udpParams.src.addr), - eq(uint16(udpParams.src.port)), - eq(udpParams.dst.addr), - eq(uint16(udpParams.dst.port))); - } - - @Test - public void testSendIpv4NfGenMsg() throws Exception { - FileDescriptor writeSocket = new FileDescriptor(); - FileDescriptor readSocket = new FileDescriptor(); - try { - Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket); - } catch (ErrnoException e) { - fail(); - return; - } - when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket); - - mOffloadHw.sendIpv4NfGenMsg(mNativeHandle, TEST_TYPE, TEST_FLAGS); - - ByteBuffer buffer = ByteBuffer.allocate(9823); // Arbitrary value > expectedLen. - buffer.order(ByteOrder.nativeOrder()); - - int read = Os.read(readSocket, buffer); - final int expectedLen = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; - assertEquals(expectedLen, read); - - buffer.flip(); - assertEquals(expectedLen, buffer.getInt()); - assertEquals(TEST_TYPE, buffer.getShort()); - assertEquals(TEST_FLAGS, buffer.getShort()); - assertEquals(0 /* seq */, buffer.getInt()); - assertEquals(0 /* pid */, buffer.getInt()); - assertEquals(AF_INET, buffer.get()); // nfgen_family - assertEquals(0 /* error */, buffer.get()); // version - assertEquals(0 /* error */, buffer.getShort()); // res_id - assertEquals(expectedLen, buffer.position()); - } - - private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) { - final NatTimeoutUpdate params = new NatTimeoutUpdate(); - params.proto = proto; - params.src.addr = "192.168.43.200"; - params.src.port = 100; - params.dst.addr = "172.50.46.169"; - params.dst.port = 150; - return params; - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java deleted file mode 100644 index 41d46e522ca4..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.networkstack.tethering; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.TetheringManager.TETHERING_ETHERNET; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.util.PrefixUtils.asIpPrefix; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.ip.IpServer; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public final class PrivateAddressCoordinatorTest { - private static final String TEST_IFNAME = "test0"; - - @Mock private IpServer mHotspotIpServer; - @Mock private IpServer mUsbIpServer; - @Mock private IpServer mEthernetIpServer; - @Mock private IpServer mWifiP2pIpServer; - @Mock private Context mContext; - @Mock private ConnectivityManager mConnectivityMgr; - @Mock private TetheringConfiguration mConfig; - - private PrivateAddressCoordinator mPrivateAddressCoordinator; - private final LinkAddress mBluetoothAddress = new LinkAddress("192.168.44.1/24"); - private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24"); - private final Network mWifiNetwork = new Network(1); - private final Network mMobileNetwork = new Network(2); - private final Network mVpnNetwork = new Network(3); - private final Network mMobileNetwork2 = new Network(4); - private final Network mMobileNetwork3 = new Network(5); - private final Network mMobileNetwork4 = new Network(6); - private final Network mMobileNetwork5 = new Network(7); - private final Network mMobileNetwork6 = new Network(8); - private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork, - mMobileNetwork2, mMobileNetwork3, mMobileNetwork4, mMobileNetwork5, mMobileNetwork6}; - private final ArrayList<IpPrefix> mTetheringPrefixes = new ArrayList<>(Arrays.asList( - new IpPrefix("192.168.0.0/16"), - new IpPrefix("172.16.0.0/12"), - new IpPrefix("10.0.0.0/8"))); - - private void setUpIpServers() throws Exception { - when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB); - when(mEthernetIpServer.interfaceType()).thenReturn(TETHERING_ETHERNET); - when(mHotspotIpServer.interfaceType()).thenReturn(TETHERING_WIFI); - when(mWifiP2pIpServer.interfaceType()).thenReturn(TETHERING_WIFI_P2P); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr); - when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks); - when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false); - when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true); - setUpIpServers(); - mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig)); - } - - private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) { - final LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( - ipServer, useLastAddress); - when(ipServer.getAddress()).thenReturn(address); - return address; - } - - @Test - public void testRequestDownstreamAddressWithoutUsingLastAddress() throws Exception { - final IpPrefix bluetoothPrefix = asIpPrefix(mBluetoothAddress); - final LinkAddress address = requestDownstreamAddress(mHotspotIpServer, - false /* useLastAddress */); - final IpPrefix hotspotPrefix = asIpPrefix(address); - assertNotEquals(hotspotPrefix, bluetoothPrefix); - - final LinkAddress newAddress = requestDownstreamAddress(mHotspotIpServer, - false /* useLastAddress */); - final IpPrefix testDupRequest = asIpPrefix(newAddress); - assertNotEquals(hotspotPrefix, testDupRequest); - assertNotEquals(bluetoothPrefix, testDupRequest); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - - final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, - false /* useLastAddress */); - final IpPrefix usbPrefix = asIpPrefix(usbAddress); - assertNotEquals(usbPrefix, bluetoothPrefix); - assertNotEquals(usbPrefix, hotspotPrefix); - mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer); - } - - @Test - public void testSanitizedAddress() throws Exception { - int fakeSubAddr = 0x2b00; // 43.0. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - LinkAddress actualAddress = requestDownstreamAddress(mHotspotIpServer, - false /* useLastAddress */); - assertEquals(new LinkAddress("192.168.43.2/24"), actualAddress); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - - fakeSubAddr = 0x2d01; // 45.1. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); - assertEquals(new LinkAddress("192.168.45.2/24"), actualAddress); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - - fakeSubAddr = 0x2eff; // 46.255. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); - assertEquals(new LinkAddress("192.168.46.254/24"), actualAddress); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - - fakeSubAddr = 0x2f05; // 47.5. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); - assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - } - - @Test - public void testReservedPrefix() throws Exception { - // - Test bluetooth prefix is reserved. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( - getSubAddress(mBluetoothAddress.getAddress().getAddress())); - final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer, - false /* useLastAddress */); - final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddress); - assertNotEquals(asIpPrefix(mBluetoothAddress), hotspotPrefix); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - - // - Test previous enabled hotspot prefix(cached prefix) is reserved. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( - getSubAddress(hotspotAddress.getAddress().getAddress())); - final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, - false /* useLastAddress */); - final IpPrefix usbPrefix = asIpPrefix(usbAddress); - assertNotEquals(asIpPrefix(mBluetoothAddress), usbPrefix); - assertNotEquals(hotspotPrefix, usbPrefix); - mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer); - - // - Test wifi p2p prefix is reserved. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( - getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress())); - final LinkAddress etherAddress = requestDownstreamAddress(mEthernetIpServer, - false /* useLastAddress */); - final IpPrefix etherPrefix = asIpPrefix(etherAddress); - assertNotEquals(asIpPrefix(mLegacyWifiP2pAddress), etherPrefix); - assertNotEquals(asIpPrefix(mBluetoothAddress), etherPrefix); - assertNotEquals(hotspotPrefix, etherPrefix); - mPrivateAddressCoordinator.releaseDownstream(mEthernetIpServer); - } - - @Test - public void testRequestLastDownstreamAddress() throws Exception { - final int fakeHotspotSubAddr = 0x2b05; // 43.5 - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); - final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.43.5/24"), hotspotAddress); - - final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.45.5/24"), usbAddress); - - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer); - - final int newFakeSubAddr = 0x3c05; - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); - - final LinkAddress newHotspotAddress = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals(hotspotAddress, newHotspotAddress); - final LinkAddress newUsbAddress = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - assertEquals(usbAddress, newUsbAddress); - - final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, - new LinkAddress("192.168.88.23/16"), null, - makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream); - verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - verify(mUsbIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - } - - private UpstreamNetworkState buildUpstreamNetworkState(final Network network, - final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(TEST_IFNAME); - if (v4Addr != null) prop.addLinkAddress(v4Addr); - - if (v6Addr != null) prop.addLinkAddress(v6Addr); - - return new UpstreamNetworkState(prop, cap, network); - } - - private NetworkCapabilities makeNetworkCapabilities(final int transportType) { - final NetworkCapabilities cap = new NetworkCapabilities(); - cap.addTransportType(transportType); - if (transportType == TRANSPORT_VPN) { - cap.removeCapability(NET_CAPABILITY_NOT_VPN); - } - - return cap; - } - - @Test - public void testNoConflictUpstreamPrefix() throws Exception { - final int fakeHotspotSubAddr = 0x2b05; // 43.5 - final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24"); - // Force always get subAddress "43.5" for conflict testing. - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); - // - Enable hotspot with prefix 192.168.43.0/24 - final LinkAddress hotspotAddr = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddr); - assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix); - // - test mobile network with null NetworkCapabilities. Ideally this should not happen - // because NetworkCapabilities update should always happen before LinkProperties update - // and the UpstreamNetworkState update, just make sure no crash in this case. - final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork, - new LinkAddress("10.0.0.8/24"), null, null); - mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - test mobile upstream with no address. - final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork, - null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - Update v6 only mobile network, hotspot prefix should not be removed. - final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork, - null, new LinkAddress("2001:db8::/64"), - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork); - // - Update v4 only mobile network, hotspot prefix should not be removed. - final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork, - new LinkAddress("10.0.0.8/24"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - Update v4v6 mobile network, hotspot prefix should not be removed. - final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork, - new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"), - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - Update v6 only wifi network, hotspot prefix should not be removed. - final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork, - null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork); - // - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored. - final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork, - new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - Update v4 only wifi network, it conflict with hotspot prefix. - final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork, - new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi); - verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - reset(mHotspotIpServer); - // - Restart hotspot again and its prefix is different previous. - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - final LinkAddress hotspotAddr2 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - final IpPrefix hotspotPrefix2 = asIpPrefix(hotspotAddr2); - assertNotEquals(hotspotPrefix, hotspotPrefix2); - mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - // - Usb tethering can be enabled and its prefix is different with conflict one. - final LinkAddress usbAddr = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - final IpPrefix usbPrefix = asIpPrefix(usbAddr); - assertNotEquals(predefinedPrefix, usbPrefix); - assertNotEquals(hotspotPrefix2, usbPrefix); - // - Disable wifi upstream, then wifi's prefix can be selected again. - mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork); - final LinkAddress ethAddr = requestDownstreamAddress(mEthernetIpServer, - true /* useLastAddress */); - final IpPrefix ethPrefix = asIpPrefix(ethAddr); - assertEquals(predefinedPrefix, ethPrefix); - } - - @Test - public void testChooseAvailablePrefix() throws Exception { - final int randomAddress = 0x8605; // 134.5 - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress); - final LinkAddress addr0 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.134.5. - assertEquals("Wrong prefix: ", new LinkAddress("192.168.134.5/24"), addr0); - final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, - new LinkAddress("192.168.134.13/26"), null, - makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream); - - // Check whether return address is next prefix of 192.168.134.0/24. - final LinkAddress addr1 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.135.5/24"), addr1); - final UpstreamNetworkState wifiUpstream2 = buildUpstreamNetworkState(mWifiNetwork, - new LinkAddress("192.168.149.16/19"), null, - makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream2); - - - // The conflict range is 128 ~ 159, so the address is 192.168.160.5/24. - final LinkAddress addr2 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.160.5/24"), addr2); - final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork, - new LinkAddress("192.168.129.53/18"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - // Update another conflict upstream which is covered by the previous one (but not the first - // one) and verify whether this would affect the result. - final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2, - new LinkAddress("192.168.170.7/19"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2); - - // The conflict range are 128 ~ 159 and 159 ~ 191, so the address is 192.168.192.5/24. - final LinkAddress addr3 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.192.5/24"), addr3); - final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3, - new LinkAddress("192.168.188.133/17"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3); - - // Conflict range: 128 ~ 255. The next available address is 192.168.0.5 because - // 192.168.134/24 ~ 192.168.255.255/24 is not available. - final LinkAddress addr4 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.0.5/24"), addr4); - final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4, - new LinkAddress("192.168.3.59/21"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4); - - // Conflict ranges: 128 ~ 255 and 0 ~ 7, so the address is 192.168.8.5/24. - final LinkAddress addr5 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr5); - final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5, - new LinkAddress("192.168.68.43/21"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5); - - // Update an upstream that does *not* conflict, check whether return the same address - // 192.168.5/24. - final LinkAddress addr6 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr6); - final UpstreamNetworkState mobileUpstream6 = buildUpstreamNetworkState(mMobileNetwork6, - new LinkAddress("192.168.10.97/21"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream6); - - // Conflict ranges: 0 ~ 15 and 128 ~ 255, so the address is 192.168.16.5/24. - final LinkAddress addr7 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.16.5/24"), addr7); - final UpstreamNetworkState mobileUpstream7 = buildUpstreamNetworkState(mMobileNetwork6, - new LinkAddress("192.168.0.0/17"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream7); - - // Choose prefix from next range(172.16.0.0/12) when no available prefix in 192.168.0.0/16. - final LinkAddress addr8 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.16.134.5/24"), addr8); - } - - @Test - public void testChoosePrefixFromDifferentRanges() throws Exception { - final int randomAddress = 0x1f2b2a; // 31.43.42 - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress); - final LinkAddress classC1 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.43.42. - assertEquals("Wrong prefix: ", new LinkAddress("192.168.43.42/24"), classC1); - final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, - new LinkAddress("192.168.88.23/17"), null, - makeNetworkCapabilities(TRANSPORT_WIFI)); - mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream); - verifyNotifyConflictAndRelease(mHotspotIpServer); - - // Check whether return address is next address of prefix 192.168.128.0/17. - final LinkAddress classC2 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("192.168.128.42/24"), classC2); - final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork, - new LinkAddress("192.1.2.3/8"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream); - verifyNotifyConflictAndRelease(mHotspotIpServer); - - // Check whether return address is under prefix 172.16.0.0/12. - final LinkAddress classB1 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.31.43.42/24"), classB1); - final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2, - new LinkAddress("172.28.123.100/14"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2); - verifyNotifyConflictAndRelease(mHotspotIpServer); - - // 172.28.0.0 ~ 172.31.255.255 is not available. - // Check whether return address is next address of prefix 172.16.0.0/14. - final LinkAddress classB2 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.16.0.42/24"), classB2); - - // Check whether new downstream is next address of address 172.16.0.42/24. - final LinkAddress classB3 = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.16.1.42/24"), classB3); - final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3, - new LinkAddress("172.16.0.1/24"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3); - verifyNotifyConflictAndRelease(mHotspotIpServer); - verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - - // Check whether return address is next address of prefix 172.16.1.42/24. - final LinkAddress classB4 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.16.2.42/24"), classB4); - final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4, - new LinkAddress("172.16.0.1/13"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4); - verifyNotifyConflictAndRelease(mHotspotIpServer); - verifyNotifyConflictAndRelease(mUsbIpServer); - - // Check whether return address is next address of prefix 172.16.0.1/13. - final LinkAddress classB5 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.24.0.42/24"), classB5); - // Check whether return address is next address of prefix 172.24.0.42/24. - final LinkAddress classB6 = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("172.24.1.42/24"), classB6); - final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5, - new LinkAddress("172.24.0.1/12"), null, - makeNetworkCapabilities(TRANSPORT_CELLULAR)); - mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5); - verifyNotifyConflictAndRelease(mHotspotIpServer); - verifyNotifyConflictAndRelease(mUsbIpServer); - - // Check whether return address is prefix 10.0.0.0/8 + subAddress 0.31.43.42. - final LinkAddress classA1 = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("10.31.43.42/24"), classA1); - // Check whether new downstream is next address of address 10.31.43.42/24. - final LinkAddress classA2 = requestDownstreamAddress(mUsbIpServer, - true /* useLastAddress */); - assertEquals("Wrong prefix: ", new LinkAddress("10.31.44.42/24"), classA2); - } - - private void verifyNotifyConflictAndRelease(final IpServer ipServer) throws Exception { - verify(ipServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - mPrivateAddressCoordinator.releaseDownstream(ipServer); - reset(ipServer); - setUpIpServers(); - } - - private int getSubAddress(final byte... ipv4Address) { - assertEquals(4, ipv4Address.length); - - int subnet = Byte.toUnsignedInt(ipv4Address[2]); - return (subnet << 8) + ipv4Address[3]; - } - - private void assertReseveredWifiP2pPrefix() throws Exception { - LinkAddress address = requestDownstreamAddress(mHotspotIpServer, - true /* useLastAddress */); - final IpPrefix hotspotPrefix = asIpPrefix(address); - final IpPrefix legacyWifiP2pPrefix = asIpPrefix(mLegacyWifiP2pAddress); - assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix); - mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - } - - @Test - public void testEnableLegacyWifiP2PAddress() throws Exception { - when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( - getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress())); - // No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix - // is resevered. - assertReseveredWifiP2pPrefix(); - - when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(true); - assertReseveredWifiP2pPrefix(); - - // If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address. - LinkAddress address = requestDownstreamAddress(mWifiP2pIpServer, - true /* useLastAddress */); - assertEquals(mLegacyWifiP2pAddress, address); - mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java deleted file mode 100644 index 237e2c27bfa1..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; -import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.net.util.SharedLog; -import android.provider.DeviceConfig; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.test.BroadcastInterceptingContext; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.util.Arrays; -import java.util.Iterator; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class TetheringConfigurationTest { - private final SharedLog mLog = new SharedLog("TetheringConfigurationTest"); - - private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; - private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; - private static final String PROVISIONING_APP_RESPONSE = "app_response"; - @Mock private Context mContext; - @Mock private TelephonyManager mTelephonyManager; - @Mock private Resources mResources; - @Mock private Resources mResourcesForSubId; - private Context mMockContext; - private boolean mHasTelephonyManager; - private boolean mEnableLegacyDhcpServer; - private MockitoSession mMockingSession; - - private class MockTetheringConfiguration extends TetheringConfiguration { - MockTetheringConfiguration(Context ctx, SharedLog log, int id) { - super(ctx, log, id); - } - - @Override - protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) { - return mResourcesForSubId; - } - } - - private class MockContext extends BroadcastInterceptingContext { - MockContext(Context base) { - super(base); - } - - @Override - public Resources getResources() { - return mResources; - } - - @Override - public Object getSystemService(String name) { - if (Context.TELEPHONY_SERVICE.equals(name)) { - return mHasTelephonyManager ? mTelephonyManager : null; - } - return super.getSystemService(name); - } - } - - @Before - public void setUp() throws Exception { - // TODO: use a dependencies class instead of mock statics. - mMockingSession = mockitoSession() - .initMocks(this) - .mockStatic(DeviceConfig.class) - .strictness(Strictness.WARN) - .startMocking(); - doReturn(null).when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER))); - - when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn( - new String[0]); - when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn( - TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); - when(mResources.getStringArray(R.array.config_tether_usb_regexs)).thenReturn(new String[0]); - when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) - .thenReturn(new String[]{ "test_wlan\\d" }); - when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)).thenReturn( - new String[0]); - when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]); - when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) - .thenReturn(new String[0]); - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - false); - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip)) - .thenReturn(false); - initializeBpfOffloadConfiguration(true, null /* unset */); - initEnableSelectAllPrefixRangeFlag(null /* unset */); - - mHasTelephonyManager = true; - mMockContext = new MockContext(mContext); - mEnableLegacyDhcpServer = false; - } - - @After - public void tearDown() throws Exception { - mMockingSession.finishMocking(); - } - - private TetheringConfiguration getTetheringConfiguration(int... legacyTetherUpstreamTypes) { - when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn( - legacyTetherUpstreamTypes); - return new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - } - - @Test - public void testNoTelephonyManagerMeansNoDun() { - mHasTelephonyManager = false; - final TetheringConfiguration cfg = getTetheringConfiguration( - new int[]{TYPE_MOBILE_DUN, TYPE_WIFI}); - assertFalse(cfg.isDunRequired); - assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN)); - // Just to prove we haven't clobbered Wi-Fi: - assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI)); - } - - @Test - public void testDunFromTelephonyManagerMeansDun() { - when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true); - - final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); - final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( - TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI); - final TetheringConfiguration cfgWifiDun = getTetheringConfiguration( - TYPE_WIFI, TYPE_MOBILE_DUN); - final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration( - TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN); - - for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, - cfgWifiDun, cfgMobileWifiHipriDun)) { - String msg = "config=" + cfg.toString(); - assertTrue(msg, cfg.isDunRequired); - assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN)); - assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); - assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); - // Just to prove we haven't clobbered Wi-Fi: - assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI)); - } - } - - @Test - public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { - when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); - - final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); - final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( - TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI); - final TetheringConfiguration cfgWifiDun = getTetheringConfiguration( - TYPE_WIFI, TYPE_MOBILE_DUN); - final TetheringConfiguration cfgWifiMobile = getTetheringConfiguration( - TYPE_WIFI, TYPE_MOBILE); - final TetheringConfiguration cfgWifiHipri = getTetheringConfiguration( - TYPE_WIFI, TYPE_MOBILE_HIPRI); - final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration( - TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN); - - String msg; - // TYPE_MOBILE_DUN should be present in none of the combinations. - // TYPE_WIFI should not be affected. - for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun, - cfgWifiMobile, cfgWifiHipri, cfgMobileWifiHipriDun)) { - msg = "config=" + cfg.toString(); - assertFalse(msg, cfg.isDunRequired); - assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN)); - assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI)); - } - - for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun, - cfgMobileWifiHipriDun)) { - msg = "config=" + cfg.toString(); - assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); - assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); - } - msg = "config=" + cfgWifiMobile.toString(); - assertTrue(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); - assertFalse(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); - msg = "config=" + cfgWifiHipri.toString(); - assertFalse(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); - assertTrue(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); - - } - - @Test - public void testNoDefinedUpstreamTypesAddsEthernet() { - when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[]{}); - when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); - - final TetheringConfiguration cfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); - // The following is because the code always adds some kind of mobile - // upstream, be it DUN or, in this case where DUN is NOT required, - // make sure there is at least one of MOBILE or HIPRI. With the empty - // list of the configuration in this test, it will always add both - // MOBILE and HIPRI, in that order. - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue()); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); - assertFalse(upstreamIterator.hasNext()); - } - - @Test - public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { - when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn( - new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); - - final TetheringConfiguration cfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_WIFI, upstreamIterator.next().intValue()); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); - assertFalse(upstreamIterator.hasNext()); - } - - @Test - public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { - when(mResources.getIntArray(R.array.config_tether_upstream_types)) - .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); - - final TetheringConfiguration cfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_WIFI, upstreamIterator.next().intValue()); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); - assertTrue(upstreamIterator.hasNext()); - assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); - assertFalse(upstreamIterator.hasNext()); - } - - private void initializeBpfOffloadConfiguration( - final boolean fromRes, final String fromDevConfig) { - when(mResources.getBoolean(R.bool.config_tether_enable_bpf_offload)).thenReturn(fromRes); - doReturn(fromDevConfig).when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD))); - } - - @Test - public void testBpfOffloadEnabledByResource() { - initializeBpfOffloadConfiguration(true, null /* unset */); - final TetheringConfiguration enableByRes = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(enableByRes.isBpfOffloadEnabled()); - } - - @Test - public void testBpfOffloadEnabledByDeviceConfigOverride() { - for (boolean res : new boolean[]{true, false}) { - initializeBpfOffloadConfiguration(res, "true"); - final TetheringConfiguration enableByDevConOverride = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(enableByDevConOverride.isBpfOffloadEnabled()); - } - } - - @Test - public void testBpfOffloadDisabledByResource() { - initializeBpfOffloadConfiguration(false, null /* unset */); - final TetheringConfiguration disableByRes = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(disableByRes.isBpfOffloadEnabled()); - } - - @Test - public void testBpfOffloadDisabledByDeviceConfigOverride() { - for (boolean res : new boolean[]{true, false}) { - initializeBpfOffloadConfiguration(res, "false"); - final TetheringConfiguration disableByDevConOverride = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(disableByDevConOverride.isBpfOffloadEnabled()); - } - } - - @Test - public void testNewDhcpServerDisabled() { - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - true); - doReturn("false").when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER))); - - final TetheringConfiguration enableByRes = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(enableByRes.enableLegacyDhcpServer); - - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - false); - doReturn("true").when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER))); - - final TetheringConfiguration enableByDevConfig = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(enableByDevConfig.enableLegacyDhcpServer); - } - - @Test - public void testNewDhcpServerEnabled() { - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - false); - doReturn("false").when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER))); - - final TetheringConfiguration cfg = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - - assertFalse(cfg.enableLegacyDhcpServer); - } - - @Test - public void testOffloadIntervalByResource() { - final TetheringConfiguration intervalByDefault = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertEquals(TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, - intervalByDefault.getOffloadPollInterval()); - - final int[] testOverrides = {0, 3000, -1}; - for (final int override : testOverrides) { - when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn( - override); - final TetheringConfiguration overrideByRes = - new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertEquals(override, overrideByRes.getOffloadPollInterval()); - } - } - - @Test - public void testGetResourcesBySubId() { - setUpResourceForSubId(); - final TetheringConfiguration cfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(cfg.provisioningApp.length == 0); - final int anyValidSubId = 1; - final MockTetheringConfiguration mockCfg = - new MockTetheringConfiguration(mMockContext, mLog, anyValidSubId); - assertEquals(mockCfg.provisioningApp[0], PROVISIONING_APP_NAME[0]); - assertEquals(mockCfg.provisioningApp[1], PROVISIONING_APP_NAME[1]); - assertEquals(mockCfg.provisioningAppNoUi, PROVISIONING_NO_UI_APP_NAME); - assertEquals(mockCfg.provisioningResponse, PROVISIONING_APP_RESPONSE); - } - - private void setUpResourceForSubId() { - when(mResourcesForSubId.getStringArray( - R.array.config_tether_dhcp_range)).thenReturn(new String[0]); - when(mResourcesForSubId.getStringArray( - R.array.config_tether_usb_regexs)).thenReturn(new String[0]); - when(mResourcesForSubId.getStringArray( - R.array.config_tether_wifi_regexs)).thenReturn(new String[]{ "test_wlan\\d" }); - when(mResourcesForSubId.getStringArray( - R.array.config_tether_bluetooth_regexs)).thenReturn(new String[0]); - when(mResourcesForSubId.getIntArray(R.array.config_tether_upstream_types)).thenReturn( - new int[0]); - when(mResourcesForSubId.getStringArray( - R.array.config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME); - when(mResourcesForSubId.getString(R.string.config_mobile_hotspot_provision_app_no_ui)) - .thenReturn(PROVISIONING_NO_UI_APP_NAME); - when(mResourcesForSubId.getString( - R.string.config_mobile_hotspot_provision_response)).thenReturn( - PROVISIONING_APP_RESPONSE); - } - - @Test - public void testEnableLegacyWifiP2PAddress() throws Exception { - final TetheringConfiguration defaultCfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(defaultCfg.shouldEnableWifiP2pDedicatedIp()); - - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip)) - .thenReturn(true); - final TetheringConfiguration testCfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp()); - } - - private void initEnableSelectAllPrefixRangeFlag(final String value) { - doReturn(value).when( - () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES))); - } - - @Test - public void testSelectAllPrefixRangeFlag() throws Exception { - // Test default value. - final TetheringConfiguration defaultCfg = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled()); - - // Test disable flag. - initEnableSelectAllPrefixRangeFlag("false"); - final TetheringConfiguration testDisable = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertFalse(testDisable.isSelectAllPrefixRangeEnabled()); - - // Test enable flag. - initEnableSelectAllPrefixRangeFlag("true"); - final TetheringConfiguration testEnable = new TetheringConfiguration( - mMockContext, mLog, INVALID_SUBSCRIPTION_ID); - assertTrue(testEnable.isSelectAllPrefixRangeEnabled()); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt deleted file mode 100644 index 75c819bb0ced..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering - -import android.app.Notification -import android.app.NotificationManager -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_IMMUTABLE -import android.content.Context -import android.content.Intent -import android.content.pm.ActivityInfo -import android.content.pm.ApplicationInfo -import android.content.pm.PackageManager -import android.content.pm.ResolveInfo -import android.content.res.Resources -import android.net.ConnectivityManager.TETHERING_WIFI -import android.net.NetworkCapabilities -import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING -import android.os.Handler -import android.os.HandlerThread -import android.os.Looper -import android.os.UserHandle -import android.provider.Settings -import android.telephony.TelephonyManager -import androidx.test.filters.SmallTest -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.runner.AndroidJUnit4 -import com.android.internal.util.test.BroadcastInterceptingContext -import com.android.networkstack.tethering.TetheringNotificationUpdater.ACTION_DISABLE_TETHERING -import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE -import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM -import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID -import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID -import com.android.networkstack.tethering.TetheringNotificationUpdater.ROAMING_NOTIFICATION_ID -import com.android.networkstack.tethering.TetheringNotificationUpdater.VERIZON_CARRIER_ID -import com.android.networkstack.tethering.TetheringNotificationUpdater.getSettingsPackageName -import com.android.testutils.waitForIdle -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Assert.fail -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import org.mockito.Mockito.never -import org.mockito.Mockito.reset -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.Mockito.verifyZeroInteractions -import org.mockito.MockitoAnnotations - -const val TEST_SUBID = 1 -const val WIFI_MASK = 1 shl TETHERING_WIFI -const val TEST_DISALLOW_TITLE = "Tether function is disallowed" -const val TEST_DISALLOW_MESSAGE = "Please contact your admin" -const val TEST_NO_UPSTREAM_TITLE = "Hotspot has no internet access" -const val TEST_NO_UPSTREAM_MESSAGE = "Device cannot connect to internet." -const val TEST_NO_UPSTREAM_BUTTON = "Turn off hotspot" -const val TEST_ROAMING_TITLE = "Hotspot is on" -const val TEST_ROAMING_MESSAGE = "Additional charges may apply while roaming." - -@RunWith(AndroidJUnit4::class) -@SmallTest -class TetheringNotificationUpdaterTest { - // lateinit used here for mocks as they need to be reinitialized between each test and the test - // should crash if they are used before being initialized. - @Mock private lateinit var mockContext: Context - @Mock private lateinit var notificationManager: NotificationManager - @Mock private lateinit var telephonyManager: TelephonyManager - @Mock private lateinit var testResources: Resources - - // lateinit for these classes under test, as they should be reset to a different instance for - // every test but should always be initialized before use (or the test should crash). - private lateinit var context: TestContext - private lateinit var notificationUpdater: TetheringNotificationUpdater - - // Initializing the following members depends on initializing some of the mocks and - // is more logically done in setup(). - private lateinit var fakeTetheringThread: HandlerThread - - private val ROAMING_CAPABILITIES = NetworkCapabilities() - private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING) - private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general - private val TIMEOUT_MS = 500L - private val ACTIVITY_PENDING_INTENT = 0 - private val BROADCAST_PENDING_INTENT = 1 - - private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) { - override fun createContextAsUser(user: UserHandle, flags: Int) = - if (user == UserHandle.ALL) mockContext else this - override fun getSystemService(name: String) = - if (name == Context.TELEPHONY_SERVICE) telephonyManager - else super.getSystemService(name) - } - - private inner class WrappedNotificationUpdater(c: Context, looper: Looper) - : TetheringNotificationUpdater(c, looper) { - override fun getResourcesForSubId(c: Context, subId: Int) = - if (subId == TEST_SUBID) testResources else super.getResourcesForSubId(c, subId) - } - - private fun setupResources() { - doReturn(5).`when`(testResources) - .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul) - doReturn(true).`when`(testResources) - .getBoolean(R.bool.config_upstream_roaming_notification) - doReturn(TEST_DISALLOW_TITLE).`when`(testResources) - .getString(R.string.disable_tether_notification_title) - doReturn(TEST_DISALLOW_MESSAGE).`when`(testResources) - .getString(R.string.disable_tether_notification_message) - doReturn(TEST_NO_UPSTREAM_TITLE).`when`(testResources) - .getString(R.string.no_upstream_notification_title) - doReturn(TEST_NO_UPSTREAM_MESSAGE).`when`(testResources) - .getString(R.string.no_upstream_notification_message) - doReturn(TEST_NO_UPSTREAM_BUTTON).`when`(testResources) - .getString(R.string.no_upstream_notification_disable_button) - doReturn(TEST_ROAMING_TITLE).`when`(testResources) - .getString(R.string.upstream_roaming_notification_title) - doReturn(TEST_ROAMING_MESSAGE).`when`(testResources) - .getString(R.string.upstream_roaming_notification_message) - } - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - context = TestContext(InstrumentationRegistry.getInstrumentation().context) - doReturn(notificationManager).`when`(mockContext) - .getSystemService(Context.NOTIFICATION_SERVICE) - fakeTetheringThread = HandlerThread(this::class.java.simpleName) - fakeTetheringThread.start() - notificationUpdater = WrappedNotificationUpdater(context, fakeTetheringThread.looper) - setupResources() - } - - @After - fun tearDown() { - fakeTetheringThread.quitSafely() - } - - private fun verifyActivityPendingIntent(intent: Intent, flags: Int) { - // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add - // the flag in creating arguments). If the described PendingIntent does not already exist, - // getActivity() will return null instead of PendingIntent object. - val pi = PendingIntent.getActivity( - context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - intent, - flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE, - null /* options */) - assertNotNull("Activity PendingIntent with FLAG_IMMUTABLE does not exist.", pi) - } - - private fun verifyBroadcastPendingIntent(intent: Intent, flags: Int) { - // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add - // the flag in creating arguments). If the described PendingIntent does not already exist, - // getBroadcast() will return null instead of PendingIntent object. - val pi = PendingIntent.getBroadcast( - context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - intent, - flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE) - assertNotNull("Broadcast PendingIntent with FLAG_IMMUTABLE does not exist.", pi) - } - - private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE) - private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT) - - private fun verifyNotification( - iconId: Int, - title: String, - text: String, - id: Int, - intentSenderType: Int, - intent: Intent, - flags: Int - ) { - verify(notificationManager, never()).cancel(any(), eq(id)) - - val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java) - verify(notificationManager, times(1)) - .notify(any(), eq(id), notificationCaptor.capture()) - - val notification = notificationCaptor.getValue() - assertEquals(iconId, notification.smallIcon.resId) - assertEquals(title, notification.title()) - assertEquals(text, notification.text()) - - when (intentSenderType) { - ACTIVITY_PENDING_INTENT -> verifyActivityPendingIntent(intent, flags) - BROADCAST_PENDING_INTENT -> verifyBroadcastPendingIntent(intent, flags) - } - - reset(notificationManager) - } - - private fun verifyNotificationCancelled( - notificationIds: List<Int>, - resetAfterVerified: Boolean = true - ) { - notificationIds.forEach { - verify(notificationManager, times(1)).cancel(any(), eq(it)) - } - if (resetAfterVerified) reset(notificationManager) - } - - @Test - fun testRestrictedNotification() { - val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS) - .setPackage(getSettingsPackageName(context.packageManager)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - // Set test sub id. - notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // User restrictions on. Show restricted notification. - notificationUpdater.notifyTetheringDisabledByRestriction() - verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE, - RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) - - // User restrictions off. Clear notification. - notificationUpdater.tetheringRestrictionLifted() - verifyNotificationCancelled(listOf(RESTRICTED_NOTIFICATION_ID)) - - // No downstream. - notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) - verifyZeroInteractions(notificationManager) - - // User restrictions on again. Show restricted notification. - notificationUpdater.notifyTetheringDisabledByRestriction() - verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE, - RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) - } - - val MAX_BACKOFF_MS = 200L - /** - * Waits for all messages, including delayed ones, to be processed. - * - * This will wait until the handler has no more messages to be processed including - * delayed ones, or the timeout has expired. It uses an exponential backoff strategy - * to wait longer and longer to consume less CPU, with the max granularity being - * MAX_BACKOFF_MS. - * - * @return true if all messages have been processed including delayed ones, false if timeout - * - * TODO: Move this method to com.android.testutils.HandlerUtils.kt. - */ - private fun Handler.waitForDelayedMessage(what: Int?, timeoutMs: Long) { - fun hasMatchingMessages() = - if (what == null) hasMessagesOrCallbacks() else hasMessages(what) - val expiry = System.currentTimeMillis() + timeoutMs - var delay = 5L - while (System.currentTimeMillis() < expiry && hasMatchingMessages()) { - // None of Handler, Looper, Message and MessageQueue expose any way to retrieve - // the time when the next (let alone the last) message will be processed, so - // short of examining the internals with reflection sleep() is the only solution. - Thread.sleep(delay) - delay = (delay * 2) - .coerceAtMost(expiry - System.currentTimeMillis()) - .coerceAtMost(MAX_BACKOFF_MS) - } - - val timeout = expiry - System.currentTimeMillis() - if (timeout <= 0) fail("Delayed message did not process yet after ${timeoutMs}ms") - waitForIdle(timeout) - } - - @Test - fun testNoUpstreamNotification() { - val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName) - - // Set test sub id. - notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Wifi downstream. - notificationUpdater.onDownstreamChanged(WIFI_MASK) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // There is no upstream. Show no upstream notification. - notificationUpdater.onUpstreamCapabilitiesChanged(null) - notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) - verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, - FLAG_IMMUTABLE) - - // Same capabilities changed. Nothing happened. - notificationUpdater.onUpstreamCapabilitiesChanged(null) - verifyZeroInteractions(notificationManager) - - // Upstream come back. Clear no upstream notification. - notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID)) - - // No upstream again. Show no upstream notification. - notificationUpdater.onUpstreamCapabilitiesChanged(null) - notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) - verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, - FLAG_IMMUTABLE) - - // No downstream. - notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Wifi downstream and home capabilities. - notificationUpdater.onDownstreamChanged(WIFI_MASK) - notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Set R.integer.delay_to_show_no_upstream_after_no_backhaul to -1 and change to no upstream - // again. Don't put up no upstream notification. - doReturn(-1).`when`(testResources) - .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul) - notificationUpdater.onUpstreamCapabilitiesChanged(null) - notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID)) - } - - @Test - fun testGetResourcesForSubId() { - doReturn(telephonyManager).`when`(telephonyManager).createForSubscriptionId(anyInt()) - doReturn(1234).`when`(telephonyManager).getSimCarrierId() - doReturn("000000").`when`(telephonyManager).getSimOperator() - - val subId = -2 // Use invalid subId to avoid getting resource from cache or real subId. - val config = context.resources.configuration - var res = notificationUpdater.getResourcesForSubId(context, subId) - assertEquals(config.mcc, res.configuration.mcc) - assertEquals(config.mnc, res.configuration.mnc) - - doReturn(VERIZON_CARRIER_ID).`when`(telephonyManager).getSimCarrierId() - res = notificationUpdater.getResourcesForSubId(context, subId) - assertEquals(config.mcc, res.configuration.mcc) - assertEquals(config.mnc, res.configuration.mnc) - - doReturn("20404").`when`(telephonyManager).getSimOperator() - res = notificationUpdater.getResourcesForSubId(context, subId) - assertEquals(311, res.configuration.mcc) - assertEquals(480, res.configuration.mnc) - } - - @Test - fun testRoamingNotification() { - val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName) - val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS) - .setPackage(getSettingsPackageName(context.packageManager)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - // Set test sub id. - notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Wifi downstream. - notificationUpdater.onDownstreamChanged(WIFI_MASK) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Upstream capabilities changed to roaming state. Show roaming notification. - notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) - verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE, - ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) - - // Same capabilities change. Nothing happened. - notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) - verifyZeroInteractions(notificationManager) - - // Upstream capabilities changed to home state. Clear roaming notification. - notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES) - verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID)) - - // Upstream capabilities changed to roaming state again. Show roaming notification. - notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) - verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE, - ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) - - // No upstream. Clear roaming notification and show no upstream notification. - notificationUpdater.onUpstreamCapabilitiesChanged(null) - notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) - verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false) - verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, - FLAG_IMMUTABLE) - - // No downstream. - notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - - // Wifi downstream again. - notificationUpdater.onDownstreamChanged(WIFI_MASK) - notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) - verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false) - verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, - FLAG_IMMUTABLE) - - // Set R.bool.config_upstream_roaming_notification to false and change upstream - // network to roaming state again. No roaming notification. - doReturn(false).`when`(testResources) - .getBoolean(R.bool.config_upstream_roaming_notification) - notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) - verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) - } - - @Test - fun testGetSettingsPackageName() { - val defaultSettingsPackageName = "com.android.settings" - val testSettingsPackageName = "com.android.test.settings" - val pm = mock(PackageManager::class.java) - doReturn(null).`when`(pm).resolveActivity(any(), anyInt()) - assertEquals(defaultSettingsPackageName, getSettingsPackageName(pm)) - - val resolveInfo = ResolveInfo().apply { - activityInfo = ActivityInfo().apply { - name = "test" - applicationInfo = ApplicationInfo().apply { - packageName = testSettingsPackageName - } - } - } - doReturn(resolveInfo).`when`(pm).resolveActivity(any(), anyInt()) - assertEquals(testSettingsPackageName, getSettingsPackageName(pm)) - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java deleted file mode 100644 index 7bba67b05f88..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.Manifest.permission.ACCESS_NETWORK_STATE; -import static android.Manifest.permission.TETHER_PRIVILEGED; -import static android.Manifest.permission.WRITE_SETTINGS; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; -import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.UiAutomation; -import android.content.Intent; -import android.net.IIntResultListener; -import android.net.ITetheringConnector; -import android.net.ITetheringEventCallback; -import android.net.TetheringRequestParcel; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.rule.ServiceTestRule; -import androidx.test.runner.AndroidJUnit4; - -import com.android.networkstack.tethering.MockTetheringService.MockTetheringConnector; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public final class TetheringServiceTest { - private static final String TEST_IFACE_NAME = "test_wlan0"; - private static final String TEST_CALLER_PKG = "com.android.shell"; - private static final String TEST_ATTRIBUTION_TAG = null; - @Mock private ITetheringEventCallback mITetheringEventCallback; - @Rule public ServiceTestRule mServiceTestRule; - private Tethering mTethering; - private Intent mMockServiceIntent; - private ITetheringConnector mTetheringConnector; - private UiAutomation mUiAutomation; - - private class TestTetheringResult extends IIntResultListener.Stub { - private int mResult = -1; // Default value that does not match any result code. - @Override - public void onResult(final int resultCode) { - mResult = resultCode; - } - - public void assertResult(final int expected) { - assertEquals(expected, mResult); - } - } - - private class MyResultReceiver extends ResultReceiver { - MyResultReceiver(Handler handler) { - super(handler); - } - private int mResult = -1; // Default value that does not match any result code. - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - mResult = resultCode; - } - - public void assertResult(int expected) { - assertEquals(expected, mResult); - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mUiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - mServiceTestRule = new ServiceTestRule(); - mMockServiceIntent = new Intent( - InstrumentationRegistry.getTargetContext(), - MockTetheringService.class); - final MockTetheringConnector mockConnector = - (MockTetheringConnector) mServiceTestRule.bindService(mMockServiceIntent); - mTetheringConnector = mockConnector.getTetheringConnector(); - final MockTetheringService service = mockConnector.getService(); - mTethering = service.getTethering(); - } - - @After - public void tearDown() throws Exception { - mServiceTestRule.unbindService(); - mUiAutomation.dropShellPermissionIdentity(); - } - - private interface TestTetheringCall { - void runTetheringCall(TestTetheringResult result) throws Exception; - } - - private void runAsNoPermission(final TestTetheringCall test) throws Exception { - runTetheringCall(test, new String[0]); - } - - private void runAsTetherPrivileged(final TestTetheringCall test) throws Exception { - runTetheringCall(test, TETHER_PRIVILEGED); - } - - private void runAsAccessNetworkState(final TestTetheringCall test) throws Exception { - runTetheringCall(test, ACCESS_NETWORK_STATE); - } - - private void runAsWriteSettings(final TestTetheringCall test) throws Exception { - runTetheringCall(test, WRITE_SETTINGS); - } - - private void runTetheringCall(final TestTetheringCall test, String... permissions) - throws Exception { - if (permissions.length > 0) mUiAutomation.adoptShellPermissionIdentity(permissions); - try { - when(mTethering.isTetheringSupported()).thenReturn(true); - test.runTetheringCall(new TestTetheringResult()); - } finally { - mUiAutomation.dropShellPermissionIdentity(); - } - } - - private void verifyNoMoreInteractionsForTethering() { - verifyNoMoreInteractions(mTethering); - verifyNoMoreInteractions(mITetheringEventCallback); - reset(mTethering, mITetheringEventCallback); - } - - private void runTether(final TestTetheringResult result) throws Exception { - when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR); - mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).tether(TEST_IFACE_NAME); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testTether() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runTether(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runTether(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runUnTether(final TestTetheringResult result) throws Exception { - when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR); - mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).untether(TEST_IFACE_NAME); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testUntether() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runUnTether(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runUnTether(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runSetUsbTethering(final TestTetheringResult result) throws Exception { - when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR); - mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, - TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).setUsbTethering(true /* enable */); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testSetUsbTethering() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, - TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runSetUsbTethering(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runSetUsbTethering(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - - } - - private void runStartTethering(final TestTetheringResult result, - final TetheringRequestParcel request) throws Exception { - mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).startTethering(eq(request), eq(result)); - } - - @Test - public void testStartTethering() throws Exception { - final TetheringRequestParcel request = new TetheringRequestParcel(); - request.tetheringType = TETHERING_WIFI; - - runAsNoPermission((result) -> { - mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runStartTethering(result, request); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runStartTethering(result, request); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runStartTetheringAndVerifyNoPermission(final TestTetheringResult result) - throws Exception { - final TetheringRequestParcel request = new TetheringRequestParcel(); - request.tetheringType = TETHERING_WIFI; - request.exemptFromEntitlementCheck = true; - mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - } - - @Test - public void testFailToBypassEntitlementWithoutNeworkStackPermission() throws Exception { - final TetheringRequestParcel request = new TetheringRequestParcel(); - request.tetheringType = TETHERING_WIFI; - request.exemptFromEntitlementCheck = true; - - runAsNoPermission((result) -> { - runStartTetheringAndVerifyNoPermission(result); - }); - - runAsTetherPrivileged((result) -> { - runStartTetheringAndVerifyNoPermission(result); - }); - - runAsWriteSettings((result) -> { - runStartTetheringAndVerifyNoPermission(result); - }); - } - - private void runStopTethering(final TestTetheringResult result) throws Exception { - mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, - TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).stopTethering(TETHERING_WIFI); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testStopTethering() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, - TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runStopTethering(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runStopTethering(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runRequestLatestTetheringEntitlementResult() throws Exception { - final MyResultReceiver result = new MyResultReceiver(null); - mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result, - true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG); - verify(mTethering).isTetheringSupported(); - verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI), - eq(result), eq(true) /* showEntitlementUi */); - } - - @Test - public void testRequestLatestTetheringEntitlementResult() throws Exception { - // Run as no permission. - final MyResultReceiver result = new MyResultReceiver(null); - mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result, - true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractions(mTethering); - - runAsTetherPrivileged((none) -> { - runRequestLatestTetheringEntitlementResult(); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((none) -> { - runRequestLatestTetheringEntitlementResult(); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runRegisterTetheringEventCallback() throws Exception { - mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback, - TEST_CALLER_PKG); - verify(mTethering).registerTetheringEventCallback(eq(mITetheringEventCallback)); - } - - @Test - public void testRegisterTetheringEventCallback() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback, - TEST_CALLER_PKG); - verify(mITetheringEventCallback).onCallbackStopped( - TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((none) -> { - runRegisterTetheringEventCallback(); - verifyNoMoreInteractionsForTethering(); - }); - - runAsAccessNetworkState((none) -> { - runRegisterTetheringEventCallback(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runUnregisterTetheringEventCallback() throws Exception { - mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback, - TEST_CALLER_PKG); - verify(mTethering).unregisterTetheringEventCallback(eq(mITetheringEventCallback)); - } - - @Test - public void testUnregisterTetheringEventCallback() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback, - TEST_CALLER_PKG); - verify(mITetheringEventCallback).onCallbackStopped( - TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((none) -> { - runUnregisterTetheringEventCallback(); - verifyNoMoreInteractionsForTethering(); - }); - - runAsAccessNetworkState((none) -> { - runUnregisterTetheringEventCallback(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runStopAllTethering(final TestTetheringResult result) throws Exception { - mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetheringSupported(); - verify(mTethering).untetherAll(); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testStopAllTethering() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runStopAllTethering(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runStopAllTethering(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } - - private void runIsTetheringSupported(final TestTetheringResult result) throws Exception { - mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).isTetheringSupported(); - result.assertResult(TETHER_ERROR_NO_ERROR); - } - - @Test - public void testIsTetheringSupported() throws Exception { - runAsNoPermission((result) -> { - mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).isTetherProvisioningRequired(); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); - }); - - runAsTetherPrivileged((result) -> { - runIsTetheringSupported(result); - verifyNoMoreInteractionsForTethering(); - }); - - runAsWriteSettings((result) -> { - runIsTetheringSupported(result); - verify(mTethering).isTetherProvisioningRequired(); - verifyNoMoreInteractionsForTethering(); - }); - } -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java deleted file mode 100644 index 114cb7ca6ec7..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ /dev/null @@ -1,2019 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.content.pm.PackageManager.GET_ACTIVITIES; -import static android.hardware.usb.UsbManager.USB_CONFIGURED; -import static android.hardware.usb.UsbManager.USB_CONNECTED; -import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; -import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; -import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED; -import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.RouteInfo.RTN_UNICAST; -import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; -import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; -import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER; -import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER; -import static android.net.TetheringManager.TETHERING_ETHERNET; -import static android.net.TetheringManager.TETHERING_NCM; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; -import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - -import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; -import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; -import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.notNull; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.usage.NetworkStatsManager; -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.hardware.usb.UsbManager; -import android.net.ConnectivityManager; -import android.net.EthernetManager; -import android.net.EthernetManager.TetheredInterfaceCallback; -import android.net.EthernetManager.TetheredInterfaceRequest; -import android.net.IIntResultListener; -import android.net.INetd; -import android.net.ITetheringEventCallback; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.RouteInfo; -import android.net.TetherStatesParcel; -import android.net.TetheredClient; -import android.net.TetheringCallbackStartedParcel; -import android.net.TetheringConfigurationParcel; -import android.net.TetheringRequestParcel; -import android.net.dhcp.DhcpServerCallbacks; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.IDhcpServer; -import android.net.ip.DadProxy; -import android.net.ip.IpNeighborMonitor; -import android.net.ip.IpServer; -import android.net.ip.RouterAdvertisementDaemon; -import android.net.util.InterfaceParams; -import android.net.util.NetworkConstants; -import android.net.util.SharedLog; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pInfo; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.PersistableBundle; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.provider.Settings; -import android.telephony.CarrierConfigManager; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; -import android.test.mock.MockContentResolver; - -import androidx.annotation.NonNull; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.StateMachine; -import com.android.internal.util.test.BroadcastInterceptingContext; -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.testutils.MiscAsserts; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Vector; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class TetheringTest { - private static final int IFINDEX_OFFSET = 100; - - private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0"; - private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0"; - private static final String TEST_USB_IFNAME = "test_rndis0"; - private static final String TEST_WIFI_IFNAME = "test_wlan0"; - private static final String TEST_WLAN_IFNAME = "test_wlan1"; - private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0"; - private static final String TEST_NCM_IFNAME = "test_ncm0"; - private static final String TEST_ETH_IFNAME = "test_eth0"; - private static final String TEST_BT_IFNAME = "test_pan0"; - private static final String TETHERING_NAME = "Tethering"; - private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; - private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; - - private static final int DHCPSERVER_START_TIMEOUT_MS = 1000; - - @Mock private ApplicationInfo mApplicationInfo; - @Mock private Context mContext; - @Mock private NetworkStatsManager mStatsManager; - @Mock private OffloadHardwareInterface mOffloadHardwareInterface; - @Mock private OffloadHardwareInterface.ForwardedStats mForwardedStats; - @Mock private Resources mResources; - @Mock private TelephonyManager mTelephonyManager; - @Mock private UsbManager mUsbManager; - @Mock private WifiManager mWifiManager; - @Mock private CarrierConfigManager mCarrierConfigManager; - @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor; - @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator; - @Mock private DadProxy mDadProxy; - @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon; - @Mock private IpNeighborMonitor mIpNeighborMonitor; - @Mock private IDhcpServer mDhcpServer; - @Mock private INetd mNetd; - @Mock private UserManager mUserManager; - @Mock private NetworkRequest mNetworkRequest; - @Mock private ConnectivityManager mCm; - @Mock private EthernetManager mEm; - @Mock private TetheringNotificationUpdater mNotificationUpdater; - @Mock private BpfCoordinator mBpfCoordinator; - @Mock private PackageManager mPackageManager; - - private final MockIpServerDependencies mIpServerDependencies = - spy(new MockIpServerDependencies()); - private final MockTetheringDependencies mTetheringDependencies = - new MockTetheringDependencies(); - - // Like so many Android system APIs, these cannot be mocked because it is marked final. - // We have to use the real versions. - private final PersistableBundle mCarrierConfig = new PersistableBundle(); - private final TestLooper mLooper = new TestLooper(); - - private Vector<Intent> mIntents; - private BroadcastInterceptingContext mServiceContext; - private MockContentResolver mContentResolver; - private BroadcastReceiver mBroadcastReceiver; - private Tethering mTethering; - private PhoneStateListener mPhoneStateListener; - private InterfaceConfigurationParcel mInterfaceConfiguration; - private TetheringConfiguration mConfig; - private EntitlementManager mEntitleMgr; - private OffloadController mOffloadCtrl; - private PrivateAddressCoordinator mPrivateAddressCoordinator; - - private class TestContext extends BroadcastInterceptingContext { - TestContext(Context base) { - super(base); - } - - @Override - public ApplicationInfo getApplicationInfo() { - return mApplicationInfo; - } - - @Override - public ContentResolver getContentResolver() { - return mContentResolver; - } - - @Override - public String getPackageName() { - return "TetheringTest"; - } - - @Override - public Resources getResources() { - return mResources; - } - - @Override - public Object getSystemService(String name) { - if (Context.WIFI_SERVICE.equals(name)) return mWifiManager; - if (Context.USB_SERVICE.equals(name)) return mUsbManager; - if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; - if (Context.USER_SERVICE.equals(name)) return mUserManager; - if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager; - if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; - if (Context.ETHERNET_SERVICE.equals(name)) return mEm; - return super.getSystemService(name); - } - - @Override - public PackageManager getPackageManager() { - return mPackageManager; - } - - @Override - public String getSystemServiceName(Class<?> serviceClass) { - if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE; - return super.getSystemServiceName(serviceClass); - } - } - - public class MockIpServerDependencies extends IpServer.Dependencies { - @Override - public DadProxy getDadProxy( - Handler handler, InterfaceParams ifParams) { - return mDadProxy; - } - - @Override - public RouterAdvertisementDaemon getRouterAdvertisementDaemon( - InterfaceParams ifParams) { - return mRouterAdvertisementDaemon; - } - - @Override - public InterfaceParams getInterfaceParams(String ifName) { - assertTrue("Non-mocked interface " + ifName, - ifName.equals(TEST_USB_IFNAME) - || ifName.equals(TEST_WLAN_IFNAME) - || ifName.equals(TEST_MOBILE_IFNAME) - || ifName.equals(TEST_P2P_IFNAME) - || ifName.equals(TEST_NCM_IFNAME) - || ifName.equals(TEST_ETH_IFNAME)); - final String[] ifaces = new String[] { - TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME, - TEST_NCM_IFNAME, TEST_ETH_IFNAME}; - return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET, - MacAddress.ALL_ZEROS_ADDRESS); - } - - @Override - public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, - DhcpServerCallbacks cb) { - new Thread(() -> { - try { - cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); - } catch (RemoteException e) { - fail(e.getMessage()); - } - }).run(); - } - - public IpNeighborMonitor getIpNeighborMonitor(Handler h, SharedLog l, - IpNeighborMonitor.NeighborEventConsumer c) { - return mIpNeighborMonitor; - } - } - - // MyTetheringConfiguration is used to override static method for testing. - private class MyTetheringConfiguration extends TetheringConfiguration { - MyTetheringConfiguration(Context ctx, SharedLog log, int id) { - super(ctx, log, id); - } - - @Override - protected String getDeviceConfigProperty(final String name) { - return null; - } - - @Override - protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) { - return mResources; - } - } - - public class MockTetheringDependencies extends TetheringDependencies { - StateMachine mUpstreamNetworkMonitorSM; - ArrayList<IpServer> mIpv6CoordinatorNotifyList; - - public void reset() { - mUpstreamNetworkMonitorSM = null; - mIpv6CoordinatorNotifyList = null; - } - - @Override - public BpfCoordinator getBpfCoordinator( - BpfCoordinator.Dependencies deps) { - return mBpfCoordinator; - } - - @Override - public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) { - return mOffloadHardwareInterface; - } - - @Override - public OffloadController getOffloadController(Handler h, SharedLog log, - OffloadController.Dependencies deps) { - mOffloadCtrl = spy(super.getOffloadController(h, log, deps)); - // Return real object here instead of mock because - // testReportFailCallbackIfOffloadNotSupported depend on real OffloadController object. - return mOffloadCtrl; - } - - @Override - public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, - StateMachine target, SharedLog log, int what) { - mUpstreamNetworkMonitorSM = target; - return mUpstreamNetworkMonitor; - } - - @Override - public IPv6TetheringCoordinator getIPv6TetheringCoordinator( - ArrayList<IpServer> notifyList, SharedLog log) { - mIpv6CoordinatorNotifyList = notifyList; - return mIPv6TetheringCoordinator; - } - - @Override - public IpServer.Dependencies getIpServerDependencies() { - return mIpServerDependencies; - } - - @Override - public NetworkRequest getDefaultNetworkRequest() { - return mNetworkRequest; - } - - @Override - public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log, - Runnable callback) { - mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback)); - return mEntitleMgr; - } - - @Override - public boolean isTetheringSupported() { - return true; - } - - @Override - public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log, - int subId) { - mConfig = spy(new MyTetheringConfiguration(ctx, log, subId)); - return mConfig; - } - - @Override - public INetd getINetd(Context context) { - return mNetd; - } - - @Override - public Looper getTetheringLooper() { - return mLooper.getLooper(); - } - - @Override - public Context getContext() { - return mServiceContext; - } - - @Override - public BluetoothAdapter getBluetoothAdapter() { - // TODO: add test for bluetooth tethering. - return null; - } - - @Override - public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) { - return mNotificationUpdater; - } - - @Override - public boolean isTetheringDenied() { - return false; - } - - - @Override - public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx, - TetheringConfiguration cfg) { - mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg); - return mPrivateAddressCoordinator; - } - } - - private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4, - boolean withIPv6, boolean with464xlat) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(TEST_MOBILE_IFNAME); - - if (withIPv4) { - prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - InetAddresses.parseNumericAddress("10.0.0.1"), - TEST_MOBILE_IFNAME, RTN_UNICAST)); - } - - if (withIPv6) { - prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2")); - prop.addLinkAddress( - new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"), - NetworkConstants.RFC7421_PREFIX_LENGTH)); - prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), - InetAddresses.parseNumericAddress("2001:db8::1"), - TEST_MOBILE_IFNAME, RTN_UNICAST)); - } - - if (with464xlat) { - final LinkProperties stackedLink = new LinkProperties(); - stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME); - stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - InetAddresses.parseNumericAddress("192.0.0.1"), - TEST_XLAT_MOBILE_IFNAME, RTN_UNICAST)); - - prop.addStackedLink(stackedLink); - } - - - final NetworkCapabilities capabilities = new NetworkCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - return new UpstreamNetworkState(prop, capabilities, new Network(100)); - } - - private static UpstreamNetworkState buildMobileIPv4UpstreamState() { - return buildMobileUpstreamState(true, false, false); - } - - private static UpstreamNetworkState buildMobileIPv6UpstreamState() { - return buildMobileUpstreamState(false, true, false); - } - - private static UpstreamNetworkState buildMobileDualStackUpstreamState() { - return buildMobileUpstreamState(true, true, false); - } - - private static UpstreamNetworkState buildMobile464xlatUpstreamState() { - return buildMobileUpstreamState(false, true, true); - } - - // See FakeSettingsProvider#clearSettingsProvider() that this needs to be called before and - // after use. - @BeforeClass - public static void setupOnce() { - FakeSettingsProvider.clearSettingsProvider(); - } - - @AfterClass - public static void tearDownOnce() { - FakeSettingsProvider.clearSettingsProvider(); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mResources.getStringArray(R.array.config_tether_dhcp_range)) - .thenReturn(new String[0]); - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - false); - when(mNetd.interfaceGetList()) - .thenReturn(new String[] { - TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME, - TEST_NCM_IFNAME, TEST_ETH_IFNAME}); - when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn(""); - mInterfaceConfiguration = new InterfaceConfigurationParcel(); - mInterfaceConfiguration.flags = new String[0]; - when(mRouterAdvertisementDaemon.start()) - .thenReturn(true); - initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */, - 0 /* defaultDisabled */); - when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats); - - mServiceContext = new TestContext(mContext); - mContentResolver = new MockContentResolver(mServiceContext); - mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); - setTetheringSupported(true /* supported */); - mIntents = new Vector<>(); - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - mIntents.addElement(intent); - } - }; - mServiceContext.registerReceiver(mBroadcastReceiver, - new IntentFilter(ACTION_TETHER_STATE_CHANGED)); - mTethering = makeTethering(); - verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any()); - verify(mNetd).registerUnsolicitedEventListener(any()); - final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)); - verify(mWifiManager).registerSoftApCallback(any(), any()); - mPhoneStateListener = phoneListenerCaptor.getValue(); - } - - private void setTetheringSupported(final boolean supported) { - Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED, - supported ? 1 : 0); - when(mUserManager.hasUserRestriction( - UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(!supported); - // Setup tetherable configuration. - when(mResources.getStringArray(R.array.config_tether_usb_regexs)) - .thenReturn(new String[] { "test_rndis\\d" }); - when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) - .thenReturn(new String[]{ "test_wlan\\d" }); - when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs)) - .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" }); - when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) - .thenReturn(new String[0]); - when(mResources.getStringArray(R.array.config_tether_ncm_regexs)) - .thenReturn(new String[] { "test_ncm\\d" }); - when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]); - when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true); - } - - private void initTetheringUpstream(UpstreamNetworkState upstreamState) { - when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState); - } - - private Tethering makeTethering() { - mTetheringDependencies.reset(); - return new Tethering(mTetheringDependencies); - } - - private TetheringRequestParcel createTetheringRequestParcel(final int type) { - return createTetheringRequestParcel(type, null, null, false); - } - - private TetheringRequestParcel createTetheringRequestParcel(final int type, - final LinkAddress serverAddr, final LinkAddress clientAddr, final boolean exempt) { - final TetheringRequestParcel request = new TetheringRequestParcel(); - request.tetheringType = type; - request.localIPv4Address = serverAddr; - request.staticClientAddress = clientAddr; - request.exemptFromEntitlementCheck = exempt; - request.showProvisioningUi = false; - - return request; - } - - @After - public void tearDown() { - mServiceContext.unregisterReceiver(mBroadcastReceiver); - } - - private void sendWifiApStateChanged(int state) { - final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - intent.putExtra(EXTRA_WIFI_AP_STATE, state); - mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void sendWifiApStateChanged(int state, String ifname, int ipmode) { - final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - intent.putExtra(EXTRA_WIFI_AP_STATE, state); - intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname); - intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode); - mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = { - android.Manifest.permission.ACCESS_FINE_LOCATION, - android.Manifest.permission.ACCESS_WIFI_STATE - }; - - private void sendWifiP2pConnectionChanged( - boolean isGroupFormed, boolean isGroupOwner, String ifname) { - WifiP2pGroup group = null; - WifiP2pInfo p2pInfo = new WifiP2pInfo(); - p2pInfo.groupFormed = isGroupFormed; - if (isGroupFormed) { - p2pInfo.isGroupOwner = isGroupOwner; - group = mock(WifiP2pGroup.class); - when(group.isGroupOwner()).thenReturn(isGroupOwner); - when(group.getInterface()).thenReturn(ifname); - } - - final Intent intent = mock(Intent.class); - when(intent.getAction()).thenReturn(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO)).thenReturn(p2pInfo); - when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)).thenReturn(group); - - mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL, - P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST); - } - - private void sendUsbBroadcast(boolean connected, boolean configured, boolean function, - int type) { - final Intent intent = new Intent(UsbManager.ACTION_USB_STATE); - intent.putExtra(USB_CONNECTED, connected); - intent.putExtra(USB_CONFIGURED, configured); - if (type == TETHERING_USB) { - intent.putExtra(USB_FUNCTION_RNDIS, function); - } else { - intent.putExtra(USB_FUNCTION_NCM, function); - } - mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void sendConfigurationChanged() { - final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); - mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void verifyInterfaceServingModeStarted(String ifname) throws Exception { - verify(mNetd, times(1)).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, times(1)).tetherInterfaceAdd(ifname); - verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, ifname); - verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname), - anyString(), anyString()); - } - - private void verifyTetheringBroadcast(String ifname, String whichExtra) { - // Verify that ifname is in the whichExtra array of the tether state changed broadcast. - final Intent bcast = mIntents.get(0); - assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction()); - final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra); - assertTrue(ifnames.contains(ifname)); - mIntents.remove(bcast); - } - - public void failingLocalOnlyHotspotLegacyApBroadcast( - boolean emulateInterfaceStatusChanged) throws Exception { - // Emulate externally-visible WifiManager effects, causing the - // per-interface state machine to start up, and telling us that - // hotspot mode is to be started. - if (emulateInterfaceStatusChanged) { - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - } - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED); - mLooper.dispatchAll(); - - // If, and only if, Tethering received an interface status changed then - // it creates a IpServer and sends out a broadcast indicating that the - // interface is "available". - if (emulateInterfaceStatusChanged) { - // There is 1 IpServer state change event: STATE_AVAILABLE - verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - } - verifyNoMoreInteractions(mNetd); - verifyNoMoreInteractions(mWifiManager); - } - - private void prepareNcmTethering() { - // Emulate startTethering(TETHERING_NCM) called - mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), null); - mLooper.dispatchAll(); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM); - - mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true); - } - - private void prepareUsbTethering(UpstreamNetworkState upstreamState) { - initTetheringUpstream(upstreamState); - - // Emulate pressing the USB tethering button in Settings UI. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null); - mLooper.dispatchAll(); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - - mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); - } - - @Test - public void testUsbConfiguredBroadcastStartsTethering() throws Exception { - UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - prepareUsbTethering(upstreamState); - - // This should produce no activity of any kind. - verifyNoMoreInteractions(mNetd); - - // Pretend we then receive USB configured broadcast. - sendUsbBroadcast(true, true, true, TETHERING_USB); - mLooper.dispatchAll(); - // Now we should see the start of tethering mechanics (in this case: - // tetherMatchingInterfaces() which starts by fetching all interfaces). - verify(mNetd, times(1)).interfaceGetList(); - - // UpstreamNetworkMonitor should receive selected upstream - verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream(); - verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network); - } - - @Test - public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception { - failingLocalOnlyHotspotLegacyApBroadcast(true); - } - - @Test - public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception { - failingLocalOnlyHotspotLegacyApBroadcast(false); - } - - public void workingLocalOnlyHotspotEnrichedApBroadcast( - boolean emulateInterfaceStatusChanged) throws Exception { - // Emulate externally-visible WifiManager effects, causing the - // per-interface state machine to start up, and telling us that - // hotspot mode is to be started. - if (emulateInterfaceStatusChanged) { - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - } - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - - verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); - verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME); - verify(mNetd, times(1)).tetherStartWithConfiguration(any()); - verifyNoMoreInteractions(mNetd); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - verifyNoMoreInteractions(mWifiManager); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY); - verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks(); - // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY - verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE); - - // Emulate externally-visible WifiManager effects, when hotspot mode - // is being torn down. - sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); - mTethering.interfaceRemoved(TEST_WLAN_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME); - verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME); - // interfaceSetCfg() called once for enabling and twice disabling IPv4. - verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, times(1)).tetherStop(); - verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME); - verify(mWifiManager, times(3)).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verifyNoMoreInteractions(mNetd); - verifyNoMoreInteractions(mWifiManager); - // Asking for the last error after the per-interface state machine - // has been reaped yields an unknown interface error. - assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME)); - } - - /** - * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator. - */ - private void sendIPv6TetherUpdates(UpstreamNetworkState upstreamState) { - // IPv6TetheringCoordinator must have been notified of downstream - verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream( - argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)), - eq(IpServer.STATE_TETHERED)); - - for (IpServer ipSrv : mTetheringDependencies.mIpv6CoordinatorNotifyList) { - UpstreamNetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false); - ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, - upstreamState.linkProperties.isIpv6Provisioned() - ? ipv6OnlyState.linkProperties - : null); - } - mLooper.dispatchAll(); - } - - private void runUsbTethering(UpstreamNetworkState upstreamState) { - prepareUsbTethering(upstreamState); - sendUsbBroadcast(true, true, true, TETHERING_USB); - mLooper.dispatchAll(); - } - - @Test - public void workingMobileUsbTethering_IPv4() throws Exception { - UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - runUsbTethering(upstreamState); - - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - - sendIPv6TetherUpdates(upstreamState); - verify(mDadProxy, never()).setUpstreamIface(notNull()); - verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull()); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - } - - @Test - public void workingMobileUsbTethering_IPv4LegacyDhcp() { - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - true); - sendConfigurationChanged(); - final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - runUsbTethering(upstreamState); - sendIPv6TetherUpdates(upstreamState); - - verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any()); - } - - @Test - public void workingMobileUsbTethering_IPv6() throws Exception { - UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState(); - runUsbTethering(upstreamState); - - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - - sendIPv6TetherUpdates(upstreamState); - // TODO: add interfaceParams to compare in verify. - verify(mDadProxy, times(1)).setUpstreamIface(notNull()); - verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - } - - @Test - public void workingMobileUsbTethering_DualStack() throws Exception { - UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState(); - runUsbTethering(upstreamState); - - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mRouterAdvertisementDaemon, times(1)).start(); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - - sendIPv6TetherUpdates(upstreamState); - verify(mDadProxy, times(1)).setUpstreamIface(notNull()); - verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - } - - @Test - public void workingMobileUsbTethering_MultipleUpstreams() throws Exception { - UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState(); - runUsbTethering(upstreamState); - - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - - sendIPv6TetherUpdates(upstreamState); - verify(mDadProxy, times(1)).setUpstreamIface(notNull()); - verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - } - - @Test - public void workingMobileUsbTethering_v6Then464xlat() throws Exception { - // Setup IPv6 - UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState(); - runUsbTethering(upstreamState); - - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - - // Then 464xlat comes up - upstreamState = buildMobile464xlatUpstreamState(); - initTetheringUpstream(upstreamState); - - // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES. - mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage( - Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK, - UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, - 0, - upstreamState); - mLooper.dispatchAll(); - - // Forwarding is added for 464xlat - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); - // Forwarding was not re-added for v6 (still times(1)) - verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); - // DHCP not restarted on downstream (still times(1)) - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - } - - @Test - public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception { - when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true); - sendConfigurationChanged(); - - // Setup IPv6 - final UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState(); - runUsbTethering(upstreamState); - - // UpstreamNetworkMonitor should choose upstream automatically - // (in this specific case: choose the default network). - verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream(); - verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any()); - - verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network); - } - - private void runNcmTethering() { - prepareNcmTethering(); - sendUsbBroadcast(true, true, true, TETHERING_NCM); - mLooper.dispatchAll(); - } - - @Test - public void workingNcmTethering() throws Exception { - runNcmTethering(); - - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - } - - @Test - public void workingNcmTethering_LegacyDhcp() { - when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( - true); - sendConfigurationChanged(); - runNcmTethering(); - - verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any()); - } - - @Test - public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception { - workingLocalOnlyHotspotEnrichedApBroadcast(true); - } - - @Test - public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception { - workingLocalOnlyHotspotEnrichedApBroadcast(false); - } - - // TODO: Test with and without interfaceStatusChanged(). - @Test - public void failingWifiTetheringLegacyApBroadcast() throws Exception { - when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true); - - // Emulate pressing the WiFi tethering button. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null); - mLooper.dispatchAll(); - verify(mWifiManager, times(1)).startTetheredHotspot(null); - verifyNoMoreInteractions(mWifiManager); - verifyNoMoreInteractions(mNetd); - - // Emulate externally-visible WifiManager effects, causing the - // per-interface state machine to start up, and telling us that - // tethering mode is to be started. - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED); - mLooper.dispatchAll(); - - // There is 1 IpServer state change event: STATE_AVAILABLE - verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verifyNoMoreInteractions(mNetd); - verifyNoMoreInteractions(mWifiManager); - } - - // TODO: Test with and without interfaceStatusChanged(). - @Test - public void workingWifiTetheringEnrichedApBroadcast() throws Exception { - when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true); - - // Emulate pressing the WiFi tethering button. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null); - mLooper.dispatchAll(); - verify(mWifiManager, times(1)).startTetheredHotspot(null); - verifyNoMoreInteractions(mWifiManager); - verifyNoMoreInteractions(mNetd); - - // Emulate externally-visible WifiManager effects, causing the - // per-interface state machine to start up, and telling us that - // tethering mode is to be started. - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - - verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); - verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME); - verify(mNetd, times(1)).tetherStartWithConfiguration(any()); - verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME), - anyString(), anyString()); - verifyNoMoreInteractions(mNetd); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED); - verifyNoMoreInteractions(mWifiManager); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER); - verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks(); - // In tethering mode, in the default configuration, an explicit request - // for a mobile network is also made. - verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest(); - // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_TETHERED - verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE); - verify(mNotificationUpdater, times(1)).onDownstreamChanged(eq(1 << TETHERING_WIFI)); - - ///// - // We do not currently emulate any upstream being found. - // - // This is why there are no calls to verify mNetd.tetherAddForward() or - // mNetd.ipfwdAddInterfaceForward(). - ///// - - // Emulate pressing the WiFi tethering button. - mTethering.stopTethering(TETHERING_WIFI); - mLooper.dispatchAll(); - verify(mWifiManager, times(1)).stopSoftAp(); - verifyNoMoreInteractions(mWifiManager); - verifyNoMoreInteractions(mNetd); - - // Emulate externally-visible WifiManager effects, when tethering mode - // is being torn down. - sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); - mTethering.interfaceRemoved(TEST_WLAN_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME); - verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME); - // interfaceSetCfg() called once for enabling and twice for disabling IPv4. - verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, times(1)).tetherStop(); - verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME); - verify(mWifiManager, times(3)).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verifyNoMoreInteractions(mNetd); - verifyNoMoreInteractions(mWifiManager); - // Asking for the last error after the per-interface state machine - // has been reaped yields an unknown interface error. - assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME)); - } - - // TODO: Test with and without interfaceStatusChanged(). - @Test - public void failureEnablingIpForwarding() throws Exception { - when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true); - doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME); - - // Emulate pressing the WiFi tethering button. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null); - mLooper.dispatchAll(); - verify(mWifiManager, times(1)).startTetheredHotspot(null); - verifyNoMoreInteractions(mWifiManager); - verifyNoMoreInteractions(mNetd); - - // Emulate externally-visible WifiManager effects, causing the - // per-interface state machine to start up, and telling us that - // tethering mode is to be started. - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - - // We verify get/set called three times here: twice for setup and once during - // teardown because all events happen over the course of the single - // dispatchAll() above. Note that once the IpServer IPv4 address config - // code is refactored the two calls during shutdown will revert to one. - verify(mNetd, times(3)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName))); - verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME); - verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME); - verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME), - anyString(), anyString()); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED); - // There are 3 IpServer state change event: - // STATE_AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE. - verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE); - verify(mNotificationUpdater, times(1)).onDownstreamChanged(eq(1 << TETHERING_WIFI)); - verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); - // This is called, but will throw. - verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME); - // This never gets called because of the exception thrown above. - verify(mNetd, times(0)).tetherStartWithConfiguration(any()); - // When the main state machine transitions to an error state it tells - // downstream interfaces, which causes us to tell Wi-Fi about the error - // so it can take down AP mode. - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME); - verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME); - verify(mWifiManager).updateInterfaceIpState( - TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR); - - verifyNoMoreInteractions(mWifiManager); - verifyNoMoreInteractions(mNetd); - } - - private void runUserRestrictionsChange( - boolean currentDisallow, boolean nextDisallow, boolean isTetheringActive, - int expectedInteractionsWithShowNotification) throws Exception { - final Bundle newRestrictions = new Bundle(); - newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow); - final Tethering mockTethering = mock(Tethering.class); - when(mockTethering.isTetheringActive()).thenReturn(isTetheringActive); - when(mUserManager.getUserRestrictions()).thenReturn(newRestrictions); - - final Tethering.UserRestrictionActionListener ural = - new Tethering.UserRestrictionActionListener( - mUserManager, mockTethering, mNotificationUpdater); - ural.mDisallowTethering = currentDisallow; - - ural.onUserRestrictionsChanged(); - - verify(mNotificationUpdater, times(expectedInteractionsWithShowNotification)) - .notifyTetheringDisabledByRestriction(); - verify(mockTethering, times(expectedInteractionsWithShowNotification)).untetherAll(); - } - - @Test - public void testDisallowTetheringWhenTetheringIsNotActive() throws Exception { - final boolean isTetheringActive = false; - final boolean currDisallow = false; - final boolean nextDisallow = true; - final int expectedInteractionsWithShowNotification = 0; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - } - - @Test - public void testDisallowTetheringWhenTetheringIsActive() throws Exception { - final boolean isTetheringActive = true; - final boolean currDisallow = false; - final boolean nextDisallow = true; - final int expectedInteractionsWithShowNotification = 1; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - } - - @Test - public void testAllowTetheringWhenTetheringIsNotActive() throws Exception { - final boolean isTetheringActive = false; - final boolean currDisallow = true; - final boolean nextDisallow = false; - final int expectedInteractionsWithShowNotification = 0; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - } - - @Test - public void testAllowTetheringWhenTetheringIsActive() throws Exception { - final boolean isTetheringActive = true; - final boolean currDisallow = true; - final boolean nextDisallow = false; - final int expectedInteractionsWithShowNotification = 0; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - } - - @Test - public void testDisallowTetheringUnchanged() throws Exception { - final boolean isTetheringActive = true; - final int expectedInteractionsWithShowNotification = 0; - boolean currDisallow = true; - boolean nextDisallow = true; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - - currDisallow = false; - nextDisallow = false; - - runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive, - expectedInteractionsWithShowNotification); - } - - private class TestTetheringEventCallback extends ITetheringEventCallback.Stub { - private final ArrayList<Network> mActualUpstreams = new ArrayList<>(); - private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs = - new ArrayList<>(); - private final ArrayList<TetherStatesParcel> mTetherStates = new ArrayList<>(); - private final ArrayList<Integer> mOffloadStatus = new ArrayList<>(); - - // This function will remove the recorded callbacks, so it must be called once for - // each callback. If this is called after multiple callback, the order matters. - // onCallbackCreated counts as the first call to expectUpstreamChanged with - // @see onCallbackCreated. - public void expectUpstreamChanged(Network... networks) { - if (networks == null) { - assertNoUpstreamChangeCallback(); - return; - } - - final ArrayList<Network> expectedUpstreams = - new ArrayList<Network>(Arrays.asList(networks)); - for (Network upstream : expectedUpstreams) { - // throws OOB if no expectations - assertEquals(mActualUpstreams.remove(0), upstream); - } - assertNoUpstreamChangeCallback(); - } - - // This function will remove the recorded callbacks, so it must be called once - // for each callback. If this is called after multiple callback, the order matters. - // onCallbackCreated counts as the first call to onConfigurationChanged with - // @see onCallbackCreated. - public void expectConfigurationChanged(TetheringConfigurationParcel... tetherConfigs) { - final ArrayList<TetheringConfigurationParcel> expectedTetherConfig = - new ArrayList<TetheringConfigurationParcel>(Arrays.asList(tetherConfigs)); - for (TetheringConfigurationParcel config : expectedTetherConfig) { - // throws OOB if no expectations - final TetheringConfigurationParcel actualConfig = mTetheringConfigs.remove(0); - assertTetherConfigParcelEqual(actualConfig, config); - } - assertNoConfigChangeCallback(); - } - - public void expectOffloadStatusChanged(final int expectedStatus) { - assertOffloadStatusChangedCallback(); - assertEquals(mOffloadStatus.remove(0), new Integer(expectedStatus)); - } - - public TetherStatesParcel pollTetherStatesChanged() { - assertStateChangeCallback(); - return mTetherStates.remove(0); - } - - @Override - public void onUpstreamChanged(Network network) { - mActualUpstreams.add(network); - } - - @Override - public void onConfigurationChanged(TetheringConfigurationParcel config) { - mTetheringConfigs.add(config); - } - - @Override - public void onTetherStatesChanged(TetherStatesParcel states) { - mTetherStates.add(states); - } - - @Override - public void onTetherClientsChanged(List<TetheredClient> clients) { - // TODO: check this - } - - @Override - public void onOffloadStatusChanged(final int status) { - mOffloadStatus.add(status); - } - - @Override - public void onCallbackStarted(TetheringCallbackStartedParcel parcel) { - mActualUpstreams.add(parcel.upstreamNetwork); - mTetheringConfigs.add(parcel.config); - mTetherStates.add(parcel.states); - mOffloadStatus.add(parcel.offloadStatus); - } - - @Override - public void onCallbackStopped(int errorCode) { } - - public void assertNoUpstreamChangeCallback() { - assertTrue(mActualUpstreams.isEmpty()); - } - - public void assertNoConfigChangeCallback() { - assertTrue(mTetheringConfigs.isEmpty()); - } - - public void assertNoStateChangeCallback() { - assertTrue(mTetherStates.isEmpty()); - } - - public void assertStateChangeCallback() { - assertFalse(mTetherStates.isEmpty()); - } - - public void assertOffloadStatusChangedCallback() { - assertFalse(mOffloadStatus.isEmpty()); - } - - public void assertNoCallback() { - assertNoUpstreamChangeCallback(); - assertNoConfigChangeCallback(); - assertNoStateChangeCallback(); - } - - private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual, - @NonNull TetheringConfigurationParcel expect) { - assertEquals(actual.subId, expect.subId); - assertArrayEquals(actual.tetherableUsbRegexs, expect.tetherableUsbRegexs); - assertArrayEquals(actual.tetherableWifiRegexs, expect.tetherableWifiRegexs); - assertArrayEquals(actual.tetherableBluetoothRegexs, expect.tetherableBluetoothRegexs); - assertEquals(actual.isDunRequired, expect.isDunRequired); - assertEquals(actual.chooseUpstreamAutomatically, expect.chooseUpstreamAutomatically); - assertArrayEquals(actual.preferredUpstreamIfaceTypes, - expect.preferredUpstreamIfaceTypes); - assertArrayEquals(actual.legacyDhcpRanges, expect.legacyDhcpRanges); - assertArrayEquals(actual.defaultIPv4DNS, expect.defaultIPv4DNS); - assertEquals(actual.enableLegacyDhcpServer, expect.enableLegacyDhcpServer); - assertArrayEquals(actual.provisioningApp, expect.provisioningApp); - assertEquals(actual.provisioningAppNoUi, expect.provisioningAppNoUi); - assertEquals(actual.provisioningCheckPeriod, expect.provisioningCheckPeriod); - } - } - - private void assertTetherStatesNotNullButEmpty(final TetherStatesParcel parcel) { - assertFalse(parcel == null); - assertEquals(0, parcel.availableList.length); - assertEquals(0, parcel.tetheredList.length); - assertEquals(0, parcel.localOnlyList.length); - assertEquals(0, parcel.erroredIfaceList.length); - assertEquals(0, parcel.lastErrorList.length); - MiscAsserts.assertFieldCountEquals(5, TetherStatesParcel.class); - } - - @Test - public void testRegisterTetheringEventCallback() throws Exception { - TestTetheringEventCallback callback = new TestTetheringEventCallback(); - TestTetheringEventCallback callback2 = new TestTetheringEventCallback(); - - // 1. Register one callback before running any tethering. - mTethering.registerTetheringEventCallback(callback); - mLooper.dispatchAll(); - callback.expectUpstreamChanged(new Network[] {null}); - callback.expectConfigurationChanged( - mTethering.getTetheringConfiguration().toStableParcelable()); - TetherStatesParcel tetherState = callback.pollTetherStatesChanged(); - assertTetherStatesNotNullButEmpty(tetherState); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - // 2. Enable wifi tethering. - UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState(); - initTetheringUpstream(upstreamState); - when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true); - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); - mLooper.dispatchAll(); - tetherState = callback.pollTetherStatesChanged(); - assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME}); - - mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null); - sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - tetherState = callback.pollTetherStatesChanged(); - assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME}); - callback.expectUpstreamChanged(upstreamState.network); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED); - - // 3. Register second callback. - mTethering.registerTetheringEventCallback(callback2); - mLooper.dispatchAll(); - callback2.expectUpstreamChanged(upstreamState.network); - callback2.expectConfigurationChanged( - mTethering.getTetheringConfiguration().toStableParcelable()); - tetherState = callback2.pollTetherStatesChanged(); - assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME}); - callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED); - - // 4. Unregister first callback and disable wifi tethering - mTethering.unregisterTetheringEventCallback(callback); - mLooper.dispatchAll(); - mTethering.stopTethering(TETHERING_WIFI); - sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); - mLooper.dispatchAll(); - tetherState = callback2.pollTetherStatesChanged(); - assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME}); - mLooper.dispatchAll(); - callback2.expectUpstreamChanged(new Network[] {null}); - callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - callback.assertNoCallback(); - } - - @Test - public void testReportFailCallbackIfOffloadNotSupported() throws Exception { - final UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState(); - TestTetheringEventCallback callback = new TestTetheringEventCallback(); - mTethering.registerTetheringEventCallback(callback); - mLooper.dispatchAll(); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - - // 1. Offload fail if no OffloadConfig. - initOffloadConfiguration(false /* offloadConfig */, true /* offloadControl */, - 0 /* defaultDisabled */); - runUsbTethering(upstreamState); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); - runStopUSBTethering(); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - reset(mUsbManager); - // 2. Offload fail if no OffloadControl. - initOffloadConfiguration(true /* offloadConfig */, false /* offloadControl */, - 0 /* defaultDisabled */); - runUsbTethering(upstreamState); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); - runStopUSBTethering(); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - reset(mUsbManager); - // 3. Offload fail if disabled by settings. - initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */, - 1 /* defaultDisabled */); - runUsbTethering(upstreamState); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); - runStopUSBTethering(); - callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - } - - private void runStopUSBTethering() { - mTethering.stopTethering(TETHERING_USB); - mLooper.dispatchAll(); - mTethering.interfaceRemoved(TEST_USB_IFNAME); - mLooper.dispatchAll(); - } - - private void initOffloadConfiguration(final boolean offloadConfig, - final boolean offloadControl, final int defaultDisabled) { - when(mOffloadHardwareInterface.initOffloadConfig()).thenReturn(offloadConfig); - when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControl); - when(mOffloadHardwareInterface.getDefaultTetherOffloadDisabled()).thenReturn( - defaultDisabled); - } - - @Test - public void testMultiSimAware() throws Exception { - final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration(); - assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.activeDataSubId); - - final int fakeSubId = 1234; - mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId); - final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration(); - assertEquals(fakeSubId, newConfig.activeDataSubId); - verify(mNotificationUpdater, times(1)).onActiveDataSubscriptionIdChanged(eq(fakeSubId)); - } - - @Test - public void testNoDuplicatedEthernetRequest() throws Exception { - final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class); - when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest); - mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null); - mLooper.dispatchAll(); - verify(mEm, times(1)).requestTetheredInterface(any(), any()); - mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null); - mLooper.dispatchAll(); - verifyNoMoreInteractions(mEm); - mTethering.stopTethering(TETHERING_ETHERNET); - mLooper.dispatchAll(); - verify(mockRequest, times(1)).release(); - mTethering.stopTethering(TETHERING_ETHERNET); - mLooper.dispatchAll(); - verifyNoMoreInteractions(mEm); - } - - private void workingWifiP2pGroupOwner( - boolean emulateInterfaceStatusChanged) throws Exception { - if (emulateInterfaceStatusChanged) { - mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true); - } - sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME); - mLooper.dispatchAll(); - - verifyInterfaceServingModeStarted(TEST_P2P_IFNAME); - verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER); - verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME); - verify(mNetd, times(1)).tetherStartWithConfiguration(any()); - verifyNoMoreInteractions(mNetd); - verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY); - verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks(); - // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY - verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE); - - assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME)); - - // Emulate externally-visible WifiP2pManager effects, when wifi p2p group - // is being removed. - sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME); - mTethering.interfaceRemoved(TEST_P2P_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, times(1)).tetherApplyDnsInterfaces(); - verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME); - verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME); - // interfaceSetCfg() called once for enabling and twice for disabling IPv4. - verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, times(1)).tetherStop(); - verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME); - verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream(); - verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any()); - verifyNoMoreInteractions(mNetd); - // Asking for the last error after the per-interface state machine - // has been reaped yields an unknown interface error. - assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); - } - - private void workingWifiP2pGroupClient( - boolean emulateInterfaceStatusChanged) throws Exception { - if (emulateInterfaceStatusChanged) { - mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true); - } - sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME); - verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME); - verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME); - verify(mNetd, never()).tetherStartWithConfiguration(any()); - - // Emulate externally-visible WifiP2pManager effects, when wifi p2p group - // is being removed. - sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME); - mTethering.interfaceRemoved(TEST_P2P_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, never()).tetherApplyDnsInterfaces(); - verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME); - verify(mNetd, never()).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME); - verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, never()).tetherStop(); - verify(mNetd, never()).ipfwdDisableForwarding(TETHERING_NAME); - verifyNoMoreInteractions(mNetd); - // Asking for the last error after the per-interface state machine - // has been reaped yields an unknown interface error. - assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); - } - - @Test - public void workingWifiP2pGroupOwnerWithIfaceChanged() throws Exception { - workingWifiP2pGroupOwner(true); - } - - @Test - public void workingWifiP2pGroupOwnerSansIfaceChanged() throws Exception { - workingWifiP2pGroupOwner(false); - } - - private void workingWifiP2pGroupOwnerLegacyMode( - boolean emulateInterfaceStatusChanged) throws Exception { - // change to legacy mode and update tethering information by chaning SIM - when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs)) - .thenReturn(new String[]{}); - final int fakeSubId = 1234; - mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId); - - if (emulateInterfaceStatusChanged) { - mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true); - } - sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME); - mLooper.dispatchAll(); - - verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class)); - verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME); - verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME); - verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME); - verify(mNetd, never()).tetherStartWithConfiguration(any()); - assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); - } - @Test - public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception { - workingWifiP2pGroupOwnerLegacyMode(true); - } - - @Test - public void workingWifiP2pGroupOwnerLegacyModeSansIfaceChanged() throws Exception { - workingWifiP2pGroupOwnerLegacyMode(false); - } - - @Test - public void workingWifiP2pGroupClientWithIfaceChanged() throws Exception { - workingWifiP2pGroupClient(true); - } - - @Test - public void workingWifiP2pGroupClientSansIfaceChanged() throws Exception { - workingWifiP2pGroupClient(false); - } - - private void setDataSaverEnabled(boolean enabled) { - final Intent intent = new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED); - mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL); - - final int status = enabled ? RESTRICT_BACKGROUND_STATUS_ENABLED - : RESTRICT_BACKGROUND_STATUS_DISABLED; - when(mCm.getRestrictBackgroundStatus()).thenReturn(status); - mLooper.dispatchAll(); - } - - @Test - public void testDataSaverChanged() { - // Start Tethering. - final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - runUsbTethering(upstreamState); - assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME); - // Data saver is ON. - setDataSaverEnabled(true); - // Verify that tethering should be disabled. - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE); - mTethering.interfaceRemoved(TEST_USB_IFNAME); - mLooper.dispatchAll(); - assertEquals(mTethering.getTetheredIfaces(), new String[0]); - reset(mUsbManager); - - runUsbTethering(upstreamState); - // Verify that user can start tethering again without turning OFF data saver. - assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME); - - // If data saver is keep ON with change event, tethering should not be OFF this time. - setDataSaverEnabled(true); - verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE); - assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME); - - // If data saver is turned OFF, it should not change tethering. - setDataSaverEnabled(false); - verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE); - assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME); - } - - private static <T> void assertContains(Collection<T> collection, T element) { - assertTrue(element + " not found in " + collection, collection.contains(element)); - } - - private class ResultListener extends IIntResultListener.Stub { - private final int mExpectedResult; - private boolean mHasResult = false; - ResultListener(final int expectedResult) { - mExpectedResult = expectedResult; - } - - @Override - public void onResult(final int resultCode) { - mHasResult = true; - if (resultCode != mExpectedResult) { - fail("expected result: " + mExpectedResult + " but actual result: " + resultCode); - } - } - - public void assertHasResult() { - if (!mHasResult) fail("No callback result"); - } - } - - @Test - public void testMultipleStartTethering() throws Exception { - final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24"); - final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24"); - final String serverAddr = "192.168.20.1"; - final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR); - final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR); - final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR); - - // Enable USB tethering and check that Tethering starts USB. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null, false), firstResult); - mLooper.dispatchAll(); - firstResult.assertHasResult(); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - verifyNoMoreInteractions(mUsbManager); - - // Enable USB tethering again with the same request and expect no change to USB. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null, false), secondResult); - mLooper.dispatchAll(); - secondResult.assertHasResult(); - verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE); - reset(mUsbManager); - - // Enable USB tethering with a different request and expect that USB is stopped and - // started. - mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr, false), thirdResult); - mLooper.dispatchAll(); - thirdResult.assertHasResult(); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - - // Expect that when USB comes up, the DHCP server is configured with the requested address. - mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); - sendUsbBroadcast(true, true, true, TETHERING_USB); - mLooper.dispatchAll(); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr))); - } - - @Test - public void testRequestStaticIp() throws Exception { - final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24"); - final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24"); - final String serverAddr = "192.168.0.123"; - final int clientAddrParceled = 0xc0a8002a; - final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor = - ArgumentCaptor.forClass(DhcpServingParamsParcel.class); - mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr, false), null); - mLooper.dispatchAll(); - verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); - sendUsbBroadcast(true, true, true, TETHERING_USB); - mLooper.dispatchAll(); - verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr))); - verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(), - any()); - final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue(); - assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress()); - assertEquals(24, params.serverAddrPrefixLength); - assertEquals(clientAddrParceled, params.singleClientAddr); - } - - @Test - public void testUpstreamNetworkChanged() { - final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM) - mTetheringDependencies.mUpstreamNetworkMonitorSM; - final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - initTetheringUpstream(upstreamState); - stateMachine.chooseUpstreamType(true); - - verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network)); - verify(mNotificationUpdater, times(1)).onUpstreamCapabilitiesChanged(any()); - } - - @Test - public void testUpstreamCapabilitiesChanged() { - final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM) - mTetheringDependencies.mUpstreamNetworkMonitorSM; - final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - initTetheringUpstream(upstreamState); - stateMachine.chooseUpstreamType(true); - - stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState); - // Should have two onUpstreamCapabilitiesChanged(). - // One is called by reportUpstreamChanged(). One is called by EVENT_ON_CAPABILITIES. - verify(mNotificationUpdater, times(2)).onUpstreamCapabilitiesChanged(any()); - reset(mNotificationUpdater); - - // Verify that onUpstreamCapabilitiesChanged won't be called if not current upstream network - // capabilities changed. - final UpstreamNetworkState upstreamState2 = new UpstreamNetworkState( - upstreamState.linkProperties, upstreamState.networkCapabilities, new Network(101)); - stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2); - verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any()); - } - - @Test - public void testDumpTetheringLog() throws Exception { - final FileDescriptor mockFd = mock(FileDescriptor.class); - final PrintWriter mockPw = mock(PrintWriter.class); - runUsbTethering(null); - mLooper.startAutoDispatch(); - mTethering.dump(mockFd, mockPw, new String[0]); - verify(mConfig).dump(any()); - verify(mEntitleMgr).dump(any()); - verify(mOffloadCtrl).dump(any()); - mLooper.stopAutoDispatch(); - } - - @Test - public void testExemptFromEntitlementCheck() throws Exception { - setupForRequiredProvisioning(); - final TetheringRequestParcel wifiNotExemptRequest = - createTetheringRequestParcel(TETHERING_WIFI, null, null, false); - mTethering.startTethering(wifiNotExemptRequest, null); - mLooper.dispatchAll(); - verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false); - verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI); - assertFalse(mEntitleMgr.isCellularUpstreamPermitted()); - mTethering.stopTethering(TETHERING_WIFI); - mLooper.dispatchAll(); - verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); - reset(mEntitleMgr); - - setupForRequiredProvisioning(); - final TetheringRequestParcel wifiExemptRequest = - createTetheringRequestParcel(TETHERING_WIFI, null, null, true); - mTethering.startTethering(wifiExemptRequest, null); - mLooper.dispatchAll(); - verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false); - verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI); - assertTrue(mEntitleMgr.isCellularUpstreamPermitted()); - mTethering.stopTethering(TETHERING_WIFI); - mLooper.dispatchAll(); - verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); - reset(mEntitleMgr); - - // If one app enables tethering without provisioning check first, then another app enables - // tethering of the same type but does not disable the provisioning check. - setupForRequiredProvisioning(); - mTethering.startTethering(wifiExemptRequest, null); - mLooper.dispatchAll(); - verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false); - verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI); - assertTrue(mEntitleMgr.isCellularUpstreamPermitted()); - reset(mEntitleMgr); - setupForRequiredProvisioning(); - mTethering.startTethering(wifiNotExemptRequest, null); - mLooper.dispatchAll(); - verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false); - verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI); - assertFalse(mEntitleMgr.isCellularUpstreamPermitted()); - mTethering.stopTethering(TETHERING_WIFI); - mLooper.dispatchAll(); - verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); - reset(mEntitleMgr); - } - - private void setupForRequiredProvisioning() { - // Produce some acceptable looking provision app setting if requested. - when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) - .thenReturn(PROVISIONING_APP_NAME); - when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui)) - .thenReturn(PROVISIONING_NO_UI_APP_NAME); - // Act like the CarrierConfigManager is present and ready unless told otherwise. - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(mCarrierConfigManager); - when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig); - mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); - mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); - sendConfigurationChanged(); - } - - private static UpstreamNetworkState buildV4UpstreamState(final LinkAddress address, - final Network network, final String iface, final int transportType) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(iface); - - prop.addLinkAddress(address); - - final NetworkCapabilities capabilities = new NetworkCapabilities() - .addTransportType(transportType); - return new UpstreamNetworkState(prop, capabilities, network); - } - - private void updateV4Upstream(final LinkAddress ipv4Address, final Network network, - final String iface, final int transportType) { - final UpstreamNetworkState upstream = buildV4UpstreamState(ipv4Address, network, iface, - transportType); - mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage( - Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK, - UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, - 0, - upstream); - mLooper.dispatchAll(); - } - - @Test - public void testHandleIpConflict() throws Exception { - final Network wifiNetwork = new Network(200); - final Network[] allNetworks = { wifiNetwork }; - when(mCm.getAllNetworks()).thenReturn(allNetworks); - runUsbTethering(null); - final ArgumentCaptor<InterfaceConfigurationParcel> ifaceConfigCaptor = - ArgumentCaptor.forClass(InterfaceConfigurationParcel.class); - verify(mNetd).interfaceSetCfg(ifaceConfigCaptor.capture()); - final String ipv4Address = ifaceConfigCaptor.getValue().ipv4Addr; - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - reset(mNetd, mUsbManager); - - // Cause a prefix conflict by assigning a /30 out of the downstream's /24 to the upstream. - updateV4Upstream(new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address), 30), - wifiNetwork, TEST_WIFI_IFNAME, TRANSPORT_WIFI); - // verify turn off usb tethering - verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE); - mTethering.interfaceRemoved(TEST_USB_IFNAME); - mLooper.dispatchAll(); - // verify restart usb tethering - verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - } - - @Test - public void testNoAddressAvailable() throws Exception { - final Network wifiNetwork = new Network(200); - final Network btNetwork = new Network(201); - final Network mobileNetwork = new Network(202); - final Network[] allNetworks = { wifiNetwork, btNetwork, mobileNetwork }; - when(mCm.getAllNetworks()).thenReturn(allNetworks); - runUsbTethering(null); - verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks( - any(), any()); - reset(mUsbManager); - final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class); - when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest); - final ArgumentCaptor<TetheredInterfaceCallback> callbackCaptor = - ArgumentCaptor.forClass(TetheredInterfaceCallback.class); - mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null); - mLooper.dispatchAll(); - verify(mEm).requestTetheredInterface(any(), callbackCaptor.capture()); - TetheredInterfaceCallback ethCallback = callbackCaptor.getValue(); - ethCallback.onAvailable(TEST_ETH_IFNAME); - mLooper.dispatchAll(); - reset(mUsbManager, mEm); - - updateV4Upstream(new LinkAddress("192.168.0.100/16"), wifiNetwork, TEST_WIFI_IFNAME, - TRANSPORT_WIFI); - updateV4Upstream(new LinkAddress("172.16.0.0/12"), btNetwork, TEST_BT_IFNAME, - TRANSPORT_BLUETOOTH); - updateV4Upstream(new LinkAddress("10.0.0.0/8"), mobileNetwork, TEST_MOBILE_IFNAME, - TRANSPORT_CELLULAR); - - mLooper.dispatchAll(); - // verify turn off usb tethering - verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE); - // verify turn off ethernet tethering - verify(mockRequest).release(); - mTethering.interfaceRemoved(TEST_USB_IFNAME); - ethCallback.onUnavailable(); - mLooper.dispatchAll(); - // verify restart usb tethering - verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); - // verify restart ethernet tethering - verify(mEm).requestTetheredInterface(any(), callbackCaptor.capture()); - ethCallback = callbackCaptor.getValue(); - ethCallback.onAvailable(TEST_ETH_IFNAME); - - reset(mUsbManager, mEm); - when(mNetd.interfaceGetList()) - .thenReturn(new String[] { - TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME, - TEST_NCM_IFNAME, TEST_ETH_IFNAME}); - - mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); - sendUsbBroadcast(true, true, true, TETHERING_USB); - mLooper.dispatchAll(); - assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_USB_IFNAME); - assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_ETH_IFNAME); - assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_USB_IFNAME)); - assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME)); - } - - @Test - public void testProvisioningNeededButUnavailable() throws Exception { - assertTrue(mTethering.isTetheringSupported()); - verify(mPackageManager, never()).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES); - - setupForRequiredProvisioning(); - assertTrue(mTethering.isTetheringSupported()); - verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES); - reset(mPackageManager); - - doThrow(PackageManager.NameNotFoundException.class).when(mPackageManager).getPackageInfo( - PROVISIONING_APP_NAME[0], GET_ACTIVITIES); - setupForRequiredProvisioning(); - assertFalse(mTethering.isTetheringSupported()); - verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES); - } - - // TODO: Test that a request for hotspot mode doesn't interfere with an - // already operating tethering mode interface. -} diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java deleted file mode 100644 index 232588c7eec0..000000000000 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.networkstack.tethering; - -import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; -import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; - -import static com.android.networkstack.tethering.UpstreamNetworkMonitor.TYPE_NONE; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.IConnectivityManager; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.Message; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class UpstreamNetworkMonitorTest { - private static final int EVENT_UNM_UPDATE = 1; - - private static final boolean INCLUDES = true; - private static final boolean EXCLUDES = false; - - // Actual contents of the request don't matter for this test. The lack of - // any specific TRANSPORT_* is sufficient to identify this request. - private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build(); - - @Mock private Context mContext; - @Mock private EntitlementManager mEntitleMgr; - @Mock private IConnectivityManager mCS; - @Mock private SharedLog mLog; - - private TestStateMachine mSM; - private TestConnectivityManager mCM; - private UpstreamNetworkMonitor mUNM; - - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - reset(mContext); - reset(mCS); - reset(mLog); - when(mLog.forSubComponent(anyString())).thenReturn(mLog); - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); - - mCM = spy(new TestConnectivityManager(mContext, mCS)); - mSM = new TestStateMachine(); - mUNM = new UpstreamNetworkMonitor( - (ConnectivityManager) mCM, mSM, mLog, EVENT_UNM_UPDATE); - } - - @After public void tearDown() throws Exception { - if (mSM != null) { - mSM.quit(); - mSM = null; - } - } - - @Test - public void testStopWithoutStartIsNonFatal() { - mUNM.stop(); - mUNM.stop(); - mUNM.stop(); - } - - @Test - public void testDoesNothingBeforeTrackDefaultAndStarted() throws Exception { - assertTrue(mCM.hasNoCallbacks()); - assertFalse(mUNM.mobileNetworkRequested()); - - mUNM.updateMobileRequiresDun(true); - assertTrue(mCM.hasNoCallbacks()); - mUNM.updateMobileRequiresDun(false); - assertTrue(mCM.hasNoCallbacks()); - } - - @Test - public void testDefaultNetworkIsTracked() throws Exception { - assertTrue(mCM.hasNoCallbacks()); - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - - mUNM.startObserveAllNetworks(); - assertEquals(1, mCM.trackingDefault.size()); - - mUNM.stop(); - assertTrue(mCM.onlyHasDefaultCallbacks()); - } - - @Test - public void testListensForAllNetworks() throws Exception { - assertTrue(mCM.listening.isEmpty()); - - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - mUNM.startObserveAllNetworks(); - assertFalse(mCM.listening.isEmpty()); - assertTrue(mCM.isListeningForAll()); - - mUNM.stop(); - assertTrue(mCM.onlyHasDefaultCallbacks()); - } - - @Test - public void testCallbacksRegistered() { - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - verify(mCM, times(1)).requestNetwork( - eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class)); - mUNM.startObserveAllNetworks(); - verify(mCM, times(1)).registerNetworkCallback( - any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class)); - - mUNM.stop(); - verify(mCM, times(1)).unregisterNetworkCallback(any(NetworkCallback.class)); - } - - @Test - public void testRequestsMobileNetwork() throws Exception { - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.startObserveAllNetworks(); - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.updateMobileRequiresDun(false); - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.registerMobileNetworkRequest(); - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(isDunRequested()); - - mUNM.stop(); - assertFalse(mUNM.mobileNetworkRequested()); - assertTrue(mCM.hasNoCallbacks()); - } - - @Test - public void testDuplicateMobileRequestsIgnored() throws Exception { - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.startObserveAllNetworks(); - verify(mCM, times(1)).registerNetworkCallback( - any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class)); - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.updateMobileRequiresDun(true); - mUNM.registerMobileNetworkRequest(); - verify(mCM, times(1)).requestNetwork( - any(NetworkRequest.class), anyInt(), anyInt(), any(Handler.class), - any(NetworkCallback.class)); - - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(isDunRequested()); - - // Try a few things that must not result in any state change. - mUNM.registerMobileNetworkRequest(); - mUNM.updateMobileRequiresDun(true); - mUNM.registerMobileNetworkRequest(); - - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(isDunRequested()); - - mUNM.stop(); - verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class)); - - verifyNoMoreInteractions(mCM); - } - - @Test - public void testRequestsDunNetwork() throws Exception { - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.startObserveAllNetworks(); - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.updateMobileRequiresDun(true); - assertFalse(mUNM.mobileNetworkRequested()); - assertEquals(0, mCM.requested.size()); - - mUNM.registerMobileNetworkRequest(); - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(isDunRequested()); - - mUNM.stop(); - assertFalse(mUNM.mobileNetworkRequested()); - assertTrue(mCM.hasNoCallbacks()); - } - - @Test - public void testUpdateMobileRequiresDun() throws Exception { - mUNM.startObserveAllNetworks(); - - // Test going from no-DUN to DUN correctly re-registers callbacks. - mUNM.updateMobileRequiresDun(false); - mUNM.registerMobileNetworkRequest(); - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(isDunRequested()); - mUNM.updateMobileRequiresDun(true); - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(isDunRequested()); - - // Test going from DUN to no-DUN correctly re-registers callbacks. - mUNM.updateMobileRequiresDun(false); - assertTrue(mUNM.mobileNetworkRequested()); - assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(isDunRequested()); - - mUNM.stop(); - assertFalse(mUNM.mobileNetworkRequested()); - } - - @Test - public void testSelectPreferredUpstreamType() throws Exception { - final Collection<Integer> preferredTypes = new ArrayList<>(); - preferredTypes.add(TYPE_WIFI); - - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - mUNM.startObserveAllNetworks(); - // There are no networks, so there is nothing to select. - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - - final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); - wifiAgent.fakeConnect(); - // WiFi is up, we should prefer it. - assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); - wifiAgent.fakeDisconnect(); - // There are no networks, so there is nothing to select. - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - - final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - cellAgent.fakeConnect(); - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - - preferredTypes.add(TYPE_MOBILE_DUN); - // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(true); - // DUN is available, but only use regular cell: no upstream selected. - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - preferredTypes.remove(TYPE_MOBILE_DUN); - // No WiFi, but our preferred flavour of cell is up. - preferredTypes.add(TYPE_MOBILE_HIPRI); - // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(false); - assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, - mUNM.selectPreferredUpstreamType(preferredTypes)); - // Check to see we filed an explicit request. - assertEquals(1, mCM.requested.size()); - NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; - assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); - assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); - // mobile is not permitted, we should not use HIPRI. - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - assertEquals(0, mCM.requested.size()); - // mobile change back to permitted, HIRPI should come back - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); - assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, - mUNM.selectPreferredUpstreamType(preferredTypes)); - - wifiAgent.fakeConnect(); - // WiFi is up, and we should prefer it over cell. - assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); - assertEquals(0, mCM.requested.size()); - - preferredTypes.remove(TYPE_MOBILE_HIPRI); - preferredTypes.add(TYPE_MOBILE_DUN); - // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(true); - assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); - - final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); - dunAgent.fakeConnect(); - - // WiFi is still preferred. - assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); - - // WiFi goes down, cell and DUN are still up but only DUN is preferred. - wifiAgent.fakeDisconnect(); - assertSatisfiesLegacyType(TYPE_MOBILE_DUN, - mUNM.selectPreferredUpstreamType(preferredTypes)); - // Check to see we filed an explicit request. - assertEquals(1, mCM.requested.size()); - netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; - assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); - assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); - // mobile is not permitted, we should not use DUN. - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); - assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); - assertEquals(0, mCM.requested.size()); - // mobile change back to permitted, DUN should come back - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); - assertSatisfiesLegacyType(TYPE_MOBILE_DUN, - mUNM.selectPreferredUpstreamType(preferredTypes)); - } - - @Test - public void testGetCurrentPreferredUpstream() throws Exception { - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - mUNM.startObserveAllNetworks(); - mUNM.updateMobileRequiresDun(false); - - // [0] Mobile connects, DUN not required -> mobile selected. - final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - cellAgent.fakeConnect(); - mCM.makeDefaultNetwork(cellAgent); - assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - - // [1] Mobile connects but not permitted -> null selected - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); - assertEquals(null, mUNM.getCurrentPreferredUpstream()); - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); - - // [2] WiFi connects but not validated/promoted to default -> mobile selected. - final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); - wifiAgent.fakeConnect(); - assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - - // [3] WiFi validates and is promoted to the default network -> WiFi selected. - mCM.makeDefaultNetwork(wifiAgent); - assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - - // [4] DUN required, no other changes -> WiFi still selected - mUNM.updateMobileRequiresDun(true); - assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - - // [5] WiFi no longer validated, mobile becomes default, DUN required -> null selected. - mCM.makeDefaultNetwork(cellAgent); - assertEquals(null, mUNM.getCurrentPreferredUpstream()); - // TODO: make sure that a DUN request has been filed. This is currently - // triggered by code over in Tethering, but once that has been moved - // into UNM we should test for this here. - - // [6] DUN network arrives -> DUN selected - final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); - dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); - dunAgent.fakeConnect(); - assertEquals(dunAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - - // [7] Mobile is not permitted -> null selected - when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); - assertEquals(null, mUNM.getCurrentPreferredUpstream()); - } - - @Test - public void testLocalPrefixes() throws Exception { - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - mUNM.startObserveAllNetworks(); - - // [0] Test minimum set of local prefixes. - Set<IpPrefix> local = mUNM.getLocalPrefixes(); - assertTrue(local.isEmpty()); - - final Set<String> alreadySeen = new HashSet<>(); - - // [1] Pretend Wi-Fi connects. - final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); - final LinkProperties wifiLp = wifiAgent.linkProperties; - wifiLp.setInterfaceName("wlan0"); - final String[] wifi_addrs = { - "fe80::827a:bfff:fe6f:374d", "100.112.103.18", - "2001:db8:4:fd00:827a:bfff:fe6f:374d", - "2001:db8:4:fd00:6dea:325a:fdae:4ef4", - "fd6a:a640:60bf:e985::123", // ULA address for good measure. - }; - for (String addrStr : wifi_addrs) { - final String cidr = addrStr.contains(":") ? "/64" : "/20"; - wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr)); - } - wifiAgent.fakeConnect(); - wifiAgent.sendLinkProperties(); - - local = mUNM.getLocalPrefixes(); - assertPrefixSet(local, INCLUDES, alreadySeen); - final String[] wifiLinkPrefixes = { - // Link-local prefixes are excluded and dealt with elsewhere. - "100.112.96.0/20", "2001:db8:4:fd00::/64", "fd6a:a640:60bf:e985::/64", - }; - assertPrefixSet(local, INCLUDES, wifiLinkPrefixes); - Collections.addAll(alreadySeen, wifiLinkPrefixes); - assertEquals(alreadySeen.size(), local.size()); - - // [2] Pretend mobile connects. - final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - final LinkProperties cellLp = cellAgent.linkProperties; - cellLp.setInterfaceName("rmnet_data0"); - final String[] cell_addrs = { - "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d", - }; - for (String addrStr : cell_addrs) { - final String cidr = addrStr.contains(":") ? "/64" : "/27"; - cellLp.addLinkAddress(new LinkAddress(addrStr + cidr)); - } - cellAgent.fakeConnect(); - cellAgent.sendLinkProperties(); - - local = mUNM.getLocalPrefixes(); - assertPrefixSet(local, INCLUDES, alreadySeen); - final String[] cellLinkPrefixes = { "10.102.211.32/27", "2001:db8:0:1::/64" }; - assertPrefixSet(local, INCLUDES, cellLinkPrefixes); - Collections.addAll(alreadySeen, cellLinkPrefixes); - assertEquals(alreadySeen.size(), local.size()); - - // [3] Pretend DUN connects. - final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); - dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); - final LinkProperties dunLp = dunAgent.linkProperties; - dunLp.setInterfaceName("rmnet_data1"); - final String[] dun_addrs = { - "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d", - }; - for (String addrStr : dun_addrs) { - final String cidr = addrStr.contains(":") ? "/64" : "/27"; - dunLp.addLinkAddress(new LinkAddress(addrStr + cidr)); - } - dunAgent.fakeConnect(); - dunAgent.sendLinkProperties(); - - local = mUNM.getLocalPrefixes(); - assertPrefixSet(local, INCLUDES, alreadySeen); - final String[] dunLinkPrefixes = { "192.0.2.32/27", "2001:db8:1:2::/64" }; - assertPrefixSet(local, INCLUDES, dunLinkPrefixes); - Collections.addAll(alreadySeen, dunLinkPrefixes); - assertEquals(alreadySeen.size(), local.size()); - - // [4] Pretend Wi-Fi disconnected. It's addresses/prefixes should no - // longer be included (should be properly removed). - wifiAgent.fakeDisconnect(); - local = mUNM.getLocalPrefixes(); - assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes); - assertPrefixSet(local, INCLUDES, cellLinkPrefixes); - assertPrefixSet(local, INCLUDES, dunLinkPrefixes); - - // [5] Pretend mobile disconnected. - cellAgent.fakeDisconnect(); - local = mUNM.getLocalPrefixes(); - assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes); - assertPrefixSet(local, EXCLUDES, cellLinkPrefixes); - assertPrefixSet(local, INCLUDES, dunLinkPrefixes); - - // [6] Pretend DUN disconnected. - dunAgent.fakeDisconnect(); - local = mUNM.getLocalPrefixes(); - assertTrue(local.isEmpty()); - } - - @Test - public void testSelectMobileWhenMobileIsNotDefault() { - final Collection<Integer> preferredTypes = new ArrayList<>(); - // Mobile has higher pirority than wifi. - preferredTypes.add(TYPE_MOBILE_HIPRI); - preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); - mUNM.startObserveAllNetworks(); - // Setup wifi and make wifi as default network. - final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); - wifiAgent.fakeConnect(); - mCM.makeDefaultNetwork(wifiAgent); - // Setup mobile network. - final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); - cellAgent.fakeConnect(); - - assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, - mUNM.selectPreferredUpstreamType(preferredTypes)); - verify(mEntitleMgr, times(1)).maybeRunProvisioning(); - } - - private void assertSatisfiesLegacyType(int legacyType, UpstreamNetworkState ns) { - if (legacyType == TYPE_NONE) { - assertTrue(ns == null); - return; - } - - final NetworkCapabilities nc = - UpstreamNetworkMonitor.networkCapabilitiesForType(legacyType); - assertTrue(nc.satisfiedByNetworkCapabilities(ns.networkCapabilities)); - } - - private void assertUpstreamTypeRequested(int upstreamType) throws Exception { - assertEquals(1, mCM.requested.size()); - assertEquals(1, mCM.legacyTypeMap.size()); - assertEquals(Integer.valueOf(upstreamType), - mCM.legacyTypeMap.values().iterator().next()); - } - - private boolean isDunRequested() { - for (NetworkRequest req : mCM.requested.values()) { - if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { - return true; - } - } - return false; - } - - public static class TestConnectivityManager extends ConnectivityManager { - public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>(); - public Set<NetworkCallback> trackingDefault = new HashSet<>(); - public TestNetworkAgent defaultNetwork = null; - public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>(); - public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>(); - public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>(); - - private int mNetworkId = 100; - - public TestConnectivityManager(Context ctx, IConnectivityManager svc) { - super(ctx, svc); - } - - boolean hasNoCallbacks() { - return allCallbacks.isEmpty() - && trackingDefault.isEmpty() - && listening.isEmpty() - && requested.isEmpty() - && legacyTypeMap.isEmpty(); - } - - boolean onlyHasDefaultCallbacks() { - return (allCallbacks.size() == 1) - && (trackingDefault.size() == 1) - && listening.isEmpty() - && requested.isEmpty() - && legacyTypeMap.isEmpty(); - } - - boolean isListeningForAll() { - final NetworkCapabilities empty = new NetworkCapabilities(); - empty.clearAll(); - - for (NetworkRequest req : listening.values()) { - if (req.networkCapabilities.equalRequestableCapabilities(empty)) { - return true; - } - } - return false; - } - - int getNetworkId() { - return ++mNetworkId; - } - - void makeDefaultNetwork(TestNetworkAgent agent) { - if (Objects.equals(defaultNetwork, agent)) return; - - final TestNetworkAgent formerDefault = defaultNetwork; - defaultNetwork = agent; - - for (NetworkCallback cb : trackingDefault) { - if (defaultNetwork != null) { - cb.onAvailable(defaultNetwork.networkId); - cb.onCapabilitiesChanged( - defaultNetwork.networkId, defaultNetwork.networkCapabilities); - cb.onLinkPropertiesChanged( - defaultNetwork.networkId, defaultNetwork.linkProperties); - } - } - } - - @Override - public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { - assertFalse(allCallbacks.containsKey(cb)); - allCallbacks.put(cb, h); - if (sDefaultRequest.equals(req)) { - assertFalse(trackingDefault.contains(cb)); - trackingDefault.add(cb); - } else { - assertFalse(requested.containsKey(cb)); - requested.put(cb, req); - } - } - - @Override - public void requestNetwork(NetworkRequest req, NetworkCallback cb) { - fail("Should never be called."); - } - - @Override - public void requestNetwork(NetworkRequest req, - int timeoutMs, int legacyType, Handler h, NetworkCallback cb) { - assertFalse(allCallbacks.containsKey(cb)); - allCallbacks.put(cb, h); - assertFalse(requested.containsKey(cb)); - requested.put(cb, req); - assertFalse(legacyTypeMap.containsKey(cb)); - if (legacyType != ConnectivityManager.TYPE_NONE) { - legacyTypeMap.put(cb, legacyType); - } - } - - @Override - public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb, Handler h) { - assertFalse(allCallbacks.containsKey(cb)); - allCallbacks.put(cb, h); - assertFalse(listening.containsKey(cb)); - listening.put(cb, req); - } - - @Override - public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) { - fail("Should never be called."); - } - - @Override - public void registerDefaultNetworkCallback(NetworkCallback cb, Handler h) { - fail("Should never be called."); - } - - @Override - public void registerDefaultNetworkCallback(NetworkCallback cb) { - fail("Should never be called."); - } - - @Override - public void unregisterNetworkCallback(NetworkCallback cb) { - if (trackingDefault.contains(cb)) { - trackingDefault.remove(cb); - } else if (listening.containsKey(cb)) { - listening.remove(cb); - } else if (requested.containsKey(cb)) { - requested.remove(cb); - legacyTypeMap.remove(cb); - } else { - fail("Unexpected callback removed"); - } - allCallbacks.remove(cb); - - assertFalse(allCallbacks.containsKey(cb)); - assertFalse(trackingDefault.contains(cb)); - assertFalse(listening.containsKey(cb)); - assertFalse(requested.containsKey(cb)); - } - } - - public static class TestNetworkAgent { - public final TestConnectivityManager cm; - public final Network networkId; - public final int transportType; - public final NetworkCapabilities networkCapabilities; - public final LinkProperties linkProperties; - - public TestNetworkAgent(TestConnectivityManager cm, int transportType) { - this.cm = cm; - this.networkId = new Network(cm.getNetworkId()); - this.transportType = transportType; - networkCapabilities = new NetworkCapabilities(); - networkCapabilities.addTransportType(transportType); - networkCapabilities.addCapability(NET_CAPABILITY_INTERNET); - linkProperties = new LinkProperties(); - } - - public void fakeConnect() { - for (NetworkCallback cb : cm.listening.keySet()) { - cb.onAvailable(networkId); - cb.onCapabilitiesChanged(networkId, copy(networkCapabilities)); - cb.onLinkPropertiesChanged(networkId, copy(linkProperties)); - } - } - - public void fakeDisconnect() { - for (NetworkCallback cb : cm.listening.keySet()) { - cb.onLost(networkId); - } - } - - public void sendLinkProperties() { - for (NetworkCallback cb : cm.listening.keySet()) { - cb.onLinkPropertiesChanged(networkId, copy(linkProperties)); - } - } - - @Override - public String toString() { - return String.format("TestNetworkAgent: %s %s", networkId, networkCapabilities); - } - } - - public static class TestStateMachine extends StateMachine { - public final ArrayList<Message> messages = new ArrayList<>(); - private final State mLoggingState = new LoggingState(); - - class LoggingState extends State { - @Override public void enter() { - messages.clear(); - } - - @Override public void exit() { - messages.clear(); - } - - @Override public boolean processMessage(Message msg) { - messages.add(msg); - return true; - } - } - - public TestStateMachine() { - super("UpstreamNetworkMonitor.TestStateMachine"); - addState(mLoggingState); - setInitialState(mLoggingState); - super.start(); - } - } - - static NetworkCapabilities copy(NetworkCapabilities nc) { - return new NetworkCapabilities(nc); - } - - static LinkProperties copy(LinkProperties lp) { - return new LinkProperties(lp); - } - - static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, String... expected) { - final Set<String> expectedSet = new HashSet<>(); - Collections.addAll(expectedSet, expected); - assertPrefixSet(prefixes, expectation, expectedSet); - } - - static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, Set<String> expected) { - for (String expectedPrefix : expected) { - final String errStr = expectation ? "did not find" : "found"; - assertEquals( - String.format("Failed expectation: %s prefix: %s", errStr, expectedPrefix), - expectation, prefixes.contains(new IpPrefix(expectedPrefix))); - } - } -} 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/backup/OWNERS b/services/backup/OWNERS index 7c7e74285bf5..3c5268c5a2a9 100644 --- a/services/backup/OWNERS +++ b/services/backup/OWNERS @@ -1,7 +1,6 @@ # Bug component: 656484 aabhinav@google.com -alsutton@google.com bryanmawhinney@google.com jstemmer@google.com nathch@google.com diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0cd6e08101da..22423fe00b6c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -65,7 +65,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.BroadcastOptions; -import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -929,13 +928,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * @see ServiceManager#checkService(String) - */ - public boolean hasService(@NonNull String name) { - return ServiceManager.checkService(name) != null; - } - - /** * @see IpConnectivityMetrics.Logger */ public IpConnectivityMetrics.Logger getMetricsLogger() { @@ -1078,7 +1070,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Do the same for Ethernet, since it's often not specified in the configs, although many // devices can use it via USB host adapters. - if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) { + if (mNetConfigs[TYPE_ETHERNET] == null + && mContext.getSystemService(Context.ETHERNET_SERVICE) != null) { mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET); mNetworksDefined++; } @@ -1152,8 +1145,7 @@ public class ConnectivityService extends IConnectivityManager.Stub dataConnectionStats.startMonitoring(); mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler); - mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager, - mContext.getSystemService(NotificationManager.class)); + mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager); final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, @@ -2437,9 +2429,9 @@ public class ConnectivityService extends IConnectivityManager.Stub try { if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu); - mNMS.setMtu(iface, mtu); - } catch (Exception e) { - Slog.e(TAG, "exception in setMtu()" + e); + mNetd.interfaceSetMtu(iface, mtu); + } catch (RemoteException | ServiceSpecificException e) { + Slog.e(TAG, "exception in interfaceSetMtu()" + e); } } @@ -4004,13 +3996,11 @@ public class ConnectivityService extends IConnectivityManager.Stub settingsPkgName + ".wifi.WifiNoInternetDialog"); } - PendingIntent pendingIntent = PendingIntent.getActivityAsUser( - mContext, + PendingIntent pendingIntent = PendingIntent.getActivity( + mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), 0 /* requestCode */, intent, - PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, - null /* options */, - UserHandle.CURRENT); + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority); } @@ -6086,7 +6076,7 @@ public class ConnectivityService extends IConnectivityManager.Stub for (final String iface : interfaceDiff.added) { try { if (DBG) log("Adding iface " + iface + " to network " + netId); - mNMS.addInterfaceToNetwork(iface, netId); + mNetd.networkAddInterface(netId, iface); wakeupModifyInterface(iface, caps, true); bs.noteNetworkInterfaceType(iface, legacyType); } catch (Exception e) { @@ -6098,7 +6088,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { if (DBG) log("Removing iface " + iface + " from network " + netId); wakeupModifyInterface(iface, caps, false); - mNMS.removeInterfaceFromNetwork(iface, netId); + mNetd.networkRemoveInterface(netId, iface); } catch (Exception e) { loge("Exception removing interface: " + e); } @@ -6264,9 +6254,9 @@ public class ConnectivityService extends IConnectivityManager.Stub final int newPermission = getNetworkPermission(newNc); if (oldPermission != newPermission && nai.created && !nai.isVPN()) { try { - mNMS.setNetworkPermission(nai.network.netId, newPermission); - } catch (RemoteException e) { - loge("Exception in setNetworkPermission: " + e); + mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission); + } catch (RemoteException | ServiceSpecificException e) { + loge("Exception in networkSetPermissionForNetwork: " + e); } } } @@ -6708,11 +6698,11 @@ public class ConnectivityService extends IConnectivityManager.Stub try { if (null != newNetwork) { - mNMS.setDefaultNetId(newNetwork.network.netId); + mNetd.networkSetDefault(newNetwork.network.netId); } else { - mNMS.clearDefaultNetId(); + mNetd.networkClearDefault(); } - } catch (Exception e) { + } catch (RemoteException | ServiceSpecificException e) { loge("Exception setting default network :" + e); } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index ea14fadff433..1c99465dfebf 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -945,17 +945,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void setMtu(String iface, int mtu) { - NetworkStack.checkNetworkStackPermission(mContext); - - try { - mNetdService.interfaceSetMtu(iface, mtu); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override public void shutdown() { // TODO: remove from aidl if nobody calls externally mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); @@ -1985,16 +1974,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { pw.println("]"); } - @Override - public void addInterfaceToNetwork(String iface, int netId) { - modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface); - } - - @Override - public void removeInterfaceFromNetwork(String iface, int netId) { - modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, netId, iface); - } - private void modifyInterfaceInNetwork(boolean add, int netId, String iface) { NetworkStack.checkNetworkStackPermission(mContext); try { @@ -2030,39 +2009,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void setDefaultNetId(int netId) { - NetworkStack.checkNetworkStackPermission(mContext); - - try { - mNetdService.networkSetDefault(netId); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void clearDefaultNetId() { - NetworkStack.checkNetworkStackPermission(mContext); - - try { - mNetdService.networkClearDefault(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void setNetworkPermission(int netId, int permission) { - NetworkStack.checkNetworkStackPermission(mContext); - - try { - mNetdService.networkSetPermissionForNetwork(netId, permission); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override public void allowProtect(int uid) { NetworkStack.checkNetworkStackPermission(mContext); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index df23da650a6f..1cdc95a46f81 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1604,10 +1604,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyDisplayInfoChanged()")) { return; } + String str = "notifyDisplayInfoChanged: PhoneId=" + phoneId + " subId=" + subId + + " telephonyDisplayInfo=" + telephonyDisplayInfo; if (VDBG) { - log("notifyDisplayInfoChanged: PhoneId=" + phoneId - + " subId=" + subId + " telephonyDisplayInfo=" + telephonyDisplayInfo); + log(str); } + mLocalLog.log(str); synchronized (mRecords) { if (validatePhoneId(phoneId)) { mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo; @@ -2101,20 +2103,20 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { if (validatePhoneId(phoneId)) { mOutgoingCallEmergencyNumber[phoneId] = emergencyNumber; - for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL) - && idMatch(r.subId, subId, phoneId)) { - try { - r.callback.onOutgoingEmergencyCall(emergencyNumber); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); - } + } + for (Record r : mRecords) { + // Send to all listeners regardless of subscription + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)) { + try { + r.callback.onOutgoingEmergencyCall(emergencyNumber, subId); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); } } } - handleRemoveListLocked(); } + handleRemoveListLocked(); } @Override @@ -2127,11 +2129,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId)) { mOutgoingSmsEmergencyNumber[phoneId] = emergencyNumber; for (Record r : mRecords) { + // Send to all listeners regardless of subscription if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS) - && idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS)) { try { - r.callback.onOutgoingEmergencySms(emergencyNumber); + r.callback.onOutgoingEmergencySms(emergencyNumber, subId); } catch (RemoteException ex) { mRemoveList.add(r.binder); } @@ -2295,10 +2297,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]); pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]); pw.println("mBarringInfo=" + mBarringInfo.get(i)); + pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]); pw.decreaseIndent(); } pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState); - pw.println("mPhoneCapability=" + mPhoneCapability); pw.println("mActiveDataSubId=" + mActiveDataSubId); pw.println("mRadioPowerState=" + mRadioPowerState); diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java new file mode 100644 index 000000000000..db7e16ca8b25 --- /dev/null +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -0,0 +1,103 @@ +/* + * 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 com.android.server; + +import static java.util.Objects.requireNonNull; + +import android.annotation.NonNull; +import android.content.Context; +import android.net.vcn.IVcnManagementService; + +/** + * VcnManagementService manages Virtual Carrier Network profiles and lifecycles. + * + * <pre>The internal structure of the VCN Management subsystem is as follows: + * + * +------------------------+ 1:1 +--------------------------------+ + * | VcnManagementService | ------------ Creates -------------> | TelephonySubscriptionManager | + * | | | | + * | Manages configs and | | Tracks subscriptions, carrier | + * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps | + * +------------------------+ carrier privilege changes +--------------------------------+ + * | 1:N ^ + * | | + * | +-------------------------------+ + * +---------------+ | + * | | + * Creates when config present, | + * subscription group active, and | + * providing app is carrier privileged Notifies of safe + * | mode state changes + * v | + * +-----------------------------------------------------------------------+ + * | VcnInstance | + * | | + * | Manages tunnel lifecycles based on fulfillable NetworkRequest(s) | + * | and overall safe-mode | + * +-----------------------------------------------------------------------+ + * | 1:N ^ + * Creates to fulfill | + * NetworkRequest(s), tears Notifies of VcnTunnel + * down when no longer needed teardown (e.g. Network reaped) + * | and safe-mode timer changes + * v | + * +-----------------------------------------------------------------------+ + * | VcnTunnel | + * | | + * | Manages a single (IKEv2) tunnel session and NetworkAgent, | + * | handles mobility events, (IPsec) Tunnel setup and safe-mode timers | + * +-----------------------------------------------------------------------+ + * | 1:1 ^ + * | | + * Creates upon instantiation Notifies of changes in + * | selected underlying network + * | or its properties + * v | + * +-----------------------------------------------------------------------+ + * | UnderlyingNetworkTracker | + * | | + * | Manages lifecycle of underlying physical networks, filing requests to | + * | bring them up, and releasing them as they become no longer necessary | + * +-----------------------------------------------------------------------+ + * </pre> + * + * @hide + */ +public class VcnManagementService extends IVcnManagementService.Stub { + @NonNull private static final String TAG = VcnManagementService.class.getSimpleName(); + + public static final boolean VDBG = false; // STOPSHIP: if true + + /* Binder context for this service */ + @NonNull private final Context mContext; + @NonNull private final Dependencies mDeps; + + private VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) { + mContext = requireNonNull(context, "Missing context"); + mDeps = requireNonNull(deps, "Missing dependencies"); + } + + // Package-visibility for SystemServer to create instances. + static VcnManagementService create(@NonNull Context context) { + return new VcnManagementService(context, new Dependencies()); + } + + private static class Dependencies {} + + /** Notifies the VcnManagementService that external dependencies can be set up */ + public void systemReady() {} +} diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index a153d4191a5c..0ee30f9ca289 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -1589,25 +1589,20 @@ public class VibratorService extends IVibratorService.Stub mWakeLock.setWorkSource(mTmpWorkSource); } - private long delayLocked(long duration) { + private void delayLocked(long wakeUpTime) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "delayLocked"); try { - long durationRemaining = duration; - if (duration > 0) { - final long bedtime = duration + SystemClock.uptimeMillis(); - do { - try { - this.wait(durationRemaining); - } - catch (InterruptedException e) { } - if (mForceStop) { - break; - } - durationRemaining = bedtime - SystemClock.uptimeMillis(); - } while (durationRemaining > 0); - return duration - durationRemaining; + long durationRemaining = wakeUpTime - SystemClock.uptimeMillis(); + while (durationRemaining > 0) { + try { + this.wait(durationRemaining); + } + catch (InterruptedException e) { } + if (mForceStop) { + break; + } + durationRemaining = wakeUpTime - SystemClock.uptimeMillis(); } - return 0; } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } @@ -1641,7 +1636,8 @@ public class VibratorService extends IVibratorService.Stub final int repeat = mWaveform.getRepeatIndex(); int index = 0; - long onDuration = 0; + long nextStepStartTime = SystemClock.uptimeMillis(); + long nextVibratorStopTime = 0; while (!mForceStop) { if (index < len) { final int amplitude = amplitudes[index]; @@ -1650,25 +1646,31 @@ public class VibratorService extends IVibratorService.Stub continue; } if (amplitude != 0) { - if (onDuration <= 0) { + long now = SystemClock.uptimeMillis(); + if (nextVibratorStopTime <= now) { // Telling the vibrator to start multiple times usually causes // effects to feel "choppy" because the motor resets at every on // command. Instead we figure out how long our next "on" period // is going to be, tell the motor to stay on for the full // duration, and then wake up to change the amplitude at the // appropriate intervals. - onDuration = getTotalOnDuration(timings, amplitudes, index - 1, - repeat); + long onDuration = getTotalOnDuration( + timings, amplitudes, index - 1, repeat); doVibratorOn(onDuration, amplitude, mUid, mAttrs); + nextVibratorStopTime = now + onDuration; } else { + // Vibrator is already ON, so just change its amplitude. doVibratorSetAmplitude(amplitude); } } - long waitTime = delayLocked(duration); - if (amplitude != 0) { - onDuration -= waitTime; - } + // We wait until the time this waveform step was supposed to end, + // calculated from the time it was supposed to start. All start times + // are calculated from the waveform original start time by adding the + // input durations. Any scheduling or processing delay should not affect + // this step's perceived total duration. They will be amortized here. + nextStepStartTime += duration; + delayLocked(nextStepStartTime); } else if (repeat < 0) { break; } else { 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/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index bc3bff1b966f..ff3193182501 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -18,7 +18,7 @@ package com.android.server.compat; import android.annotation.Nullable; import android.compat.annotation.ChangeId; -import android.compat.annotation.EnabledAfter; +import android.compat.annotation.EnabledSince; import android.content.pm.ApplicationInfo; import com.android.internal.compat.CompatibilityChangeInfo; @@ -43,8 +43,8 @@ public final class CompatChange extends CompatibilityChangeInfo { * A change ID to be used only in the CTS test for this SystemApi */ @ChangeId - @EnabledAfter(targetSdkVersion = 1234) // Needs to be > test APK targetSdkVersion. - private static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id. + @EnabledSince(targetSdkVersion = 1235) // Needs to be > test APK targetSdkVersion. + static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id. /** * Callback listener for when compat changes are updated for a package. diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 38664fe09044..2c19a2d2855c 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -375,6 +375,9 @@ public class PlatformCompat extends IPlatformCompat.Stub { if (change.getLoggingOnly()) { return false; } + if (change.getId() == CompatChange.CTS_SYSTEM_API_CHANGEID) { + return false; + } if (change.getEnableSinceTargetSdk() > 0) { if (change.getEnableSinceTargetSdk() < sMinTargetSdk || change.getEnableSinceTargetSdk() > sMaxTargetSdk) { diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java index 0304cdc47515..fbd089c1f0ee 100644 --- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java +++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java @@ -19,12 +19,12 @@ package com.android.server.connectivity; import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS; +import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; -import android.os.Looper; import android.os.RemoteException; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; @@ -36,6 +36,9 @@ import android.util.Log; import com.android.internal.app.IBatteryStats; import com.android.server.am.BatteryStatsService; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; + public class DataConnectionStats extends BroadcastReceiver { private static final String TAG = "DataConnectionStats"; private static final boolean DEBUG = false; @@ -49,13 +52,13 @@ public class DataConnectionStats extends BroadcastReceiver { private SignalStrength mSignalStrength; private ServiceState mServiceState; private int mDataState = TelephonyManager.DATA_DISCONNECTED; - private int mNrState = NetworkRegistrationInfo.NR_STATE_NONE; public DataConnectionStats(Context context, Handler listenerHandler) { mContext = context; mBatteryStats = BatteryStatsService.getService(); mListenerHandler = listenerHandler; - mPhoneStateListener = new PhoneStateListenerImpl(listenerHandler.getLooper()); + mPhoneStateListener = + new PhoneStateListenerImpl(new PhoneStateListenerExecutor(listenerHandler)); } public void startMonitoring() { @@ -96,7 +99,7 @@ public class DataConnectionStats extends BroadcastReceiver { : regInfo.getAccessNetworkTechnology(); // If the device is in NSA NR connection the networkType will report as LTE. // For cell dwell rate metrics, this should report NR instead. - if (mNrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) { + if (regInfo != null && regInfo.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED) { networkType = TelephonyManager.NETWORK_TYPE_NR; } if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible", @@ -140,9 +143,24 @@ public class DataConnectionStats extends BroadcastReceiver { && mServiceState.getState() != ServiceState.STATE_POWER_OFF; } + private static class PhoneStateListenerExecutor implements Executor { + @NonNull + private final Handler mHandler; + + PhoneStateListenerExecutor(@NonNull Handler handler) { + mHandler = handler; + } + @Override + public void execute(Runnable command) { + if (!mHandler.post(command)) { + throw new RejectedExecutionException(mHandler + " is shutting down"); + } + } + } + private class PhoneStateListenerImpl extends PhoneStateListener { - PhoneStateListenerImpl(Looper looper) { - super(looper); + PhoneStateListenerImpl(Executor executor) { + super(executor); } @Override @@ -153,7 +171,6 @@ public class DataConnectionStats extends BroadcastReceiver { @Override public void onServiceStateChanged(ServiceState state) { mServiceState = state; - mNrState = state.getNrState(); notePhoneDataConnectionState(); } diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java index 04c000f6453a..f99f4c65594b 100644 --- a/services/core/java/com/android/server/connectivity/LingerMonitor.java +++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java @@ -159,8 +159,11 @@ public class LingerMonitor { @VisibleForTesting protected PendingIntent createNotificationIntent() { - return PendingIntent.getActivityAsUser(mContext, 0, CELLULAR_SETTINGS, - PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + return PendingIntent.getActivity( + mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), + 0 /* requestCode */, + CELLULAR_SETTINGS, + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); } // Removes any notification that was put up as a result of switching to nai. diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 34b0aa246433..338539312278 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import android.annotation.NonNull; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -75,16 +76,21 @@ public class NetworkNotificationManager { private static final boolean DBG = true; private static final boolean VDBG = false; + // The context is for the current user (system server) private final Context mContext; private final TelephonyManager mTelephonyManager; + // The notification manager is created from a context for User.ALL, so notifications + // will be sent to all users. private final NotificationManager mNotificationManager; // Tracks the types of notifications managed by this instance, from creation to cancellation. private final SparseIntArray mNotificationTypeMap; - public NetworkNotificationManager(Context c, TelephonyManager t, NotificationManager n) { + public NetworkNotificationManager(@NonNull final Context c, @NonNull final TelephonyManager t) { mContext = c; mTelephonyManager = t; - mNotificationManager = n; + mNotificationManager = + (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */) + .getSystemService(Context.NOTIFICATION_SERVICE); mNotificationTypeMap = new SparseIntArray(); } @@ -282,7 +288,7 @@ public class NetworkNotificationManager { mNotificationTypeMap.put(id, eventId); try { - mNotificationManager.notifyAsUser(tag, eventId, notification, UserHandle.ALL); + mNotificationManager.notify(tag, eventId, notification); } catch (NullPointerException npe) { Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe); } @@ -311,7 +317,7 @@ public class NetworkNotificationManager { nameOf(eventId))); } try { - mNotificationManager.cancelAsUser(tag, eventId, UserHandle.ALL); + mNotificationManager.cancel(tag, eventId); } catch (NullPointerException npe) { Slog.d(TAG, String.format( "failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe); @@ -325,7 +331,8 @@ public class NetworkNotificationManager { public void setProvNotificationVisible(boolean visible, int id, String action) { if (visible) { Intent intent = new Intent(action); - PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE); showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false); } else { clearNotification(id); diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 35f9e2fae688..1a83272f5077 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -199,8 +199,11 @@ public class Vpn { // automated reconnection private final Context mContext; + // The context is for specific user which is created from mUserId + private final Context mUserIdContext; @VisibleForTesting final Dependencies mDeps; private final NetworkInfo mNetworkInfo; + private int mLegacyState; @VisibleForTesting protected String mPackage; private int mOwnerUID; private boolean mIsPackageTargetingAtLeastQ; @@ -398,6 +401,7 @@ public class Vpn { int userId, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator) { mContext = context; + mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mDeps = deps; mNetd = netService; mUserId = userId; @@ -415,6 +419,7 @@ public class Vpn { Log.wtf(TAG, "Problem registering observer", e); } + mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE, "" /* subtypeName */); mNetworkCapabilities = new NetworkCapabilities(); @@ -440,6 +445,7 @@ public class Vpn { @VisibleForTesting protected void updateState(DetailedState detailedState, String reason) { if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); + mLegacyState = LegacyVpnInfo.stateFromNetworkInfo(detailedState); mNetworkInfo.setDetailedState(detailedState, reason, null); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); @@ -1243,6 +1249,7 @@ public class Vpn { // behaves the same as when it uses the default network. mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + mLegacyState = LegacyVpnInfo.STATE_CONNECTING; mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); @@ -1921,9 +1928,10 @@ public class Vpn { final UserHandle user = UserHandle.of(mUserId); final long token = Binder.clearCallingIdentity(); try { - final NotificationManager notificationManager = NotificationManager.from(mContext); + final NotificationManager notificationManager = + mUserIdContext.getSystemService(NotificationManager.class); if (!visible) { - notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user); + notificationManager.cancel(TAG, SystemMessage.NOTE_VPN_DISCONNECTED); return; } final Intent intent = new Intent(); @@ -1943,8 +1951,7 @@ public class Vpn { .setVisibility(Notification.VISIBILITY_PUBLIC) .setOngoing(true) .setColor(mContext.getColor(R.color.system_notification_accent_color)); - notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, - builder.build(), user); + notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build()); } finally { Binder.restoreCallingIdentity(token); } @@ -1969,8 +1976,9 @@ public class Vpn { */ public PendingIntent pendingIntentGetActivityAsUser( Intent intent, int flags, UserHandle user) { - return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags, - null /*options*/, user); + return PendingIntent.getActivity( + mContext.createContextAsUser(user, 0 /* flags */), 0 /* requestCode */, + intent, flags); } /** @@ -2264,7 +2272,7 @@ public class Vpn { final LegacyVpnInfo info = new LegacyVpnInfo(); info.key = mConfig.user; - info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); + info.state = mLegacyState; if (mNetworkInfo.isConnected()) { info.intent = mStatusIntent; } 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/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index 28bd97e4843c..fe97f701e089 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -122,13 +122,31 @@ 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); addValidationInfo(Constants.MESSAGE_CEC_VERSION, oneByteValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE, - new FixedLengthValidator(3), DEST_BROADCAST); + new AsciiValidator(3), DEST_BROADCAST); // TODO: Handle messages for the Deck Control. @@ -148,12 +166,14 @@ public class HdmiCecMessageValidator { maxLengthValidator, DEST_ALL | SRC_UNREGISTERED); // Messages for the OSD. - addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, maxLengthValidator, DEST_DIRECT); - addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, maxLengthValidator, DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, new OsdStringValidator(), DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, new AsciiValidator(1, 14), DEST_DIRECT); // Messages for the Device Menu Control. - addValidationInfo(Constants.MESSAGE_MENU_REQUEST, oneByteValidator, DEST_DIRECT); - addValidationInfo(Constants.MESSAGE_MENU_STATUS, oneByteValidator, DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_MENU_REQUEST, new OneByteRangeValidator(0x00, 0x02), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT); // Messages for the Remote Control Passthrough. // TODO: Parse the first parameter and determine if it can have the next parameter. @@ -161,7 +181,10 @@ public class HdmiCecMessageValidator { new VariableLengthValidator(1, 2), DEST_DIRECT); // Messages for the Power Status. - addValidationInfo(Constants.MESSAGE_REPORT_POWER_STATUS, oneByteValidator, DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_REPORT_POWER_STATUS, + new OneByteRangeValidator(0x00, 0x03), + DEST_DIRECT); // Messages for the General Protocol. addValidationInfo(Constants.MESSAGE_FEATURE_ABORT, @@ -173,12 +196,20 @@ public class HdmiCecMessageValidator { new FixedLengthValidator(3), DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR, oneByteValidator, DEST_DIRECT); - addValidationInfo(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, oneByteValidator, DEST_ALL); - addValidationInfo(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, - oneByteValidator, DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, + new OneByteRangeValidator(0x00, 0x01), + DEST_ALL); + addValidationInfo( + Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, + new OneByteRangeValidator(0x00, 0x01), + DEST_DIRECT); // Messages for the Audio Rate Control. - addValidationInfo(Constants.MESSAGE_SET_AUDIO_RATE, oneByteValidator, DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_AUDIO_RATE, + new OneByteRangeValidator(0x00, 0x06), + DEST_DIRECT); // All Messages for the ARC have no parameters. @@ -299,6 +330,308 @@ public class HdmiCecMessageValidator { return (value >= min && value <= max); } + /** + * Check if the given value is a valid Display Control. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Display Control + * @return true if the Display Control is valid + */ + private boolean isValidDisplayControl(int value) { + value = value & 0xFF; + return (value == 0x00 || value == 0x40 || value == 0x80 || value == 0xC0); + } + + /** + * Check if the given params has valid ASCII characters. + * A valid ASCII character is a printable character. It should fall within range description + * defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param params parameter consisting of string + * @param offset Start offset of string + * @param maxLength Maximum length of string to be evaluated + * @return true if the given type is valid + */ + private boolean isValidAsciiString(byte[] params, int offset, int maxLength) { + for (int i = offset; i < params.length && i < maxLength; i++) { + if (!isWithinRange(params[i], 0x20, 0x7E)) { + return false; + } + } + 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) { @@ -359,4 +692,175 @@ public class HdmiCecMessageValidator { || params[0] == 0x1F); } } + + /** + * Check if the given parameters represents printable characters. + * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 + * Specification : Operand Descriptions (Section 17) + */ + private class AsciiValidator implements ParameterValidator { + private final int mMinLength; + private final int mMaxLength; + + AsciiValidator(int length) { + mMinLength = length; + mMaxLength = length; + } + + AsciiValidator(int minLength, int maxLength) { + mMinLength = minLength; + mMaxLength = maxLength; + } + + @Override + public int isValid(byte[] params) { + // If the length is longer than expected, we assume it's OK since the parameter can be + // extended in the future version. + if (params.length < mMinLength) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isValidAsciiString(params, 0, mMaxLength)); + } + } + + /** + * Check if the given parameters is valid OSD String. + * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 + * Specification : Operand Descriptions (Section 17) + */ + private class OsdStringValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + // If the length is longer than expected, we assume it's OK since the parameter can be + // extended in the future version. + if (params.length < 2) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + // Display Control + isValidDisplayControl(params[0]) + // OSD String + && isValidAsciiString(params, 1, 14)); + } + } + + /** Check if the given parameters are one byte parameters and within range. */ + private class OneByteRangeValidator implements ParameterValidator { + private final int mMinValue, mMaxValue; + + OneByteRangeValidator(int minValue, int maxValue) { + mMinValue = minValue; + mMaxValue = maxValue; + } + + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + 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/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 05f280884432..06cebac501e7 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -65,6 +65,7 @@ public class LockdownVpnTracker { @NonNull private final Context mContext; @NonNull private final ConnectivityService mConnService; + @NonNull private final NotificationManager mNotificationManager; @NonNull private final Handler mHandler; @NonNull private final Vpn mVpn; @NonNull private final VpnProfile mProfile; @@ -93,13 +94,16 @@ public class LockdownVpnTracker { mHandler = Objects.requireNonNull(handler); mVpn = Objects.requireNonNull(vpn); mProfile = Objects.requireNonNull(profile); + mNotificationManager = mContext.getSystemService(NotificationManager.class); final Intent configIntent = new Intent(ACTION_VPN_SETTINGS); - mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0); + mConfigIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */, configIntent, + PendingIntent.FLAG_IMMUTABLE); final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET); resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0); + mResetIntent = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, resetIntent, + PendingIntent.FLAG_IMMUTABLE); } /** @@ -264,11 +268,11 @@ public class LockdownVpnTracker { .setColor(mContext.getColor( com.android.internal.R.color.system_notification_accent_color)); - NotificationManager.from(mContext).notify(null, SystemMessage.NOTE_VPN_STATUS, + mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS, builder.build()); } private void hideNotification() { - NotificationManager.from(mContext).cancel(null, SystemMessage.NOTE_VPN_STATUS); + mNotificationManager.cancel(null, SystemMessage.NOTE_VPN_STATUS); } } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index a31aacbde46f..7d0457bdaec4 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -96,7 +96,9 @@ import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; import static com.android.internal.util.XmlUtils.readLongAttribute; import static com.android.internal.util.XmlUtils.readStringAttribute; +import static com.android.internal.util.XmlUtils.readThisIntArrayXml; import static com.android.internal.util.XmlUtils.writeBooleanAttribute; +import static com.android.internal.util.XmlUtils.writeIntArrayXml; import static com.android.internal.util.XmlUtils.writeIntAttribute; import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; @@ -229,6 +231,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.StatLogger; +import com.android.internal.util.XmlUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.ServiceThread; @@ -239,6 +242,7 @@ import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.File; @@ -313,7 +317,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int VERSION_ADDED_NETWORK_ID = 9; private static final int VERSION_SWITCH_UID = 10; private static final int VERSION_ADDED_CYCLE = 11; - private static final int VERSION_LATEST = VERSION_ADDED_CYCLE; + private static final int VERSION_ADDED_NETWORK_TYPES = 12; + private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_TYPES; @VisibleForTesting public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING; @@ -332,6 +337,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String TAG_WHITELIST = "whitelist"; private static final String TAG_RESTRICT_BACKGROUND = "restrict-background"; private static final String TAG_REVOKED_RESTRICT_BACKGROUND = "revoked-restrict-background"; + private static final String TAG_XML_UTILS_INT_ARRAY = "int-array"; private static final String ATTR_VERSION = "version"; private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground"; @@ -360,6 +366,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String ATTR_USAGE_BYTES = "usageBytes"; private static final String ATTR_USAGE_TIME = "usageTime"; private static final String ATTR_OWNER_PACKAGE = "ownerPackage"; + private static final String ATTR_NETWORK_TYPES = "networkTypes"; + private static final String ATTR_XML_UTILS_NAME = "name"; private static final String ACTION_ALLOW_BACKGROUND = "com.android.server.net.action.ALLOW_BACKGROUND"; @@ -518,8 +526,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final SparseBooleanArray mRestrictBackgroundAllowlistRevokedUids = new SparseBooleanArray(); + final Object mMeteredIfacesLock = new Object(); /** Set of ifaces that are metered. */ - @GuardedBy("mNetworkPoliciesSecondLock") + @GuardedBy("mMeteredIfacesLock") private ArraySet<String> mMeteredIfaces = new ArraySet<>(); /** Set of over-limit templates that have been notified. */ @GuardedBy("mNetworkPoliciesSecondLock") @@ -1972,13 +1981,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // Remove quota from any interfaces that are no longer metered. - for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) { - final String iface = mMeteredIfaces.valueAt(i); - if (!newMeteredIfaces.contains(iface)) { - removeInterfaceQuotaAsync(iface); + synchronized (mMeteredIfacesLock) { + for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) { + final String iface = mMeteredIfaces.valueAt(i); + if (!newMeteredIfaces.contains(iface)) { + removeInterfaceQuotaAsync(iface); + } } + mMeteredIfaces = newMeteredIfaces; } - mMeteredIfaces = newMeteredIfaces; final ContentResolver cr = mContext.getContentResolver(); final boolean quotaEnabled = Settings.Global.getInt(cr, @@ -2030,7 +2041,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mSubscriptionOpportunisticQuota.put(subId, quotaBytes); } - final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); + final String[] meteredIfaces; + synchronized (mMeteredIfacesLock) { + meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); + } mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget(); @@ -2311,13 +2325,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final int subId = readIntAttribute(in, ATTR_SUB_ID); + final String ownerPackage = readStringAttribute(in, ATTR_OWNER_PACKAGE); + + if (version >= VERSION_ADDED_NETWORK_TYPES) { + final int depth = in.getDepth(); + while (XmlUtils.nextElementWithin(in, depth)) { + if (TAG_XML_UTILS_INT_ARRAY.equals(in.getName()) + && ATTR_NETWORK_TYPES.equals( + readStringAttribute(in, ATTR_XML_UTILS_NAME))) { + final int[] networkTypes = + readThisIntArrayXml(in, TAG_XML_UTILS_INT_ARRAY, null); + builder.setNetworkTypes(networkTypes); + } + } + } + final SubscriptionPlan plan = builder.build(); mSubscriptionPlans.put(subId, ArrayUtils.appendElement( SubscriptionPlan.class, mSubscriptionPlans.get(subId), plan)); - - final String ownerPackage = readStringAttribute(in, ATTR_OWNER_PACKAGE); mSubscriptionPlansOwner.put(subId, ownerPackage); - } else if (TAG_UID_POLICY.equals(tag)) { final int uid = readIntAttribute(in, ATTR_UID); final int policy = readIntAttribute(in, ATTR_POLICY); @@ -2513,6 +2539,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { writeIntAttribute(out, ATTR_LIMIT_BEHAVIOR, plan.getDataLimitBehavior()); writeLongAttribute(out, ATTR_USAGE_BYTES, plan.getDataUsageBytes()); writeLongAttribute(out, ATTR_USAGE_TIME, plan.getDataUsageTime()); + try { + writeIntArrayXml(plan.getNetworkTypes(), ATTR_NETWORK_TYPES, out); + } catch (XmlPullParserException ignored) { } out.endTag(null, TAG_SUBSCRIPTION_PLAN); } } @@ -3310,7 +3339,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // let in core system components (like the Settings app). final String ownerPackage = mSubscriptionPlansOwner.get(subId); if (Objects.equals(ownerPackage, callingPackage) - || (UserHandle.getCallingAppId() == android.os.Process.SYSTEM_UID)) { + || (UserHandle.getCallingAppId() == android.os.Process.SYSTEM_UID) + || (UserHandle.getCallingAppId() == android.os.Process.PHONE_UID)) { return mSubscriptionPlans.get(subId); } else { Log.w(TAG, "Not returning plans because caller " + callingPackage @@ -3436,7 +3466,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.print("Restrict background: "); fout.println(mRestrictBackground); fout.print("Restrict power: "); fout.println(mRestrictPower); fout.print("Device idle: "); fout.println(mDeviceIdleMode); - fout.print("Metered ifaces: "); fout.println(mMeteredIfaces); + synchronized (mMeteredIfacesLock) { + fout.print("Metered ifaces: "); + fout.println(mMeteredIfaces); + } fout.println(); fout.print("mRestrictBackgroundLowPowerMode: " + mRestrictBackgroundLowPowerMode); @@ -4632,7 +4665,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } case MSG_LIMIT_REACHED: { final String iface = (String) msg.obj; - synchronized (mNetworkPoliciesSecondLock) { + synchronized (mMeteredIfacesLock) { // fast return if not needed. if (!mMeteredIfaces.contains(iface)) { return true; @@ -5274,7 +5307,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { isBackgroundRestricted = mRestrictBackground; } final boolean isNetworkMetered; - synchronized (mNetworkPoliciesSecondLock) { + synchronized (mMeteredIfacesLock) { isNetworkMetered = mMeteredIfaces.contains(ifname); } final boolean ret = isUidNetworkingBlockedInternal(uid, uidRules, isNetworkMetered, 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/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 39b320318302..b571a9c5ce13 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -104,6 +104,7 @@ import android.util.SparseArray; import com.android.internal.content.PackageHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata; @@ -139,7 +140,7 @@ class PackageManagerShellCommand extends ShellCommand { private static final String STDIN_PATH = "-"; /** Path where ART profiles snapshots are dumped for the shell user */ private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/"; - private static final int DEFAULT_WAIT_MS = 60 * 1000; + private static final int DEFAULT_STAGED_READY_TIMEOUT_MS = 60 * 1000; private static final String TAG = "PackageManagerShellCommand"; final IPackageManager mInterface; @@ -455,9 +456,20 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } - private int runRollbackApp() { + private int runRollbackApp() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); + String opt; + long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--staged-ready-timeout": + stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); + break; + default: + throw new IllegalArgumentException("Unknown option: " + opt); + } + } final String packageName = getNextArgRequired(); if (packageName == null) { pw.println("Error: package name not specified"); @@ -465,11 +477,10 @@ class PackageManagerShellCommand extends ShellCommand { } final LocalIntentReceiver receiver = new LocalIntentReceiver(); + RollbackInfo rollback = null; try { IRollbackManager rm = IRollbackManager.Stub.asInterface( ServiceManager.getService(Context.ROLLBACK_SERVICE)); - - RollbackInfo rollback = null; for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) { for (PackageRollbackInfo info : r.getPackages()) { if (packageName.equals(info.getPackageName())) { @@ -494,14 +505,21 @@ class PackageManagerShellCommand extends ShellCommand { final Intent result = receiver.getResult(); final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, RollbackManager.STATUS_FAILURE); - if (status == RollbackManager.STATUS_SUCCESS) { - pw.println("Success"); - return 0; - } else { + + if (status != RollbackManager.STATUS_SUCCESS) { pw.println("Failure [" + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]"); return 1; } + + if (rollback.isStaged() && stagedReadyTimeoutMs > 0) { + final int committedSessionId = rollback.getCommittedSessionId(); + return doWaitForStagedSessionReady(committedSessionId, stagedReadyTimeoutMs, pw); + } + + pw.println("Success"); + return 0; + } private void setParamsSize(InstallParams params, List<String> inPaths) { @@ -1304,11 +1322,12 @@ class PackageManagerShellCommand extends ShellCommand { } abandonSession = false; - if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) { - pw.println("Success"); - return 0; + if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) { + return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw); } - return doWaitForStagedSessionRead(sessionId, params.timeoutMs, pw); + + pw.println("Success"); + return 0; } finally { if (abandonSession) { try { @@ -1319,11 +1338,9 @@ class PackageManagerShellCommand extends ShellCommand { } } - private int doWaitForStagedSessionRead(int sessionId, long timeoutMs, PrintWriter pw) + private int doWaitForStagedSessionReady(int sessionId, long timeoutMs, PrintWriter pw) throws RemoteException { - if (timeoutMs <= 0) { - timeoutMs = DEFAULT_WAIT_MS; - } + Preconditions.checkArgument(timeoutMs > 0); PackageInstaller.SessionInfo si = mInterface.getPackageInstaller() .getSessionInfo(sessionId); if (si == null) { @@ -1373,25 +1390,14 @@ class PackageManagerShellCommand extends ShellCommand { private int runInstallCommit() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); String opt; - boolean waitForStagedSessionReady = true; - long timeoutMs = -1; + long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; while ((opt = getNextOption()) != null) { switch (opt) { - case "--wait-for-staged-ready": - waitForStagedSessionReady = true; - // If there is only one remaining argument, then it represents the sessionId, we - // shouldn't try to parse it as timeoutMs. - if (getRemainingArgsCount() > 1) { - try { - timeoutMs = Long.parseLong(peekNextArg()); - getNextArg(); - } catch (NumberFormatException ignore) { - } - } - break; - case "--no-wait": - waitForStagedSessionReady = false; + case "--staged-ready-timeout": + stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); break; + default: + throw new IllegalArgumentException("Unknown option: " + opt); } } final int sessionId = Integer.parseInt(getNextArg()); @@ -1400,11 +1406,11 @@ class PackageManagerShellCommand extends ShellCommand { } final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller() .getSessionInfo(sessionId); - if (si == null || !si.isStaged() || !waitForStagedSessionReady) { - pw.println("Success"); - return 0; + if (si != null && si.isStaged() && stagedReadyTimeoutMs > 0) { + return doWaitForStagedSessionReady(sessionId, stagedReadyTimeoutMs, pw); } - return doWaitForStagedSessionRead(sessionId, timeoutMs, pw); + pw.println("Success"); + return 0; } private int runInstallCreate() throws RemoteException { @@ -2735,8 +2741,7 @@ class PackageManagerShellCommand extends ShellCommand { SessionParams sessionParams; String installerPackageName; int userId = UserHandle.USER_ALL; - boolean mWaitForStagedSessionReady = true; - long timeoutMs = DEFAULT_WAIT_MS; + long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; } private InstallParams makeInstallParams() { @@ -2865,16 +2870,8 @@ class PackageManagerShellCommand extends ShellCommand { } sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; break; - case "--wait-for-staged-ready": - params.mWaitForStagedSessionReady = true; - try { - params.timeoutMs = Long.parseLong(peekNextArg()); - getNextArg(); - } catch (NumberFormatException ignore) { - } - break; - case "--no-wait": - params.mWaitForStagedSessionReady = false; + case "--staged-ready-timeout": + params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); break; case "--skip-verification": sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION; @@ -3597,7 +3594,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); pw.println(" [--enable-rollback]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); - pw.println(" [--apex] [--wait-for-staged-ready TIMEOUT]"); + pw.println(" [--apex] [--staged-ready-timeout TIMEOUT]"); pw.println(" [PATH [SPLIT...]|-]"); pw.println(" Install an application. Must provide the apk data to install, either as"); pw.println(" file path(s) or '-' to read from stdin. Options are:"); @@ -3625,9 +3622,11 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" 3=device setup, 4=user request"); pw.println(" --force-uuid: force install on to disk volume with given UUID"); pw.println(" --apex: install an .apex file, not an .apk"); - pw.println(" --wait-for-staged-ready: when performing staged install, wait TIMEOUT"); - pw.println(" ms for pre-reboot verification to complete. If TIMEOUT is not"); - pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds."); + pw.println(" --staged-ready-timeout: By default, staged sessions wait " + + DEFAULT_STAGED_READY_TIMEOUT_MS); + pw.println(" milliseconds for pre-reboot verification to complete when"); + pw.println(" performing staged install. This flag is used to alter the waiting"); + pw.println(" time. You can skip the waiting time by specifying a TIMEOUT of '0'"); pw.println(""); pw.println(" install-existing [--user USER_ID|all|current]"); pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE"); diff --git a/services/core/java/com/android/server/telecom/InternalServiceRepository.java b/services/core/java/com/android/server/telecom/InternalServiceRepository.java new file mode 100644 index 000000000000..76ea5c788bd7 --- /dev/null +++ b/services/core/java/com/android/server/telecom/InternalServiceRepository.java @@ -0,0 +1,63 @@ +/* + * 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 com.android.server.telecom; + +import android.content.Context; +import android.os.Binder; +import android.os.Process; + +import com.android.internal.telecom.IDeviceIdleControllerAdapter; +import com.android.internal.telecom.IInternalServiceRetriever; +import com.android.server.DeviceIdleInternal; + +/** + * The Telecom APK can not access services stored in LocalService directly and since it is in the + * SYSTEM process, it also can not use the *Manager interfaces + * (see {@link Context#enforceCallingPermission(String, String)}). Instead, we must wrap these local + * services in binder interfaces to allow Telecom access. + */ +public class InternalServiceRepository extends IInternalServiceRetriever.Stub { + + private final IDeviceIdleControllerAdapter.Stub mDeviceIdleControllerAdapter = + new IDeviceIdleControllerAdapter.Stub() { + @Override + public void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle, + String reason) { + mDeviceIdleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, + duration, userHandle, true /*sync*/, reason); + } + }; + + private final DeviceIdleInternal mDeviceIdleController; + + public InternalServiceRepository(DeviceIdleInternal deviceIdleController) { + mDeviceIdleController = deviceIdleController; + } + + @Override + public IDeviceIdleControllerAdapter getDeviceIdleController() { + ensureSystemProcess(); + return mDeviceIdleControllerAdapter; + } + + private void ensureSystemProcess() { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + // Correctness check - this should never happen. + throw new SecurityException("SYSTEM ONLY API."); + } + } +} diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index a853529f49e4..52ad893a9ace 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -35,7 +35,10 @@ import android.util.IntArray; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.telecom.ITelecomLoader; +import com.android.internal.telecom.ITelecomService; import com.android.internal.telephony.SmsApplication; +import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.UserManagerService; @@ -53,16 +56,13 @@ public class TelecomLoaderService extends SystemService { @Override public void onServiceConnected(ComponentName name, IBinder service) { // Normally, we would listen for death here, but since telecom runs in the same process - // as this loader (process="system") thats redundant here. + // as this loader (process="system") that's redundant here. try { - service.linkToDeath(new IBinder.DeathRecipient() { - @Override - public void binderDied() { - connectToTelecom(); - } - }, 0); + ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service); + ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo); + SmsApplication.getDefaultMmsApplication(mContext, false); - ServiceManager.addService(Context.TELECOM_SERVICE, service); + ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder()); synchronized (mLock) { final PermissionManagerServiceInternal permissionManager = @@ -114,6 +114,8 @@ public class TelecomLoaderService extends SystemService { @GuardedBy("mLock") private TelecomServiceConnection mServiceConnection; + private InternalServiceRepository mServiceRepo; + public TelecomLoaderService(Context context) { super(context); mContext = context; @@ -129,6 +131,8 @@ public class TelecomLoaderService extends SystemService { if (phase == PHASE_ACTIVITY_MANAGER_READY) { registerDefaultAppNotifier(); registerCarrierConfigChangedReceiver(); + // core services will have already been loaded. + setupServiceRepository(); connectToTelecom(); } } @@ -154,6 +158,11 @@ public class TelecomLoaderService extends SystemService { } } + private void setupServiceRepository() { + DeviceIdleInternal deviceIdleInternal = getLocalService(DeviceIdleInternal.class); + mServiceRepo = new InternalServiceRepository(deviceIdleInternal); + } + private void registerDefaultAppProviders() { final PermissionManagerServiceInternal permissionManager = diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index b08868e2c7f8..0e68f5b89a91 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "BatteryStatsService" //#define LOG_NDEBUG 0 -#include <climits> #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -28,6 +27,7 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <climits> #include <unordered_map> #include <utility> @@ -46,15 +46,16 @@ #include <utils/misc.h> #include <utils/Log.h> +using android::hardware::hidl_vec; using android::hardware::Return; using android::hardware::Void; -using android::system::suspend::BnSuspendCallback; +using android::hardware::power::stats::V1_0::IPowerStats; using android::hardware::power::V1_0::PowerStatePlatformSleepState; using android::hardware::power::V1_0::PowerStateVoter; using android::hardware::power::V1_0::Status; using android::hardware::power::V1_1::PowerStateSubsystem; using android::hardware::power::V1_1::PowerStateSubsystemSleepState; -using android::hardware::hidl_vec; +using android::system::suspend::BnSuspendCallback; using android::system::suspend::ISuspendControlService; using IPowerV1_1 = android::hardware::power::V1_1::IPower; using IPowerV1_0 = android::hardware::power::V1_0::IPower; @@ -62,10 +63,9 @@ using IPowerV1_0 = android::hardware::power::V1_0::IPower; namespace android { -#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason" -#define MAX_REASON_SIZE 512 - static bool wakeup_init = false; +static std::mutex mReasonsMutex; +static std::vector<std::string> mWakeupReasons; static sem_t wakeup_sem; extern sp<IPowerV1_0> getPowerHalHidlV1_0(); extern sp<IPowerV1_1> getPowerHalHidlV1_1(); @@ -84,7 +84,8 @@ std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> gPowerStatsHalStateNames = {}; std::vector<uint32_t> gPowerStatsHalPlatformIds = {}; std::vector<uint32_t> gPowerStatsHalSubsystemIds = {}; -sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0 = nullptr; +sp<IPowerStats> gPowerStatsHalV1_0 = nullptr; + std::function<void(JNIEnv*, jobject)> gGetLowPowerStatsImpl = {}; std::function<jint(JNIEnv*, jobject)> gGetPlatformLowPowerStatsImpl = {}; std::function<jint(JNIEnv*, jobject)> gGetSubsystemLowPowerStatsImpl = {}; @@ -115,9 +116,25 @@ struct PowerHalDeathRecipient : virtual public hardware::hidl_death_recipient { sp<PowerHalDeathRecipient> gDeathRecipient = new PowerHalDeathRecipient(); class WakeupCallback : public BnSuspendCallback { - public: - binder::Status notifyWakeup(bool success) override { +public: + binder::Status notifyWakeup(bool success, + const std::vector<std::string>& wakeupReasons) override { ALOGI("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted"); + bool reasonsCaptured = false; + { + std::unique_lock<std::mutex> reasonsLock(mReasonsMutex, std::defer_lock); + if (reasonsLock.try_lock() && mWakeupReasons.empty()) { + mWakeupReasons = std::move(wakeupReasons); + reasonsCaptured = true; + } + } + if (!reasonsCaptured) { + ALOGE("Failed to write wakeup reasons. Reasons dropped:"); + for (auto wakeupReason : wakeupReasons) { + ALOGE("\t%s", wakeupReason.c_str()); + } + } + int ret = sem_post(&wakeup_sem); if (ret < 0) { char buf[80]; @@ -157,8 +174,6 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf) // Wait for wakeup. ALOGV("Waiting for wakeup..."); - // TODO(b/116747600): device can suspend and wakeup after sem_wait() finishes and before wakeup - // reason is recorded, i.e. BatteryStats might occasionally miss wakeup events. int ret = sem_wait(&wakeup_sem); if (ret < 0) { char buf[80]; @@ -168,20 +183,27 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf) return 0; } - FILE *fp = fopen(LAST_RESUME_REASON, "r"); - if (fp == NULL) { - ALOGE("Failed to open %s", LAST_RESUME_REASON); - return -1; - } - char* mergedreason = (char*)env->GetDirectBufferAddress(outBuf); int remainreasonlen = (int)env->GetDirectBufferCapacity(outBuf); ALOGV("Reading wakeup reasons"); + std::vector<std::string> wakeupReasons; + { + std::unique_lock<std::mutex> reasonsLock(mReasonsMutex, std::defer_lock); + if (reasonsLock.try_lock() && !mWakeupReasons.empty()) { + wakeupReasons = std::move(mWakeupReasons); + mWakeupReasons.clear(); + } + } + + if (wakeupReasons.empty()) { + return 0; + } + char* mergedreasonpos = mergedreason; - char reasonline[128]; int i = 0; - while (fgets(reasonline, sizeof(reasonline), fp) != NULL) { + for (auto wakeupReason : wakeupReasons) { + auto reasonline = const_cast<char*>(wakeupReason.c_str()); char* pos = reasonline; char* endPos; int len; @@ -238,10 +260,6 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf) *mergedreasonpos = 0; } - if (fclose(fp) != 0) { - ALOGE("Failed to close %s", LAST_RESUME_REASON); - return -1; - } return mergedreasonpos - mergedreason; } @@ -340,7 +358,7 @@ static bool initializePowerStats() { // The caller must be holding gPowerHalMutex. static bool getPowerStatsHalLocked() { if (gPowerStatsHalV1_0 == nullptr) { - gPowerStatsHalV1_0 = android::hardware::power::stats::V1_0::IPowerStats::getService(); + gPowerStatsHalV1_0 = IPowerStats::getService(); if (gPowerStatsHalV1_0 == nullptr) { ALOGE("Unable to get power.stats HAL service."); return false; @@ -833,7 +851,7 @@ static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) { static void setUpPowerStatsLocked() { // First see if power.stats HAL is available. Fall back to power HAL if // power.stats HAL is unavailable. - if (android::hardware::power::stats::V1_0::IPowerStats::getService() != nullptr) { + if (IPowerStats::getService() != nullptr) { ALOGI("Using power.stats HAL"); gGetLowPowerStatsImpl = getPowerStatsHalLowPowerData; gGetPlatformLowPowerStatsImpl = getPowerStatsHalPlatformData; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index cc8c75194031..2ba94e8557ac 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1018,6 +1018,7 @@ public final class SystemServer { IStorageManager storageManager = null; NetworkManagementService networkManagement = null; IpSecService ipSecService = null; + VcnManagementService vcnManagement = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; IConnectivityManager connectivity = null; @@ -1225,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(); @@ -1453,6 +1454,15 @@ public final class SystemServer { } t.traceEnd(); + t.traceBegin("StartVcnManagementService"); + try { + vcnManagement = VcnManagementService.create(context); + ServiceManager.addService(Context.VCN_MANAGEMENT_SERVICE, vcnManagement); + } catch (Throwable e) { + reportWtf("starting VCN Management Service", e); + } + t.traceEnd(); + t.traceBegin("StartTextServicesManager"); mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class); t.traceEnd(); @@ -2228,6 +2238,7 @@ public final class SystemServer { final MediaRouterService mediaRouterF = mediaRouter; final MmsServiceBroker mmsServiceF = mmsService; final IpSecService ipSecServiceF = ipSecService; + final VcnManagementService vcnManagementF = vcnManagement; final WindowManagerService windowManagerF = wm; final ConnectivityManager connectivityF = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -2316,6 +2327,15 @@ public final class SystemServer { reportWtf("making IpSec Service ready", e); } t.traceEnd(); + t.traceBegin("MakeVcnManagementServiceReady"); + try { + if (vcnManagementF != null) { + vcnManagementF.systemReady(); + } + } catch (Throwable e) { + reportWtf("making VcnManagementService ready", e); + } + t.traceEnd(); t.traceBegin("MakeNetworkStatsServiceReady"); try { if (networkStatsF != null) { diff --git a/services/net/Android.bp b/services/net/Android.bp index afea1a073cab..72ad36677c23 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -66,5 +66,8 @@ filegroup { ":framework-annotations", "java/android/net/util/NetworkConstants.java", ], - visibility: ["//frameworks/base/packages/Tethering"], + visibility: [ + "//frameworks/base/packages/Tethering", + "//packages/modules/Connectivity/Tethering" + ], } 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 5a05fc6eda4c..553df3bafd00 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -17,6 +17,7 @@ package com.android.server.hdmi; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION; +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE; import static com.android.server.hdmi.HdmiCecMessageValidator.OK; @@ -65,10 +66,291 @@ public class HdmiCecMessageValidatorTest { @Test public void isValid_reportPowerStatus() { assertMessageValidity("04:90:00").isEqualTo(OK); + assertMessageValidity("04:90:03:05").isEqualTo(OK); assertMessageValidity("0F:90:00").isEqualTo(ERROR_DESTINATION); assertMessageValidity("F0:90").isEqualTo(ERROR_SOURCE); assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("04:90:04").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_menuRequest() { + assertMessageValidity("40:8D:00").isEqualTo(OK); + assertMessageValidity("40:8D:02:04").isEqualTo(OK); + + assertMessageValidity("0F:8D:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:8D").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:8D").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:8D:03").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_menuStatus() { + assertMessageValidity("40:8E:00").isEqualTo(OK); + assertMessageValidity("40:8E:01:00").isEqualTo(OK); + + assertMessageValidity("0F:8E:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:8E").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:8E").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:8E:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setSystemAudioMode() { + assertMessageValidity("40:72:00").isEqualTo(OK); + assertMessageValidity("4F:72:01:03").isEqualTo(OK); + + assertMessageValidity("F0:72").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:72").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:72:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_systemAudioModeStatus() { + assertMessageValidity("40:7E:00").isEqualTo(OK); + assertMessageValidity("40:7E:01:01").isEqualTo(OK); + + assertMessageValidity("0F:7E:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:7E").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:7E").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:7E:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setAudioRate() { + assertMessageValidity("40:9A:00").isEqualTo(OK); + assertMessageValidity("40:9A:03").isEqualTo(OK); + assertMessageValidity("40:9A:06:02").isEqualTo(OK); + + assertMessageValidity("0F:9A:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:9A").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:9A").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:9A:07").isEqualTo(ERROR_PARAMETER); + } + + @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); + + assertMessageValidity("40:32:53:50:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:32").isEqualTo(ERROR_SOURCE); + assertMessageValidity("4F:32:45:55").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("4F:32:19:7F:83").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdString() { + assertMessageValidity("40:64:80:41").isEqualTo(OK); + // Even though the parameter string in this message is longer than 14 bytes, it is accepted + // as this parameter might be extended in future versions. + assertMessageValidity("04:64:00:4C:69:76:69:6E:67:52:6F:6F:6D:20:54:56:C4").isEqualTo(OK); + + assertMessageValidity("4F:64:40:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:64:C0:41").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:64:00").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Display Control + assertMessageValidity("40:64:20:4C:69:76").isEqualTo(ERROR_PARAMETER); + // Invalid ASCII characters + assertMessageValidity("40:64:40:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdName() { + assertMessageValidity("40:47:4C:69:76:69:6E:67:52:6F:6F:6D:54:56").isEqualTo(OK); + assertMessageValidity("40:47:54:56").isEqualTo(OK); + + assertMessageValidity("4F:47:54:56").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:47:54:56").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:47").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:47:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_recordStatus() { + assertMessageValidity("40:0A:01").isEqualTo(OK); + assertMessageValidity("40:0A:13").isEqualTo(OK); + assertMessageValidity("40:0A:1F:04:01").isEqualTo(OK); + + assertMessageValidity("0F:0A:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:0A:01").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:0A").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:0A:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:0A:0F").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:0A:1D").isEqualTo(ERROR_PARAMETER); + 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) { 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/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index f7fe1ba1f998..1472a4ac27bc 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.media.ToneGenerator; import android.os.Parcel; import android.os.Parcelable; @@ -97,10 +96,7 @@ public final class DisconnectCause implements Parcelable { * * This reason code is only used for communication between a {@link ConnectionService} and * Telecom and should not be surfaced to the user. - * - * @hide */ - @SystemApi public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; /** diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index cb57df0b2bbc..5024ae27ee49 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -27,6 +27,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.TelephonyManager; import android.text.TextUtils; import java.util.ArrayList; @@ -47,12 +48,20 @@ import java.util.Objects; public final class PhoneAccount implements Parcelable { /** - * String extra which determines the order in which {@link PhoneAccount}s are sorted + * Integer extra which determines the order in which {@link PhoneAccount}s are sorted * * This is an extras key set via {@link Builder#setExtras} which determines the order in which * {@link PhoneAccount}s from the same {@link ConnectionService} are sorted. The accounts - * are sorted by this key via standard lexicographical order, and this ordering is used to + * are sorted in ascending order by this key, and this ordering is used to * determine priority when a call can be placed via multiple accounts. + * + * When multiple {@link PhoneAccount}s are supplied with the same sort order key, no ordering is + * guaranteed between those {@link PhoneAccount}s. Additionally, no ordering is guaranteed + * between {@link PhoneAccount}s that do not supply this extra, and all such accounts + * will be sorted after the accounts that do supply this extra. + * + * An example of a sort order key is slot index (see {@link TelephonyManager#getSlotIndex()}), + * which is the one used by the cell Telephony stack. * @hide */ @SystemApi diff --git a/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl new file mode 100644 index 000000000000..50bbf4c41284 --- /dev/null +++ b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl @@ -0,0 +1,26 @@ +/* + * 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 com.android.internal.telecom; + +/* + * Adapter interface for using DeviceIdleController, since the PowerWhitelistManager is not + * directly accessible in the SYSTEM process. + */ +interface IDeviceIdleControllerAdapter { + void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle, + String reason); +}
\ No newline at end of file diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl index c0280d3dbfaf..b56010696361 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl +++ b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl @@ -14,18 +14,14 @@ * limitations under the License. */ -package android.net; +package com.android.internal.telecom; -import android.net.LinkAddress; +import com.android.internal.telecom.IDeviceIdleControllerAdapter; -/** - * Configuration details for requesting tethering. - * @hide +/* + * Interface used to retrieve services that are only accessible via LocalService in the SYSTEM + * process. */ -parcelable TetheringRequestParcel { - int tetheringType; - LinkAddress localIPv4Address; - LinkAddress staticClientAddress; - boolean exemptFromEntitlementCheck; - boolean showProvisioningUi; +interface IInternalServiceRetriever { + IDeviceIdleControllerAdapter getDeviceIdleController(); } diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl index 253eacbd23e7..eda0f5b24958 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl @@ -14,22 +14,15 @@ * limitations under the License. */ -package android.net; +package com.android.internal.telecom; -import android.net.Network; -import android.net.TetheredClient; -import android.net.TetheringConfigurationParcel; -import android.net.TetherStatesParcel; +import com.android.internal.telecom.ITelecomService; +import com.android.internal.telecom.IInternalServiceRetriever; -/** - * Initial information reported by tethering upon callback registration. - * @hide +/* + * Internal interface for getting an instance of the ITelecomService for external publication. + * Allows the TelecomLoaderService to pass additional dependencies required for creation. */ -parcelable TetheringCallbackStartedParcel { - boolean tetheringSupported; - Network upstreamNetwork; - TetheringConfigurationParcel config; - TetherStatesParcel states; - List<TetheredClient> tetheredClients; - int offloadStatus; +interface ITelecomLoader { + ITelecomService createTelecomService(IInternalServiceRetriever retriever); } diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt deleted file mode 100644 index 5ad377273b90..000000000000 --- a/telephony/api/system-current.txt +++ /dev/null @@ -1,2001 +0,0 @@ -// Signature format: 2.0 -package android.telephony { - - public final class AccessNetworkConstants { - field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff - } - - public static final class AccessNetworkConstants.NgranBands { - method public static int getFrequencyRangeGroup(int); - field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1 - field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2 - field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0 - } - - public final class BarringInfo implements android.os.Parcelable { - ctor public BarringInfo(); - method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy(); - } - - public final class CallAttributes implements android.os.Parcelable { - ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality); - method public int describeContents(); - method @NonNull public android.telephony.CallQuality getCallQuality(); - method public int getNetworkType(); - method @NonNull public android.telephony.PreciseCallState getPreciseCallState(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR; - } - - public final class CallQuality implements android.os.Parcelable { - ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); - ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean); - method public int describeContents(); - method public int getAverageRelativeJitter(); - method public int getAverageRoundTripTime(); - method public int getCallDuration(); - method public int getCodecType(); - method public int getDownlinkCallQualityLevel(); - method public int getMaxRelativeJitter(); - method public int getNumRtpPacketsNotReceived(); - method public int getNumRtpPacketsReceived(); - method public int getNumRtpPacketsTransmitted(); - method public int getNumRtpPacketsTransmittedLost(); - method public int getUplinkCallQualityLevel(); - method public boolean isIncomingSilenceDetectedAtCallSetup(); - method public boolean isOutgoingSilenceDetectedAtCallSetup(); - method public boolean isRtpInactivityDetected(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CALL_QUALITY_BAD = 4; // 0x4 - field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0 - field public static final int CALL_QUALITY_FAIR = 2; // 0x2 - field public static final int CALL_QUALITY_GOOD = 1; // 0x1 - field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5 - field public static final int CALL_QUALITY_POOR = 3; // 0x3 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR; - } - - public class CarrierConfigManager { - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName(); - method @NonNull public static android.os.PersistableBundle getDefaultConfig(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String); - field public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string"; - field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool"; - } - - public static final class CarrierConfigManager.Wifi { - field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count"; - field public static final String KEY_PREFIX = "wifi."; - } - - public final class CarrierRestrictionRules implements android.os.Parcelable { - method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); - method public int describeContents(); - method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(); - method public int getDefaultCarrierRestriction(); - method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers(); - method public int getMultiSimPolicy(); - method public boolean isAllCarriersAllowed(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1 - field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR; - field public static final int MULTISIM_POLICY_NONE = 0; // 0x0 - field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1 - } - - public static final class CarrierRestrictionRules.Builder { - ctor public CarrierRestrictionRules.Builder(); - method @NonNull public android.telephony.CarrierRestrictionRules build(); - method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed(); - method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); - method @NonNull public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int); - method @NonNull public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); - method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int); - } - - public class CbGeoUtils { - } - - public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry { - ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double); - method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); - method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter(); - method public double getRadius(); - } - - public static interface CbGeoUtils.Geometry { - method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); - } - - public static class CbGeoUtils.LatLng { - ctor public CbGeoUtils.LatLng(double, double); - method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng); - method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng); - field public final double lat; - field public final double lng; - } - - public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry { - ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>); - method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); - method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices(); - } - - public abstract class CellBroadcastService extends android.app.Service { - ctor public CellBroadcastService(); - method @NonNull @WorkerThread public abstract CharSequence getCellBroadcastAreaInfo(int); - method public android.os.IBinder onBind(@Nullable android.content.Intent); - method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int); - method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>); - method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]); - field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService"; - } - - public abstract class CellIdentity implements android.os.Parcelable { - method @NonNull public abstract android.telephony.CellLocation asCellLocation(); - method @NonNull public abstract android.telephony.CellIdentity sanitizeLocationInfo(); - } - - public final class CellIdentityCdma extends android.telephony.CellIdentity { - method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityCdma sanitizeLocationInfo(); - } - - public final class CellIdentityGsm extends android.telephony.CellIdentity { - method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityGsm sanitizeLocationInfo(); - } - - public final class CellIdentityLte extends android.telephony.CellIdentity { - method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityLte sanitizeLocationInfo(); - } - - public final class CellIdentityNr extends android.telephony.CellIdentity { - method @NonNull public android.telephony.CellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityNr sanitizeLocationInfo(); - } - - public final class CellIdentityTdscdma extends android.telephony.CellIdentity { - method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityTdscdma sanitizeLocationInfo(); - } - - public final class CellIdentityWcdma extends android.telephony.CellIdentity { - method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); - method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo(); - } - - public final class DataFailCause { - field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be - } - - public final class DataSpecificRegistrationInfo implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; - } - - public final class ImsiEncryptionInfo implements android.os.Parcelable { - method public int describeContents(); - method @Nullable public String getKeyIdentifier(); - method @Nullable public java.security.PublicKey getPublicKey(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR; - } - - public final class LteVopsSupportInfo implements android.os.Parcelable { - ctor public LteVopsSupportInfo(int, int); - method public int describeContents(); - method public int getEmcBearerSupport(); - method public int getVopsSupport(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR; - field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 - field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3 - field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2 - } - - public class MbmsDownloadSession implements java.lang.AutoCloseable { - field public static final String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload"; - } - - public class MbmsGroupCallSession implements java.lang.AutoCloseable { - field public static final String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall"; - } - - public class MbmsStreamingSession implements java.lang.AutoCloseable { - field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; - } - - public final class NetworkRegistrationInfo implements android.os.Parcelable { - method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); - method public int getRegistrationState(); - method public int getRejectCause(); - method public int getRoamingType(); - method public boolean isEmergencyEnabled(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3 - field public static final int REGISTRATION_STATE_HOME = 1; // 0x1 - field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0 - field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2 - field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5 - field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4 - } - - public static final class NetworkRegistrationInfo.Builder { - ctor public NetworkRegistrationInfo.Builder(); - method @NonNull public android.telephony.NetworkRegistrationInfo build(); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int); - method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int); - } - - public abstract class NetworkService extends android.app.Service { - ctor public NetworkService(); - method public android.os.IBinder onBind(android.content.Intent); - method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int); - field public static final String SERVICE_INTERFACE = "android.telephony.NetworkService"; - } - - public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable { - ctor public NetworkService.NetworkServiceProvider(int); - method public abstract void close(); - method public final int getSlotIndex(); - method public final void notifyNetworkRegistrationInfoChanged(); - method public void requestNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback); - } - - public class NetworkServiceCallback { - method public void onRequestNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo); - field public static final int RESULT_ERROR_BUSY = 3; // 0x3 - field public static final int RESULT_ERROR_FAILED = 5; // 0x5 - field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 - field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2 - field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1 - field public static final int RESULT_SUCCESS = 0; // 0x0 - } - - public interface NumberVerificationCallback { - method public default void onCallReceived(@NonNull String); - method public default void onVerificationFailed(int); - field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4 - field public static final int REASON_IN_ECBM = 5; // 0x5 - field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6 - field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2 - field public static final int REASON_TIMED_OUT = 1; // 0x1 - field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3 - field public static final int REASON_UNSPECIFIED = 0; // 0x0 - } - - public final class PhoneNumberRange implements android.os.Parcelable { - ctor public PhoneNumberRange(@NonNull String, @NonNull String, @NonNull String, @NonNull String); - method public int describeContents(); - method public boolean matches(@NonNull String); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR; - } - - public class PhoneNumberUtils { - method @NonNull public static String getUsernameFromUriNumber(@NonNull String); - method public static boolean isUriNumber(@Nullable String); - method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String); - } - - public final class PreciseCallState implements android.os.Parcelable { - ctor public PreciseCallState(int, int, int, int, int); - method public int describeContents(); - method public int getBackgroundCallState(); - method public int getForegroundCallState(); - method public int getRingingCallState(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseCallState> CREATOR; - field public static final int PRECISE_CALL_STATE_ACTIVE = 1; // 0x1 - field public static final int PRECISE_CALL_STATE_ALERTING = 4; // 0x4 - field public static final int PRECISE_CALL_STATE_DIALING = 3; // 0x3 - field public static final int PRECISE_CALL_STATE_DISCONNECTED = 7; // 0x7 - field public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; // 0x8 - field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2 - field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0 - field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5 - field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff - field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6 - } - - public final class PreciseDataConnectionState implements android.os.Parcelable { - method @Deprecated @NonNull public String getDataConnectionApn(); - method @Deprecated public int getDataConnectionApnTypeBitMask(); - method @Deprecated public int getDataConnectionFailCause(); - method @Deprecated public int getDataConnectionState(); - method public int getId(); - } - - public final class PreciseDisconnectCause { - field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104 - field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b - field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44 - field public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57; // 0x39 - field public static final int BEARER_NOT_AVAIL = 58; // 0x3a - field public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65; // 0x41 - field public static final int BUSY = 17; // 0x11 - field public static final int CALL_BARRED = 240; // 0xf0 - field public static final int CALL_REJECTED = 21; // 0x15 - field public static final int CDMA_ACCESS_BLOCKED = 1009; // 0x3f1 - field public static final int CDMA_ACCESS_FAILURE = 1006; // 0x3ee - field public static final int CDMA_DROP = 1001; // 0x3e9 - field public static final int CDMA_INTERCEPT = 1002; // 0x3ea - field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000; // 0x3e8 - field public static final int CDMA_NOT_EMERGENCY = 1008; // 0x3f0 - field public static final int CDMA_PREEMPTED = 1007; // 0x3ef - field public static final int CDMA_REORDER = 1003; // 0x3eb - field public static final int CDMA_RETRY_ORDER = 1005; // 0x3ed - field public static final int CDMA_SO_REJECT = 1004; // 0x3ec - field public static final int CHANNEL_NOT_AVAIL = 44; // 0x2c - field public static final int CHANNEL_UNACCEPTABLE = 6; // 0x6 - field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64 - field public static final int DESTINATION_OUT_OF_ORDER = 27; // 0x1b - field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff - field public static final int FACILITY_REJECTED = 29; // 0x1d - field public static final int FDN_BLOCKED = 241; // 0xf1 - field public static final int IMEI_NOT_ACCEPTED = 243; // 0xf3 - field public static final int IMSI_UNKNOWN_IN_VLR = 242; // 0xf2 - field public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55; // 0x37 - field public static final int INCOMPATIBLE_DESTINATION = 88; // 0x58 - field public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99; // 0x63 - field public static final int INTERWORKING_UNSPECIFIED = 127; // 0x7f - field public static final int INVALID_MANDATORY_INFORMATION = 96; // 0x60 - field public static final int INVALID_NUMBER_FORMAT = 28; // 0x1c - field public static final int INVALID_TRANSACTION_IDENTIFIER = 81; // 0x51 - field public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101; // 0x65 - field public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97; // 0x61 - field public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98; // 0x62 - field public static final int NETWORK_DETACH = 261; // 0x105 - field public static final int NETWORK_OUT_OF_ORDER = 38; // 0x26 - field public static final int NETWORK_REJECT = 252; // 0xfc - field public static final int NETWORK_RESP_TIMEOUT = 251; // 0xfb - field public static final int NORMAL = 16; // 0x10 - field public static final int NORMAL_UNSPECIFIED = 31; // 0x1f - field public static final int NOT_VALID = -1; // 0xffffffff - field public static final int NO_ANSWER_FROM_USER = 19; // 0x13 - field public static final int NO_CIRCUIT_AVAIL = 34; // 0x22 - field public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0; // 0x0 - field public static final int NO_ROUTE_TO_DESTINATION = 3; // 0x3 - field public static final int NO_USER_RESPONDING = 18; // 0x12 - field public static final int NO_VALID_SIM = 249; // 0xf9 - field public static final int NUMBER_CHANGED = 22; // 0x16 - field public static final int OEM_CAUSE_1 = 61441; // 0xf001 - field public static final int OEM_CAUSE_10 = 61450; // 0xf00a - field public static final int OEM_CAUSE_11 = 61451; // 0xf00b - field public static final int OEM_CAUSE_12 = 61452; // 0xf00c - field public static final int OEM_CAUSE_13 = 61453; // 0xf00d - field public static final int OEM_CAUSE_14 = 61454; // 0xf00e - field public static final int OEM_CAUSE_15 = 61455; // 0xf00f - field public static final int OEM_CAUSE_2 = 61442; // 0xf002 - field public static final int OEM_CAUSE_3 = 61443; // 0xf003 - field public static final int OEM_CAUSE_4 = 61444; // 0xf004 - field public static final int OEM_CAUSE_5 = 61445; // 0xf005 - field public static final int OEM_CAUSE_6 = 61446; // 0xf006 - field public static final int OEM_CAUSE_7 = 61447; // 0xf007 - field public static final int OEM_CAUSE_8 = 61448; // 0xf008 - field public static final int OEM_CAUSE_9 = 61449; // 0xf009 - field public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70; // 0x46 - field public static final int OPERATOR_DETERMINED_BARRING = 8; // 0x8 - field public static final int OUT_OF_SRV = 248; // 0xf8 - field public static final int PREEMPTION = 25; // 0x19 - field public static final int PROTOCOL_ERROR_UNSPECIFIED = 111; // 0x6f - field public static final int QOS_NOT_AVAIL = 49; // 0x31 - field public static final int RADIO_ACCESS_FAILURE = 253; // 0xfd - field public static final int RADIO_INTERNAL_ERROR = 250; // 0xfa - field public static final int RADIO_LINK_FAILURE = 254; // 0xfe - field public static final int RADIO_LINK_LOST = 255; // 0xff - field public static final int RADIO_OFF = 247; // 0xf7 - field public static final int RADIO_RELEASE_ABNORMAL = 259; // 0x103 - field public static final int RADIO_RELEASE_NORMAL = 258; // 0x102 - field public static final int RADIO_SETUP_FAILURE = 257; // 0x101 - field public static final int RADIO_UPLINK_FAILURE = 256; // 0x100 - field public static final int RECOVERY_ON_TIMER_EXPIRED = 102; // 0x66 - field public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69; // 0x45 - field public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50; // 0x32 - field public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47; // 0x2f - field public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95; // 0x5f - field public static final int SERVICE_OPTION_NOT_AVAILABLE = 63; // 0x3f - field public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79; // 0x4f - field public static final int STATUS_ENQUIRY = 30; // 0x1e - field public static final int SWITCHING_CONGESTION = 42; // 0x2a - field public static final int TEMPORARY_FAILURE = 41; // 0x29 - field public static final int UNOBTAINABLE_NUMBER = 1; // 0x1 - field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57 - } - - public class ServiceState implements android.os.Parcelable { - method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int); - method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); - method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int); - field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2 - field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3 - field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0 - field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1 - } - - public final class SmsCbCmasInfo implements android.os.Parcelable { - ctor public SmsCbCmasInfo(int, int, int, int, int, int); - method public int describeContents(); - method public int getCategory(); - method public int getCertainty(); - method public int getMessageClass(); - method public int getResponseType(); - method public int getSeverity(); - method public int getUrgency(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CMAS_CATEGORY_CBRNE = 10; // 0xa - field public static final int CMAS_CATEGORY_ENV = 7; // 0x7 - field public static final int CMAS_CATEGORY_FIRE = 5; // 0x5 - field public static final int CMAS_CATEGORY_GEO = 0; // 0x0 - field public static final int CMAS_CATEGORY_HEALTH = 6; // 0x6 - field public static final int CMAS_CATEGORY_INFRA = 9; // 0x9 - field public static final int CMAS_CATEGORY_MET = 1; // 0x1 - field public static final int CMAS_CATEGORY_OTHER = 11; // 0xb - field public static final int CMAS_CATEGORY_RESCUE = 4; // 0x4 - field public static final int CMAS_CATEGORY_SAFETY = 2; // 0x2 - field public static final int CMAS_CATEGORY_SECURITY = 3; // 0x3 - field public static final int CMAS_CATEGORY_TRANSPORT = 8; // 0x8 - field public static final int CMAS_CATEGORY_UNKNOWN = -1; // 0xffffffff - field public static final int CMAS_CERTAINTY_LIKELY = 1; // 0x1 - field public static final int CMAS_CERTAINTY_OBSERVED = 0; // 0x0 - field public static final int CMAS_CERTAINTY_UNKNOWN = -1; // 0xffffffff - field public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 3; // 0x3 - field public static final int CMAS_CLASS_CMAS_EXERCISE = 5; // 0x5 - field public static final int CMAS_CLASS_EXTREME_THREAT = 1; // 0x1 - field public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 6; // 0x6 - field public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0; // 0x0 - field public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 4; // 0x4 - field public static final int CMAS_CLASS_SEVERE_THREAT = 2; // 0x2 - field public static final int CMAS_CLASS_UNKNOWN = -1; // 0xffffffff - field public static final int CMAS_RESPONSE_TYPE_ASSESS = 6; // 0x6 - field public static final int CMAS_RESPONSE_TYPE_AVOID = 5; // 0x5 - field public static final int CMAS_RESPONSE_TYPE_EVACUATE = 1; // 0x1 - field public static final int CMAS_RESPONSE_TYPE_EXECUTE = 3; // 0x3 - field public static final int CMAS_RESPONSE_TYPE_MONITOR = 4; // 0x4 - field public static final int CMAS_RESPONSE_TYPE_NONE = 7; // 0x7 - field public static final int CMAS_RESPONSE_TYPE_PREPARE = 2; // 0x2 - field public static final int CMAS_RESPONSE_TYPE_SHELTER = 0; // 0x0 - field public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1; // 0xffffffff - field public static final int CMAS_SEVERITY_EXTREME = 0; // 0x0 - field public static final int CMAS_SEVERITY_SEVERE = 1; // 0x1 - field public static final int CMAS_SEVERITY_UNKNOWN = -1; // 0xffffffff - field public static final int CMAS_URGENCY_EXPECTED = 1; // 0x1 - field public static final int CMAS_URGENCY_IMMEDIATE = 0; // 0x0 - field public static final int CMAS_URGENCY_UNKNOWN = -1; // 0xffffffff - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbCmasInfo> CREATOR; - } - - public final class SmsCbEtwsInfo implements android.os.Parcelable { - ctor public SmsCbEtwsInfo(int, boolean, boolean, boolean, @Nullable byte[]); - method public int describeContents(); - method @Nullable public byte[] getPrimaryNotificationSignature(); - method public long getPrimaryNotificationTimestamp(); - method public int getWarningType(); - method public boolean isEmergencyUserAlert(); - method public boolean isPopupAlert(); - method public boolean isPrimary(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbEtwsInfo> CREATOR; - field public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0; // 0x0 - field public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 2; // 0x2 - field public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 4; // 0x4 - field public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 3; // 0x3 - field public static final int ETWS_WARNING_TYPE_TSUNAMI = 1; // 0x1 - field public static final int ETWS_WARNING_TYPE_UNKNOWN = -1; // 0xffffffff - } - - public final class SmsCbLocation implements android.os.Parcelable { - ctor public SmsCbLocation(@NonNull String, int, int); - method public int describeContents(); - method public int getCid(); - method public int getLac(); - method @NonNull public String getPlmn(); - method public boolean isInLocationArea(@NonNull android.telephony.SmsCbLocation); - method public boolean isInLocationArea(@Nullable String, int, int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbLocation> CREATOR; - } - - public final class SmsCbMessage implements android.os.Parcelable { - ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int); - method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor); - method public int describeContents(); - method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo(); - method @NonNull public android.content.ContentValues getContentValues(); - method public int getDataCodingScheme(); - method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo(); - method public int getGeographicalScope(); - method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries(); - method @Nullable public String getLanguageCode(); - method @NonNull public android.telephony.SmsCbLocation getLocation(); - method public int getMaximumWaitingDuration(); - method @Nullable public String getMessageBody(); - method public int getMessageFormat(); - method public int getMessagePriority(); - method public long getReceivedTime(); - method public int getSerialNumber(); - method public int getServiceCategory(); - method public int getSlotIndex(); - method public int getSubscriptionId(); - method public boolean isCmasMessage(); - method public boolean isEmergencyMessage(); - method public boolean isEtwsMessage(); - method public boolean needGeoFencingCheck(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbMessage> CREATOR; - field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; // 0x3 - field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; // 0x0 - field public static final int GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2; // 0x2 - field public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; // 0x1 - field public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; // 0xff - field public static final int MESSAGE_FORMAT_3GPP = 1; // 0x1 - field public static final int MESSAGE_FORMAT_3GPP2 = 2; // 0x2 - field public static final int MESSAGE_PRIORITY_EMERGENCY = 3; // 0x3 - field public static final int MESSAGE_PRIORITY_INTERACTIVE = 1; // 0x1 - field public static final int MESSAGE_PRIORITY_NORMAL = 0; // 0x0 - field public static final int MESSAGE_PRIORITY_URGENT = 2; // 0x2 - } - - public final class SmsManager { - method public boolean disableCellBroadcastRange(int, int, int); - method public boolean enableCellBroadcastRange(int, int, int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int); - field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3 - field public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; // 0x1 - field public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; // 0x2 - field public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; // 0x0 - } - - public class SmsMessage { - method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean); - method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0, to=255) int, @IntRange(from=1, to=255) int, @IntRange(from=1, to=255) int); - } - - public class SubscriptionInfo implements android.os.Parcelable { - method public boolean areUiccApplicationsEnabled(); - method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); - method public int getProfileClass(); - method public boolean isGroupDisabled(); - } - - public class SubscriptionManager { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription(); - method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String); - method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList(); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int); - method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int); - method public void requestEmbeddedSubscriptionInfoListRefresh(); - method public void requestEmbeddedSubscriptionInfoListRefresh(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(int, boolean); - field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED"; - field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI; - field @Deprecated public static final int PROFILE_CLASS_DEFAULT; - field public static final int PROFILE_CLASS_OPERATIONAL; - field public static final int PROFILE_CLASS_PROVISIONING; - field public static final int PROFILE_CLASS_TESTING; - field public static final int PROFILE_CLASS_UNSET; - field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI; - field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI; - field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI; - field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI; - field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI; - } - - public final class TelephonyHistogram implements android.os.Parcelable { - ctor public TelephonyHistogram(int, int, int); - ctor public TelephonyHistogram(android.telephony.TelephonyHistogram); - ctor public TelephonyHistogram(android.os.Parcel); - method public void addTimeTaken(int); - method public int describeContents(); - method public int getAverageTime(); - method public int getBucketCount(); - method public int[] getBucketCounters(); - method public int[] getBucketEndPoints(); - method public int getCategory(); - method public int getId(); - method public int getMaxTime(); - method public int getMinTime(); - method public int getSampleCount(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR; - field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1 - } - - public class TelephonyManager { - method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); - method public int checkCarrierPrivilegesForPackage(String); - method public int checkCarrierPrivilegesForPackageAnyPhone(String); - method public void dial(String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean); - method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); - method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); - method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); - method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); - method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(int); - method public String getCdmaPrlVersion(); - method public int getCurrentPhoneType(); - method public int getCurrentPhoneType(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState(); - method @Deprecated public boolean getDataEnabled(); - method @Deprecated public boolean getDataEnabled(int); - method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain(); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst(); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping(); - method public int getMaxNumberOfSimultaneouslyActiveSims(); - method public static long getMaxNumberVerificationTimeoutMillis(); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask(); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState(); - method public int getSimApplicationState(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int); - method public int getSimCardState(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo(); - method @Nullable public android.os.Bundle getVisualVoicemailSettings(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String); - method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int); - method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int); - method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String); - method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean 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(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled(); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled(); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn(); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isTetheringApnRequired(); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled(); - method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean matchesCurrentSimOperator(@NonNull String, int, @Nullable String); - method public boolean needsOtaServiceProvisioning(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean); - method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int); - method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig(); - method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); - method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); - method @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); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>); - method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios(); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); - method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor); - method public void updateServiceLocation(); - field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED"; - field public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED"; - field public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED"; - field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE"; - field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED"; - field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED"; - field public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE"; - field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS"; - field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; - field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; - field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; - field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe - field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 - field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 - field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff - field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION"; - field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID"; - field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE"; - field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL"; - field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; - field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; - field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; - field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff - field public static final int KEY_TYPE_EPDG = 1; // 0x1 - field public static final int KEY_TYPE_WLAN = 2; // 0x2 - field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L - field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L - field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L - field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L - field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L - field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L - field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L - field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L - field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L - field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L - field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L - field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L - field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L - field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L - field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L - field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L - field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L - field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L - field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L - field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L - field public static final int RADIO_POWER_OFF = 0; // 0x0 - field public static final int RADIO_POWER_ON = 1; // 0x1 - field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2 - field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2 - field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1 - field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0 - field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2 - field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1 - field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3 - field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4 - field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0 - field public static final int SIM_STATE_LOADED = 10; // 0xa - field public static final int SIM_STATE_PRESENT = 11; // 0xb - field public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; // 0x3 - field public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1; // 0x1 - field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2 - field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff - field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 - } - - public final class UiccAccessRule implements android.os.Parcelable { - ctor public UiccAccessRule(byte[], @Nullable String, long); - method public int describeContents(); - method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo); - method public int getCarrierPrivilegeStatus(android.content.pm.Signature, String); - method public String getCertificateHexString(); - method @Nullable public String getPackageName(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR; - } - - public class UiccSlotInfo implements android.os.Parcelable { - ctor @Deprecated public UiccSlotInfo(boolean, boolean, String, int, int, boolean); - method public int describeContents(); - method public String getCardId(); - method public int getCardStateInfo(); - method public boolean getIsActive(); - method public boolean getIsEuicc(); - method public boolean getIsExtendedApduSupported(); - method public int getLogicalSlotIdx(); - method public boolean isRemovable(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1 - field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3 - field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2 - field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR; - } - - public abstract class VisualVoicemailService extends android.app.Service { - method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent); - method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); - } - -} - -package android.telephony.cdma { - - public final class CdmaSmsCbProgramData implements android.os.Parcelable { - method public int describeContents(); - method public int getCategory(); - method public int getOperation(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = 4099; // 0x1003 - field public static final int CATEGORY_CMAS_EXTREME_THREAT = 4097; // 0x1001 - field public static final int CATEGORY_CMAS_LAST_RESERVED_VALUE = 4351; // 0x10ff - field public static final int CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT = 4096; // 0x1000 - field public static final int CATEGORY_CMAS_SEVERE_THREAT = 4098; // 0x1002 - field public static final int CATEGORY_CMAS_TEST_MESSAGE = 4100; // 0x1004 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.cdma.CdmaSmsCbProgramData> CREATOR; - field public static final int OPERATION_ADD_CATEGORY = 1; // 0x1 - field public static final int OPERATION_CLEAR_CATEGORIES = 2; // 0x2 - field public static final int OPERATION_DELETE_CATEGORY = 0; // 0x0 - } - -} - -package android.telephony.data { - - public final class DataCallResponse implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public java.util.List<android.net.LinkAddress> getAddresses(); - method public int getCause(); - method @NonNull public java.util.List<java.net.InetAddress> getDnsAddresses(); - method @NonNull public java.util.List<java.net.InetAddress> getGatewayAddresses(); - method public int getHandoverFailureMode(); - method public int getId(); - method @NonNull public String getInterfaceName(); - method public int getLinkStatus(); - method @Deprecated public int getMtu(); - method public int getMtuV4(); - method public int getMtuV6(); - method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses(); - method public int getProtocolType(); - method public int getSuggestedRetryTime(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR; - field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 2; // 0x2 - field public static final int HANDOVER_FAILURE_MODE_LEGACY = 1; // 0x1 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 3; // 0x3 - field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 4; // 0x4 - field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = 0; // 0x0 - field public static final int LINK_STATUS_ACTIVE = 2; // 0x2 - field public static final int LINK_STATUS_DORMANT = 1; // 0x1 - field public static final int LINK_STATUS_INACTIVE = 0; // 0x0 - field public static final int LINK_STATUS_UNKNOWN = -1; // 0xffffffff - } - - public static final class DataCallResponse.Builder { - ctor public DataCallResponse.Builder(); - method @NonNull public android.telephony.data.DataCallResponse build(); - method @NonNull public android.telephony.data.DataCallResponse.Builder setAddresses(@NonNull java.util.List<android.net.LinkAddress>); - method @NonNull public android.telephony.data.DataCallResponse.Builder setCause(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setDnsAddresses(@NonNull java.util.List<java.net.InetAddress>); - method @NonNull public android.telephony.data.DataCallResponse.Builder setGatewayAddresses(@NonNull java.util.List<java.net.InetAddress>); - method @NonNull public android.telephony.data.DataCallResponse.Builder setHandoverFailureMode(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String); - method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int); - method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>); - method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int); - } - - public final class DataProfile implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public String getApn(); - method public int getAuthType(); - method public int getBearerBitmask(); - method @Deprecated public int getMtu(); - method public int getMtuV4(); - method public int getMtuV6(); - method @Nullable public String getPassword(); - method public int getProfileId(); - method public int getProtocolType(); - method public int getRoamingProtocolType(); - method public int getSupportedApnTypesBitmask(); - method public int getType(); - method @Nullable public String getUserName(); - method public boolean isEnabled(); - method public boolean isPersistent(); - method public boolean isPreferred(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR; - field public static final int TYPE_3GPP = 1; // 0x1 - field public static final int TYPE_3GPP2 = 2; // 0x2 - field public static final int TYPE_COMMON = 0; // 0x0 - } - - public static final class DataProfile.Builder { - ctor public DataProfile.Builder(); - method @NonNull public android.telephony.data.DataProfile build(); - method @NonNull public android.telephony.data.DataProfile.Builder enable(boolean); - method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String); - method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int); - method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int); - method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int); - method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int); - method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int); - method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String); - method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean); - method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean); - method @NonNull public android.telephony.data.DataProfile.Builder setProfileId(int); - method @NonNull public android.telephony.data.DataProfile.Builder setProtocolType(int); - method @NonNull public android.telephony.data.DataProfile.Builder setRoamingProtocolType(int); - method @NonNull public android.telephony.data.DataProfile.Builder setSupportedApnTypesBitmask(int); - method @NonNull public android.telephony.data.DataProfile.Builder setType(int); - method @NonNull public android.telephony.data.DataProfile.Builder setUserName(@NonNull String); - } - - public abstract class DataService extends android.app.Service { - ctor public DataService(); - method public android.os.IBinder onBind(android.content.Intent); - method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int); - field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3 - field public static final int REQUEST_REASON_NORMAL = 1; // 0x1 - field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2 - field public static final int REQUEST_REASON_UNKNOWN = 0; // 0x0 - field public static final String SERVICE_INTERFACE = "android.telephony.data.DataService"; - } - - public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable { - ctor public DataService.DataServiceProvider(int); - method public abstract void close(); - method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback); - method public final int getSlotIndex(); - method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>); - method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback); - method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback); - method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback); - method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback); - } - - public class DataServiceCallback { - method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>); - method public void onDeactivateDataCallComplete(int); - method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>); - method public void onSetDataProfileComplete(int); - method public void onSetInitialAttachApnComplete(int); - method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse); - field public static final int RESULT_ERROR_BUSY = 3; // 0x3 - field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 - field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2 - field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1 - field public static final int RESULT_SUCCESS = 0; // 0x0 - } - - public abstract class QualifiedNetworksService extends android.app.Service { - ctor public QualifiedNetworksService(); - method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int); - field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService"; - } - - public abstract class QualifiedNetworksService.NetworkAvailabilityProvider implements java.lang.AutoCloseable { - ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int); - method public abstract void close(); - method public final int getSlotIndex(); - method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>); - } - -} - -package android.telephony.euicc { - - public final class DownloadableSubscription implements android.os.Parcelable { - method public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); - method @Nullable public String getCarrierName(); - } - - public static final class DownloadableSubscription.Builder { - ctor public DownloadableSubscription.Builder(); - ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription); - method public android.telephony.euicc.DownloadableSubscription build(); - method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>); - method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(String); - method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(String); - method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(String); - } - - public class EuiccCardManager { - method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); - method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void removeNotificationFromList(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void requestAllProfiles(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>); - method public void requestDefaultSmdpAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); - method public void requestEuiccChallenge(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void requestEuiccInfo1(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void requestEuiccInfo2(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); - method public void requestProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); - method public void requestRulesAuthTable(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>); - method public void requestSmdsAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); - method public void resetMemory(String, @android.telephony.euicc.EuiccCardManager.ResetOption int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void retrieveNotification(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>); - method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); - method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); - method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); - field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0 - field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1 - field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3 - field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2 - field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2 - field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1 - field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4 - field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd - field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe - field public static final int RESULT_OK = 0; // 0x0 - field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff - } - - @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason { - } - - @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption { - } - - public static interface EuiccCardManager.ResultCallback<T> { - method public void onComplete(int, T); - } - - public class EuiccManager { - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle); - method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus(); - method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getSupportedCountries(); - method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getUnsupportedCountries(); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>); - field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED"; - field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED"; - field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; - field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED"; - field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED"; - field public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4; // 0x4 - field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2 - field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1 - field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3 - field public static final int EUICC_OTA_FAILED = 2; // 0x2 - field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1 - field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4 - field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5 - field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3 - field public static final String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE"; - field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS"; - field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION"; - field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION"; - field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID"; - field public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID"; - field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID"; - field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME"; - } - - @IntDef(prefix={"EUICC_OTA_"}, value={android.telephony.euicc.EuiccManager.EUICC_OTA_IN_PROGRESS, android.telephony.euicc.EuiccManager.EUICC_OTA_FAILED, android.telephony.euicc.EuiccManager.EUICC_OTA_SUCCEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_NOT_NEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccManager.OtaStatus { - } - - public final class EuiccNotification implements android.os.Parcelable { - ctor public EuiccNotification(int, String, @android.telephony.euicc.EuiccNotification.Event int, @Nullable byte[]); - method public int describeContents(); - method @Nullable public byte[] getData(); - method @android.telephony.euicc.EuiccNotification.Event public int getEvent(); - method public int getSeq(); - method public String getTargetAddr(); - method public void writeToParcel(android.os.Parcel, int); - field @android.telephony.euicc.EuiccNotification.Event public static final int ALL_EVENTS = 15; // 0xf - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR; - field public static final int EVENT_DELETE = 8; // 0x8 - field public static final int EVENT_DISABLE = 4; // 0x4 - field public static final int EVENT_ENABLE = 2; // 0x2 - field public static final int EVENT_INSTALL = 1; // 0x1 - } - - @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event { - } - - public final class EuiccRulesAuthTable implements android.os.Parcelable { - method public int describeContents(); - method public int findIndex(@android.service.euicc.EuiccProfileInfo.PolicyRule int, android.service.carrier.CarrierIdentifier); - method public boolean hasPolicyRuleFlag(int, @android.telephony.euicc.EuiccRulesAuthTable.PolicyRuleFlag int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR; - field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1 - } - - public static final class EuiccRulesAuthTable.Builder { - ctor public EuiccRulesAuthTable.Builder(int); - method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int); - method public android.telephony.euicc.EuiccRulesAuthTable build(); - } - - @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { - } - -} - -package android.telephony.ims { - - public final class ImsCallForwardInfo implements android.os.Parcelable { - ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int); - method public int describeContents(); - method public int getCondition(); - method public String getNumber(); - method public int getServiceClass(); - method public int getStatus(); - method public int getTimeSeconds(); - method public int getToA(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CDIV_CF_REASON_ALL = 4; // 0x4 - field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5 - field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1 - field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6 - field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3 - field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2 - field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR; - field public static final int STATUS_ACTIVE = 1; // 0x1 - field public static final int STATUS_NOT_ACTIVE = 0; // 0x0 - field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91 - field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81 - } - - public final class ImsCallProfile implements android.os.Parcelable { - ctor public ImsCallProfile(); - ctor public ImsCallProfile(int, int); - ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile); - method public int describeContents(); - method public String getCallExtra(String); - method public String getCallExtra(String, String); - method public boolean getCallExtraBoolean(String); - method public boolean getCallExtraBoolean(String, boolean); - method public int getCallExtraInt(String); - method public int getCallExtraInt(String, int); - method public android.os.Bundle getCallExtras(); - method public int getCallType(); - method public static int getCallTypeFromVideoState(int); - method public int getCallerNumberVerificationStatus(); - method public int getEmergencyCallRouting(); - method public int getEmergencyServiceCategories(); - method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); - method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); - method @NonNull public android.os.Bundle getProprietaryCallExtras(); - method public int getRestrictCause(); - method public int getServiceType(); - method public static int getVideoStateFromCallType(int); - method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); - method public boolean hasKnownUserIntentEmergency(); - method public boolean isEmergencyCallTesting(); - method public boolean isVideoCall(); - method public boolean isVideoPaused(); - method public static int presentationToOir(int); - method public void setCallExtra(String, String); - method public void setCallExtraBoolean(String, boolean); - method public void setCallExtraInt(String, int); - method public void setCallRestrictCause(int); - method public void setCallerNumberVerificationStatus(int); - method public void setEmergencyCallRouting(int); - method public void setEmergencyCallTesting(boolean); - method public void setEmergencyServiceCategories(int); - method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>); - method public void setHasKnownUserIntentEmergency(boolean); - method public void updateCallExtras(android.telephony.ims.ImsCallProfile); - method public void updateCallType(android.telephony.ims.ImsCallProfile); - method public void updateMediaProfile(android.telephony.ims.ImsCallProfile); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2 - field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3 - field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0 - field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1 - field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3 - field public static final int CALL_TYPE_VOICE = 2; // 0x2 - field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1 - field public static final int CALL_TYPE_VS = 8; // 0x8 - field public static final int CALL_TYPE_VS_RX = 10; // 0xa - field public static final int CALL_TYPE_VS_TX = 9; // 0x9 - field public static final int CALL_TYPE_VT = 4; // 0x4 - field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7 - field public static final int CALL_TYPE_VT_RX = 6; // 0x6 - field public static final int CALL_TYPE_VT_TX = 5; // 0x5 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR; - field public static final int DIALSTRING_NORMAL = 0; // 0x0 - field public static final int DIALSTRING_SS_CONF = 1; // 0x1 - field public static final int DIALSTRING_USSD = 2; // 0x2 - field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo"; - field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS"; - field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE"; - field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE"; - field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech"; - field public static final String EXTRA_CHILD_NUMBER = "ChildNum"; - field public static final String EXTRA_CNA = "cna"; - field public static final String EXTRA_CNAP = "cnap"; - field public static final String EXTRA_CODEC = "Codec"; - field public static final String EXTRA_DIALSTRING = "dialstring"; - field public static final String EXTRA_DISPLAY_TEXT = "DisplayText"; - field public static final String EXTRA_EMERGENCY_CALL = "e_call"; - field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER"; - field public static final String EXTRA_IS_CALL_PULL = "CallPull"; - field public static final String EXTRA_OI = "oi"; - field public static final String EXTRA_OIR = "oir"; - field public static final String EXTRA_REMOTE_URI = "remote_uri"; - field public static final String EXTRA_USSD = "ussd"; - field public static final int OIR_DEFAULT = 0; // 0x0 - field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2 - field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4 - field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1 - field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3 - field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2 - field public static final int SERVICE_TYPE_NONE = 0; // 0x0 - field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1 - field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2 - field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0 - field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1 - } - - public class ImsCallSessionListener { - method public void callQualityChanged(@NonNull android.telephony.CallQuality); - method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); - method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); - method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState); - method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo); - method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo); - method public void callSessionHeld(android.telephony.ims.ImsCallProfile); - method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile); - method public void callSessionInitiated(android.telephony.ims.ImsCallProfile); - method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionInviteParticipantsRequestDelivered(); - method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); - method @Deprecated public void callSessionMayHandover(int, int); - method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase); - method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); - method public void callSessionMultipartyStateChanged(boolean); - method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile); - method public void callSessionRemoveParticipantsRequestDelivered(); - method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile); - method public void callSessionResumed(android.telephony.ims.ImsCallProfile); - method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile); - method public void callSessionRttMessageReceived(String); - method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile); - method public void callSessionRttModifyResponseReceived(int); - method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification); - method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo); - method public void callSessionTtyModeReceived(int); - method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo); - method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile); - method public void callSessionUpdated(android.telephony.ims.ImsCallProfile); - method public void callSessionUssdMessageReceived(int, String); - method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo); - method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo); - method public void onMayHandover(int, int); - } - - public final class ImsConferenceState implements android.os.Parcelable { - method public int describeContents(); - method public static int getConnectionStateForStatus(String); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR; - field public static final String DISPLAY_TEXT = "display-text"; - field public static final String ENDPOINT = "endpoint"; - field public static final String SIP_STATUS_CODE = "sipstatuscode"; - field public static final String STATUS = "status"; - field public static final String STATUS_ALERTING = "alerting"; - field public static final String STATUS_CONNECTED = "connected"; - field public static final String STATUS_CONNECT_FAIL = "connect-fail"; - field public static final String STATUS_DIALING_IN = "dialing-in"; - field public static final String STATUS_DIALING_OUT = "dialing-out"; - field public static final String STATUS_DISCONNECTED = "disconnected"; - field public static final String STATUS_DISCONNECTING = "disconnecting"; - field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus"; - field public static final String STATUS_ON_HOLD = "on-hold"; - field public static final String STATUS_PENDING = "pending"; - field public static final String STATUS_SEND_ONLY = "sendonly"; - field public static final String STATUS_SEND_RECV = "sendrecv"; - field public static final String USER = "user"; - field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants; - } - - public final class ImsException extends java.lang.Exception { - ctor public ImsException(@Nullable String); - ctor public ImsException(@Nullable String, int); - ctor public ImsException(@Nullable String, int, @Nullable Throwable); - } - - public final class ImsExternalCallState implements android.os.Parcelable { - ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean); - method public int describeContents(); - method @NonNull public android.net.Uri getAddress(); - method public int getCallId(); - method public int getCallState(); - method public int getCallType(); - method @Nullable public android.net.Uri getLocalAddress(); - method public boolean isCallHeld(); - method public boolean isCallPullable(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CALL_STATE_CONFIRMED = 1; // 0x1 - field public static final int CALL_STATE_TERMINATED = 2; // 0x2 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; - } - - public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { - method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; - method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); - method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); - } - - @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { - ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); - } - - public final class ImsReasonInfo implements android.os.Parcelable { - field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; - } - - public class ImsService extends android.app.Service { - ctor public ImsService(); - method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); - method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); - method public void disableIms(int); - method public void enableIms(int); - method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); - method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); - method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; - method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); - method public void readyForFeatureCreation(); - } - - public final class ImsSsData implements android.os.Parcelable { - ctor public ImsSsData(int, int, int, int, int); - method public int describeContents(); - method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo(); - method public int getRequestType(); - method public int getResult(); - method public int getServiceClass(); - method public int getServiceType(); - method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo(); - method public int getTeleserviceType(); - method public boolean isTypeBarring(); - method public boolean isTypeCf(); - method public boolean isTypeClip(); - method public boolean isTypeClir(); - method public boolean isTypeColp(); - method public boolean isTypeColr(); - method public boolean isTypeCw(); - method public boolean isTypeIcb(); - method public boolean isTypeInterrogation(); - method public boolean isTypeUnConditional(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR; - field public static final int RESULT_SUCCESS = 0; // 0x0 - field public static final int SERVICE_CLASS_DATA = 2; // 0x2 - field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20 - field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10 - field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40 - field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80 - field public static final int SERVICE_CLASS_FAX = 4; // 0x4 - field public static final int SERVICE_CLASS_NONE = 0; // 0x0 - field public static final int SERVICE_CLASS_SMS = 8; // 0x8 - field public static final int SERVICE_CLASS_VOICE = 1; // 0x1 - field public static final int SS_ACTIVATION = 0; // 0x0 - field public static final int SS_ALL_BARRING = 18; // 0x12 - field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3 - field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5 - field public static final int SS_ALL_TELESEVICES = 1; // 0x1 - field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0 - field public static final int SS_BAIC = 16; // 0x10 - field public static final int SS_BAIC_ROAMING = 17; // 0x11 - field public static final int SS_BAOC = 13; // 0xd - field public static final int SS_BAOIC = 14; // 0xe - field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf - field public static final int SS_CFU = 0; // 0x0 - field public static final int SS_CFUT = 6; // 0x6 - field public static final int SS_CF_ALL = 4; // 0x4 - field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5 - field public static final int SS_CF_BUSY = 1; // 0x1 - field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3 - field public static final int SS_CF_NO_REPLY = 2; // 0x2 - field public static final int SS_CLIP = 7; // 0x7 - field public static final int SS_CLIR = 8; // 0x8 - field public static final int SS_CNAP = 11; // 0xb - field public static final int SS_COLP = 9; // 0x9 - field public static final int SS_COLR = 10; // 0xa - field public static final int SS_DEACTIVATION = 1; // 0x1 - field public static final int SS_ERASURE = 4; // 0x4 - field public static final int SS_INCOMING_BARRING = 20; // 0x14 - field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16 - field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15 - field public static final int SS_INTERROGATION = 2; // 0x2 - field public static final int SS_OUTGOING_BARRING = 19; // 0x13 - field public static final int SS_REGISTRATION = 3; // 0x3 - field public static final int SS_SMS_SERVICES = 4; // 0x4 - field public static final int SS_TELEPHONY = 2; // 0x2 - field public static final int SS_WAIT = 12; // 0xc - } - - public static final class ImsSsData.Builder { - ctor public ImsSsData.Builder(int, int, int, int, int); - method @NonNull public android.telephony.ims.ImsSsData build(); - method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>); - method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>); - } - - public final class ImsSsInfo implements android.os.Parcelable { - ctor @Deprecated public ImsSsInfo(int, @Nullable String); - method public int describeContents(); - method public int getClirInterrogationStatus(); - method public int getClirOutgoingState(); - method @Deprecated public String getIcbNum(); - method @Nullable public String getIncomingCommunicationBarringNumber(); - method public int getProvisionStatus(); - method public int getStatus(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0 - field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1 - field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2 - field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0 - field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1 - field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4 - field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3 - field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR; - field public static final int DISABLED = 0; // 0x0 - field public static final int ENABLED = 1; // 0x1 - field public static final int NOT_REGISTERED = -1; // 0xffffffff - field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0 - field public static final int SERVICE_PROVISIONED = 1; // 0x1 - field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff - } - - public static final class ImsSsInfo.Builder { - ctor public ImsSsInfo.Builder(int); - method @NonNull public android.telephony.ims.ImsSsInfo build(); - method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int); - method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int); - method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String); - method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int); - } - - public final class ImsStreamMediaProfile implements android.os.Parcelable { - ctor public ImsStreamMediaProfile(int, int, int, int, int); - method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); - method public int describeContents(); - method public int getAudioDirection(); - method public int getAudioQuality(); - method public int getRttMode(); - method public int getVideoDirection(); - method public int getVideoQuality(); - method public boolean isReceivingRttAudio(); - method public boolean isRttCall(); - method public void setReceivingRttAudio(boolean); - method public void setRttMode(int); - method public void writeToParcel(android.os.Parcel, int); - field public static final int AUDIO_QUALITY_AMR = 1; // 0x1 - field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2 - field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4 - field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5 - field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7 - field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6 - field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14 - field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11 - field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13 - field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12 - field public static final int AUDIO_QUALITY_G711A = 13; // 0xd - field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf - field public static final int AUDIO_QUALITY_G711U = 11; // 0xb - field public static final int AUDIO_QUALITY_G722 = 14; // 0xe - field public static final int AUDIO_QUALITY_G723 = 12; // 0xc - field public static final int AUDIO_QUALITY_G729 = 16; // 0x10 - field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8 - field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9 - field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa - field public static final int AUDIO_QUALITY_NONE = 0; // 0x0 - field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3 - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR; - field public static final int DIRECTION_INACTIVE = 0; // 0x0 - field public static final int DIRECTION_INVALID = -1; // 0xffffffff - field public static final int DIRECTION_RECEIVE = 1; // 0x1 - field public static final int DIRECTION_SEND = 2; // 0x2 - field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3 - field public static final int RTT_MODE_DISABLED = 0; // 0x0 - field public static final int RTT_MODE_FULL = 1; // 0x1 - field public static final int VIDEO_QUALITY_NONE = 0; // 0x0 - field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1 - field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2 - field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4 - field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8 - field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10 - } - - public final class ImsSuppServiceNotification implements android.os.Parcelable { - ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR; - field public final int code; - field public final String[] history; - field public final int index; - field public final int notificationType; - field public final String number; - field public final int type; - } - - public class ImsUtListener { - method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo); - method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData); - method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]); - method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]); - method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]); - method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle); - method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo); - method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo); - method public void onUtConfigurationUpdated(int); - field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir"; - field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; - } - - public abstract class ImsVideoCallProvider { - ctor public ImsVideoCallProvider(); - method public void changeCallDataUsage(long); - method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); - method public void changePeerDimensions(int, int); - method public void changeVideoQuality(int); - method public void handleCallSessionEvent(int); - method public abstract void onRequestCallDataUsage(); - method public abstract void onRequestCameraCapabilities(); - method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile); - method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile); - method public abstract void onSetCamera(String); - method public void onSetCamera(String, int); - method public abstract void onSetDeviceOrientation(int); - method public abstract void onSetDisplaySurface(android.view.Surface); - method public abstract void onSetPauseImage(android.net.Uri); - method public abstract void onSetPreviewSurface(android.view.Surface); - method public abstract void onSetZoom(float); - method public void receiveSessionModifyRequest(android.telecom.VideoProfile); - method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile); - } - - public class ProvisioningManager { - method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); - field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 - field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b - field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a - field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 - field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1 - field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC"; - field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY"; - } - - public static class ProvisioningManager.Callback { - ctor public ProvisioningManager.Callback(); - method public void onProvisioningIntChanged(int, int); - method public void onProvisioningStringChanged(int, @NonNull String); - } - - public class RcsUceAdapter { - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; - } - -} - -package android.telephony.ims.feature { - - public final class CapabilityChangeRequest implements android.os.Parcelable { - method public void addCapabilitiesToDisableForTech(int, int); - method public void addCapabilitiesToEnableForTech(int, int); - method public int describeContents(); - method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable(); - method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR; - } - - public static class CapabilityChangeRequest.CapabilityPair { - ctor public CapabilityChangeRequest.CapabilityPair(int, int); - method public int getCapability(); - method public int getRadioTech(); - } - - public abstract class ImsFeature { - ctor public ImsFeature(); - method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); - method public int getFeatureState(); - method public final int getSlotIndex(); - method public abstract void onFeatureReady(); - method public abstract void onFeatureRemoved(); - method public final void setFeatureState(int); - field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff - field public static final int CAPABILITY_SUCCESS = 0; // 0x0 - field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0 - field public static final int FEATURE_MMTEL = 1; // 0x1 - field public static final int FEATURE_RCS = 2; // 0x2 - field public static final int STATE_INITIALIZING = 1; // 0x1 - field public static final int STATE_READY = 2; // 0x2 - field public static final int STATE_UNAVAILABLE = 0; // 0x0 - } - - @Deprecated public static class ImsFeature.Capabilities { - field @Deprecated protected int mCapabilities; - } - - protected static class ImsFeature.CapabilityCallbackProxy { - method public void onChangeCapabilityConfigurationError(int, int, int); - } - - public class MmTelFeature extends android.telephony.ims.feature.ImsFeature { - ctor public MmTelFeature(); - method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); - method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int); - method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile); - method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm(); - method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint(); - method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation(); - method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt(); - method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); - method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle); - method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo); - method public final void notifyVoiceMessageCountUpdate(int); - method public void onFeatureReady(); - method public void onFeatureRemoved(); - method public boolean queryCapabilityConfiguration(int, int); - method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); - method public void setUiTtyMode(int, @Nullable android.os.Message); - method public int shouldProcessCall(@NonNull String[]); - field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; - field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; - field public static final int PROCESS_CALL_CSFB = 1; // 0x1 - field public static final int PROCESS_CALL_IMS = 0; // 0x0 - } - - public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities { - ctor public MmTelFeature.MmTelCapabilities(); - ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities); - ctor public MmTelFeature.MmTelCapabilities(int); - method public final void addCapabilities(int); - method public final void removeCapabilities(int); - } - - public class RcsFeature extends android.telephony.ims.feature.ImsFeature { - ctor public RcsFeature(); - method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); - method public void onFeatureReady(); - method public void onFeatureRemoved(); - } - -} - -package android.telephony.ims.stub { - - public class ImsCallSessionImplBase implements java.lang.AutoCloseable { - ctor public ImsCallSessionImplBase(); - method public void accept(int, android.telephony.ims.ImsStreamMediaProfile); - method public void close(); - method public void deflect(String); - method public void extendToConference(String[]); - method public String getCallId(); - method public android.telephony.ims.ImsCallProfile getCallProfile(); - method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider(); - method public android.telephony.ims.ImsCallProfile getLocalCallProfile(); - method public String getProperty(String); - method public android.telephony.ims.ImsCallProfile getRemoteCallProfile(); - method public int getState(); - method public void hold(android.telephony.ims.ImsStreamMediaProfile); - method public void inviteParticipants(String[]); - method public boolean isInCall(); - method public boolean isMultiparty(); - method public void merge(); - method public void reject(int); - method public void removeParticipants(String[]); - method public void resume(android.telephony.ims.ImsStreamMediaProfile); - method public void sendDtmf(char, android.os.Message); - method public void sendRttMessage(String); - method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile); - method public void sendRttModifyResponse(boolean); - method public void sendUssd(String); - method public void setListener(android.telephony.ims.ImsCallSessionListener); - method public void setMute(boolean); - method public void start(String, android.telephony.ims.ImsCallProfile); - method public void startConference(String[], android.telephony.ims.ImsCallProfile); - method public void startDtmf(char); - method public void stopDtmf(); - method public void terminate(int); - method public void update(int, android.telephony.ims.ImsStreamMediaProfile); - field public static final int USSD_MODE_NOTIFY = 0; // 0x0 - field public static final int USSD_MODE_REQUEST = 1; // 0x1 - } - - public static class ImsCallSessionImplBase.State { - method public static String toString(int); - field public static final int ESTABLISHED = 4; // 0x4 - field public static final int ESTABLISHING = 3; // 0x3 - field public static final int IDLE = 0; // 0x0 - field public static final int INITIATED = 1; // 0x1 - field public static final int INVALID = -1; // 0xffffffff - field public static final int NEGOTIATING = 2; // 0x2 - field public static final int REESTABLISHING = 6; // 0x6 - field public static final int RENEGOTIATING = 5; // 0x5 - field public static final int TERMINATED = 8; // 0x8 - field public static final int TERMINATING = 7; // 0x7 - } - - public class ImsConfigImplBase { - ctor public ImsConfigImplBase(); - method public int getConfigInt(int); - method public String getConfigString(int); - method public final void notifyProvisionedValueChanged(int, int); - method public final void notifyProvisionedValueChanged(int, String); - method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); - method public int setConfig(int, int); - method public int setConfig(int, String); - field public static final int CONFIG_RESULT_FAILED = 1; // 0x1 - field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0 - field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff - } - - public class ImsEcbmImplBase { - ctor public ImsEcbmImplBase(); - method public final void enteredEcbm(); - method public void exitEmergencyCallbackMode(); - method public final void exitedEcbm(); - } - - public final class ImsFeatureConfiguration implements android.os.Parcelable { - method public int describeContents(); - method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR; - } - - public static class ImsFeatureConfiguration.Builder { - ctor public ImsFeatureConfiguration.Builder(); - method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int); - method public android.telephony.ims.stub.ImsFeatureConfiguration build(); - } - - public static final class ImsFeatureConfiguration.FeatureSlotPair { - ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int); - field public final int featureType; - field public final int slotId; - } - - public class ImsMultiEndpointImplBase { - ctor public ImsMultiEndpointImplBase(); - method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>); - method public void requestImsExternalCallStateInfo(); - } - - public class ImsRegistrationImplBase { - ctor public ImsRegistrationImplBase(); - method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); - method public final void onRegistered(int); - method public final void onRegistering(int); - method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]); - method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); - field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 - field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 - field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff - } - - public class ImsSmsImplBase { - ctor public ImsSmsImplBase(); - method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int); - method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int); - method public String getSmsFormat(); - method public void onReady(); - method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException; - method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException; - method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException; - method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException; - method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException; - method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException; - method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]); - field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2 - field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3 - field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4 - field public static final int DELIVER_STATUS_OK = 1; // 0x1 - field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff - field public static final int SEND_STATUS_ERROR = 2; // 0x2 - field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4 - field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3 - field public static final int SEND_STATUS_OK = 1; // 0x1 - field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2 - field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1 - } - - public class ImsUtImplBase { - ctor public ImsUtImplBase(); - method public void close(); - method public int queryCallBarring(int); - method public int queryCallBarringForServiceClass(int, int); - method public int queryCallForward(int, String); - method public int queryCallWaiting(); - method public int queryClip(); - method public int queryClir(); - method public int queryColp(); - method public int queryColr(); - method public void setListener(android.telephony.ims.ImsUtListener); - method public int transact(android.os.Bundle); - method public int updateCallBarring(int, int, String[]); - method public int updateCallBarringForServiceClass(int, int, String[], int); - method public int updateCallForward(int, int, String, int, int); - method public int updateCallWaiting(boolean, int); - method public int updateClip(boolean); - method public int updateClir(int); - method public int updateColp(boolean); - method public int updateColr(int); - } - -} - -package android.telephony.mbms { - - public static class DownloadRequest.Builder { - method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String); - } - - public final class FileInfo implements android.os.Parcelable { - ctor public FileInfo(android.net.Uri, String); - } - - public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { - ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>); - } - - public class MbmsDownloadReceiver extends android.content.BroadcastReceiver { - field public static final int RESULT_APP_NOTIFICATION_ERROR = 6; // 0x6 - field public static final int RESULT_BAD_TEMP_FILE_ROOT = 3; // 0x3 - field public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4; // 0x4 - field public static final int RESULT_INVALID_ACTION = 1; // 0x1 - field public static final int RESULT_MALFORMED_INTENT = 2; // 0x2 - field public static final int RESULT_OK = 0; // 0x0 - field public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5; // 0x5 - } - - public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { - ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date); - } - - public final class UriPathPair implements android.os.Parcelable { - method public int describeContents(); - method public android.net.Uri getContentUri(); - method public android.net.Uri getFilePathUri(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR; - } - -} - -package android.telephony.mbms.vendor { - - public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface { - ctor public MbmsDownloadServiceBase(); - method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; - method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; - method public android.os.IBinder asBinder(); - method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; - method public void dispose(int) throws android.os.RemoteException; - method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; - method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException; - method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException; - method public void onAppCallbackDied(int, int); - method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException; - method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; - method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; - method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; - method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException; - method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; - method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException; - } - - public class MbmsGroupCallServiceBase extends android.app.Service { - ctor public MbmsGroupCallServiceBase(); - method public void dispose(int) throws android.os.RemoteException; - method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException; - method public void onAppCallbackDied(int, int); - method public android.os.IBinder onBind(android.content.Intent); - method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback); - method public void stopGroupCall(int, long); - method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>); - } - - public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface { - ctor public MbmsStreamingServiceBase(); - method public android.os.IBinder asBinder(); - method public void dispose(int) throws android.os.RemoteException; - method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException; - method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException; - method public void onAppCallbackDied(int, int); - method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException; - method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException; - method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException; - method public void stopStreaming(int, String) throws android.os.RemoteException; - } - - public class VendorUtils { - ctor public VendorUtils(); - method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String); - field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP"; - field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL"; - field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST"; - field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT"; - field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI"; - field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST"; - field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST"; - field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST"; - field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID"; - field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE"; - field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT"; - field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST"; - } - -} - diff --git a/telephony/api/system-removed.txt b/telephony/api/system-removed.txt deleted file mode 100644 index ae46075c4829..000000000000 --- a/telephony/api/system-removed.txt +++ /dev/null @@ -1,19 +0,0 @@ -// Signature format: 2.0 -package android.telephony { - - public class TelephonyManager { - method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void answerRingingCall(); - method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public boolean endCall(); - method @Deprecated public void silenceRinger(); - } - -} - -package android.telephony.data { - - public final class DataCallResponse implements android.os.Parcelable { - ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, int); - } - -} - diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index e57b03098758..7aecfdde71bc 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -124,11 +124,7 @@ public final class CarrierAppUtils { } private static boolean isUpdatedSystemApp(ApplicationInfo ai) { - if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { - return true; - } - - return false; + return (ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; } /** diff --git a/telephony/framework-telephony-jarjar-rules.txt b/telephony/framework-telephony-jarjar-rules.txt deleted file mode 100644 index 212eba153a15..000000000000 --- a/telephony/framework-telephony-jarjar-rules.txt +++ /dev/null @@ -1,9 +0,0 @@ -rule android.telephony.Annotation* android.telephony.framework.Annotation@1 -rule android.util.RecurrenceRule* android.telephony.RecurrenceRule@1 -rule com.android.i18n.phonenumbers.** com.android.telephony.framework.phonenumbers.@1 -rule com.android.internal.os.SomeArgs* android.telephony.SomeArgs@1 -rule com.android.internal.util.BitwiseInputStream* android.telephony.BitwiseInputStream@1 -rule com.android.internal.util.BitwiseOutputStream* android.telephony.BitwiseOutputStream@1 -rule com.android.internal.util.Preconditions* android.telephony.Preconditions@1 -rule com.android.internal.util.IndentingPrintWriter* android.telephony.IndentingPrintWriter@1 -rule com.android.internal.util.HexDump* android.telephony.HexDump@1 diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java index 7e777fae46eb..6ae6d002d990 100644 --- a/telephony/java/android/telephony/CallForwardingInfo.java +++ b/telephony/java/android/telephony/CallForwardingInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -33,50 +34,14 @@ import java.util.Objects; * Defines the call forwarding information. * @hide */ +@SystemApi public final class CallForwardingInfo implements Parcelable { private static final String TAG = "CallForwardingInfo"; /** - * Indicates the call forwarding status is inactive. - * - * @hide - */ - public static final int STATUS_INACTIVE = 0; - - /** - * Indicates the call forwarding status is active. - * - * @hide - */ - public static final int STATUS_ACTIVE = 1; - - /** - * Indicates the call forwarding could not be enabled because the recipient is not on - * Fixed Dialing Number (FDN) list. - * - * @hide - */ - public static final int STATUS_FDN_CHECK_FAILURE = 2; - - /** - * Indicates the call forwarding status is with an unknown error. - * - * @hide - */ - public static final int STATUS_UNKNOWN_ERROR = 3; - - /** - * Indicates the call forwarding is not supported (e.g. called via CDMA). - * - * @hide - */ - public static final int STATUS_NOT_SUPPORTED = 4; - - /** - * Indicates the call forwarding reason is "unconditional". + * Indicates that call forwarding reason is "unconditional". * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_UNCONDITIONAL = 0; @@ -84,7 +49,6 @@ public final class CallForwardingInfo implements Parcelable { * Indicates the call forwarding status is "busy". * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_BUSY = 1; @@ -92,7 +56,6 @@ public final class CallForwardingInfo implements Parcelable { * Indicates the call forwarding reason is "no reply". * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_NO_REPLY = 2; @@ -100,7 +63,6 @@ public final class CallForwardingInfo implements Parcelable { * Indicates the call forwarding reason is "not reachable". * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_NOT_REACHABLE = 3; @@ -109,7 +71,6 @@ public final class CallForwardingInfo implements Parcelable { * simultaneously (unconditional, busy, no reply, and not reachable). * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_ALL = 4; @@ -118,26 +79,12 @@ public final class CallForwardingInfo implements Parcelable { * forwarding reasons simultaneously (busy, no reply, and not reachable). * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC - * @hide */ public static final int REASON_ALL_CONDITIONAL = 5; /** - * Call forwarding function status - */ - @IntDef(prefix = { "STATUS_" }, value = { - STATUS_ACTIVE, - STATUS_INACTIVE, - STATUS_UNKNOWN_ERROR, - STATUS_NOT_SUPPORTED, - STATUS_FDN_CHECK_FAILURE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CallForwardingStatus { - } - - /** * Call forwarding reason types + * @hide */ @IntDef(flag = true, prefix = { "REASON_" }, value = { REASON_UNCONDITIONAL, @@ -152,9 +99,9 @@ public final class CallForwardingInfo implements Parcelable { } /** - * The call forwarding status. + * Whether call forwarding is enabled for this reason. */ - private int mStatus; + private boolean mEnabled; /** * The call forwarding reason indicates the condition under which calls will be forwarded. @@ -178,39 +125,35 @@ public final class CallForwardingInfo implements Parcelable { /** * Construct a CallForwardingInfo. * - * @param status the call forwarding status + * @param enabled Whether to enable call forwarding for the reason specified + * in {@link #getReason()}. * @param reason the call forwarding reason * @param number the phone number to which calls will be forwarded * @param timeSeconds the timeout (in seconds) before the forwarding is attempted - * @hide */ - public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason, + public CallForwardingInfo(boolean enabled, @CallForwardingReason int reason, @Nullable String number, int timeSeconds) { - mStatus = status; + mEnabled = enabled; mReason = reason; mNumber = number; mTimeSeconds = timeSeconds; } /** - * Returns the call forwarding status. + * Whether call forwarding is enabled for the reason from {@link #getReason()}. * - * @return the call forwarding status. - * - * @hide + * @return {@code true} if enabled, {@code false} otherwise. */ - public @CallForwardingStatus int getStatus() { - return mStatus; + public boolean isEnabled() { + return mEnabled; } /** * Returns the call forwarding reason. The call forwarding reason indicates the condition - * under which calls will be forwarded. For example, {@link #REASON_NO_REPLY} indicates - * that calls will be forward to {@link #getNumber()} when the user fails to answer the call. + * under which calls will be forwarded. For example, {@link #REASON_NO_REPLY} indicates + * that calls will be forwarded when the user fails to answer the call. * * @return the call forwarding reason. - * - * @hide */ public @CallForwardingReason int getReason() { return mReason; @@ -220,9 +163,7 @@ public final class CallForwardingInfo implements Parcelable { * Returns the phone number to which calls will be forwarded. * * @return the number calls will be forwarded to, or {@code null} if call forwarding - * is being disabled. - * - * @hide + * is disabled. */ @Nullable public String getNumber() { @@ -230,16 +171,14 @@ public final class CallForwardingInfo implements Parcelable { } /** - * Gets the timeout (in seconds) before the forwarding is attempted. For example, + * Gets the timeout (in seconds) before forwarding is attempted. For example, * if {@link #REASON_NO_REPLY} is the call forwarding reason, the device will wait this - * duration of time before forwarding the call to {@link #getNumber()}. + * duration of time before forwarding the call to the number returned by {@link #getNumber()}. * * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 * 7.11 Call forwarding number and conditions +CCFC * * @return the timeout (in seconds) before the forwarding is attempted. - * - * @hide */ @SuppressLint("MethodNameUnits") public int getTimeoutSeconds() { @@ -257,14 +196,14 @@ public final class CallForwardingInfo implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeString(mNumber); - out.writeInt(mStatus); + out.writeBoolean(mEnabled); out.writeInt(mReason); out.writeInt(mTimeSeconds); } private CallForwardingInfo(Parcel in) { mNumber = in.readString(); - mStatus = in.readInt(); + mEnabled = in.readBoolean(); mReason = in.readInt(); mTimeSeconds = in.readInt(); } @@ -281,7 +220,7 @@ public final class CallForwardingInfo implements Parcelable { } CallForwardingInfo other = (CallForwardingInfo) o; - return mStatus == other.mStatus + return mEnabled == other.mEnabled && mNumber == other.mNumber && mReason == other.mReason && mTimeSeconds == other.mTimeSeconds; @@ -292,7 +231,7 @@ public final class CallForwardingInfo implements Parcelable { */ @Override public int hashCode() { - return Objects.hash(mStatus, mNumber, mReason, mTimeSeconds); + return Objects.hash(mEnabled, mNumber, mReason, mTimeSeconds); } public static final @NonNull Parcelable.Creator<CallForwardingInfo> CREATOR = @@ -313,7 +252,7 @@ public final class CallForwardingInfo implements Parcelable { */ @Override public String toString() { - return "[CallForwardingInfo: status=" + mStatus + return "[CallForwardingInfo: enabled=" + mEnabled + ", reason= " + mReason + ", timeSec= " + mTimeSeconds + " seconds" + ", number=" + Rlog.pii(TAG, mNumber) + "]"; diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index a4f48af93a8d..d5e834d5e2ef 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3785,11 +3785,26 @@ public class CarrierConfigManager { public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = KEY_PREFIX + "wifi_off_deferring_time_millis_int"; + /** + * A boolean flag specifying whether or not this carrier requires one IMS registration for + * all IMS services (MMTEL and RCS). + * <p> + * If set to {@code true}, the IMS Service must use one IMS registration for all IMS + * services. If set to {@code false}, IMS services may use separate IMS registrations for + * MMTEL and RCS. + * <p> + * The default value for this configuration is {@code false}. + * @see android.telephony.ims.SipDelegateManager + */ + public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = + KEY_PREFIX + "ims_single_registration_required_bool"; + private Ims() {} private static PersistableBundle getDefaults() { PersistableBundle defaults = new PersistableBundle(); defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000); + defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false); return defaults; } } @@ -4449,7 +4464,7 @@ public class CarrierConfigManager { }); sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true); sDefaults.putAll(Ims.getDefaults()); - sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, null); + sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[0]); sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false); sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY, new int[] {4 /* BUSY */}); diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java index 2e7bde3b3d89..e0896570d3ed 100644 --- a/telephony/java/android/telephony/CellSignalStrength.java +++ b/telephony/java/android/telephony/CellSignalStrength.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.IntRange; +import android.annotation.SystemApi; import android.os.PersistableBundle; /** @@ -155,11 +156,12 @@ public abstract class CellSignalStrength { /** * Returns the number of signal strength levels. - * @return Number of signal strength levels, enforced to be 5 + * @return Number of signal strength levels, currently defined in the HAL as 5. * * @hide */ - public static final int getNumSignalStrengthLevels() { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static int getNumSignalStrengthLevels() { return NUM_SIGNAL_STRENGTH_BINS; } } diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java index 3984bd769edd..28feab27a794 100644 --- a/telephony/java/android/telephony/ImsManager.java +++ b/telephony/java/android/telephony/ImsManager.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.telephony.SubscriptionManager; @@ -125,4 +126,24 @@ public class ImsManager { return new ImsMmTelManager(subscriptionId); } + + /** + * Create an instance of SipDelegateManager for the subscription id specified. + * <p> + * Used for RCS single registration cases, where an IMS application needs to forward SIP + * traffic through the device's IMS service. + * @param subscriptionId The ID of the subscription that this SipDelegateManager will use. + * @throws IllegalArgumentException if the subscription is invalid. + * @return a SipDelegateManager instance for the specified subscription ID. + * @hide + */ + @SystemApi + @NonNull + public SipDelegateManager getSipDelegateManager(int subscriptionId) { + if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId); + } + + return new SipDelegateManager(mContext, subscriptionId); + } } diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 92238420fd32..f8a200a5f8d3 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -369,7 +369,6 @@ public final class NetworkRegistrationInfo implements Parcelable { * Get the 5G NR connection state. * * @return the 5G NR connection state. - * @hide */ public @NRState int getNrState() { return mNrState; 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/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fc20f8a4a2fc..73244859c336 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -96,6 +96,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.IBooleanConsumer; +import com.android.internal.telephony.ICallForwardingInfoCallback; +import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.INumberVerificationCallback; import com.android.internal.telephony.IOns; import com.android.internal.telephony.IPhoneSubInfo; @@ -303,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; @@ -2800,7 +2804,11 @@ public class TelephonyManager { /** Current network is LTE_CA {@hide} */ @UnsupportedAppUsage public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19. - /** Current network is NR(New Radio) 5G. */ + /** + * Current network is NR (New Radio) 5G. + * This will only be returned for 5G SA. + * For 5G NSA, the network type will be {@link #NETWORK_TYPE_LTE}. + */ public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20. private static final @NetworkType int[] NETWORK_TYPES = { @@ -2827,11 +2835,13 @@ public class TelephonyManager { }; /** - * Return a collection of all network types - * @return network types + * Returns an array of all valid network types. + * + * @return An integer array containing all valid network types in no particular order. * * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static @NonNull @NetworkType int[] getAllNetworkTypes() { return NETWORK_TYPES; } @@ -4177,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. @@ -5496,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() { @@ -9152,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) { @@ -9162,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); } } @@ -9382,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; } /** @@ -10319,6 +10351,9 @@ public class TelephonyManager { * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} * + * If you want continuous updates of service state info, register a {@link PhoneStateListener} + * via {@link #listen} with the {@link PhoneStateListener#LISTEN_SERVICE_STATE} event. + * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. @@ -10945,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); } } @@ -11043,18 +11077,142 @@ 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; } /** @@ -11192,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 { @@ -12607,7 +12769,7 @@ public class TelephonyManager { * 1) User data is turned on, or * 2) APN is un-metered for this subscription, or * 3) APN type is whitelisted. E.g. MMS is whitelisted if - * {@link #setAlwaysAllowMmsData(boolean)} is turned on. + * {@link #MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled. * * @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}. * @return whether data is enabled for a apn type. @@ -12746,246 +12908,402 @@ public class TelephonyManager { } /** - * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward - * reason. + * Callback to be used with {@link #getCallForwarding} + * @hide + */ + @SystemApi + public interface CallForwardingInfoCallback { + /** + * Indicates that the operation was successful. + */ + int RESULT_SUCCESS = 0; + + /** + * Indicates that setting or retrieving the call forwarding info failed with an unknown + * error. + */ + int RESULT_ERROR_UNKNOWN = 1; + + /** + * Indicates that call forwarding is not enabled because the recipient is not on a + * Fixed Dialing Number (FDN) list. + */ + int RESULT_ERROR_FDN_CHECK_FAILURE = 2; + + /** + * Indicates that call forwarding is not supported on the network at this time. + */ + int RESULT_ERROR_NOT_SUPPORTED = 3; + + /** + * Call forwarding errors + * @hide + */ + @IntDef(prefix = { "RESULT_ERROR_" }, value = { + RESULT_ERROR_UNKNOWN, + RESULT_ERROR_NOT_SUPPORTED, + RESULT_ERROR_FDN_CHECK_FAILURE + }) + @Retention(RetentionPolicy.SOURCE) + @interface CallForwardingError{ + } + /** + * Called when the call forwarding info is successfully retrieved from the network. + * @param info information about how calls are forwarded + */ + void onCallForwardingInfoAvailable(@NonNull CallForwardingInfo info); + + /** + * Called when there was an error retrieving the call forwarding information. + * @param error + */ + void onError(@CallForwardingError int error); + } + + /** + * Gets the voice call forwarding info for a given call forwarding reason. * - * @param callForwardingReason the call forwarding reasons + * This method queries the network for the currently set call forwarding configuration for the + * provided call forwarding reason. When the network has provided its response, the result will + * be supplied via the provided {@link Executor} on the provided + * {@link CallForwardingInfoCallback}. * - * @throws IllegalArgumentException if callForwardingReason is not any of - * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY}, - * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE}, - * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL} + * @param callForwardingReason the call forwarding reason to query. + * @param executor The executor on which to execute the callback once the result is ready. + * @param callback The callback the results should be delivered on. * - * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE} - * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls - * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status - * {@link CallForwardingInfo#STATUS_UNKNOWN_ERROR}, - * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED}, - * or {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation. + * @throws IllegalArgumentException if callForwardingReason is not any of + * {@link CallForwardingInfo#REASON_UNCONDITIONAL}, {@link CallForwardingInfo#REASON_BUSY}, + * {@link CallForwardingInfo#REASON_NO_REPLY}, {@link CallForwardingInfo#REASON_NOT_REACHABLE}, + * {@link CallForwardingInfo#REASON_ALL}, or {@link CallForwardingInfo#REASON_ALL_CONDITIONAL} * * @hide */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - @NonNull - public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) { + @SystemApi + public void getCallForwarding(@CallForwardingReason int callForwardingReason, + @NonNull Executor executor, @NonNull CallForwardingInfoCallback callback) { if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) { throw new IllegalArgumentException("callForwardingReason is out of range"); } + + ICallForwardingInfoCallback internalCallback = new ICallForwardingInfoCallback.Stub() { + @Override + public void onCallForwardingInfoAvailable(CallForwardingInfo info) { + executor.execute(() -> + Binder.withCleanCallingIdentity(() -> + callback.onCallForwardingInfoAvailable(info))); + } + + @Override + public void onError(int error) { + executor.execute(() -> + Binder.withCleanCallingIdentity(() -> + callback.onError(error))); + } + }; + try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.getCallForwarding(getSubId(), callForwardingReason); + telephony.getCallForwarding(getSubId(), callForwardingReason, internalCallback); } } catch (RemoteException ex) { Rlog.e(TAG, "getCallForwarding RemoteException", ex); - } catch (NullPointerException ex) { - Rlog.e(TAG, "getCallForwarding NPE", ex); + ex.rethrowAsRuntimeException(); } - return new CallForwardingInfo( - CallForwardingInfo.STATUS_UNKNOWN_ERROR, 0 /* reason */, null /* number */, - 0 /* timeout */); } /** - * Sets the voice call forwarding info including status (enable/disable), call forwarding - * reason, the number to forward, and the timeout before the forwarding is attempted. + * Sets voice call forwarding behavior as described by the provided {@link CallForwardingInfo}. * - * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding. - * Enabling if {@link CallForwardingInfo#getStatus()} returns - * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if - * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}. + * This method will enable call forwarding if the provided {@link CallForwardingInfo} returns + * {@code true} from its {@link CallForwardingInfo#isEnabled()} method, and disables call + * forwarding otherwise. * - * @throws IllegalArgumentException if any of the following for parameter callForwardingInfo: - * 0) it is {@code null}. - * 1) {@link CallForwardingInfo#getStatus()} returns neither - * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}. - * 2) {@link CallForwardingInfo#getReason()} is not any of - * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY}, - * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE}, - * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL} - * 3) {@link CallForwardingInfo#getNumber()} returns {@code null}. - * 4) {@link CallForwardingInfo#getTimeoutSeconds()} doesn't return a positive value. + * If you wish to be notified about the results of this operation, provide an {@link Executor} + * and {@link Consumer<Integer>} to be notified asynchronously when the operation completes. * - * @return {@code true} to indicate it was set successfully; {@code false} otherwise. + * @param callForwardingInfo Info about whether calls should be forwarded and where they + * should be forwarded to. + * @param executor The executor on which the listener will be called. Must be non-null if + * {@code listener} is non-null. + * @param resultListener Asynchronous listener that'll be called when the operation completes. + * Called with {@link CallForwardingInfoCallback#RESULT_SUCCESS} if the + * operation succeeded and an error code from + * {@link CallForwardingInfoCallback} it failed. * + * @throws IllegalArgumentException if any of the following are true for the parameter + * callForwardingInfo: + * <ul> + * <li>it is {@code null}.</li> + * <li>{@link CallForwardingInfo#getReason()} is not any of: + * <ul> + * <li>{@link CallForwardingInfo#REASON_UNCONDITIONAL}</li> + * <li>{@link CallForwardingInfo#REASON_BUSY}</li> + * <li>{@link CallForwardingInfo#REASON_NO_REPLY}</li> + * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE}</li> + * <li>{@link CallForwardingInfo#REASON_ALL}</li> + * <li>{@link CallForwardingInfo#REASON_ALL_CONDITIONAL}</li> + * </ul> + * <li>{@link CallForwardingInfo#getNumber()} returns {@code null} when enabling call + * forwarding</li> + * <li>{@link CallForwardingInfo#getTimeoutSeconds()} returns a non-positive value when + * enabling call forwarding</li> + * </ul> * @hide */ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) { + @SystemApi + public void setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo, + @Nullable @CallbackExecutor Executor executor, + @Nullable @CallForwardingInfoCallback.CallForwardingError + Consumer<Integer> resultListener) { if (callForwardingInfo == null) { throw new IllegalArgumentException("callForwardingInfo is null"); } - int callForwardingStatus = callForwardingInfo.getStatus(); - if (callForwardingStatus != CallForwardingInfo.STATUS_ACTIVE - && callForwardingStatus != CallForwardingInfo.STATUS_INACTIVE) { - throw new IllegalArgumentException( - "callForwardingStatus is neither active nor inactive"); - } int callForwardingReason = callForwardingInfo.getReason(); if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) { throw new IllegalArgumentException("callForwardingReason is out of range"); } - if (callForwardingInfo.getNumber() == null) { - throw new IllegalArgumentException("callForwarding number is null"); + if (callForwardingInfo.isEnabled()) { + if (callForwardingInfo.getNumber() == null) { + throw new IllegalArgumentException("callForwarding number is null"); + } + if (callForwardingInfo.getTimeoutSeconds() <= 0) { + throw new IllegalArgumentException("callForwarding timeout isn't positive"); + } } - if (callForwardingInfo.getTimeoutSeconds() <= 0) { - throw new IllegalArgumentException("callForwarding timeout isn't positive"); + if (resultListener != null) { + Objects.requireNonNull(executor); } + + IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> + Binder.withCleanCallingIdentity(() -> resultListener.accept(result))); + } + }; + try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.setCallForwarding(getSubId(), callForwardingInfo); + telephony.setCallForwarding(getSubId(), callForwardingInfo, internalCallback); } } catch (RemoteException ex) { Rlog.e(TAG, "setCallForwarding RemoteException", ex); + ex.rethrowAsRuntimeException(); } catch (NullPointerException ex) { Rlog.e(TAG, "setCallForwarding NPE", ex); + throw ex; } - return false; } /** - * Indicates the call waiting status is active. + * Indicates that call waiting is enabled. * * @hide */ - public static final int CALL_WAITING_STATUS_ACTIVE = 1; + @SystemApi + public static final int CALL_WAITING_STATUS_ENABLED = 1; /** - * Indicates the call waiting status is inactive. + * Indicates that call waiting is disabled. * * @hide */ - public static final int CALL_WAITING_STATUS_INACTIVE = 2; + @SystemApi + public static final int CALL_WAITING_STATUS_DISABLED = 2; /** - * Indicates the call waiting status is with an unknown error. + * Indicates there was an unknown error retrieving the call waiting status. * * @hide */ + @SystemApi public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; /** - * Indicates the call waiting is not supported (e.g. called via CDMA). + * Indicates the call waiting is not supported on the current network. * * @hide */ + @SystemApi public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; /** - * Call waiting function status - * * @hide */ @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = { - CALL_WAITING_STATUS_ACTIVE, - CALL_WAITING_STATUS_INACTIVE, - CALL_WAITING_STATUS_NOT_SUPPORTED, - CALL_WAITING_STATUS_UNKNOWN_ERROR + CALL_WAITING_STATUS_ENABLED, + CALL_WAITING_STATUS_DISABLED, + CALL_WAITING_STATUS_UNKNOWN_ERROR, + CALL_WAITING_STATUS_NOT_SUPPORTED, }) @Retention(RetentionPolicy.SOURCE) public @interface CallWaitingStatus { } /** - * Gets the status of voice call waiting function. Call waiting function enables the waiting - * for the incoming call when it reaches the user who is busy to make another call and allows - * users to decide whether to switch to the incoming call. + * Retrieves the call waiting status of this device from the network. + * + * When call waiting is enabled, an incoming call that arrives when the user is already on + * an active call will be held in a waiting state while the user is notified instead of being + * rejected with a busy signal. * - * @return the status of call waiting function. + * @param executor The executor on which the result listener will be called. + * @param resultListener A {@link Consumer} that will be called with the result fetched + * from the network. The result will be one of: + * <ul> + * <li>{@link #CALL_WAITING_STATUS_ENABLED}}</li> + * <li>{@link #CALL_WAITING_STATUS_DISABLED}}</li> + * <li>{@link #CALL_WAITING_STATUS_UNKNOWN_ERROR}}</li> + * <li>{@link #CALL_WAITING_STATUS_NOT_SUPPORTED}}</li> + * </ul> * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public @CallWaitingStatus int getCallWaitingStatus() { + public void getCallWaitingStatus(@NonNull Executor executor, + @NonNull @CallWaitingStatus Consumer<Integer> resultListener) { + Objects.requireNonNull(executor); + Objects.requireNonNull(resultListener); + + IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> Binder.withCleanCallingIdentity( + () -> resultListener.accept(result))); + } + }; + try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.getCallWaitingStatus(getSubId()); + telephony.getCallWaitingStatus(getSubId(), internalCallback); } } catch (RemoteException ex) { Rlog.e(TAG, "getCallWaitingStatus RemoteException", ex); + ex.rethrowAsRuntimeException(); } catch (NullPointerException ex) { Rlog.e(TAG, "getCallWaitingStatus NPE", ex); + throw ex; } - return CALL_WAITING_STATUS_UNKNOWN_ERROR; } /** - * Sets the status for voice call waiting function. Call waiting function enables the waiting - * for the incoming call when it reaches the user who is busy to make another call and allows - * users to decide whether to switch to the incoming call. + * Sets the call waiting status of this device with the network. * - * @param isEnable {@code true} to enable; {@code false} to disable. - * @return {@code true} to indicate it was set successfully; {@code false} otherwise. + * If you wish to be notified about the results of this operation, provide an {@link Executor} + * and {@link Consumer<Integer>} to be notified asynchronously when the operation completes. * + * @see #getCallWaitingStatus for a description of the call waiting functionality. + * + * @param enabled {@code true} to enable; {@code false} to disable. + * @param executor The executor on which the listener will be called. Must be non-null if + * {@code listener} is non-null. + * @param resultListener Asynchronous listener that'll be called when the operation completes. + * Called with the new call waiting status (either + * {@link #CALL_WAITING_STATUS_ENABLED} or + * {@link #CALL_WAITING_STATUS_DISABLED} if the operation succeeded and + * {@link #CALL_WAITING_STATUS_NOT_SUPPORTED} or + * {@link #CALL_WAITING_STATUS_UNKNOWN_ERROR} if it failed. * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public boolean setCallWaitingStatus(boolean isEnable) { + public void setCallWaitingEnabled(boolean enabled, @Nullable Executor executor, + @Nullable Consumer<Integer> resultListener) { + if (resultListener != null) { + Objects.requireNonNull(executor); + } + + IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> + Binder.withCleanCallingIdentity(() -> resultListener.accept(result))); + } + }; + try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.setCallWaitingStatus(getSubId(), isEnable); + telephony.setCallWaitingStatus(getSubId(), enabled, internalCallback); } } catch (RemoteException ex) { Rlog.e(TAG, "setCallWaitingStatus RemoteException", ex); + ex.rethrowAsRuntimeException(); } catch (NullPointerException ex) { Rlog.e(TAG, "setCallWaitingStatus NPE", ex); + throw ex; } - return false; } /** - * Set allowing mobile data during voice call. This is used for allowing data on the non-default - * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will - * not be able to use mobile data. By calling this API, data will be temporarily enabled on the - * non-default data SIM during the life cycle of the voice call. + * Controls whether mobile data on the non-default SIM is allowed during a voice call. * - * @param allow {@code true} if allowing using data during voice call, {@code false} if - * disallowed. + * This is used for allowing data on the non-default data SIM when a voice call is placed on + * the non-default data SIM on DSDS devices. If this policy is disabled, users will not be able + * to use mobile data via the non-default data SIM during the call, which may mean no mobile + * data at all since some modem implementations disallow mobile data via the default data SIM + * during voice calls. + * If this policy is enabled, data will be temporarily enabled on the non-default data SIM + * during any voice calls. * - * @return {@code true} if operation is successful. otherwise {@code false}. + * This policy can be enabled and disabled via {@link #setMobileDataPolicyEnabledStatus}. + * @hide + */ + @SystemApi + @TestApi + public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; + + /** + * Controls whether MMS messages bypass the user-specified "mobile data" toggle. * - * @throws SecurityException if the caller doesn't have the permission. + * When enabled, requests for connections to the MMS APN will be accepted by telephony even if + * the user has turned "mobile data" off on this specific sim card. {@link #isDataEnabledForApn} + * will also return true for {@link ApnSetting#TYPE_MMS}. + * When disabled, the MMS APN will be governed by the same rules as all other APNs. * + * This policy can be enabled and disabled via {@link #setMobileDataPolicyEnabledStatus}. * @hide */ - @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public boolean setDataAllowedDuringVoiceCall(boolean allow) { - try { - ITelephony service = getITelephony(); - if (service != null) { - return service.setDataAllowedDuringVoiceCall(getSubId(), allow); - } - } catch (RemoteException ex) { - // This could happen if binder process crashes. - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } - } - return false; - } + @SystemApi + @TestApi + public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; /** - * Check whether data is allowed during voice call. This is used for allowing data on the - * non-default data SIM. When a voice call is placed on the non-default data SIM on DSDS - * devices, users will not be able to use mobile data. By calling this API, data will be - * temporarily enabled on the non-default data SIM during the life cycle of the voice call. - * - * @return {@code true} if data is allowed during voice call. + * @hide + */ + @IntDef(prefix = { "MOBILE_DATA_POLICY_" }, value = { + MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL, + MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MobileDataPolicy { } + + /** + * Enables or disables a piece of mobile data policy. * - * @throws SecurityException if the caller doesn't have the permission. + * Enables or disables the mobile data policy specified in {@code policy}. See the detailed + * description of each policy constant for what they do. * + * @param policy The data policy to enable. + * @param enabled Whether to enable or disable the policy. * @hide */ - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isDataAllowedInVoiceCall() { + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void setMobileDataPolicyEnabledStatus(@MobileDataPolicy int policy, boolean enabled) { try { ITelephony service = getITelephony(); if (service != null) { - return service.isDataAllowedInVoiceCall(getSubId()); + service.setMobileDataPolicyEnabledStatus(getSubId(), policy, enabled); } } catch (RemoteException ex) { // This could happen if binder process crashes. @@ -12993,27 +13311,26 @@ public class TelephonyManager { ex.rethrowAsRuntimeException(); } } - return false; } /** - * Set whether the specific sim card always allows MMS connection. If true, MMS network - * request will be accepted by telephony even if user turns "mobile data" off - * on this specific sim card. - * - * @param alwaysAllow whether Mms data is always allowed. - * @return whether operation is successful. + * Fetches the status of a piece of mobile data policy. * + * @param policy The data policy that you want the status for. + * @return {@code true} if enabled, {@code false} otherwise. * @hide */ - @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public boolean setAlwaysAllowMmsData(boolean alwaysAllow) { + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int policy) { try { ITelephony service = getITelephony(); if (service != null) { - return service.setAlwaysAllowMmsData(getSubId(), alwaysAllow); + return service.isMobileDataPolicyEnabled(getSubId(), policy); } } catch (RemoteException ex) { + // This could happen if binder process crashes. if (!isSystemProcess()) { ex.rethrowAsRuntimeException(); } @@ -13155,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; @@ -13171,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/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 5ead8decdb63..39859b1e4fdb 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -80,33 +80,33 @@ public final class DataCallResponse implements Parcelable { /** * Data handover failure mode is unknown. */ - public static final int HANDOVER_FAILURE_MODE_UNKNOWN = 0; + public static final int HANDOVER_FAILURE_MODE_UNKNOWN = -1; /** * Perform fallback to the source data transport on data handover failure using * the legacy logic, which is fallback if the fail cause is * {@link DataFailCause#HANDOFF_PREFERENCE_CHANGED}. */ - public static final int HANDOVER_FAILURE_MODE_LEGACY = 1; + public static final int HANDOVER_FAILURE_MODE_LEGACY = 0; /** * Perform fallback to the source data transport on data handover failure. */ - public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 2; + public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; /** * Do not perform fallback to the source data transport on data handover failure. - * Frameworks should keep retrying handover by sending + * Framework will retry setting up a new data connection by sending * {@link DataService#REQUEST_REASON_HANDOVER} request to the underlying {@link DataService}. */ - public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 3; + public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2; /** * Do not perform fallback to the source transport on data handover failure. - * Frameworks should retry setup a new data connection by sending + * Framework will retry setting up a new data connection by sending * {@link DataService#REQUEST_REASON_NORMAL} request to the underlying {@link DataService}. */ - public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 4; + public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3; private final @DataFailureCause int mCause; private final int mSuggestedRetryTime; @@ -332,6 +332,7 @@ public final class DataCallResponse implements Parcelable { .append(" mtu=").append(getMtu()) .append(" mtuV4=").append(getMtuV4()) .append(" mtuV6=").append(getMtuV6()) + .append(" handoverFailureMode=").append(getHandoverFailureMode()) .append("}"); return sb.toString(); } @@ -361,14 +362,15 @@ public final class DataCallResponse implements Parcelable { && mPcscfAddresses.containsAll(other.mPcscfAddresses) && mMtu == other.mMtu && mMtuV4 == other.mMtuV4 - && mMtuV6 == other.mMtuV6; + && mMtuV6 == other.mMtuV6 + && mHandoverFailureMode == other.mHandoverFailureMode; } @Override public int hashCode() { return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses, - mMtu, mMtuV4, mMtuV6); + mMtu, mMtuV4, mMtuV6, mHandoverFailureMode); } @Override 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/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 75aeb0419cff..9ab5aeb9c34c 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -17,6 +17,8 @@ package android.telephony.ims; import android.annotation.LongDef; +import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -29,12 +31,14 @@ import android.telephony.ims.aidl.IImsRcsFeature; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsServiceController; import android.telephony.ims.aidl.IImsServiceControllerListener; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsConfigImplBase; import android.telephony.ims.stub.ImsFeatureConfiguration; import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.telephony.ims.stub.SipTransportImplBase; import android.util.Log; import android.util.SparseArray; @@ -103,18 +107,46 @@ public class ImsService extends Service { /** * This ImsService supports the capability to place emergency calls over MMTEL. + * <p> + * Note: This should never be set by {@link #getImsServiceCapabilities()}, as whether it is + * there or not depends on whether or not {@link ImsFeature#FEATURE_EMERGENCY_MMTEL} is defined + * for this ImsService. If it is set, it will be removed during sanitization before the final + * capabilities bitfield is sent back to the framework. * @hide This is encoded into the {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, but we will be * adding other capabilities in a central location, so track this capability here as well. */ public static final long CAPABILITY_EMERGENCY_OVER_MMTEL = 1 << 0; /** + * This ImsService supports the capability to create SIP delegates for other IMS applications + * to use to proxy SIP messaging traffic through it. + * <p> + * In order for the framework to report SipDelegate creation as being available for this + * ImsService implementation, this ImsService must report this capability flag in + * {@link #getImsServiceCapabilities()}, {@link #getSipTransport(int)} must not return null, and + * this ImsService MUST report the ability to create both {@link ImsFeature#FEATURE_MMTEL} and + * {@link ImsFeature#FEATURE_RCS} features. + */ + public static final long CAPABILITY_SIP_DELEGATE_CREATION = 1 << 1; + + /** + * Used for internal correctness checks of capabilities set by the ImsService implementation and + * tracks the index of the largest defined flag in the capabilities long. + * @hide + */ + public static final long CAPABILITY_MAX_INDEX = + Long.numberOfTrailingZeros(CAPABILITY_SIP_DELEGATE_CREATION); + + /** * @hide */ @LongDef(flag = true, prefix = "CAPABILITY_", value = { - CAPABILITY_EMERGENCY_OVER_MMTEL + // CAPABILITY_EMERGENCY_OVER_MMTEL is not included here because it is managed by + // whether or not ImsFeature.FEATURE_EMERGENCY_MMTEL feature is set and should + // not be set by users of ImsService. + CAPABILITY_SIP_DELEGATE_CREATION }) @Retention(RetentionPolicy.SOURCE) public @interface ImsServiceCapability {} @@ -125,6 +157,7 @@ public class ImsService extends Service { */ private static final Map<Long, String> CAPABILITIES_LOG_MAP = new HashMap<Long, String>() {{ put(CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL"); + put(CAPABILITY_SIP_DELEGATE_CREATION, "SIP_DELEGATE_CREATION"); }}; /** @@ -199,6 +232,17 @@ public class ImsService extends Service { } @Override + public long getImsServiceCapabilities() { + long caps = ImsService.this.getImsServiceCapabilities(); + long sanitizedCaps = sanitizeCapabilities(caps); + if (caps != sanitizedCaps) { + Log.w(LOG_TAG, "removing invalid bits from field: 0x" + + Long.toHexString(caps ^ sanitizedCaps)); + } + return sanitizedCaps; + } + + @Override public void notifyImsServiceReadyForFeatureCreation() { ImsService.this.readyForFeatureCreation(); } @@ -216,6 +260,12 @@ public class ImsService extends Service { } @Override + public ISipTransport getSipTransport(int slotId) { + SipTransportImplBase s = ImsService.this.getSipTransport(slotId); + return s != null ? s.getBinder() : null; + } + + @Override public void enableIms(int slotId) { ImsService.this.enableIms(slotId); } @@ -369,6 +419,20 @@ public class ImsService extends Service { } /** + * The optional capabilities that this ImsService supports. + * <p> + * This should be a static configuration and should not change at runtime. + * @return The optional static capabilities of this ImsService implementation. + */ + // ImsService follows a different convention, since it is a stub class. The on* methods are + // final and call back into the framework with a state update. + @SuppressLint("OnNameExpected") + public @ImsServiceCapability long getImsServiceCapabilities() { + // Stub implementation to be implemented by ImsService. + return 0L; + } + + /** * The ImsService has been bound and is ready for ImsFeature creation based on the Features that * the ImsService has registered for with the framework, either in the manifest or via * {@link #querySupportedImsFeatures()}. @@ -441,7 +505,40 @@ public class ImsService extends Service { } /** - * @return A string representation of the ImsService capabilties for logging. + * Return the {@link SipTransportImplBase} implementation associated with the provided slot. + * <p> + * This is an optional interface used for devices that must support IMS single registration and + * proxy SIP traffic to remote IMS applications. If this is not supported for this IMS service, + * this method should return {@code null}. If this feature is supported, then this method must + * never be {@code null} and the optional ImsService capability flag + * {@link #CAPABILITY_SIP_DELEGATE_CREATION} must be set in + * {@link #getImsServiceCapabilities()}. Otherwise the framework will assume this feature is not + * supported for this ImsService. + * @param slotId The slot that is associated with the SipTransport implementation. + * @return the SipTransport implementation for the specified slot. + */ + // ImsService follows a different convention, since it is a stub class. The on* methods are + // final and call back into the framework with a state update. + @SuppressLint("OnNameExpected") + public @Nullable SipTransportImplBase getSipTransport(int slotId) { + // Stub implementation for ImsServices that do not support SipTransport. + return null; + } + + private static long sanitizeCapabilities(@ImsServiceCapability long caps) { + long filter = 0xFFFFFFFFFFFFFFFFL; + // pad the "allowed" set with zeros + filter <<= CAPABILITY_MAX_INDEX + 1; + // remove values above the allowed set. + caps &= ~filter; + // CAPABILITY_EMERGENCY_OVER_MMTEL should also not be set here, will be set by telephony + // internally. + caps &= ~CAPABILITY_EMERGENCY_OVER_MMTEL; + return caps; + } + + /** + * @return A string representation of the ImsService capabilities for logging. * @hide */ public static String getCapabilitiesString(@ImsServiceCapability long caps) { 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/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java new file mode 100644 index 000000000000..82c8a9cd58f4 --- /dev/null +++ b/telephony/java/android/telephony/ims/SipDelegateManager.java @@ -0,0 +1,93 @@ +/* + * 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.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.telephony.CarrierConfigManager; +import android.telephony.TelephonyFrameworkInitializer; +import android.telephony.ims.aidl.IImsRcsController; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Manages the creation and destruction of SipDelegates, which allow an IMS application to forward + * SIP messages for the purposes of providing a single IMS registration to the carrier's IMS network + * from multiple sources. + * @hide + */ +@SystemApi +public class SipDelegateManager { + + private final Context mContext; + private final int mSubId; + + /** + * Only visible for testing. To instantiate an instance of this class, please use + * {@link ImsManager#getSipDelegateManager(int)}. + * @hide + */ + @VisibleForTesting + public SipDelegateManager(Context context, int subId) { + mContext = context; + mSubId = subId; + } + + /** + * Determines if creating SIP delegates are supported for the subscription specified. + * <p> + * If SIP delegates are not supported on this device or the carrier associated with this + * subscription, creating a SIP delegate will always fail, as this feature is not supported. + * @return true if this device supports creating a SIP delegate and the carrier associated with + * this subscription supports single registration, false if creating SIP delegates is not + * supported. + * @throws ImsException If the remote ImsService is not available for any reason or the + * subscription associated with this instance is no longer active. See + * {@link ImsException#getCode()} for more information. + * + * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isSupported() throws ImsException { + try { + IImsRcsController controller = getIImsRcsController(); + if (controller == null) { + throw new ImsException("Telephony server is down", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + return controller.isSipDelegateSupported(mSubId); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); + } catch (RemoteException e) { + throw new ImsException(e.getMessage(), + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + private IImsRcsController getIImsRcsController() { + IBinder binder = TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyImsServiceRegisterer() + .get(); + return IImsRcsController.Stub.asInterface(binder); + } +} 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 e01ea9179452..8e84e9373f65 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -47,12 +47,18 @@ 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); void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c); void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c); + // SipDelegateManager + boolean isSipDelegateSupported(int subId); + // Internal commands that should not be made public void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback); void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback); 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/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl index c956cbcc816c..c6966b3cf53e 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl @@ -21,6 +21,7 @@ import android.telephony.ims.aidl.IImsRcsFeature; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsServiceControllerListener; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.stub.ImsFeatureConfiguration; import com.android.ims.internal.IImsFeatureStatusCallback; @@ -34,6 +35,7 @@ interface IImsServiceController { IImsMmTelFeature createMmTelFeature(int slotId); IImsRcsFeature createRcsFeature(int slotId); ImsFeatureConfiguration querySupportedImsFeatures(); + long getImsServiceCapabilities(); void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); // Synchronous call to ensure the ImsService is ready before continuing with feature creation. @@ -41,6 +43,7 @@ interface IImsServiceController { void removeImsFeature(int slotId, int featureType); IImsConfig getConfig(int slotId); IImsRegistration getRegistration(int slotId); + ISipTransport getSipTransport(int slotId); oneway void enableIms(int slotId); oneway void disableIms(int slotId); } 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/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl index 3d842b337428..a8c8329fe55e 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl +++ b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,18 +14,16 @@ * limitations under the License. */ -package android.net; +package android.telephony.ims.aidl; + +import java.util.List; /** - * Status details for tethering downstream interfaces. + * Interface used by the framework to receive the response from the remote user + * through {@link RcsCapabilityExchangeImplBase#sendOptionsCapabilityRequest} * {@hide} */ -parcelable TetherStatesParcel { - String[] availableList; - String[] tetheredList; - String[] localOnlyList; - String[] erroredIfaceList; - // List of Last error code corresponding to each errored iface in erroredIfaceList. */ - // TODO: Improve this as b/143122247. - int[] lastErrorList; +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/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl index c3d66ee14526..fe233430ffad 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (c) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,11 @@ * limitations under the License. */ -package android.net; +package android.telephony.ims.aidl; /** - * Listener interface allowing objects to listen to various module event. + * Interface for commands to the SIP Transport implementation. * {@hide} */ -oneway interface IIntResultListener { - void onResult(int resultCode); +interface ISipTransport { } 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/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java new file mode 100644 index 000000000000..b2b2914b3739 --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java @@ -0,0 +1,58 @@ +/* + * 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.NonNull; +import android.annotation.SystemApi; +import android.telephony.ims.aidl.ISipTransport; + +import java.util.concurrent.Executor; + +/** + * Manages the creation and destruction of SipDelegates in order to proxy SIP traffic to other + * IMS applications in order to support IMS single registration. + * @hide + */ +@SystemApi +public class SipTransportImplBase { + + private final Executor mBinderExecutor; + private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() { + + }; + + /** + * Create an implementation of SipTransportImplBase. + * + * @param executor The executor that remote calls from the framework should be called on. + */ + public SipTransportImplBase(@NonNull Executor executor) { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } + + mBinderExecutor = executor; + } + + /** + * @return The IInterface used by the framework. + * @hide + */ + public ISipTransport getBinder() { + return mSipTransportImpl; + } +} diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.java b/telephony/java/com/android/ims/ImsFeatureContainer.java index b259679ea1bf..80c1d43480cc 100644 --- a/telephony/java/com/android/ims/ImsFeatureContainer.java +++ b/telephony/java/com/android/ims/ImsFeatureContainer.java @@ -17,12 +17,14 @@ package com.android.ims; import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.telephony.ims.ImsService; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsRegistration; +import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.ImsFeature; import java.util.Objects; @@ -49,6 +51,11 @@ public final class ImsFeatureContainer implements Parcelable { public final IImsRegistration imsRegistration; /** + * An optional interface containing the SIP transport implementation from the ImsService. + */ + public final ISipTransport sipTransport; + + /** * State of the feature that is being tracked. */ private @ImsFeature.ImsState int mState = ImsFeature.STATE_UNAVAILABLE; @@ -66,10 +73,11 @@ public final class ImsFeatureContainer implements Parcelable { * @param initialCaps The initial capabilities that the ImsService supports. */ public ImsFeatureContainer(@NonNull IBinder iFace, @NonNull IImsConfig iConfig, - @NonNull IImsRegistration iReg, long initialCaps) { + @NonNull IImsRegistration iReg, @Nullable ISipTransport transport, long initialCaps) { imsFeature = iFace; imsConfig = iConfig; imsRegistration = iReg; + sipTransport = transport; mCapabilities = initialCaps; } @@ -80,6 +88,7 @@ public final class ImsFeatureContainer implements Parcelable { imsFeature = in.readStrongBinder(); imsConfig = IImsConfig.Stub.asInterface(in.readStrongBinder()); imsRegistration = IImsRegistration.Stub.asInterface(in.readStrongBinder()); + sipTransport = ISipTransport.Stub.asInterface(in.readStrongBinder()); mState = in.readInt(); mCapabilities = in.readLong(); } @@ -123,13 +132,15 @@ public final class ImsFeatureContainer implements Parcelable { return imsFeature.equals(that.imsFeature) && imsConfig.equals(that.imsConfig) && imsRegistration.equals(that.imsRegistration) && + sipTransport.equals(that.sipTransport) && mState == that.getState() && mCapabilities == that.getCapabilities(); } @Override public int hashCode() { - return Objects.hash(imsFeature, imsConfig, imsRegistration, mState, mCapabilities); + return Objects.hash(imsFeature, imsConfig, imsRegistration, sipTransport, mState, + mCapabilities); } @Override @@ -138,6 +149,7 @@ public final class ImsFeatureContainer implements Parcelable { "imsFeature=" + imsFeature + ", imsConfig=" + imsConfig + ", imsRegistration=" + imsRegistration + + ", sipTransport=" + sipTransport + ", state=" + ImsFeature.STATE_LOG_MAP.get(mState) + ", capabilities = " + ImsService.getCapabilitiesString(mCapabilities) + '}'; @@ -153,6 +165,7 @@ public final class ImsFeatureContainer implements Parcelable { dest.writeStrongBinder(imsFeature); dest.writeStrongInterface(imsConfig); dest.writeStrongInterface(imsRegistration); + dest.writeStrongInterface(sipTransport); dest.writeInt(mState); dest.writeLong(mCapabilities); } diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl index 29c0a817b6f4..4d3b9f4636df 100644 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ b/telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.net.util; -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; +package com.android.internal.telephony; + +import android.telephony.CallForwardingInfo; -} +// Callback interface for the getCallForwarding API in TelephonyManager. +oneway interface ICallForwardingInfoCallback { + void onCallForwardingInfoAvailable(in CallForwardingInfo info); + void onError(int error); +}
\ No newline at end of file diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 934103ebe2b6..79456360c377 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -58,6 +58,7 @@ import android.telephony.ims.aidl.IImsRegistrationCallback; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.IBooleanConsumer; +import com.android.internal.telephony.ICallForwardingInfoCallback; import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.INumberVerificationCallback; import com.android.internal.telephony.OperatorInfo; @@ -974,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. @@ -1001,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. * @@ -1604,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. @@ -1639,86 +1641,15 @@ interface ITelephony { */ void carrierActionResetAll(int subId); - /** - * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward - * reason. - * - * @param callForwardingReason the call forwarding reasons which are the bitwise-OR combination - * of the following constants: - * <ol> - * <li>{@link CallForwardingInfo#REASON_BUSY} </li> - * <li>{@link CallForwardingInfo#REASON_NO_REPLY} </li> - * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE} </li> - * </ol> - * - * @throws IllegalArgumentException if callForwardingReason is not a bitwise-OR combination - * of {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_BUSY}, - * {@link CallForwardingInfo.REASON_NOT_REACHABLE} - * - * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE} - * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls - * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status - * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED} or - * {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation. - * - * @hide - */ - CallForwardingInfo getCallForwarding(int subId, int callForwardingReason); + void getCallForwarding(int subId, int callForwardingReason, + ICallForwardingInfoCallback callback); - /** - * Sets the voice call forwarding info including status (enable/disable), call forwarding - * reason, the number to forward, and the timeout before the forwarding is attempted. - * - * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding. - * Enabling if {@link CallForwardingInfo#getStatus()} returns - * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if - * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}. - * - * @throws IllegalArgumentException if any of the following: - * 0) callForwardingInfo is null. - * 1) {@link CallForwardingInfo#getStatus()} for callForwardingInfo returns neither - * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}. - * 2) {@link CallForwardingInfo#getReason()} for callForwardingInfo doesn't return the - * bitwise-OR combination of {@link CallForwardingInfo.REASON_BUSY}, - * {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE} - * 3) {@link CallForwardingInfo#getNumber()} for callForwardingInfo returns null. - * 4) {@link CallForwardingInfo#getTimeout()} for callForwardingInfo returns nagetive value. - * - * @return {@code true} to indicate it was set successfully; {@code false} otherwise. - * - * @hide - */ - boolean setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo); + void setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo, + IIntegerConsumer callback); - /** - * Gets the status of voice call waiting function. Call waiting function enables the waiting - * for the incoming call when it reaches the user who is busy to make another call and allows - * users to decide whether to switch to the incoming call. - * - * @return the status of call waiting function. - * @hide - */ - int getCallWaitingStatus(int subId); - - /** - * Sets the status for voice call waiting function. Call waiting function enables the waiting - * for the incoming call when it reaches the user who is busy to make another call and allows - * users to decide whether to switch to the incoming call. - * - * @param isEnable {@code true} to enable; {@code false} to disable. - * @return {@code true} to indicate it was set successfully; {@code false} otherwise. - * - * @hide - */ - boolean setCallWaitingStatus(int subId, boolean isEnable); + void getCallWaitingStatus(int subId, 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); + void setCallWaitingStatus(int subId, boolean enabled, IIntegerConsumer callback); /** * Get Client request stats which will contain statistical information @@ -2233,21 +2164,9 @@ interface ITelephony { */ String getMmsUAProfUrl(int subId); - /** - * Set allowing mobile data during voice call. - */ - boolean setDataAllowedDuringVoiceCall(int subId, boolean allow); + void setMobileDataPolicyEnabledStatus(int subscriptionId, int policy, boolean enabled); - /** - * Check whether data is allowed during voice call. Note this is for dual sim device that - * data might be disabled on non-default data subscription but explicitly turned on by settings. - */ - boolean isDataAllowedInVoiceCall(int subId); - - /** - * Set whether a subscription always allows MMS connection. - */ - boolean setAlwaysAllowMmsData(int subId, boolean allow); + boolean isMobileDataPolicyEnabled(int subscriptionId, int policy); /** * Command line command to enable or disable handling of CEP data for test purposes. 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/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp index 0e7a049f5faa..b001fe105bc1 100644 --- a/tests/StagedInstallTest/Android.bp +++ b/tests/StagedInstallTest/Android.bp @@ -23,7 +23,7 @@ android_test_helper_app { java_test_host { name: "StagedInstallInternalTest", srcs: ["src/**/*.java"], - libs: ["tradefed"], + libs: ["tradefed", "cts-shim-host-lib"], static_libs: [ "testng", "compatibility-tradefed", diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index ccd18dd25167..407c65ba4944 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -16,6 +16,8 @@ package com.android.tests.stagedinstallinternal.host; +import static com.android.cts.shim.lib.ShimPackage.SHIM_APEX_PACKAGE_NAME; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; @@ -93,43 +95,78 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Verify"); } + // Test waiting time for staged session to be ready using adb staged install can be altered @Test - public void testAdbStagedInstallWaitForReadyFlagWorks() throws Exception { + public void testAdbStagdReadyTimeoutFlagWorks() throws Exception { assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); - File apexFile = mTestUtils.getTestFile(SHIM_V2); - String output = getDevice().executeAdbCommand("install", "--staged", - "--wait-for-staged-ready", "60000", apexFile.getAbsolutePath()); + final File apexFile = mTestUtils.getTestFile(SHIM_V2); + final String output = getDevice().executeAdbCommand("install", "--staged", + "--staged-ready-timeout", "60000", apexFile.getAbsolutePath()); assertThat(output).contains("Reboot device to apply staged session"); - String sessionId = getDevice().executeShellCommand( + final String sessionId = getDevice().executeShellCommand( "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); assertThat(sessionId).isNotEmpty(); } + // Test adb staged installation wait for session to be ready by default @Test - public void testAdbStagedInstallNoWaitFlagWorks() throws Exception { + public void testAdbStagedInstallWaitsTillReadyByDefault() throws Exception { assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); - File apexFile = mTestUtils.getTestFile(SHIM_V2); - String output = getDevice().executeAdbCommand("install", "--staged", - "--no-wait", apexFile.getAbsolutePath()); + final File apexFile = mTestUtils.getTestFile(SHIM_V2); + final String output = getDevice().executeAdbCommand("install", "--staged", + apexFile.getAbsolutePath()); + assertThat(output).contains("Reboot device to apply staged session"); + final String sessionId = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); + assertThat(sessionId).isNotEmpty(); + } + + // Test we can skip waiting for staged session to be ready + @Test + public void testAdbStagedReadyWaitCanBeSkipped() throws Exception { + assumeTrue("Device does not support updating APEX", + mHostUtils.isApexUpdateSupported()); + + final File apexFile = mTestUtils.getTestFile(SHIM_V2); + final String output = getDevice().executeAdbCommand("install", "--staged", + "--staged-ready-timeout", "0", apexFile.getAbsolutePath()); assertThat(output).doesNotContain("Reboot device to apply staged session"); assertThat(output).contains("Success"); - String sessionId = getDevice().executeShellCommand( + final String sessionId = getDevice().executeShellCommand( "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); assertThat(sessionId).isEmpty(); } + // Test rollback-app command waits for staged sessions to be ready + @Test + public void testAdbRollbackAppWaitsForStagedReady() throws Exception { + assumeTrue("Device does not support updating APEX", + mHostUtils.isApexUpdateSupported()); + + final File apexFile = mTestUtils.getTestFile(SHIM_V2); + String output = getDevice().executeAdbCommand("install", "--staged", + "--enable-rollback", apexFile.getAbsolutePath()); + assertThat(output).contains("Reboot device to apply staged session"); + getDevice().reboot(); + output = getDevice().executeShellCommand("pm rollback-app " + SHIM_APEX_PACKAGE_NAME); + assertThat(output).contains("Reboot device to apply staged session"); + final String sessionId = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); + assertThat(sessionId).isNotEmpty(); + } + @Test public void testAdbInstallMultiPackageCommandWorks() throws Exception { assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); - File apexFile = mTestUtils.getTestFile(SHIM_V2); - File apkFile = mTestUtils.getTestFile(APK_A); - String output = getDevice().executeAdbCommand("install-multi-package", + final File apexFile = mTestUtils.getTestFile(SHIM_V2); + final File apkFile = mTestUtils.getTestFile(APK_A); + final String output = getDevice().executeAdbCommand("install-multi-package", apexFile.getAbsolutePath(), apkFile.getAbsolutePath()); assertThat(output).contains("Created parent session"); assertThat(output).contains("Created child session"); @@ -154,10 +191,10 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { getDevice().disableAdbRoot(); // Wait for new system server process to start - long start = System.currentTimeMillis(); + final long start = System.currentTimeMillis(); long newStartTime = oldStartTime; while (System.currentTimeMillis() < start + SYSTEM_SERVER_TIMEOUT_MS) { - ProcessInfo newPs = getDevice().getProcessByName("system_server"); + final ProcessInfo newPs = getDevice().getProcessByName("system_server"); if (newPs != null) { newStartTime = newPs.getStartTime(); if (newStartTime != oldStartTime) { diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index e1693129892f..11a83ebf6dd7 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -30,6 +30,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; +import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; @@ -359,6 +360,33 @@ public class NetworkCapabilitiesTest { } @Test + public void testOemPrivate() { + NetworkCapabilities nc = new NetworkCapabilities(); + // By default OEM_PRIVATE is neither in the unwanted or required lists and the network is + // not restricted. + assertFalse(nc.hasUnwantedCapability(NET_CAPABILITY_OEM_PRIVATE)); + assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE)); + nc.maybeMarkCapabilitiesRestricted(); + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // Adding OEM_PRIVATE to capability list should make network restricted. + nc.addCapability(NET_CAPABILITY_OEM_PRIVATE); + nc.addCapability(NET_CAPABILITY_INTERNET); // Combine with unrestricted capability. + nc.maybeMarkCapabilitiesRestricted(); + assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE)); + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // Now let's make request for OEM_PRIVATE network. + NetworkCapabilities nr = new NetworkCapabilities(); + nr.addCapability(NET_CAPABILITY_OEM_PRIVATE); + nr.maybeMarkCapabilitiesRestricted(); + assertTrue(nr.satisfiedByNetworkCapabilities(nc)); + + // Request fails for network with the default capabilities. + assertFalse(nr.satisfiedByNetworkCapabilities(new NetworkCapabilities())); + } + + @Test public void testUnwantedCapabilities() { NetworkCapabilities network = new NetworkCapabilities(); diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java index 02f5286506a8..603c87519532 100644 --- a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java +++ b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java @@ -19,6 +19,8 @@ package android.net.ipmemorystore; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk; +import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirkParcelable; import android.os.Parcel; import android.os.Parcelable; @@ -46,7 +48,7 @@ public class ParcelableTests { builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4")); // lease will expire in two hours builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 7_200_000); - // groupHint stays null this time around + // cluster stays null this time around builder.setDnsAddresses(Collections.emptyList()); builder.setMtu(18); in = builder.build(); @@ -69,7 +71,7 @@ public class ParcelableTests { // Verify that this test does not miss any new field added later. // If any field is added to NetworkAttributes it must be tested here for parceling // roundtrip. - assertEquals(5, Arrays.stream(NetworkAttributes.class.getDeclaredFields()) + assertEquals(6, Arrays.stream(NetworkAttributes.class.getDeclaredFields()) .filter(f -> !Modifier.isStatic(f.getModifiers())).count()); } @@ -104,6 +106,22 @@ public class ParcelableTests { assertEquals(in.confidence, out.confidence, 0.01f /* delta */); } + @Test + public void testIPv6ProvisioningLossQuirkParceling() throws Exception { + final NetworkAttributes.Builder builder = new NetworkAttributes.Builder(); + final IPv6ProvisioningLossQuirkParcelable parcelable = + new IPv6ProvisioningLossQuirkParcelable(); + final long expiry = System.currentTimeMillis() + 7_200_000; + + parcelable.detectionCount = 3; + parcelable.quirkExpiry = expiry; // quirk info will expire in two hours + builder.setIpv6ProvLossQuirk(IPv6ProvisioningLossQuirk.fromStableParcelable(parcelable)); + final NetworkAttributes in = builder.build(); + + final NetworkAttributes out = new NetworkAttributes(parcelingRoundTrip(in.toParcelable())); + assertEquals(out.ipv6ProvisioningLossQuirk, in.ipv6ProvisioningLossQuirk); + } + private <T extends Parcelable> T parcelingRoundTrip(final T in) throws Exception { final Parcel p = Parcel.obtain(); in.writeToParcel(p, /* flags */ 0); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 118d7c1dc821..3a462912addb 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -147,6 +147,7 @@ import android.net.ConnectivityManager.PacketKeepaliveCallback; import android.net.ConnectivityManager.TooManyRequestsException; import android.net.ConnectivityThread; import android.net.DataStallReportParcelable; +import android.net.EthernetManager; import android.net.IConnectivityDiagnosticsCallback; import android.net.IDnsResolver; import android.net.IIpConnectivityMetrics; @@ -250,6 +251,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.AdditionalAnswers; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; @@ -358,6 +360,7 @@ public class ConnectivityServiceTest { @Mock AppOpsManager mAppOpsManager; @Mock TelephonyManager mTelephonyManager; @Mock MockableSystemProperties mSystemProperties; + @Mock EthernetManager mEthernetManager; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -445,10 +448,18 @@ public class ConnectivityServiceTest { if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager; if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; + if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager; return super.getSystemService(name); } @Override + public Context createContextAsUser(UserHandle user, int flags) { + final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this)); + doReturn(user).when(asUser).getUser(); + return asUser; + } + + @Override public ContentResolver getContentResolver() { return mContentResolver; } @@ -1274,7 +1285,6 @@ public class ConnectivityServiceTest { doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics(); doReturn(mBatteryStatsService).when(deps).getBatteryStatsService(); - doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE); doAnswer(inv -> { mPolicyTracker = new WrappedMultinetworkPolicyTracker( inv.getArgument(0), inv.getArgument(1), inv.getArgument(2)); @@ -4990,22 +5000,22 @@ public class ConnectivityServiceTest { // simulate that situation and check if ConnectivityService could filter that case. mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL)); + verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(), + eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any()); // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be // shown. mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */); mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL)); + verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(), + eq(NotificationType.PRIVATE_DNS_BROKEN.eventId)); // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be // shown again. mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */); mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL)); + verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(), + eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any()); } @Test @@ -6021,23 +6031,23 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mNetworkManagementService); + verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); + reset(mMockNetd); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId)); - reset(mNetworkManagementService); + verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId)); + reset(mMockNetd); mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mNetworkManagementService); + verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); + reset(mMockNetd); mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - verify(mNetworkManagementService).clearDefaultNetId(); + verify(mMockNetd).networkClearDefault(); mCm.unregisterNetworkCallback(trustedCallback); } @@ -6141,6 +6151,7 @@ public class ConnectivityServiceTest { verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute); verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); + verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME); verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), TYPE_MOBILE); @@ -6197,7 +6208,7 @@ public class ConnectivityServiceTest { .getStackedLinks(); assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0)); assertRoutesAdded(cellNetId, stackedDefault); - + verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); // Change trivial linkproperties and see if stacked link is preserved. cellLp.addDnsServer(InetAddress.getByName("8.8.8.8")); mCellNetworkAgent.sendLinkProperties(cellLp); @@ -6228,6 +6239,7 @@ public class ConnectivityServiceTest { (lp) -> lp.getStackedLinks().size() == 0); verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); assertRoutesRemoved(cellNetId, stackedDefault); + verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString()); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, @@ -6236,6 +6248,7 @@ public class ConnectivityServiceTest { networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 1); assertRoutesAdded(cellNetId, stackedDefault); + verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); reset(mMockNetd); // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked @@ -6260,7 +6273,7 @@ public class ConnectivityServiceTest { // The interface removed callback happens but has no effect after stop is called. clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME); networkCallback.assertNoCallback(); - + verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); reset(mNetworkManagementService); @@ -6293,6 +6306,7 @@ public class ConnectivityServiceTest { networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null); assertRoutesAdded(cellNetId, stackedDefault); + verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); // NAT64 prefix is removed. Expect that clat is stopped. mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, @@ -6305,8 +6319,8 @@ public class ConnectivityServiceTest { verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 0); + verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); verifyNoMoreInteractions(mMockNetd); - // Clean up. mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index 47db5d431671..b47be97ed002 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; @@ -36,6 +37,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.NetworkCapabilities; import android.net.NetworkInfo; +import android.os.UserHandle; import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; @@ -47,6 +49,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.AdditionalAnswers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -104,17 +107,22 @@ public class NetworkNotificationManagerTest { when(mCtx.getResources()).thenReturn(mResources); when(mCtx.getPackageManager()).thenReturn(mPm); when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo()); + final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mCtx)); + doReturn(UserHandle.ALL).when(asUserCtx).getUser(); + when(mCtx.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); + when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE))) + .thenReturn(mNotificationManager); when(mNetworkInfo.getExtraInfo()).thenReturn("extra"); when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B); - mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager); + mManager = new NetworkNotificationManager(mCtx, mTelephonyManager); } private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) { final String tag = NetworkNotificationManager.tagFor(id); mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true); verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any()); + .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any()); final int transportType = NetworkNotificationManager.approximateTransportType(nai); if (transportType == NetworkCapabilities.TRANSPORT_WIFI) { verify(mResources, times(1)).getString(title, eq(any())); @@ -164,8 +172,8 @@ public class NetworkNotificationManagerTest { final int id = ids.get(i); final int eventId = types.get(i).eventId; final String tag = NetworkNotificationManager.tagFor(id); - verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any()); - verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any()); + verify(mNotificationManager, times(1)).cancel(eq(tag), eq(eventId)); } } @@ -174,13 +182,13 @@ public class NetworkNotificationManagerTest { mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false); mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false); - verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any()); + verify(mNotificationManager, never()).notify(any(), anyInt(), any()); mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false); final int eventId = NO_INTERNET.eventId; final String tag = NetworkNotificationManager.tagFor(102); - verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any()); } @Test @@ -191,7 +199,7 @@ public class NetworkNotificationManagerTest { mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false); mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any()); + verify(mNotificationManager, never()).notify(any(), anyInt(), any()); } @Test @@ -201,19 +209,16 @@ public class NetworkNotificationManagerTest { // Show first NO_INTERNET mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any()); // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any()); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any()); + verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId)); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any()); // Network disconnects mManager.clearNotification(id); - verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any()); + verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId)); } @Test @@ -223,18 +228,17 @@ public class NetworkNotificationManagerTest { // Show first SIGN_IN mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any()); reset(mNotificationManager); // NO_INTERNET arrives after, but is ignored. mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any()); - verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any()); + verify(mNotificationManager, never()).cancel(any(), anyInt()); + verify(mNotificationManager, never()).notify(any(), anyInt(), any()); // Network disconnects mManager.clearNotification(id); - verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any()); + verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId)); } @Test @@ -246,24 +250,20 @@ public class NetworkNotificationManagerTest { // to previous type or not. If they are equal then clear the notification; if they are not // equal then return. mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any()); // Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification // should be cleared. mManager.clearNotification(id, NO_INTERNET); - verify(mNotificationManager, times(1)) - .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any()); + verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId)); // SIGN_IN is popped-up. mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any()); + verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any()); // The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be // cleared. mManager.clearNotification(id, PARTIAL_CONNECTIVITY); - verify(mNotificationManager, never()) - .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any()); + verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId)); } } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index daa2627d64cf..2fa0914dabbd 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -45,6 +45,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -106,6 +107,7 @@ import com.android.server.IpSecService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.AdditionalAnswers; import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; @@ -215,6 +217,8 @@ public class VpnTest { when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); + when(mContext.getSystemServiceName(NotificationManager.class)) + .thenReturn(Context.NOTIFICATION_SERVICE); when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) .thenReturn(mNotificationManager); when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) @@ -594,26 +598,23 @@ public class VpnTest { // Don't show a notification for regular disconnected states. vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(mNotificationManager, atLeastOnce()) - .cancelAsUser(anyString(), anyInt(), eq(userHandle)); + order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt()); // Start showing a notification for disconnected once always-on. vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore); - order.verify(mNotificationManager) - .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); + order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); // Stop showing the notification once connected. vpn.updateState(DetailedState.CONNECTED, TAG); - order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); + order.verify(mNotificationManager).cancel(anyString(), anyInt()); // Show the notification if we disconnect again. vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(mNotificationManager) - .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); + order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); // Notification should be cleared after unsetting always-on package. vpn.setAlwaysOnPackage(null, false, null, mKeyStore); - order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); + order.verify(mNotificationManager).cancel(anyString(), anyInt()); } @Test @@ -1272,6 +1273,10 @@ public class VpnTest { * Mock some methods of vpn object. */ private Vpn createVpn(@UserIdInt int userId) { + final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); + doReturn(UserHandle.of(userId)).when(asUserContext).getUser(); + when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt())) + .thenReturn(asUserContext); return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService, userId, mKeyStore, mSystemServices, mIkev2SessionCreator); } diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java index fb84611cb662..ebbc0ef62548 100644 --- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java +++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java @@ -19,6 +19,7 @@ package com.android.server.net.ipmemorystore; import static org.junit.Assert.assertEquals; import android.net.ipmemorystore.NetworkAttributes; +import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -52,6 +53,8 @@ public class NetworkAttributesTest { } assertEquals(sum, NetworkAttributes.TOTAL_WEIGHT, EPSILON); + final IPv6ProvisioningLossQuirk ipv6ProvisioningLossQuirk = + new IPv6ProvisioningLossQuirk(3, System.currentTimeMillis() + 7_200_000); // Use directly the constructor with all attributes, and make sure that when compared // to itself the score is a clean 1.0f. final NetworkAttributes na = @@ -61,7 +64,7 @@ public class NetworkAttributesTest { "some hint", Arrays.asList(Inet4Address.getByAddress(new byte[] {5, 6, 7, 8}), Inet4Address.getByAddress(new byte[] {9, 0, 1, 2})), - 98); + 98, ipv6ProvisioningLossQuirk); assertEquals(1.0f, na.getNetworkGroupSamenessConfidence(na), EPSILON); } } 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/packages/Tethering/tests/integration/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml index fddfaad29f0f..2ad9aac67029 100644 --- a/packages/Tethering/tests/integration/AndroidManifest.xml +++ b/tests/vcn/AndroidManifest.xml @@ -13,16 +13,16 @@ 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.networkstack.tethering.tests.integration"> - <uses-permission android:name="android.permission.INTERNET"/> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.frameworks.tests.vcn"> - <application android:debuggable="true"> + <application> <uses-library android:name="android.test.runner" /> </application> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.networkstack.tethering.tests.integration" - android:label="Tethering integration tests"> - </instrumentation> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.frameworks.tests.vcn" + android:label="Frameworks VCN Tests" /> </manifest> diff --git a/packages/Tethering/res/values-mcc310-mnc004/config.xml b/tests/vcn/AndroidTest.xml index 5c5be0466a36..dc521fd7bcd9 100644 --- a/packages/Tethering/res/values-mcc310-mnc004/config.xml +++ b/tests/vcn/AndroidTest.xml @@ -13,11 +13,16 @@ See the License for the specific language governing permissions and limitations under the License. --> -<resources> - <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to - "0" for disable this feature. --> - <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> +<configuration description="Runs VCN Tests."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="FrameworksVcnTests.apk" /> + </target_preparer> - <!-- Config for showing upstream roaming notification. --> - <bool name="config_upstream_roaming_notification">true</bool> -</resources>
\ No newline at end of file + <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 diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index da644021e30e..28ff606d0381 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -15,7 +15,7 @@ # limitations under the License. """Generate API lists for non-SDK API enforcement.""" import argparse -from collections import defaultdict +from collections import defaultdict, namedtuple import functools import os import re @@ -54,16 +54,21 @@ ALL_FLAGS = FLAGS_API_LIST + [ FLAGS_API_LIST_SET = set(FLAGS_API_LIST) ALL_FLAGS_SET = set(ALL_FLAGS) -# Suffix used in command line args to express that only known and -# otherwise unassigned entries should be assign the given flag. +# Option specified after one of FLAGS_API_LIST to indicate that +# only known and otherwise unassigned entries should be assign the +# given flag. # For example, the max-target-P list is checked in as it was in P, # but signatures have changes since then. The flag instructs this # script to skip any entries which do not exist any more. -FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts" +FLAG_IGNORE_CONFLICTS = "ignore-conflicts" -# Suffix used in command line args to express that all apis within a given set -# of packages should be assign the given flag. -FLAG_PACKAGES_SUFFIX = "-packages" +# Option specified after one of FLAGS_API_LIST to express that all +# apis within a given set of packages should be assign the given flag. +FLAG_PACKAGES = "packages" + +# Option specified after one of FLAGS_API_LIST to indicate an extra +# tag that should be added to the matching APIs. +FLAG_TAG = "tag" # Regex patterns of fields/methods used in serialization. These are # considered public API despite being hidden. @@ -86,6 +91,17 @@ HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersectio IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) +class StoreOrderedOptions(argparse.Action): + """An argparse action that stores a number of option arguments in the order that + they were specified. + """ + def __call__(self, parser, args, values, option_string = None): + items = getattr(args, self.dest, None) + if items is None: + items = [] + items.append([option_string.lstrip('-'), values]) + setattr(args, self.dest, items) + def get_args(): """Parses command line arguments. @@ -98,17 +114,19 @@ def get_args(): help='CSV files to be merged into output') for flag in ALL_FLAGS: - ignore_conflicts_flag = flag + FLAG_IGNORE_CONFLICTS_SUFFIX - packages_flag = flag + FLAG_PACKAGES_SUFFIX - parser.add_argument('--' + flag, dest=flag, nargs='*', default=[], metavar='TXT_FILE', - help='lists of entries with flag "' + flag + '"') - parser.add_argument('--' + ignore_conflicts_flag, dest=ignore_conflicts_flag, nargs='*', - default=[], metavar='TXT_FILE', - help='lists of entries with flag "' + flag + - '". skip entry if missing or flag conflict.') - parser.add_argument('--' + packages_flag, dest=packages_flag, nargs='*', - default=[], metavar='TXT_FILE', - help='lists of packages to be added to ' + flag + ' list') + parser.add_argument('--' + flag, dest='ordered_flags', metavar='TXT_FILE', + action=StoreOrderedOptions, help='lists of entries with flag "' + flag + '"') + parser.add_argument('--' + FLAG_IGNORE_CONFLICTS, dest='ordered_flags', nargs=0, + action=StoreOrderedOptions, help='Indicates that only known and otherwise unassigned ' + 'entries should be assign the given flag. Must follow a list of entries and applies ' + 'to the preceding such list.') + parser.add_argument('--' + FLAG_PACKAGES, dest='ordered_flags', nargs=0, + action=StoreOrderedOptions, help='Indicates that the previous list of entries ' + 'is a list of packages. All members in those packages will be given the flag. ' + 'Must follow a list of entries and applies to the preceding such list.') + parser.add_argument('--' + FLAG_TAG, dest='ordered_flags', nargs=1, + action=StoreOrderedOptions, help='Adds an extra tag to the previous list of entries. ' + 'Must follow a list of entries and applies to the preceding such list.') return parser.parse_args() @@ -170,11 +188,10 @@ class FlagsDict: def _check_entries_set(self, keys_subset, source): assert isinstance(keys_subset, set) assert keys_subset.issubset(self._dict_keyset), ( - "Error processing: {}\n" - "The following entries were unexpected:\n" + "Error: {} specifies signatures not present in code:\n" "{}" "Please visit go/hiddenapi for more information.").format( - source, "".join(map(lambda x: " " + str(x), keys_subset - self._dict_keyset))) + source, "".join(map(lambda x: " " + str(x) + "\n", keys_subset - self._dict_keyset))) def _check_flags_set(self, flags_subset, source): assert isinstance(flags_subset, set) @@ -258,7 +275,7 @@ class FlagsDict: flags.append(FLAG_SDK) self._dict[csv[0]].update(flags) - def assign_flag(self, flag, apis, source="<unknown>"): + def assign_flag(self, flag, apis, source="<unknown>", tag = None): """Assigns a flag to given subset of entries. Args: @@ -278,11 +295,44 @@ class FlagsDict: # Iterate over the API subset, find each entry in dict and assign the flag to it. for api in apis: self._dict[api].add(flag) + if tag: + self._dict[api].add(tag) + + +FlagFile = namedtuple('FlagFile', ('flag', 'file', 'ignore_conflicts', 'packages', 'tag')) + +def parse_ordered_flags(ordered_flags): + r = [] + currentflag, file, ignore_conflicts, packages, tag = None, None, False, False, None + for flag_value in ordered_flags: + flag, value = flag_value[0], flag_value[1] + if flag in ALL_FLAGS_SET: + if currentflag: + r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) + ignore_conflicts, packages, tag = False, False, None + currentflag = flag + file = value + else: + if currentflag is None: + raise argparse.ArgumentError('--%s is only allowed after one of %s' % ( + flag, ' '.join(['--%s' % f for f in ALL_FLAGS_SET]))) + if flag == FLAG_IGNORE_CONFLICTS: + ignore_conflicts = True + elif flag == FLAG_PACKAGES: + packages = True + elif flag == FLAG_TAG: + tag = value[0] + + + if currentflag: + r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) + return r def main(argv): # Parse arguments. args = vars(get_args()) + flagfiles = parse_ordered_flags(args['ordered_flags']) # Initialize API->flags dictionary. flags = FlagsDict() @@ -300,28 +350,28 @@ def main(argv): flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION)) # (2) Merge text files with a known flag into the dictionary. - for flag in ALL_FLAGS: - for filename in args[flag]: - flags.assign_flag(flag, read_lines(filename), filename) + for info in flagfiles: + if (not info.ignore_conflicts) and (not info.packages): + flags.assign_flag(info.flag, read_lines(info.file), info.file, info.tag) # Merge text files where conflicts should be ignored. # This will only assign the given flag if: # (a) the entry exists, and # (b) it has not been assigned any other flag. # Because of (b), this must run after all strict assignments have been performed. - for flag in ALL_FLAGS: - for filename in args[flag + FLAG_IGNORE_CONFLICTS_SUFFIX]: - valid_entries = flags.get_valid_subset_of_unassigned_apis(read_lines(filename)) - flags.assign_flag(flag, valid_entries, filename) + for info in flagfiles: + if info.ignore_conflicts: + valid_entries = flags.get_valid_subset_of_unassigned_apis(read_lines(info.file)) + flags.assign_flag(info.flag, valid_entries, filename, info.tag) # All members in the specified packages will be assigned the appropriate flag. - for flag in ALL_FLAGS: - for filename in args[flag + FLAG_PACKAGES_SUFFIX]: - packages_needing_list = set(read_lines(filename)) + for info in flagfiles: + if info.packages: + packages_needing_list = set(read_lines(info.file)) should_add_signature_to_list = lambda sig,lists: extract_package( sig) in packages_needing_list and not lists valid_entries = flags.filter_apis(should_add_signature_to_list) - flags.assign_flag(flag, valid_entries) + flags.assign_flag(info.flag, valid_entries, info.file, info.tag) # Mark all remaining entries as blocked. flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt index eef08b54f570..b489be23b737 100644 --- a/wifi/jarjar-rules.txt +++ b/wifi/jarjar-rules.txt @@ -36,6 +36,7 @@ rule android.net.ipmemorystore.IOnStatusListener* com.android.wifi.x.@0 rule android.net.ipmemorystore.NetworkAttributesParcelable* com.android.wifi.x.@0 rule android.net.ipmemorystore.SameL3NetworkResponseParcelable* com.android.wifi.x.@0 rule android.net.ipmemorystore.StatusParcelable* com.android.wifi.x.@0 +rule android.net.networkstack.aidl.** com.android.wifi.x.@0 # Net utils (includes Network Stack helper classes). rule android.net.DhcpResults* com.android.wifi.x.@0 |