diff options
296 files changed, 5271 insertions, 4710 deletions
diff --git a/Android.bp b/Android.bp index 1aaa6044111a..baa715e3bcac 100644 --- a/Android.bp +++ b/Android.bp @@ -35,22 +35,96 @@ filegroup { } // These are subset of framework-core-sources that are needed by the -// android.test.mock library. Ideally, the library should use public APIs only, -// but unfortunately its API signature has some references to these private APIs. +// android.test.mock library. The implementation of android.test.mock references +// private members of various components to allow mocking of classes that cannot +// be mocked without access to those internal implementation details. filegroup { name: "framework-core-sources-for-test-mock", srcs: [ + "core/java/android/accounts/AccountManagerCallback.java", + "core/java/android/accounts/AccountManagerFuture.java", + "core/java/android/accounts/AccountManager.java", + "core/java/android/accounts/AccountsException.java", + "core/java/android/accounts/AuthenticatorException.java", + "core/java/android/accounts/OperationCanceledException.java", + "core/java/android/annotation/AnimatorRes.java", + "core/java/android/annotation/AnimRes.java", + "core/java/android/annotation/AnyRes.java", + "core/java/android/annotation/ArrayRes.java", + "core/java/android/annotation/AttrRes.java", + "core/java/android/annotation/BoolRes.java", + "core/java/android/annotation/BroadcastBehavior.java", + "core/java/android/annotation/CallbackExecutor.java", + "core/java/android/annotation/CallSuper.java", + "core/java/android/annotation/CheckResult.java", + "core/java/android/annotation/ColorInt.java", + "core/java/android/annotation/ColorRes.java", + "core/java/android/annotation/DimenRes.java", + "core/java/android/annotation/DrawableRes.java", + "core/java/android/annotation/FontRes.java", + "core/java/android/annotation/FractionRes.java", + "core/java/android/annotation/IntDef.java", + "core/java/android/annotation/IntegerRes.java", + "core/java/android/annotation/IntRange.java", + "core/java/android/annotation/LayoutRes.java", + "core/java/android/annotation/NonNull.java", + "core/java/android/annotation/Nullable.java", + "core/java/android/annotation/PluralsRes.java", + "core/java/android/annotation/RawRes.java", + "core/java/android/annotation/RequiresPermission.java", + "core/java/android/annotation/SdkConstant.java", + "core/java/android/annotation/Size.java", + "core/java/android/annotation/StringDef.java", + "core/java/android/annotation/StringRes.java", + "core/java/android/annotation/StyleableRes.java", + "core/java/android/annotation/StyleRes.java", + "core/java/android/annotation/SuppressLint.java", + "core/java/android/annotation/SystemApi.java", + "core/java/android/annotation/SystemService.java", + "core/java/android/annotation/TestApi.java", + "core/java/android/annotation/UserIdInt.java", + "core/java/android/annotation/XmlRes.java", + "core/java/android/app/Application.java", "core/java/android/app/IApplicationThread.aidl", "core/java/android/app/IServiceConnection.aidl", + "core/java/android/app/PackageDeleteObserver.java", + "core/java/android/content/ComponentCallbacks2.java", + "core/java/android/content/ComponentCallbacks.java", + "core/java/android/content/ContentInterface.java", + "core/java/android/content/ContentProvider.java", + "core/java/android/content/ContentProviderNative.java", + "core/java/android/content/ContentResolver.java", + "core/java/android/content/Context.java", + "core/java/android/content/ContextWrapper.java", + "core/java/android/content/DialogInterface.java", "core/java/android/content/IContentProvider.java", - "core/java/android/content/pm/IPackageDataObserver.aidl", + "core/java/android/content/Intent.java", + "core/java/android/content/IntentSender.java", + "core/java/android/content/OperationApplicationException.java", + "core/java/android/content/pm/ActivityInfo.java", + "core/java/android/content/pm/ApplicationInfo.java", "core/java/android/content/pm/InstantAppInfo.java", + "core/java/android/content/pm/IPackageDataObserver.aidl", "core/java/android/content/pm/KeySet.java", "core/java/android/content/pm/PackageManager.java", "core/java/android/content/pm/VerifierDeviceIdentity.java", "core/java/android/content/res/Resources.java", + "core/java/android/database/CrossProcessCursor.java", + "core/java/android/database/CrossProcessCursorWrapper.java", + "core/java/android/database/Cursor.java", + "core/java/android/database/CursorWrapper.java", + "core/java/android/os/Binder.java", + "core/java/android/os/Bundle.java", + "core/java/android/os/IBinder.java", + "core/java/android/os/IInterface.java", + "core/java/android/os/Parcelable.java", + "core/java/android/os/ParcelFileDescriptor.java", + "core/java/android/os/RemoteException.java", "core/java/android/os/storage/VolumeInfo.java", + "core/java/android/util/AndroidException.java", "core/java/android/view/DisplayAdjustments.java", + "core/java/android/view/ViewDebug.java", + "core/java/com/android/internal/annotations/VisibleForTesting.java", ], path: "core/java", visibility: ["//frameworks/base/test-mock"], @@ -608,7 +682,7 @@ filegroup { java_library { name: "framework-annotations-lib", srcs: [ ":framework-annotations" ], - sdk_version: "current", + sdk_version: "core_current", } filegroup { @@ -739,7 +813,7 @@ java_library { "core/proto/android/privacy.proto", "core/proto/android/section.proto", ], - sdk_version: "current", + sdk_version: "9", srcs: [ "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", @@ -762,6 +836,7 @@ java_library { "core/proto/android/privacy.proto", "core/proto/android/section.proto", ], + sdk_version: "core_current", // Protos have lots of MissingOverride and similar. errorprone: { javacflags: ["-XepDisableAllChecks"], diff --git a/Android.mk b/Android.mk index d3627e118ae3..d8532489a786 100644 --- a/Android.mk +++ b/Android.mk @@ -60,7 +60,7 @@ $(SDK_METADATA): .KATI_IMPLICIT_OUTPUTS := $(filter-out $(SDK_METADATA),$(SDK_ME $(SDK_METADATA): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/framework-doc-stubs-metadata.zip rm -rf $(SDK_METADATA_DIR) mkdir -p $(SDK_METADATA_DIR) - unzip -qo $< -d $(SDK_METADATA_DIR) + unzip -DDqo $< -d $(SDK_METADATA_DIR) .PHONY: framework-doc-stubs framework-doc-stubs: $(SDK_METADATA) diff --git a/ApiDocs.bp b/ApiDocs.bp index bd4a32bfab7a..029699efe3b9 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -66,7 +66,7 @@ stubs_defaults { ":opt-telephony-srcs", ":opt-net-voip-srcs", ":art-module-public-api-stubs-source", - ":conscrypt.module.public.api.stubs.source", + ":conscrypt.module.public.api{.public.stubs.source}", ":android_icu4j_public_api_files", "test-mock/src/**/*.java", "test-runner/src/**/*.java", @@ -79,7 +79,7 @@ stubs_defaults { "sdk-dir", "api-versions-jars-dir", ], - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], @@ -101,7 +101,7 @@ droidstubs { arg_files: [ "core/res/AndroidManifest.xml", ], - args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ", + args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ", write_sdk_values: true, } diff --git a/METADATA b/METADATA new file mode 100644 index 000000000000..d97975ca3b99 --- /dev/null +++ b/METADATA @@ -0,0 +1,3 @@ +third_party { + license_type: NOTICE +} diff --git a/StubLibraries.bp b/StubLibraries.bp index 74b0524f4fd2..7d1b3d069f59 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -48,13 +48,12 @@ stubs_defaults { ":opt-telephony-srcs", ":opt-net-voip-srcs", ":art-module-public-api-stubs-source", - ":conscrypt.module.public.api.stubs.source", ":android_icu4j_public_api_files", ], libs: ["framework-internal-utils"], installable: false, annotations_enabled: true, - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], @@ -65,7 +64,10 @@ stubs_defaults { stubs_defaults { name: "metalava-full-api-stubs-default", defaults: ["metalava-base-api-stubs-default"], - srcs: [":framework-updatable-sources"], + srcs: [ + ":conscrypt.module.public.api{.public.stubs.source}", + ":framework-updatable-sources", + ], sdk_version: "core_platform", } @@ -97,13 +99,13 @@ droidstubs { removed_api_file: "api/removed.txt", }, last_released: { - api_file: ":last-released-public-api", + api_file: ":android.api.public.latest", removed_api_file: "api/removed.txt", baseline_file: ":public-api-incompatibilities-with-last-released", }, api_lint: { enabled: true, - new_since: ":last-released-public-api", + new_since: ":android.api.public.latest", baseline_file: "api/lint-baseline.txt", }, }, @@ -139,13 +141,13 @@ droidstubs { removed_api_file: "api/system-removed.txt", }, last_released: { - api_file: ":last-released-system-api", + api_file: ":android.api.system.latest", removed_api_file: "api/system-removed.txt", baseline_file: ":system-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-system-api", + new_since: ":android.api.system.latest", baseline_file: "api/system-lint-baseline.txt", }, }, @@ -207,13 +209,13 @@ droidstubs { removed_api_file: "api/module-lib-removed.txt", }, last_released: { - api_file: ":last-released-module-lib-api", + api_file: ":android.api.module-lib.latest", removed_api_file: "api/module-lib-removed.txt", baseline_file: ":module-lib-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-module-lib-api", + new_since: ":android.api.module-lib.latest", baseline_file: "api/module-lib-lint-baseline.txt", }, }, @@ -314,7 +316,7 @@ droidstubs { installable: false, sdk_version: "core_platform", annotations_enabled: true, - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], diff --git a/apex/Android.bp b/apex/Android.bp index c381c0f100a5..505c3fc12d05 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -63,6 +63,68 @@ mainline_service_stubs_args = "--hide-annotation android.annotation.Hide " + "--hide InternalClasses " // com.android.* classes are okay in this interface +// Defaults for mainline module provided java_sdk_library instances. +java_defaults { + name: "framework-module-defaults", + + // Additional annotations used for compiling both the implementation and the + // stubs libraries. + libs: ["framework-annotations-lib"], + + // Framework modules are not generally shared libraries, i.e. they are not + // intended, and must not be allowed, to be used in a <uses-library> manifest + // entry. + shared_library: false, + + // Enable api lint. This will eventually become the default for java_sdk_library + // but it cannot yet be turned on because some usages have not been cleaned up. + // TODO(b/156126315) - Remove when no longer needed. + api_lint: { + enabled: true, + }, + + // The API scope specific properties. + public: { + enabled: true, + sdk_version: "module_current", + }, + system: { + enabled: true, + sdk_version: "module_current", + }, + module_lib: { + enabled: true, + sdk_version: "module_current", + }, + + // Configure framework module specific metalava options. + droiddoc_options: [mainline_stubs_args], + + // The stub libraries must be visible to frameworks/base so they can be combined + // into API specific libraries. + stubs_library_visibility: [ + "//frameworks/base", // Framework + ], + + // Set the visibility of the modules creating the stubs source. + stubs_source_visibility: [ + // Ignore any visibility rules specified on the java_sdk_library when + // setting the visibility of the stubs source modules. + "//visibility:override", + + // Currently, the stub source is not required for anything other than building + // the stubs library so is private to avoid misuse. + "//visibility:private", + ], + + // Collates API usages from each module for further analysis. + plugins: ["java_api_finder"], + + // Mainline modules should only rely on 'module_lib' APIs provided by other modules + // and the non updatable parts of the platform. + sdk_version: "module_current", +} + stubs_defaults { name: "framework-module-stubs-defaults-publicapi", args: mainline_framework_stubs_args, diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp deleted file mode 100644 index dbb5bd3d660f..000000000000 --- a/apex/sdkextensions/Android.bp +++ /dev/null @@ -1,84 +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 { - default_visibility: [":__subpackages__"], -} - -apex { - name: "com.android.sdkext", - defaults: [ "com.android.sdkext-defaults" ], - binaries: [ "derive_sdk" ], - prebuilts: [ "cur_sdkinfo" ], - manifest: "manifest.json", - min_sdk_version: "current", -} - -apex_defaults { - name: "com.android.sdkext-defaults", - updatable: true, - min_sdk_version: "R", - java_libs: [ "framework-sdkextensions" ], - prebuilts: [ - "derive_sdk.rc", - ], - key: "com.android.sdkext.key", - certificate: ":com.android.sdkext.certificate", -} - -sdk { - name: "sdkextensions-sdk", - java_header_libs: [ "framework-sdkextensions-stubs-systemapi" ], -} - -apex_key { - name: "com.android.sdkext.key", - public_key: "com.android.sdkext.avbpubkey", - private_key: "com.android.sdkext.pem", -} - -android_app_certificate { - name: "com.android.sdkext.certificate", - certificate: "com.android.sdkext", -} - -python_binary_host { - name: "gen_sdkinfo", - srcs: [ - "sdk.proto", - "gen_sdkinfo.py", - ], - proto: { - canonical_path_from_root: false, - }, - version: { - py3: { - embedded_launcher: true, - }, - }, -} - -gensrcs { - name: "cur_sdkinfo_src", - srcs: [""], - tools: [ "gen_sdkinfo" ], - cmd: "$(location) -v 0 -o $(out)", -} - -prebuilt_etc { - name: "cur_sdkinfo", - src: ":cur_sdkinfo_src", - filename: "sdkinfo.binarypb", - installable: false, -} diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS deleted file mode 100644 index a6e55228596b..000000000000 --- a/apex/sdkextensions/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -dariofreni@google.com -hansson@google.com diff --git a/apex/sdkextensions/TEST_MAPPING b/apex/sdkextensions/TEST_MAPPING deleted file mode 100644 index 3dc1b9fa5dd0..000000000000 --- a/apex/sdkextensions/TEST_MAPPING +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presubmit": [ - { - "name": "CtsSdkExtensionsTestCases" - }, - { - "name": "sdkextensions_e2e_tests" - } - ] -} diff --git a/apex/sdkextensions/com.android.sdkext.avbpubkey b/apex/sdkextensions/com.android.sdkext.avbpubkey Binary files differdeleted file mode 100644 index 8f47741ed3b8..000000000000 --- a/apex/sdkextensions/com.android.sdkext.avbpubkey +++ /dev/null diff --git a/apex/sdkextensions/com.android.sdkext.pem b/apex/sdkextensions/com.android.sdkext.pem deleted file mode 100644 index 816460183aa3..000000000000 --- a/apex/sdkextensions/com.android.sdkext.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKQIBAAKCAgEAr72pTSavrziDP54AtQZlRclDxJf9HXRZwFRbYx9hWZ4z7ZtO -pNBDPvPJCiAOVUsILgCQhBUolz2dyLob25Fd0PVp0n9ibIPEQYjTfHjOK40qb57N -LhEp2ceGiAfsywPSi0TH1PQ6JgbCe/RM4TefI/sj3gYJPka3ksMvylhMIgUVLgME -kYizhzwHqlLMspB858SioREZdGwcdZrMMIajGFU69Q9ZRDBzhPvxyKhYoObcOtk1 -uVaiE/fNoi3wKGJz2l2vhUuNrQW7MWlVMag+Qes4YACUTk9LZrOVFEJFjWc8xGUi -ABtfKGs5JgNr/sWnhvifLn8lJuf0/BJmjD+L5QwXYs2cS7gcZJtTM12J94r0Twgw -wF2lNmIxAE9sYqj5Rh3dIlTPE5vMUECmQEGjIBB/hzT65VxVqSjU/IlS506JTg3p -IOQtZ15cUzTBpda4jrvqcq6RNVvgBCu2bV5D8Z4z9FUlPyvD+Zq/6lcoJfLtznAs -G2463hyPAHTGBIcZ5p5bTuGxoAb6ivyqo4b9Qi4yYA6je9HJmuy8T3Mn5JROoeu9 -BH1K54r/mpT4TQPwuKUvRRtBAV2OPHjo+zp0Gd4Y6rxDYxEIdfEae7pQr/QExSPB -q/QCr9RhixR1mO373LHuja+MxdAxIxugb2HTS61PQo+PbYrhJMcVuxTwJOECAwEA -AQKCAgAH7ToRrMkH0ji5SdsmTx+KQkW4PFLCXVke/68PjX7KmAQnl3W4oVwnHr/W -oROEbVn1GTlre7jU+YaAY0SWZrwgjLE1OWGrG1ZizlUbrCdAd6GOX09J4KROml1L -DXB0x7tbZMLOrCVjSbLD/ITrM6MN8Gnxvbv0/yOQjxU8vzbP4gLOjHxMRCo001RV -Ll7lPvcjTQ84zJilU6sE8vJ6zdfVZSK/ou2X0cekG+kP7+fvefo8/UcbEPlGhUrV -IdVPPQGUu90K2hmN0FBdLi8Vik0klAN68Qu/bHwuKbNzsnmIoztucFFUR+fG3u84 -87aPS0L/J3+mjT2Tv6qhJANUGBmrK/h7MkelpKXlRTCITJLX9xP7hfSbJ4f6aLVq -ZYPPciGxSBbUDgAwvPtOlMDzccg7YsYyiBBO28wh8MN97rePmc0z6nGmjeXhcbCC -QktG50VYFCyqp5muKgqQmRfRjHFHLWs8GEqgxMeEL3U3HjYfCYr+6E8Sr5OnOBeH -3buCi1+zgnNYCvbamgY/OJmW7f9h5O31hxmTplc2E1ZuxUGQZthabt1rN3bmNkyf -KUmPwnIYkDkWBSV5lzyQExfS3/EVvj0EnHhx8faamimNrGo8xCcfnLT3c0WEFVmo -yIyVRX3EpXJFM2JkeJ21/IEZXTzHSoNxk12CBG8i8lLSflWSMQKCAQEA2ZqVnOuV -SZfLCUYUUh8Hvhc5zONstfq7ma1Zsttsdaj9t68nLRiBDvLOGnMjDkYZzoSd4fyl -oy+YqWGBqcqa5kg1NOCH0I46p9d8RcWAfDnB4sqbLgWh70qsvni6igRijmsMDvkA -U9HeEdPaLCjQ4UXw7GQvN5rRxuRt+OSqV3tV/Pk9JYyYjz7faC8dmbKDrWHHuOvm -/9y6Xy+L5IgftykNlUeddSCIoMOAadM7BiRjsrHnOYBQ8xBcn0OYafpIswItrgVi -IrsPJaBFidx8QYK4MVibyka6U0cm28OocDSPtSk/4jrnCEEhLjFUnWwuMXuBGlrd -W7wP/muoJqb1VwKCAQEAzsAT90kkOCvAcrfGRE3KkUjwWAsQyP8u2+27JIQPqrpW -GfWAzJXFt80TSp0Zf/Lrq3/SQ9n4AaL4K9dcMoreedoQN9C9JI7zPtZAWNrJVUcV -dq2gZjBQ78+oK7uQgvFNWxga5D+Nh+Y+9Tp537fc5HIh0Y13PgsxxPk2OnZJTvLX -HM5H7Aua9ssmqChsrKihuUsDSPozfBz+H7FNHEdKMqVLqJJSK6m0uMxuLovdVfka -5S7iBMjEGZc46Iz3ckE0pdOiQLooNqfEQqFe5Uou/KZxxKI1NW25rEEBTVyQWt+2 -BNUCfKP7noZ45u5sUY3eJrgI7BrPEDbNS81WYaLchwKCAQA8Q4mHyd6wYO+EA/qA -u8NDK9+AFMP4qhXme5HJ7Obetwx9IG7zGEQ1xZy6yoQ84cEn5qZq/bNJvFbFIhHs -2gWIHRtPJ5e1dI5eCVmLYSUyQjSmAIJ1fm3YfY/VuE3BB3HcC11tkBw9GnQr78YO -UMd4fAw7C4vgFGpgcMbcFUfvrmKkCsqaaZOeqETq75F9DWlWTSwo1HxHA/RBhENz -6RcPfLkcTJcY5wevrjUUGcHQ86cAyDBHRngkuLVODkRZpU0Y9lN8TFVfVPre6sIX -ag6nffJRCD8tB+V2RtBGMKunV4ctHt1oY/Oz34W260aJynoIjjG1ANEpJK4xQdNx -0O9FAoIBAQCz2AGGKemHswdEwveEkuaSWpA3Bekj7lYkmTchHH9EU7JyAkx3qhDD -QXB2hxGXawf1tsqAmypQwiJ+gGeCz6mW9UkGRF1DX9XX4yc2I5rew2a4RXAxc/Xz -pP70i8O5I43Wn7FEusOyY2aAis1Y/eb4EQ+56QTAw5wXa3DwidRbCIJ2XDnT6oRy -CWUnAYMG7ek/9TB2Wq5OWCn2B5S79IdmZsLZb+5qbMT3u1xcwO1Xy8jJc27IGpv6 -ZsDqCTV1/aJ+XQnWpBg28tiV3Sle6pjUzTRJh5AhWcEZRbKMSOiJI/CBY4k2Qq6t -xuuEdgFjL7T+mTepqehUglcyiPuLEtAhAoIBAQDDQ5pTFOlunfYzm+CIvvImAgy7 -vrEabJYABATytAbXRMMbrKoEdU2ApEDyEW7PgysDnYLAZ+icObnJlBTYvNdlWFly -XiviGVfpjFWDT9U/gUwFQu2lfEjoiivoGS92USHUy4UMVHiiznnm20VLLkgd3xna -HUNSDdHIEgzOTmDsKJwMfA9zGckx23JJimPR5ekv6vr6QllYtECs4lTC1gVQAp2f -5daxHRbkmO6gw1RgQADLkAnYz3aI1jNuHm5VyAZGt/d3JCtZ3Wwwejll8uJ4J09G -oEtqyY9RVeHK50bLO4lyAXFiE+J6qqXjsGC20cpxeZYW5llMY/dhA6WV4YXV ------END RSA PRIVATE KEY----- diff --git a/apex/sdkextensions/com.android.sdkext.pk8 b/apex/sdkextensions/com.android.sdkext.pk8 Binary files differdeleted file mode 100644 index ccc0bf438cd1..000000000000 --- a/apex/sdkextensions/com.android.sdkext.pk8 +++ /dev/null diff --git a/apex/sdkextensions/com.android.sdkext.x509.pem b/apex/sdkextensions/com.android.sdkext.x509.pem deleted file mode 100644 index 45d2ade354d4..000000000000 --- a/apex/sdkextensions/com.android.sdkext.x509.pem +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGIzCCBAugAwIBAgIUXuDL7QvzQh7S6rihWz2KRvCFVT0wDQYJKoZIhvcNAQEL -BQAwgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy -b2lkMRswGQYDVQQDDBJjb20uYW5kcm9pZC5zZGtleHQxIjAgBgkqhkiG9w0BCQEW -E2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjAyMTQyNDM0WhgPNDc1NzEwMjgx -NDI0MzRaMIGfMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG -A1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwH -QW5kcm9pZDEbMBkGA1UEAwwSY29tLmFuZHJvaWQuc2RrZXh0MSIwIAYJKoZIhvcN -AQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxFvZZ6ES1oqAu1K74/ZxnC3SOhHnLISLBgJEe7DqtdpuNFAwvdVO -RL/HULhDbjYlOhpU2x3SavDIZZ2lRfiS9Q+M25WftxTRHVjBcpgwbV77TVxPKlAa -tVN2lUVOY+s4QAVMNIXjC4kCKK/pCQtacH715EtdV47fWdg/Nx4iP/Aord8k3KGI -9iI2ZOUjaugTRxu5lKRNDrv0bw5rEzyYmDyMud+kR/iS3/5oog57wPE0ffAkZXWE -p3L2Cejre3ekCizsvVh6EmH6ForKLtL6f0z5Zir1f4R9+YcENspTlJR3pDhg7y3I -uTQT/iDCtV0l+g2PjGZPEeAQHND3+kDQR7Sno/WC1Nhws6vcu1MdrC+kIh1ewx4y -8moy/yqb5M98PJDzTSi/AOTB/OiqLXo/T8rjLBmirs9y3fTT6gJ6qXxOWgt8dle9 -7TBfa84Xi8uVY61c+A+YI0nLal7QDPsP3RPv5sJSQ9x9YnweVfD9Q0EOi52sSNu+ -QuN/kcUrMgPgha20VhfH/CkkPDyIp6aZyHHM69MIl+cYEm8vPa5uy3dosuRomT0f -I4HOBjULDIuj+rIi+Rg3qHvmpuejwZXI/FBNWIhLEUG3ytgksjMaBoYAYflGdrcj -BQexuF3EO+j4uo7JGjNcaT7wRoCH9gt29VHckDg2qz6VWXrlpmME4UkCAwEAAaNT -MFEwHQYDVR0OBBYEFISN2nmUHllgPZMZ62U7mU3ZxzlXMB8GA1UdIwQYMBaAFISN -2nmUHllgPZMZ62U7mU3ZxzlXMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggIBAFHIwyBNIVyHXUsDUdcjxfojXQsF/BCL9ehE3pgdkvDfQanaIREWn0nc -oCFDFkYMRqaXOGC5TKq4OCjXOLsdfODt8HQ3F9J1B0ghQ5tfOdw7xDugNAszqP/Q -h7kpvqLTycjrqOeZ5KjxEEYtP/KlUmALgOKcTcSH+XhWyxhjF4j24T9F2yJRr3/A -r1NGU/djH953bHKC8OpJ2teUpDLA4TxVp/EhslH2eVigF80c/w74QPLEWkD9zv/4 -YeRg/R5N83zHs99NtlWMIeHfK6fUbzMyaSZtvm+jK20tkByQb/OQRed+drk25MtL -68IRvxqri367qRScdpTZbu0ByLO4X8gFdubRUWr+tcO4pZX+DJRVriExbOkU2xhS -Vtslq23V/hwTuUNm1CXjR70mPS13BTmHrIQDqLoIw/WTQlGh+vxnlAFRIHM3KB2c -OdzUBu+NcB4aZEd0KKtct600A0DKPr1MQPb5jDq9wEtPSQYwMF0nRFNnXltbrXMd -4hhwnhKr74fVMUmb+7eQP56XE/Nk4D+npMO54vv1pav+DI2/nxCND9BOLBweY38p -Tvd2RjesMok0zXuVXiCIu4GEpwo7WkSnv25xrb0Ey2M8QWnGNnCcX7Kv6ip3RdWy -HiN0G8RJrs/yNEVSDRx8ZhtwTpXVPQxbARbmhNF4/fnolElkmrMP ------END CERTIFICATE----- diff --git a/apex/sdkextensions/derive_sdk/Android.bp b/apex/sdkextensions/derive_sdk/Android.bp deleted file mode 100644 index 41eae09b1351..000000000000 --- a/apex/sdkextensions/derive_sdk/Android.bp +++ /dev/null @@ -1,55 +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. - -cc_defaults { - name: "derive_sdk-defaults", - srcs: [ - "derive_sdk.cpp", - "sdk.proto", - ], - proto: { - type: "lite", - static: true, - }, - min_sdk_version: "current", - shared_libs: ["liblog"], - // static c++/libbase for smaller size - stl: "c++_static", - static_libs: ["libbase"], -} - -cc_binary { - name: "derive_sdk", - defaults: [ "derive_sdk-defaults" ], - apex_available: [ "com.android.sdkext" ], - visibility: [ "//frameworks/base/apex/sdkextensions" ] -} - -// Work around testing using a 64-bit test suite on 32-bit test device by -// using a prefer32 version of derive_sdk in testing. -cc_binary { - name: "derive_sdk_prefer32", - defaults: [ "derive_sdk-defaults" ], - compile_multilib: "prefer32", - stem: "derive_sdk", - apex_available: [ "test_com.android.sdkext" ], - visibility: [ "//frameworks/base/apex/sdkextensions/testing" ], - installable: false, -} - -prebuilt_etc { - name: "derive_sdk.rc", - src: "derive_sdk.rc", - installable: false, -} diff --git a/apex/sdkextensions/derive_sdk/derive_sdk.cpp b/apex/sdkextensions/derive_sdk/derive_sdk.cpp deleted file mode 100644 index 900193a6bd0d..000000000000 --- a/apex/sdkextensions/derive_sdk/derive_sdk.cpp +++ /dev/null @@ -1,79 +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. - */ - -#define LOG_TAG "derive_sdk" - -#include <algorithm> -#include <dirent.h> -#include <iostream> -#include <sys/stat.h> -#include <vector> - -#include <android-base/file.h> -#include <android-base/logging.h> -#include <android-base/properties.h> - -#include "frameworks/base/apex/sdkextensions/derive_sdk/sdk.pb.h" - -using com::android::sdkext::proto::SdkVersion; - -int main(int, char**) { - std::unique_ptr<DIR, decltype(&closedir)> apex(opendir("/apex"), closedir); - if (!apex) { - LOG(ERROR) << "Could not read /apex"; - return EXIT_FAILURE; - } - struct dirent* de; - std::vector<std::string> paths; - while ((de = readdir(apex.get()))) { - std::string name = de->d_name; - if (name[0] == '.' || name.find('@') != std::string::npos) { - // Skip <name>@<ver> dirs, as they are bind-mounted to <name> - continue; - } - std::string path = "/apex/" + name + "/etc/sdkinfo.binarypb"; - struct stat statbuf; - if (stat(path.c_str(), &statbuf) == 0) { - paths.push_back(path); - } - } - - std::vector<int> versions; - for (const auto& path : paths) { - std::string contents; - if (!android::base::ReadFileToString(path, &contents, true)) { - LOG(ERROR) << "failed to read " << path; - continue; - } - SdkVersion sdk_version; - if (!sdk_version.ParseFromString(contents)) { - LOG(ERROR) << "failed to parse " << path; - continue; - } - LOG(INFO) << "Read version " << sdk_version.version() << " from " << path; - versions.push_back(sdk_version.version()); - } - auto itr = std::min_element(versions.begin(), versions.end()); - std::string prop_value = itr == versions.end() ? "0" : std::to_string(*itr); - - if (!android::base::SetProperty("build.version.extensions.r", prop_value)) { - LOG(ERROR) << "failed to set sdk_info prop"; - return EXIT_FAILURE; - } - - LOG(INFO) << "R extension version is " << prop_value; - return EXIT_SUCCESS; -} diff --git a/apex/sdkextensions/derive_sdk/derive_sdk.rc b/apex/sdkextensions/derive_sdk/derive_sdk.rc deleted file mode 100644 index 18f021ccadff..000000000000 --- a/apex/sdkextensions/derive_sdk/derive_sdk.rc +++ /dev/null @@ -1,5 +0,0 @@ -service derive_sdk /apex/com.android.sdkext/bin/derive_sdk - user nobody - group nobody - oneshot - disabled diff --git a/apex/sdkextensions/derive_sdk/sdk.proto b/apex/sdkextensions/derive_sdk/sdk.proto deleted file mode 100644 index d15b93552ff4..000000000000 --- a/apex/sdkextensions/derive_sdk/sdk.proto +++ /dev/null @@ -1,25 +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. - */ - -syntax = "proto3"; -package com.android.sdkext.proto; - -option java_outer_classname = "SdkProto"; -option optimize_for = LITE_RUNTIME; - -message SdkVersion { - int32 version = 1; -} diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp deleted file mode 100644 index 707113b9672c..000000000000 --- a/apex/sdkextensions/framework/Android.bp +++ /dev/null @@ -1,114 +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 { - default_visibility: [ ":__pkg__" ] -} - -filegroup { - name: "framework-sdkextensions-sources", - srcs: [ - "java/**/*.java", - ], - path: "java", - visibility: [ "//frameworks/base" ] // For the "global" stubs. -} - -java_library { - name: "framework-sdkextensions", - srcs: [ ":framework-sdkextensions-sources" ], - sdk_version: "system_current", - libs: [ "framework-annotations-lib" ], - permitted_packages: [ "android.os.ext" ], - installable: true, - plugins: ["java_api_finder"], - visibility: [ - "//frameworks/base/apex/sdkextensions", - "//frameworks/base/apex/sdkextensions/testing", - ], - hostdex: true, // for hiddenapi check - apex_available: [ - "com.android.sdkext", - "test_com.android.sdkext", - ], -} - -stubs_defaults { - name: "framework-sdkextensions-stubs-defaults", - srcs: [ ":framework-sdkextensions-sources" ], - libs: [ "framework-annotations-lib" ], - sdk_version: "system_current", -} - -droidstubs { - name: "framework-sdkextensions-stubs-srcs-publicapi", - defaults: [ - "framework-module-stubs-defaults-publicapi", - "framework-sdkextensions-stubs-defaults", - ] -} - -droidstubs { - name: "framework-sdkextensions-stubs-srcs-systemapi", - defaults: [ - "framework-module-stubs-defaults-systemapi", - "framework-sdkextensions-stubs-defaults", - ] -} - -droidstubs { - name: "framework-sdkextensions-api-module_libs_api", - defaults: [ - "framework-module-api-defaults-module_libs_api", - "framework-sdkextensions-stubs-defaults", - ] -} - -droidstubs { - name: "framework-sdkextensions-stubs-srcs-module_libs_api", - defaults: [ - "framework-module-stubs-defaults-module_libs_api", - "framework-sdkextensions-stubs-defaults", - ] -} - -java_library { - name: "framework-sdkextensions-stubs-publicapi", - srcs: [":framework-sdkextensions-stubs-srcs-publicapi"], - defaults: ["framework-module-stubs-lib-defaults-publicapi"], - visibility: [ - "//frameworks/base", // Framework - "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] -} - -java_library { - name: "framework-sdkextensions-stubs-systemapi", - srcs: [":framework-sdkextensions-stubs-srcs-systemapi"], - defaults: ["framework-module-stubs-lib-defaults-systemapi"], - visibility: [ - "//frameworks/base", // Framework - "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] -} - -java_library { - name: "framework-sdkextensions-stubs-module_libs_api", - srcs: [":framework-sdkextensions-stubs-srcs-module_libs_api"], - defaults: ["framework-module-stubs-lib-defaults-module_libs_api"], - visibility: [ - "//frameworks/base", // Framework - "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] -} diff --git a/apex/sdkextensions/framework/api/current.txt b/apex/sdkextensions/framework/api/current.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/sdkextensions/framework/api/current.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/sdkextensions/framework/api/module-lib-current.txt b/apex/sdkextensions/framework/api/module-lib-current.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/sdkextensions/framework/api/module-lib-current.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/sdkextensions/framework/api/module-lib-removed.txt b/apex/sdkextensions/framework/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/sdkextensions/framework/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/sdkextensions/framework/api/removed.txt b/apex/sdkextensions/framework/api/removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/sdkextensions/framework/api/removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/sdkextensions/framework/api/system-current.txt b/apex/sdkextensions/framework/api/system-current.txt deleted file mode 100644 index bbff4c5ae6f4..000000000000 --- a/apex/sdkextensions/framework/api/system-current.txt +++ /dev/null @@ -1,9 +0,0 @@ -// Signature format: 2.0 -package android.os.ext { - - public class SdkExtensions { - method public static int getExtensionVersion(int); - } - -} - diff --git a/apex/sdkextensions/framework/api/system-removed.txt b/apex/sdkextensions/framework/api/system-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/sdkextensions/framework/api/system-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java b/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java deleted file mode 100644 index c268ff4291e4..000000000000 --- a/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os.ext; - -import android.annotation.IntDef; -import android.annotation.SystemApi; -import android.os.Build.VERSION_CODES; -import android.os.SystemProperties; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Methods for interacting with the extension SDK. - * - * This class provides information about the extension SDK version present - * on this device. Use the {@link #getExtensionVersion(int) getExtension} to - * query for the extension version for the given SDK version. - - * @hide - */ -@SystemApi -public class SdkExtensions { - - private static final int R_EXTENSION_INT; - static { - R_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.r", 0); - } - - /** - * Values suitable as parameters for {@link #getExtensionVersion(int)}. - * @hide - */ - @IntDef(value = { VERSION_CODES.R }) - @Retention(RetentionPolicy.SOURCE) - public @interface SdkVersion {} - - private SdkExtensions() { } - - /** - * Return the version of the extension to the given SDK. - * - * @param sdk the SDK version to get the extension version of. - * @see SdkVersion - * @throws IllegalArgumentException if sdk is not an sdk version with extensions - */ - public static int getExtensionVersion(@SdkVersion int sdk) { - if (sdk < VERSION_CODES.R) { - throw new IllegalArgumentException(String.valueOf(sdk) + " does not have extensions"); - } - - if (sdk == VERSION_CODES.R) { - return R_EXTENSION_INT; - } - return 0; - } - -} diff --git a/apex/sdkextensions/framework/java/android/os/ext/package.html b/apex/sdkextensions/framework/java/android/os/ext/package.html deleted file mode 100644 index 34c1697c01fd..000000000000 --- a/apex/sdkextensions/framework/java/android/os/ext/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<HTML> -<BODY> -Provides APIs to interface with the SDK extensions. -</BODY> -</HTML> diff --git a/apex/sdkextensions/gen_sdkinfo.py b/apex/sdkextensions/gen_sdkinfo.py deleted file mode 100644 index 5af478ba7fe6..000000000000 --- a/apex/sdkextensions/gen_sdkinfo.py +++ /dev/null @@ -1,19 +0,0 @@ -import sdk_pb2 -import sys - -if __name__ == '__main__': - argv = sys.argv[1:] - if not len(argv) == 4 or sorted([argv[0], argv[2]]) != ['-o', '-v']: - print('usage: gen_sdkinfo -v <version> -o <output-file>') - sys.exit(1) - - for i in range(len(argv)): - if sys.argv[i] == '-o': - filename = sys.argv[i+1] - if sys.argv[i] == '-v': - version = int(sys.argv[i+1]) - - proto = sdk_pb2.SdkVersion() - proto.version = version - with open(filename, 'wb') as f: - f.write(proto.SerializeToString()) diff --git a/apex/sdkextensions/manifest.json b/apex/sdkextensions/manifest.json deleted file mode 100644 index 048f5c4f177b..000000000000 --- a/apex/sdkextensions/manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.sdkext", - "version": 1 -} diff --git a/apex/sdkextensions/sdk.proto b/apex/sdkextensions/sdk.proto deleted file mode 100644 index d15b93552ff4..000000000000 --- a/apex/sdkextensions/sdk.proto +++ /dev/null @@ -1,25 +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. - */ - -syntax = "proto3"; -package com.android.sdkext.proto; - -option java_outer_classname = "SdkProto"; -option optimize_for = LITE_RUNTIME; - -message SdkVersion { - int32 version = 1; -} diff --git a/apex/sdkextensions/testing/Android.bp b/apex/sdkextensions/testing/Android.bp deleted file mode 100644 index f2f5b321fafe..000000000000 --- a/apex/sdkextensions/testing/Android.bp +++ /dev/null @@ -1,46 +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_test { - name: "test_com.android.sdkext", - visibility: [ "//system/apex/tests" ], - defaults: ["com.android.sdkext-defaults"], - manifest: "test_manifest.json", - prebuilts: [ "sdkinfo_45" ], - file_contexts: ":com.android.sdkext-file_contexts", - installable: false, // Should never be installed on the systemimage - multilib: { - prefer32: { - binaries: ["derive_sdk_prefer32"], - }, - }, - // The automated test infra ends up building this apex for 64+32-bit and - // then installs it on a 32-bit-only device. Work around this weirdness - // by preferring 32-bit. - compile_multilib: "prefer32", -} - -genrule { - name: "sdkinfo_45_src", - out: [ "sdkinfo.binarypb" ], - tools: [ "gen_sdkinfo" ], - cmd: "$(location) -v 45 -o $(out)", -} - -prebuilt_etc { - name: "sdkinfo_45", - src: ":sdkinfo_45_src", - filename: "sdkinfo.binarypb", - installable: false, -} diff --git a/apex/sdkextensions/testing/test_manifest.json b/apex/sdkextensions/testing/test_manifest.json deleted file mode 100644 index 1b4a2b0c6e60..000000000000 --- a/apex/sdkextensions/testing/test_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.sdkext", - "version": 2147483647 -} diff --git a/api/current.txt b/api/current.txt index c84f00669b5f..8163426f953c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29175,6 +29175,7 @@ package android.net { field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf field public static final int NET_CAPABILITY_RCS = 8; // 0x8 field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 + field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19 field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 @@ -34538,6 +34539,7 @@ package android.os { field public static final String PRODUCT; field @Deprecated public static final String RADIO; field @Deprecated public static final String SERIAL; + field @NonNull public static final String SKU; field public static final String[] SUPPORTED_32_BIT_ABIS; field public static final String[] SUPPORTED_64_BIT_ABIS; field public static final String[] SUPPORTED_ABIS; @@ -41302,6 +41304,7 @@ package android.security.keystore { method public int getPurposes(); method @NonNull public String[] getSignaturePaddings(); method public int getUserAuthenticationValidityDurationSeconds(); + method public boolean isDevicePropertiesAttestationIncluded(); method @NonNull public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); method public boolean isRandomizedEncryptionRequired(); @@ -41323,6 +41326,7 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateNotBefore(@NonNull java.util.Date); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSerialNumber(@NonNull java.math.BigInteger); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(@NonNull javax.security.auth.x500.X500Principal); + method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDevicePropertiesAttestationIncluded(boolean); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean); @@ -45279,6 +45283,7 @@ package android.telephony { field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70; // 0x46 field public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67; // 0x43 field public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68; // 0x44 + field public static final int EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 78; // 0x4e field public static final int EMERGENCY_PERM_FAILURE = 64; // 0x40 field public static final int EMERGENCY_TEMP_FAILURE = 63; // 0x3f field public static final int ERROR_UNSPECIFIED = 36; // 0x24 @@ -45297,6 +45302,7 @@ package android.telephony { field public static final int LOST_SIGNAL = 14; // 0xe field public static final int LOW_BATTERY = 61; // 0x3d field public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53; // 0x35 + field public static final int MEDIA_TIMEOUT = 77; // 0x4d field public static final int MMI = 6; // 0x6 field public static final int NORMAL = 2; // 0x2 field public static final int NORMAL_UNSPECIFIED = 65; // 0x41 @@ -45318,6 +45324,7 @@ package android.telephony { field public static final int UNOBTAINABLE_NUMBER = 25; // 0x19 field public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50; // 0x32 field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28 + field public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79; // 0x4f field public static final int WIFI_LOST = 59; // 0x3b } @@ -45337,12 +45344,14 @@ package android.telephony { public class MbmsDownloadSession implements java.lang.AutoCloseable { method public void addProgressListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.DownloadProgressListener); + method public void addServiceAnnouncementFile(@NonNull byte[]); method public void addStatusListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.DownloadStatusListener); method public void cancelDownload(@NonNull android.telephony.mbms.DownloadRequest); method public void close(); method public static android.telephony.MbmsDownloadSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsDownloadSessionCallback); method @Nullable public static android.telephony.MbmsDownloadSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, int, @NonNull android.telephony.mbms.MbmsDownloadSessionCallback); method public void download(@NonNull android.telephony.mbms.DownloadRequest); + method public static int getMaximumServiceAnnouncementFileSize(); method @Nullable public java.io.File getTempFileRootDirectory(); method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(); method public void removeProgressListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull android.telephony.mbms.DownloadProgressListener); @@ -46629,12 +46638,8 @@ package android.telephony.ims { method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); } - public class ImsRcsManager implements android.telephony.ims.RegistrationManager { - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + public class ImsRcsManager { method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter(); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); field public static final String ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN = "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; } @@ -46953,6 +46958,7 @@ package android.telephony.mbms { public static class MbmsErrors.DownloadErrors { field public static final int ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT = 401; // 0x191 + field public static final int ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE = 404; // 0x194 field public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402; // 0x192 field public static final int ERROR_UNKNOWN_FILE_INFO = 403; // 0x193 } diff --git a/api/system-current.txt b/api/system-current.txt index 3b349bf6a9bb..26153caebfce 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6572,6 +6572,7 @@ package android.provider { field public static final String NAMESPACE_APP_COMPAT = "app_compat"; field public static final String NAMESPACE_ATTENTION_MANAGER_SERVICE = "attention_manager_service"; field public static final String NAMESPACE_AUTOFILL = "autofill"; + field public static final String NAMESPACE_BLUETOOTH = "bluetooth"; field public static final String NAMESPACE_CONNECTIVITY = "connectivity"; field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; field public static final String NAMESPACE_DEX_BOOT = "dex_boot"; @@ -10320,6 +10321,7 @@ 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 addServiceAnnouncementFile(int, @NonNull byte[]); 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; diff --git a/api/test-current.txt b/api/test-current.txt index 31b4ca82c68e..9747647845ed 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1440,6 +1440,7 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={"android.permission.MANAGE_TEST_NETWORKS", android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; @@ -4098,6 +4099,7 @@ 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 addServiceAnnouncementFile(int, @NonNull byte[]); 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; diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc index 9f4f314a4324..ad4de0ab737a 100644 --- a/cmds/bootanimation/bootanim.rc +++ b/cmds/bootanimation/bootanim.rc @@ -5,4 +5,4 @@ service bootanim /system/bin/bootanimation disabled oneshot ioprio rt 0 - writepid /dev/stune/top-app/tasks + task_profiles MaxPerformance diff --git a/cmds/device_config/Android.bp b/cmds/device_config/Android.bp new file mode 100644 index 000000000000..67e014a20506 --- /dev/null +++ b/cmds/device_config/Android.bp @@ -0,0 +1,7 @@ +// Copyright 2018 The Android Open Source Project +// + +sh_binary { + name: "device_config", + src: "device_config", +} diff --git a/cmds/device_config/Android.mk b/cmds/device_config/Android.mk deleted file mode 100644 index 4041e01927df..000000000000 --- a/cmds/device_config/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2018 The Android Open Source Project -# -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := device_config -LOCAL_SRC_FILES := device_config -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_MODULE_TAGS := optional -include $(BUILD_PREBUILT) diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 72a8bea9a918..24fbf21f463f 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -382,7 +382,7 @@ cc_benchmark { // ==== java proto device library (for test only) ============================== java_library { name: "statsdprotolite", - sdk_version: "core_platform", + sdk_version: "core_current", proto: { type: "lite", include_dirs: ["external/protobuf/src"], diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 3519a157472b..52e93856a0c7 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -149,8 +149,10 @@ message Atom { HardwareFailed hardware_failed = 72; PhysicalDropDetected physical_drop_detected = 73; ChargeCyclesReported charge_cycles_reported = 74; - MobileConnectionStateChanged mobile_connection_state_changed = 75; - MobileRadioTechnologyChanged mobile_radio_technology_changed = 76; + MobileConnectionStateChanged mobile_connection_state_changed = + 75 [(log_from_module) = "telephony"]; + MobileRadioTechnologyChanged mobile_radio_technology_changed = + 76 [(log_from_module) = "telephony"]; UsbDeviceAttached usb_device_attached = 77; AppCrashOccurred app_crash_occurred = 78; ANROccurred anr_occurred = 79; @@ -5882,11 +5884,11 @@ message NetworkDnsEventReported { * Logs when a data stall event occurs. * * Log from: - * frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java + * packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java */ message DataStallEvent { // Data stall evaluation type. - // See frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java + // See packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java // Refer to the definition of DATA_STALL_EVALUATION_TYPE_*. optional int32 evaluation_type = 1; // See definition in data_stall_event.proto. @@ -5899,6 +5901,10 @@ message DataStallEvent { optional com.android.server.connectivity.CellularData cell_info = 5 [(log_mode) = MODE_BYTES]; // See definition in data_stall_event.proto. optional com.android.server.connectivity.DnsEvent dns_event = 6 [(log_mode) = MODE_BYTES]; + // The tcp packets fail rate from the latest tcp polling. + optional int32 tcp_fail_rate = 7; + // Number of packets sent since the last received packet. + optional int32 tcp_sent_since_last_recv = 8; } /* diff --git a/config/OWNERS b/config/OWNERS index 53f80e698d83..3d4924df3462 100644 --- a/config/OWNERS +++ b/config/OWNERS @@ -1,5 +1,5 @@ # compat-team@ for changes to hiddenapi files -per-file hiddenapi-* = andreionea@google.com, atrost@google.com, mathewi@google.com, satayev@google.com +per-file hiddenapi-* = andreionea@google.com, mathewi@google.com, satayev@google.com # Escalations: -per-file hiddenapi-* = bdc@google.com, narayan@google.com
\ No newline at end of file +per-file hiddenapi-* = bdc@google.com, narayan@google.com diff --git a/core/java/android/annotation/CallbackExecutor.java b/core/java/android/annotation/CallbackExecutor.java index 5671a3d2b6d6..4258f730eb16 100644 --- a/core/java/android/annotation/CallbackExecutor.java +++ b/core/java/android/annotation/CallbackExecutor.java @@ -19,9 +19,6 @@ package android.annotation; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.content.Context; -import android.os.AsyncTask; - import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.concurrent.Executor; @@ -30,9 +27,10 @@ import java.util.concurrent.Executor; * @paramDoc Callback and listener events are dispatched through this * {@link Executor}, providing an easy way to control which thread is * used. To dispatch events through the main thread of your - * application, you can use {@link Context#getMainExecutor()}. To - * dispatch events through a shared thread pool, you can use - * {@link AsyncTask#THREAD_POOL_EXECUTOR}. + * application, you can use + * {@link android.content.Context#getMainExecutor() Context.getMainExecutor()}. + * To dispatch events through a shared thread pool, you can use + * {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR AsyncTask#THREAD_POOL_EXECUTOR}. * @hide */ @Retention(SOURCE) diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS index 8aceb565315c..e1ef54460b56 100644 --- a/core/java/android/annotation/OWNERS +++ b/core/java/android/annotation/OWNERS @@ -1,3 +1,3 @@ tnorbye@google.com aurimas@google.com -per-file UnsupportedAppUsage.java = mathewi@google.com, dbrazdil@google.com, atrost@google.com, andreionea@google.com +per-file UnsupportedAppUsage.java = mathewi@google.com, satayev@google.com, andreionea@google.com diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java index e5c0654f8bbe..1d89e31b2b99 100644 --- a/core/java/android/annotation/RequiresPermission.java +++ b/core/java/android/annotation/RequiresPermission.java @@ -15,9 +15,6 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; @@ -25,6 +22,9 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Denotes that the annotated element requires (or may require) one or more permissions. * <p/> @@ -55,7 +55,8 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; * <p> * When specified on a parameter, the annotation indicates that the method requires * a permission which depends on the value of the parameter. For example, consider - * {@link android.app.Activity#startActivity(android.content.Intent)}: + * {@link android.app.Activity#startActivity(android.content.Intent) + * Activity#startActivity(Intent)}: * <pre>{@code * public void startActivity(@RequiresPermission Intent intent) { ... } * }</pre> diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b6f61a2b8f01..4f1d7f2c761c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3618,7 +3618,6 @@ public class Activity extends ContextThemeWrapper * To receive this callback, you must return true from onKeyDown for the current * event stream. * - * @see KeyEvent.Callback#onKeyLongPress() * @see KeyEvent.Callback#onKeyLongPress(int, KeyEvent) */ public boolean onKeyLongPress(int keyCode, KeyEvent event) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index bdaa44034565..85cd21dec283 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2082,8 +2082,7 @@ public class ActivityManager { * has access to it. * * @see ActivityOptions#setLaunchDisplayId(int) - * @see android.view.Display.FLAG_PRIVATE - * @see android.view.Display.TYPE_VIRTUAL + * @see android.view.Display#FLAG_PRIVATE * * @param context Source context, from which an activity will be started. * @param displayId Target display id. diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index b669d775b3c1..647f63025cf7 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -37,7 +37,6 @@ import android.util.proto.ProtoOutputStream; import libcore.timezone.ZoneInfoDb; -import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -998,12 +997,7 @@ public class AlarmManager { // Reject this timezone if it isn't an Olson zone we recognize. if (mTargetSdkVersion >= Build.VERSION_CODES.M) { - boolean hasTimeZone = false; - try { - hasTimeZone = ZoneInfoDb.getInstance().hasTimeZone(timeZone); - } catch (IOException ignored) { - } - + boolean hasTimeZone = ZoneInfoDb.getInstance().hasTimeZone(timeZone); if (!hasTimeZone) { throw new IllegalArgumentException("Timezone: " + timeZone + " is not an Olson ID"); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 7a560c07a365..0feed7383020 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -299,7 +299,8 @@ interface IActivityManager { void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask, in StrictMode.ViolationInfo crashInfo); boolean isTopActivityImmersive(); - void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message); + void crashApplication(int uid, int initialPid, in String packageName, int userId, + in String message, boolean force); @UnsupportedAppUsage String getProviderMimeType(in Uri uri, int userId); // Cause the specified process to dump the specified heap. diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index cff6411c882c..2049b3408c64 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -729,7 +729,7 @@ public class Instrumentation { * a non-null value if the intent needs to be intercepted. * * <p> Whenever a new activity is started, this method will be called on instances created - * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case + * using {@link #ActivityMonitor()} to check if there is a match. In case * of a match, the activity start will be blocked and the returned result will be used. * * @param intent The intent used for starting the activity. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cefec441e702..f2b2635c8636 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3437,7 +3437,7 @@ public class Notification implements Parcelable } /** - * @deprecated use {@link Notification.Builder#Notification.Builder(Context, String)} + * @deprecated use {@link #Builder(Context, String)} * instead. All posted Notifications must specify a NotificationChannel Id. */ @Deprecated @@ -7071,7 +7071,7 @@ public class Notification implements Parcelable * Should be unique amongst all individuals in the conversation, and should be * consistent during re-posts of the notification. * - * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence) + * @see Message#Message(CharSequence, long, CharSequence) * * @return this object for method chaining * @@ -7091,7 +7091,7 @@ public class Notification implements Parcelable * Should be <code>null</code> for messages by the current user, in which case * the platform will insert the user set in {@code MessagingStyle(Person)}. * - * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence) + * @see Message#Message(CharSequence, long, CharSequence) * * @return this object for method chaining */ diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index e25558f16f26..925586feaf1d 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -294,7 +294,7 @@ public class NotificationManager { * </p> * </p> * - * @see {@link #addAutomaticZenRule(AutomaticZenRule)} + * @see #addAutomaticZenRule(AutomaticZenRule) */ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_AUTOMATIC_ZEN_RULE = diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index dc815b631e46..067a35fe1aba 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -803,7 +803,7 @@ public class BackupManager { * has a work profile that was restored from another work profile with serial number * {@code ancestralSerialNumber}. * - * @see UserManager#getSerialNumberForUser(UserHandle) + * @see android.os.UserManager#getSerialNumberForUser(UserHandle) */ @Nullable public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) { diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java index 08b1c2b9f548..ec9c57466310 100644 --- a/core/java/android/app/job/JobScheduler.java +++ b/core/java/android/app/job/JobScheduler.java @@ -41,7 +41,7 @@ import java.util.List; * system will execute this job on your application's {@link android.app.job.JobService}. * You identify the service component that implements the logic for your job when you * construct the JobInfo using - * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}. + * {@link android.app.job.JobInfo.Builder#Builder(int,android.content.ComponentName)}. * </p> * <p> * The framework will be intelligent about when it executes jobs, and attempt to batch @@ -147,7 +147,7 @@ public abstract class JobScheduler { * method is ignored. * * @param jobId unique identifier for the job to be canceled, as supplied to - * {@link JobInfo.Builder#JobInfo.Builder(int, android.content.ComponentName) + * {@link JobInfo.Builder#Builder(int, android.content.ComponentName) * JobInfo.Builder(int, android.content.ComponentName)}. */ public abstract void cancel(int jobId); diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java index 2eb9459af877..4e5443a18bf2 100644 --- a/core/java/android/app/role/RoleManager.java +++ b/core/java/android/app/role/RoleManager.java @@ -102,8 +102,6 @@ public final class RoleManager { /** * The name of the emergency role - * - * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE */ public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY"; diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 9a17346334d1..2888fbd8a363 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -110,8 +110,9 @@ public final class BluetoothLeScanner { * off to save power. Scanning is resumed when screen is turned on again. To avoid this, use * {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}. * <p> - * An app must hold - * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or + * An app must have + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission + * in order to get results. An App targeting Android Q or later must have * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission * in order to get results. * @@ -129,8 +130,9 @@ public final class BluetoothLeScanner { * resumed when screen is turned on again. To avoid this, do filetered scanning by * using proper {@link ScanFilter}. * <p> - * An app must hold - * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or + * An app must have + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission + * in order to get results. An App targeting Android Q or later must have * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission * in order to get results. * @@ -150,8 +152,9 @@ public final class BluetoothLeScanner { * the PendingIntent. Use this method of scanning if your process is not always running and it * should be started when scan results are available. * <p> - * An app must hold - * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or + * An app must have + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission + * in order to get results. An App targeting Android Q or later must have * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission * in order to get results. * <p> diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 3ed585c18e57..6e0ce3ff032a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3519,7 +3519,6 @@ public abstract class Context { * @see android.telephony.CarrierConfigManager * @see #EUICC_SERVICE * @see android.telephony.euicc.EuiccManager - * @see #MMS_SERVICE * @see android.telephony.MmsManager * @see #INPUT_METHOD_SERVICE * @see android.view.inputmethod.InputMethodManager diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index d5dadbff419f..7e8bb08e0086 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -16,8 +16,6 @@ package android.hardware.hdmi; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -31,7 +29,7 @@ import android.annotation.SystemService; import android.content.Context; import android.content.pm.PackageManager; import android.os.RemoteException; -import android.os.SystemProperties; +import android.sysprop.HdmiProperties; import android.util.ArrayMap; import android.util.Log; @@ -316,8 +314,7 @@ public final class HdmiControlManager { mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK); mHasAudioSystemDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mHasSwitchDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH); - mIsSwitchDevice = SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + mIsSwitchDevice = HdmiProperties.is_switch().orElse(false); } private static boolean hasDeviceType(int[] types, int type) { diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 9086d49231bb..275e38c74451 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -437,7 +437,7 @@ public class ConnectivityDiagnosticsManager { */ private long mReportTimestamp; - /** The detection method used to identify the suspected data stall */ + /** A bitmask of the detection methods used to identify the suspected data stall */ @DetectionMethod private final int mDetectionMethod; /** LinkProperties available on the Network at the reported timestamp */ @@ -499,9 +499,9 @@ public class ConnectivityDiagnosticsManager { } /** - * Returns the detection method used to identify this suspected data stall. + * Returns the bitmask of detection methods used to identify this suspected data stall. * - * @return The detection method used to identify the suspected data stall + * @return The bitmask of detection methods used to identify the suspected data stall */ public int getDetectionMethod() { return mDetectionMethod; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ad07e7cf4d5f..6b713602215a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -48,6 +48,7 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -4735,4 +4736,28 @@ public class ConnectivityManager { Log.d(TAG, "StackLog:" + sb.toString()); } } + + /** + * Simulates a Data Stall for the specified Network. + * + * <p>The caller must be the owner of the specified Network. + * + * @param detectionMethod The detection method used to identify the Data Stall. + * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds. + * @param network The Network for which a Data Stall is being simluated. + * @param extras The PersistableBundle of extras included in the Data Stall notification. + * @throws SecurityException if the caller is not the owner of the given network. + * @hide + */ + @TestApi + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_STACK}) + public void simulateDataStall(int detectionMethod, long timestampMillis, + @NonNull Network network, @NonNull PersistableBundle extras) { + try { + mService.simulateDataStall(detectionMethod, timestampMillis, network, extras); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index b0f79bcc0b23..d7f178cd0a9b 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.app.PendingIntent; import android.net.ConnectionInfo; +import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; import android.net.LinkProperties; import android.net.Network; @@ -33,6 +34,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Messenger; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.ResultReceiver; import com.android.internal.net.LegacyVpnInfo; @@ -228,4 +230,7 @@ interface IConnectivityManager void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); IBinder startOrGetTestNetworkService(); + + void simulateDataStall(int detectionMethod, long timestampMillis, in Network network, + in PersistableBundle extras); } diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java index 81d03f07d0be..407ff04dc4a3 100644 --- a/core/java/android/net/Ikev2VpnProfile.java +++ b/core/java/android/net/Ikev2VpnProfile.java @@ -70,6 +70,15 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private static final String MISSING_PARAM_MSG_TMPL = "Required parameter was not provided: %s"; private static final String EMPTY_CERT = ""; + /** @hide */ + public static final List<String> DEFAULT_ALGORITHMS = + Collections.unmodifiableList(Arrays.asList( + IpSecAlgorithm.CRYPT_AES_CBC, + IpSecAlgorithm.AUTH_HMAC_SHA256, + IpSecAlgorithm.AUTH_HMAC_SHA384, + IpSecAlgorithm.AUTH_HMAC_SHA512, + IpSecAlgorithm.AUTH_CRYPT_AES_GCM)); + @NonNull private final String mServerAddr; @NonNull private final String mUserIdentity; @@ -92,6 +101,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private final boolean mIsBypassable; // Defaults in builder private final boolean mIsMetered; // Defaults in builder private final int mMaxMtu; // Defaults in builder + private final boolean mIsRestrictedToTestNetworks; private Ikev2VpnProfile( int type, @@ -107,7 +117,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @NonNull List<String> allowedAlgorithms, boolean isBypassable, boolean isMetered, - int maxMtu) { + int maxMtu, + boolean restrictToTestNetworks) { super(type); checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address"); @@ -131,6 +142,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mIsBypassable = isBypassable; mIsMetered = isMetered; mMaxMtu = maxMtu; + mIsRestrictedToTestNetworks = restrictToTestNetworks; validate(); } @@ -172,7 +184,56 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { throw new IllegalArgumentException("Invalid auth method set"); } - VpnProfile.validateAllowedAlgorithms(mAllowedAlgorithms); + validateAllowedAlgorithms(mAllowedAlgorithms); + } + + /** + * Validates that the allowed algorithms are a valid set for IPsec purposes + * + * <p>In order for the algorithm list to be a valid set, it must contain at least one algorithm + * that provides Authentication, and one that provides Encryption. Authenticated Encryption with + * Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption. + * + * @param allowedAlgorithms The list to be validated + */ + private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) { + VpnProfile.validateAllowedAlgorithms(algorithmNames); + + // First, make sure no insecure algorithms were proposed. + if (algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_MD5) + || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA1)) { + throw new IllegalArgumentException("Algorithm not supported for IKEv2 VPN profiles"); + } + + // Validate that some valid combination (AEAD or AUTH + CRYPT) is present + if (hasAeadAlgorithms(algorithmNames) || hasNormalModeAlgorithms(algorithmNames)) { + return; + } + + throw new IllegalArgumentException("Algorithm set missing support for Auth, Crypt or both"); + } + + /** + * Checks if the provided list has AEAD algorithms + * + * @hide + */ + public static boolean hasAeadAlgorithms(@NonNull List<String> algorithmNames) { + return algorithmNames.contains(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); + } + + /** + * Checks the provided list has acceptable (non-AEAD) authentication and encryption algorithms + * + * @hide + */ + public static boolean hasNormalModeAlgorithms(@NonNull List<String> algorithmNames) { + final boolean hasCrypt = algorithmNames.contains(IpSecAlgorithm.CRYPT_AES_CBC); + final boolean hasAuth = algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA256) + || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA384) + || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA512); + + return hasCrypt && hasAuth; } /** Retrieves the server address string. */ @@ -271,6 +332,15 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return mMaxMtu; } + /** + * Returns whether or not this VPN profile is restricted to test networks. + * + * @hide + */ + public boolean isRestrictedToTestNetworks() { + return mIsRestrictedToTestNetworks; + } + @Override public int hashCode() { return Objects.hash( @@ -287,7 +357,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, - mMaxMtu); + mMaxMtu, + mIsRestrictedToTestNetworks); } @Override @@ -310,7 +381,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms) && mIsBypassable == other.mIsBypassable && mIsMetered == other.mIsMetered - && mMaxMtu == other.mMaxMtu; + && mMaxMtu == other.mMaxMtu + && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks; } /** @@ -323,7 +395,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { */ @NonNull public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException { - final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */); + final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */, + mIsRestrictedToTestNetworks); profile.type = mType; profile.server = mServerAddr; profile.ipsecIdentifier = mUserIdentity; @@ -391,6 +464,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { builder.setBypassable(profile.isBypassable); builder.setMetered(profile.isMetered); builder.setMaxMtu(profile.maxMtu); + if (profile.isRestrictedToTestNetworks) { + builder.restrictToTestNetworks(); + } switch (profile.type) { case TYPE_IKEV2_IPSEC_USER_PASS: @@ -559,10 +635,11 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable private X509Certificate mUserCert; @Nullable private ProxyInfo mProxyInfo; - @NonNull private List<String> mAllowedAlgorithms = new ArrayList<>(); + @NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS; private boolean mIsBypassable = false; private boolean mIsMetered = true; private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; + private boolean mIsRestrictedToTestNetworks = false; /** * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. @@ -745,7 +822,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { * @param isMetered {@code true} if the VPN network should be treated as metered regardless * of underlying network meteredness. Defaults to {@code true}. * @return this {@link Builder} object to facilitate chaining of method calls - * @see NetworkCapabilities.NET_CAPABILITY_NOT_METERED + * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED */ @NonNull public Builder setMetered(boolean isMetered) { @@ -756,7 +833,19 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { /** * Sets the allowable set of IPsec algorithms * - * <p>A list of allowed IPsec algorithms as defined in {@link IpSecAlgorithm} + * <p>If set, this will constrain the set of algorithms that the IPsec tunnel will use for + * integrity verification and encryption to the provided list. + * + * <p>The set of allowed IPsec algorithms is defined in {@link IpSecAlgorithm}. Adding of + * algorithms that are considered insecure (such as AUTH_HMAC_MD5 and AUTH_HMAC_SHA1) is not + * permitted, and will result in an IllegalArgumentException being thrown. + * + * <p>The provided algorithm list must contain at least one algorithm that provides + * Authentication, and one that provides Encryption. Authenticated Encryption with + * Associated Data (AEAD) algorithms provide both Authentication and Encryption. + * + * <p>By default, this profile will use any algorithm defined in {@link IpSecAlgorithm}, + * with the exception of those considered insecure (as described above). * * @param algorithmNames the list of supported IPsec algorithms * @return this {@link Builder} object to facilitate chaining of method calls @@ -765,13 +854,28 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @NonNull public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) { checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames"); - VpnProfile.validateAllowedAlgorithms(algorithmNames); + validateAllowedAlgorithms(algorithmNames); mAllowedAlgorithms = algorithmNames; return this; } /** + * Restricts this profile to use test networks (only). + * + * <p>This method is for testing only, and must not be used by apps. Calling + * provisionVpnProfile() with a profile where test-network usage is enabled will require the + * MANAGE_TEST_NETWORKS permission. + * + * @hide + */ + @NonNull + public Builder restrictToTestNetworks() { + mIsRestrictedToTestNetworks = true; + return this; + } + + /** * Validates, builds and provisions the VpnProfile. * * @throws IllegalArgumentException if any of the required keys or values were invalid @@ -792,7 +896,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, - mMaxMtu); + mMaxMtu, + mIsRestrictedToTestNetworks); } } } diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java index 68a39355198b..70c4a7235b9d 100644 --- a/core/java/android/net/MatchAllNetworkSpecifier.java +++ b/core/java/android/net/MatchAllNetworkSpecifier.java @@ -43,7 +43,8 @@ public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements } /** @hide */ - public boolean satisfiedBy(NetworkSpecifier other) { + @Override + public boolean canBeSatisfiedBy(NetworkSpecifier other) { /* * The method is called by a NetworkRequest to see if it is satisfied by a proposed * network (e.g. as offered by a network factory). Since MatchAllNetweorkSpecifier must diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index fea3245784b2..57d5d03a6cf2 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -169,6 +169,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_OEM_PAID, NET_CAPABILITY_MCX, NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, }) public @interface NetCapability { } @@ -336,8 +337,16 @@ public final class NetworkCapabilities implements Parcelable { @SystemApi public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; + /** + * This capability will be set for networks that are generally metered, but are currently + * unmetered, e.g., because the user is in a particular area. This capability can be changed at + * any time. When it is removed, applications are responsible for stopping any data transfer + * that should not occur on a metered network. + */ + public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -353,7 +362,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_NOT_CONGESTED) | (1 << NET_CAPABILITY_NOT_SUSPENDED) - | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED)); /** * Network capabilities that are not allowed in NetworkRequests. This exists because the @@ -424,6 +434,7 @@ public final class NetworkCapabilities implements Parcelable { */ private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) | (1 << NET_CAPABILITY_NOT_RESTRICTED) | (1 << NET_CAPABILITY_NOT_VPN) | (1 << NET_CAPABILITY_NOT_ROAMING) @@ -666,16 +677,27 @@ public final class NetworkCapabilities implements Parcelable { * restrictions. * @hide */ - public void restrictCapabilitesForTestNetwork() { + public void restrictCapabilitesForTestNetwork(int creatorUid) { final long originalCapabilities = mNetworkCapabilities; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; final int originalSignalStrength = mSignalStrength; + final int originalOwnerUid = getOwnerUid(); + final int[] originalAdministratorUids = getAdministratorUids(); clearAll(); // Reset the transports to only contain TRANSPORT_TEST. mTransportTypes = (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; + + // Only retain the owner and administrator UIDs if they match the app registering the remote + // caller that registered the network. + if (originalOwnerUid == creatorUid) { + setOwnerUid(creatorUid); + } + if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { + setAdministratorUids(new int[] {creatorUid}); + } } /** @@ -1866,6 +1888,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; case NET_CAPABILITY_MCX: return "MCX"; case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; + case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; default: return Integer.toString(capability); } } diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index c233ec0e52cf..6539e0563794 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; @@ -468,11 +469,13 @@ public class NetworkScoreManager { * * @param networks List of {@link ScoredNetwork} containing updated scores. */ + @SuppressLint("CallbackMethodName") void updateScores(@NonNull List<ScoredNetwork> networks); /** * Invokes when all the previously provided scores are no longer valid. */ + @SuppressLint("CallbackMethodName") void clearScores(); } diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 63e510733907..9c2c5b839302 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -836,7 +836,7 @@ public class VpnService extends Service { * @param isMetered {@code true} if VPN network should be treated as metered regardless of * underlying network meteredness * @return this {@link Builder} object to facilitate chaining method calls - * @see #setUnderlyingNetworks(Networks[]) + * @see #setUnderlyingNetworks(Network[]) * @see ConnectivityManager#isActiveNetworkMetered() */ @NonNull diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index eb67492483f1..0f53d4f84920 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -106,6 +106,12 @@ public class Build { public static final String HARDWARE = getString("ro.hardware"); /** + * The hardware variant (SKU), if available. + */ + @NonNull + public static final String SKU = getString("ro.boot.product.hardware.sku"); + + /** * Whether this build was for an emulator device. * @hide */ diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 6632ca51e74c..9b360edb7238 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -118,7 +118,21 @@ public interface Parcelable { * by this Parcelable object instance. */ public @ContentsFlags int describeContents(); - + + /** + * 'Stable' means this parcelable is guaranteed to be stable for multiple years. + * It must be guaranteed by setting stability field in aidl_interface, + * OR explicitly override this method from @JavaOnlyStableParcelable marked Parcelable. + * WARNING: isStable() is only expected to be overridden by auto-generated code, + * OR @JavaOnlyStableParcelable marked Parcelable only if there is guaranteed to + * be only once copy of the parcelable on the system. + * @return true if this parcelable is stable. + * @hide + */ + default boolean isStable() { + return false; + } + /** * Flatten this object in to a Parcel. * diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java index d6afd049f156..bde7ec14f37a 100644 --- a/core/java/android/os/Registrant.java +++ b/core/java/android/os/Registrant.java @@ -46,7 +46,7 @@ public class Registrant { internalNotifyRegistrant (null, null); } - + @UnsupportedAppUsage public void notifyResult(Object result) @@ -81,9 +81,7 @@ public class Registrant Message msg = Message.obtain(); msg.what = what; - msg.obj = new AsyncResult(userObj, result, exception); - h.sendMessage(msg); } } @@ -126,4 +124,3 @@ public class Registrant int what; Object userObj; } - diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java index 98f949bbfd84..b36734bcd199 100644 --- a/core/java/android/os/RegistrantList.java +++ b/core/java/android/os/RegistrantList.java @@ -42,9 +42,9 @@ public class RegistrantList { // if the handler is already in the registrant list, remove it remove(h); - add(new Registrant(h, what, obj)); + add(new Registrant(h, what, obj)); } - + @UnsupportedAppUsage public synchronized void add(Registrant r) @@ -59,13 +59,17 @@ public class RegistrantList { for (int i = registrants.size() - 1; i >= 0 ; i--) { Registrant r = (Registrant) registrants.get(i); - + if (r.refH == null) { registrants.remove(i); } } } + public synchronized void removeAll() { + registrants.clear(); + } + @UnsupportedAppUsage public synchronized int size() @@ -88,7 +92,7 @@ public class RegistrantList r.internalNotifyRegistrant(result, exception); } } - + @UnsupportedAppUsage public /*synchronized*/ void notifyRegistrants() @@ -109,14 +113,14 @@ public class RegistrantList internalNotifyRegistrants (result, null); } - + @UnsupportedAppUsage public /*synchronized*/ void notifyRegistrants(AsyncResult ar) { internalNotifyRegistrants(ar.result, ar.exception); } - + @UnsupportedAppUsage public synchronized void remove(Handler h) diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 3faaff73a0ea..81457074f2fc 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1015,7 +1015,6 @@ public final class StrictMode { * behaviors or empty states. Instead, apps should store data needed * while a user is locked under device protected storage areas. * - * @see Context#createCredentialProtectedStorageContext() * @see Context#createDeviceProtectedStorageContext() */ public @NonNull Builder detectCredentialProtectedWhileLocked() { diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java index de274c082c80..e907e2204b7b 100644 --- a/core/java/android/os/UpdateEngine.java +++ b/core/java/android/os/UpdateEngine.java @@ -614,9 +614,6 @@ public class UpdateEngine { * encountered. Device is corrupted, and future updates must not be applied. * The device cannot recover without flashing and factory resets. * </ul> - * - * @throws ServiceSpecificException if other transient errors has occurred. - * A reboot may or may not help resolving the issue. */ @WorkerThread @ErrorCode diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 75b4724c7d26..890057371471 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -55,21 +55,16 @@ public abstract class VibrationEffect implements Parcelable { /** * A click effect. Use this effect as a baseline, as it's the most common type of click effect. - * - * @see #get(int) */ public static final int EFFECT_CLICK = Effect.CLICK; /** * A double click effect. - * - * @see #get(int) */ public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK; /** * A tick effect. This effect is less strong compared to {@link #EFFECT_CLICK}. - * @see #get(int) */ public static final int EFFECT_TICK = Effect.TICK; @@ -93,7 +88,6 @@ public abstract class VibrationEffect implements Parcelable { /** * A heavy click effect. This effect is stronger than {@link #EFFECT_CLICK}. - * @see #get(int) */ public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK; diff --git a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java index 12503f650ab5..89cd43003529 100644 --- a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java +++ b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java @@ -28,7 +28,6 @@ import android.content.Context; * store data needed while a user is locked under device protected storage * areas. * - * @see Context#createCredentialProtectedStorageContext() * @see Context#createDeviceProtectedStorageContext() */ public final class CredentialProtectedWhileLockedViolation extends Violation { diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 9c6c92ace483..17fae1cafe62 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -797,7 +797,6 @@ public final class CalendarContract { * to changes. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = @@ -1796,7 +1795,6 @@ public final class CalendarContract { * to changes. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = @@ -2010,7 +2008,6 @@ public final class CalendarContract { * {@link DevicePolicyManager#setCrossProfileCalendarPackages(ComponentName, Set)}. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index c837b9346173..5e1b22399d57 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -110,6 +110,14 @@ public final class DeviceConfig { public static final String NAMESPACE_AUTOFILL = "autofill"; /** + * Namespace for all Bluetooth related features. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_BLUETOOTH = "bluetooth"; + + /** * Namespace for all networking connectivity related features. * * @hide diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 4bbd213753c2..3980a5f75eda 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; -import android.content.ContentInterface; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -248,14 +247,14 @@ public final class DocumentsContract { * Get string array identifies the type or types of metadata returned * using DocumentsContract#getDocumentMetadata. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TYPES = "android:documentMetadataTypes"; /** * Get Exif information using DocumentsContract#getDocumentMetadata. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_EXIF = "android:documentExif"; @@ -263,7 +262,7 @@ public final class DocumentsContract { * Get total count of all documents currently stored under the given * directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TREE_COUNT = "android:metadataTreeCount"; @@ -271,7 +270,7 @@ public final class DocumentsContract { * Get total size of all documents currently stored under the given * directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TREE_SIZE = "android:metadataTreeSize"; @@ -395,7 +394,7 @@ public final class DocumentsContract { * Flag indicating that a document can be represented as a thumbnail. * * @see #COLUMN_FLAGS - * @see DocumentsContract#getDocumentThumbnail(ContentInterface, Uri, + * @see DocumentsContract#getDocumentThumbnail(ContentResolver, Uri, * Point, CancellationSignal) * @see DocumentsProvider#openDocumentThumbnail(String, Point, * android.os.CancellationSignal) @@ -421,7 +420,7 @@ public final class DocumentsContract { * Flag indicating that a document is deletable. * * @see #COLUMN_FLAGS - * @see DocumentsContract#deleteDocument(ContentInterface, Uri) + * @see DocumentsContract#deleteDocument(ContentResolver, Uri) * @see DocumentsProvider#deleteDocument(String) */ public static final int FLAG_SUPPORTS_DELETE = 1 << 2; @@ -459,7 +458,7 @@ public final class DocumentsContract { * Flag indicating that a document can be renamed. * * @see #COLUMN_FLAGS - * @see DocumentsContract#renameDocument(ContentInterface, Uri, String) + * @see DocumentsContract#renameDocument(ContentResolver, Uri, String) * @see DocumentsProvider#renameDocument(String, String) */ public static final int FLAG_SUPPORTS_RENAME = 1 << 6; @@ -469,7 +468,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#copyDocument(ContentInterface, Uri, Uri) + * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#copyDocument(String, String) */ public static final int FLAG_SUPPORTS_COPY = 1 << 7; @@ -479,7 +478,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#moveDocument(ContentInterface, Uri, Uri, Uri) + * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri) * @see DocumentsProvider#moveDocument(String, String, String) */ public static final int FLAG_SUPPORTS_MOVE = 1 << 8; @@ -503,7 +502,7 @@ public final class DocumentsContract { * Flag indicating that a document can be removed from a parent. * * @see #COLUMN_FLAGS - * @see DocumentsContract#removeDocument(ContentInterface, Uri, Uri) + * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#removeDocument(String, String) */ public static final int FLAG_SUPPORTS_REMOVE = 1 << 10; @@ -539,7 +538,7 @@ public final class DocumentsContract { * using DocumentsContract#getDocumentMetadata * * @see #COLUMN_FLAGS - * @see DocumentsContract#getDocumentMetadata(ContentInterface, Uri) + * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri) */ public static final int FLAG_SUPPORTS_METADATA = 1 << 14; } @@ -721,7 +720,7 @@ public final class DocumentsContract { * Flag indicating that this root can be ejected. * * @see #COLUMN_FLAGS - * @see DocumentsContract#ejectRoot(ContentInterface, Uri) + * @see DocumentsContract#ejectRoot(ContentResolver, Uri) * @see DocumentsProvider#ejectRoot(String) */ public static final int FLAG_SUPPORTS_EJECT = 1 << 5; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7923b586ada5..cadae5cecc6d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12061,17 +12061,6 @@ public final class Settings { public static final String ALWAYS_ON_DISPLAY_CONSTANTS = "always_on_display_constants"; /** - * System VDSO global setting. This links to the "sys.vdso" system property. - * The following values are supported: - * false -> both 32 and 64 bit vdso disabled - * 32 -> 32 bit vdso enabled - * 64 -> 64 bit vdso enabled - * Any other value defaults to both 32 bit and 64 bit true. - * @hide - */ - public static final String SYS_VDSO = "sys_vdso"; - - /** * UidCpuPower global setting. This links the sys.uidcpupower system property. * The following values are supported: * 0 -> /proc/uid_cpupower/* are disabled diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java index c28d2bbe30ea..e274460cdf03 100644 --- a/core/java/android/service/autofill/CustomDescription.java +++ b/core/java/android/service/autofill/CustomDescription.java @@ -262,7 +262,7 @@ public final class CustomDescription implements Parcelable { * * @param condition condition used to trigger the updates. * @param updates actions to be applied to the - * {@link #CustomDescription.Builder(RemoteViews) template presentation} when the condition + * {@link #Builder(RemoteViews) template presentation} when the condition * is satisfied. * * @return this builder diff --git a/core/java/android/service/autofill/ImageTransformation.java b/core/java/android/service/autofill/ImageTransformation.java index 12376e85e63e..974f0ead9d19 100644 --- a/core/java/android/service/autofill/ImageTransformation.java +++ b/core/java/android/service/autofill/ImageTransformation.java @@ -123,7 +123,7 @@ public final class ImageTransformation extends InternalTransformation implements * {@link RemoteViews presentation} must contain a {@link ImageView} child with that id. * * @deprecated use - * {@link #ImageTransformation.Builder(AutofillId, Pattern, int, CharSequence)} instead. + * {@link #Builder(AutofillId, Pattern, int, CharSequence)} instead. */ @Deprecated public Builder(@NonNull AutofillId id, @NonNull Pattern regex, @DrawableRes int resId) { diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index 94b9d050a44d..3a70befb3558 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -628,7 +628,7 @@ public final class SaveInfo implements Parcelable { * * <p>The sanitizer can also be used as an alternative for a * {@link #setValidator(Validator) validator}. If any of the {@code ids} is a - * {@link #SaveInfo.Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails + * {@link #Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails * because of it, then the save UI is not shown. * * @param sanitizer an implementation provided by the Android System. @@ -686,7 +686,7 @@ public final class SaveInfo implements Parcelable { * Builds a new {@link SaveInfo} instance. * * @throws IllegalStateException if no - * {@link #SaveInfo.Builder(int, AutofillId[]) required ids}, + * {@link #Builder(int, AutofillId[]) required ids}, * or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE} * were set */ diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index b92731e6d6d4..d64077525905 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -379,8 +379,6 @@ public class PhoneStateListener { * * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). - * - * @see #onEmergencyNumberListChanged */ public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000; @@ -459,7 +457,7 @@ public class PhoneStateListener { * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @see #onRegistrationFailed() + * @see #onRegistrationFailed */ @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000; @@ -470,7 +468,7 @@ public class PhoneStateListener { * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @see #onBarringInfoChanged() + * @see #onBarringInfoChanged */ @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_BARRING_INFO = 0x80000000; @@ -764,7 +762,8 @@ public class PhoneStateListener { * */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) - public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) { + public void onCallDisconnectCauseChanged(@Annotation.DisconnectCauses int disconnectCause, + int preciseDisconnectCause) { // default implementation empty } diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index 248e321df467..8e8409d15143 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -21,7 +21,6 @@ import android.util.TimeFormatException; import libcore.timezone.ZoneInfoDb; import libcore.util.ZoneInfo; -import java.io.IOException; import java.util.Locale; import java.util.TimeZone; @@ -1106,19 +1105,14 @@ public class Time { } private static ZoneInfo lookupZoneInfo(String timezoneId) { - try { - ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId); - if (zoneInfo == null) { - zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT"); - } - if (zoneInfo == null) { - throw new AssertionError("GMT not found: \"" + timezoneId + "\""); - } - return zoneInfo; - } catch (IOException e) { - // This should not ever be thrown. - throw new AssertionError("Error loading timezone: \"" + timezoneId + "\"", e); + ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId); + if (zoneInfo == null) { + zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT"); + } + if (zoneInfo == null) { + throw new AssertionError("GMT not found: \"" + timezoneId + "\""); } + return zoneInfo; } public void switchTimeZone(String timezone) { diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 3a6c8dd3720f..489307beb878 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -189,12 +189,12 @@ public class Surface implements Parcelable { } /** - * Create a Surface assosciated with a given {@link SurfaceControl}. Buffers submitted to this + * Create a Surface associated with a given {@link SurfaceControl}. Buffers submitted to this * surface will be displayed by the system compositor according to the parameters * specified by the control. Multiple surfaces may be constructed from one SurfaceControl, * but only one can be connected (e.g. have an active EGL context) at a time. * - * @param from The SurfaceControl to assosciate this Surface with + * @param from The SurfaceControl to associate this Surface with */ public Surface(@NonNull SurfaceControl from) { copyFrom(from); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index fcd8127bbaa4..4f7bedaf1117 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -2259,7 +2259,7 @@ public final class SurfaceControl implements Parcelable { } /** - * Specify how the buffer assosciated with this Surface is mapped in to the + * Specify how the buffer associated with this Surface is mapped in to the * parent coordinate space. The source frame will be scaled to fit the destination * frame, after being rotated according to the orientation parameter. * diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fe60bba92739..40dfcfc391a0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -25801,9 +25801,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Returns the View object that had been passed to the - * {@link #View.DragShadowBuilder(View)} + * {@link #DragShadowBuilder(View)} * constructor. If that View parameter was {@code null} or if the - * {@link #View.DragShadowBuilder()} + * {@link #DragShadowBuilder()} * constructor was used to instantiate the builder object, this method will return * null. * diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index d9d92788a434..859b137dc2ce 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -614,7 +614,6 @@ public interface WindowManager extends ViewManager { * @see #TYPE_TOAST * @see #TYPE_SYSTEM_OVERLAY * @see #TYPE_PRIORITY_PHONE - * @see #TYPE_STATUS_BAR_PANEL * @see #TYPE_SYSTEM_DIALOG * @see #TYPE_KEYGUARD_DIALOG * @see #TYPE_SYSTEM_ERROR diff --git a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java index 42a892dedf4d..903fc13a03ea 100644 --- a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java +++ b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; /** * An inspection companion provider that finds companions as inner classes or generated code. - * - * @see android.processor.view.inspector.PlatformInspectableProcessor */ public class StaticInspectionCompanionProvider implements InspectionCompanionProvider { /** diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 9cbb03508d67..f44f24a4d492 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -16,6 +16,8 @@ package android.widget; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.InterpolatorRes; import android.annotation.NonNull; @@ -246,6 +248,8 @@ public class ProgressBar extends View { private AccessibilityEventSender mAccessibilityEventSender; + private ObjectAnimator mLastProgressAnimator; + /** * Create a new progress bar with range 0...100 and initial progress of 0. * @param context the application environment @@ -1544,8 +1548,19 @@ public class ProgressBar extends View { animator.setAutoCancel(true); animator.setDuration(PROGRESS_ANIM_DURATION); animator.setInterpolator(PROGRESS_ANIM_INTERPOLATOR); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLastProgressAnimator = null; + } + }); animator.start(); + mLastProgressAnimator = animator; } else { + if (isPrimary && mLastProgressAnimator != null) { + mLastProgressAnimator.cancel(); + mLastProgressAnimator = null; + } setVisualProgress(id, scale); } diff --git a/core/java/com/android/internal/accessibility/OWNERS b/core/java/com/android/internal/accessibility/OWNERS new file mode 100644 index 000000000000..b3c09e9d539a --- /dev/null +++ b/core/java/com/android/internal/accessibility/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 44214 +svetoslavganov@google.com +pweaver@google.com +qasid@google.com diff --git a/core/java/com/android/internal/app/SystemUserHomeActivity.java b/core/java/com/android/internal/app/SystemUserHomeActivity.java index 26fbf6f826a8..ee936a3f9abc 100644 --- a/core/java/com/android/internal/app/SystemUserHomeActivity.java +++ b/core/java/com/android/internal/app/SystemUserHomeActivity.java @@ -17,10 +17,27 @@ package com.android.internal.app; import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +import com.android.internal.R; /** * Placeholder home activity, which is always installed on the system user. At least one home * activity must be present and enabled in order for the system to boot. */ public class SystemUserHomeActivity extends Activity { + private static final String TAG = "SystemUserHome"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.i(TAG, "onCreate"); + setContentView(R.layout.system_user_home); + } + + protected void onDestroy() { + super.onDestroy(); + Log.i(TAG, "onDestroy"); + } } diff --git a/core/java/com/android/internal/compat/OWNERS b/core/java/com/android/internal/compat/OWNERS index 2b7cdb0cbce9..cfd0a4b079ad 100644 --- a/core/java/com/android/internal/compat/OWNERS +++ b/core/java/com/android/internal/compat/OWNERS @@ -2,6 +2,5 @@ platform-compat-eng+reviews@google.com andreionea@google.com -atrost@google.com mathewi@google.com satayev@google.com diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java index 829bd8a5a2a7..8ea5aa815a1c 100644 --- a/core/java/com/android/internal/net/VpnProfile.java +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -136,13 +136,19 @@ public final class VpnProfile implements Cloneable, Parcelable { public boolean isMetered = false; // 21 public int maxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; // 22 public boolean areAuthParamsInline = false; // 23 + public final boolean isRestrictedToTestNetworks; // 24 // Helper fields. @UnsupportedAppUsage public transient boolean saveLogin = false; public VpnProfile(String key) { + this(key, false); + } + + public VpnProfile(String key, boolean isRestrictedToTestNetworks) { this.key = key; + this.isRestrictedToTestNetworks = isRestrictedToTestNetworks; } @UnsupportedAppUsage @@ -171,6 +177,7 @@ public final class VpnProfile implements Cloneable, Parcelable { isMetered = in.readBoolean(); maxMtu = in.readInt(); areAuthParamsInline = in.readBoolean(); + isRestrictedToTestNetworks = in.readBoolean(); } /** @@ -220,6 +227,7 @@ public final class VpnProfile implements Cloneable, Parcelable { out.writeBoolean(isMetered); out.writeInt(maxMtu); out.writeBoolean(areAuthParamsInline); + out.writeBoolean(isRestrictedToTestNetworks); } /** @@ -237,12 +245,21 @@ public final class VpnProfile implements Cloneable, Parcelable { String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1); // Acceptable numbers of values are: // 14-19: Standard profile, with option for serverCert, proxy - // 24: Standard profile with serverCert, proxy and platform-VPN parameters. - if ((values.length < 14 || values.length > 19) && values.length != 24) { + // 24: Standard profile with serverCert, proxy and platform-VPN parameters + // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks + if ((values.length < 14 || values.length > 19) + && values.length != 24 && values.length != 25) { return null; } - VpnProfile profile = new VpnProfile(key); + final boolean isRestrictedToTestNetworks; + if (values.length >= 25) { + isRestrictedToTestNetworks = Boolean.parseBoolean(values[24]); + } else { + isRestrictedToTestNetworks = false; + } + + VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks); profile.name = values[0]; profile.type = Integer.parseInt(values[1]); if (profile.type < 0 || profile.type > TYPE_MAX) { @@ -283,6 +300,8 @@ public final class VpnProfile implements Cloneable, Parcelable { profile.areAuthParamsInline = Boolean.parseBoolean(values[23]); } + // isRestrictedToTestNetworks (values[24]) assigned as part of the constructor + profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty(); return profile; } catch (Exception e) { @@ -330,6 +349,7 @@ public final class VpnProfile implements Cloneable, Parcelable { builder.append(VALUE_DELIMITER).append(isMetered); builder.append(VALUE_DELIMITER).append(maxMtu); builder.append(VALUE_DELIMITER).append(areAuthParamsInline); + builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks); return builder.toString().getBytes(StandardCharsets.UTF_8); } @@ -421,7 +441,8 @@ public final class VpnProfile implements Cloneable, Parcelable { return Objects.hash( key, type, server, username, password, dnsServers, searchDomains, routes, mppe, l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert, - proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline); + proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline, + isRestrictedToTestNetworks); } /** Checks VPN profiles for interior equality. */ @@ -453,7 +474,8 @@ public final class VpnProfile implements Cloneable, Parcelable { && isBypassable == other.isBypassable && isMetered == other.isMetered && maxMtu == other.maxMtu - && areAuthParamsInline == other.areAuthParamsInline; + && areAuthParamsInline == other.areAuthParamsInline + && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks; } @NonNull diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java index 8182d60ef459..8b659f927633 100644 --- a/core/java/com/android/internal/os/RoSystemProperties.java +++ b/core/java/com/android/internal/os/RoSystemProperties.java @@ -18,6 +18,7 @@ package com.android.internal.os; import android.os.SystemProperties; import android.sysprop.CryptoProperties; +import android.sysprop.HdmiProperties; /** * This is a cache of various ro.* properties so that they can be read just once @@ -37,16 +38,7 @@ public class RoSystemProperties { * mode is off. */ public static final boolean CEC_AUDIO_DEVICE_FORWARD_VOLUME_KEYS_SYSTEM_AUDIO_MODE_OFF = - SystemProperties.getBoolean( - "ro.hdmi.cec_audio_device_forward_volume_keys_system_audio_mode_off", false); - - /** - * Property to indicate if the current device is a cec switch device. - * - * <p> Default is false. - */ - public static final String PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH = - "ro.hdmi.property_is_device_hdmi_cec_switch"; + HdmiProperties.forward_volume_keys_when_system_audio_mode_off().orElse(false); // ------ ro.config.* -------- // public static final boolean CONFIG_AVOID_GFX_ACCEL = diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index b30fed674309..544340eaba89 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -693,6 +693,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX]; char extraOptsBuf[PROPERTY_VALUE_MAX]; char voldDecryptBuf[PROPERTY_VALUE_MAX]; + char perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX]; enum { kEMDefault, kEMIntPortable, @@ -807,6 +808,16 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p addOption("-verbose:gc"); //addOption("-verbose:class"); + // On Android, we always want to allow loading the PerfettoHprof plugin. + // Even with this option set, we will still only actually load the plugin + // if we are on a userdebug build or the app is debuggable or profileable. + // This is enforced in art/runtime/runtime.cc. + // + // We want to be able to disable this, because this does not work on host, + // and we do not want to enable it in tests. + parseRuntimeOption("dalvik.vm.perfetto_hprof", perfettoHprofOptBuf, "-XX:PerfettoHprof=", + "true"); + if (primary_zygote) { addOption("-Xprimaryzygote"); } diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp index 10c30260d7e3..913952f9e76c 100644 --- a/core/jni/android/graphics/pdf/PdfEditor.cpp +++ b/core/jni/android/graphics/pdf/PdfEditor.cpp @@ -111,7 +111,7 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); - FPDF_PAGE* page = (FPDF_PAGE*) FPDF_LoadPage(document, pageIndex); + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); if (!page) { jniThrowException(env, "java/lang/IllegalStateException", "cannot open page"); diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index d723ecc13dd0..eb8d26e7bf71 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -475,7 +475,11 @@ static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, j if (fd < 0) return NULL; fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); if (fd < 0) return NULL; - return jniCreateFileDescriptor(env, fd); + jobject jifd = jniCreateFileDescriptor(env, fd); + if (jifd == NULL) { + close(fd); + } + return jifd; } return NULL; } diff --git a/core/jni/android_os_SharedMemory.cpp b/core/jni/android_os_SharedMemory.cpp index c33405def25e..a812c35036f3 100644 --- a/core/jni/android_os_SharedMemory.cpp +++ b/core/jni/android_os_SharedMemory.cpp @@ -69,7 +69,11 @@ jobject SharedMemory_nCreate(JNIEnv* env, jobject, jstring jname, jint size) { return nullptr; } - return jniCreateFileDescriptor(env, fd); + jobject jifd = jniCreateFileDescriptor(env, fd); + if (jifd == nullptr) { + close(fd); + } + return jifd; } jint SharedMemory_nGetSize(JNIEnv* env, jobject, jobject fileDescriptor) { diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index ca4735ec665a..8fc1758c44dc 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -35,6 +35,7 @@ static const char* kPathWhitelist[] = { "/apex/com.android.conscrypt/javalib/conscrypt.jar", "/apex/com.android.ipsec/javalib/ike.jar", + "/apex/com.android.i18n/javalib/core-icu4j.jar", "/apex/com.android.media/javalib/updatable-media.jar", "/apex/com.android.sdkext/javalib/framework-sdkextensions.jar", "/apex/com.android.tethering/javalib/framework-tethering.jar", @@ -81,11 +82,18 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { } // Framework jars are allowed. - static const char* kFrameworksPrefix = "/system/framework/"; + static const char* kFrameworksPrefix[] = { + "/system/framework/", + "/system_ext/framework/", + }; + static const char* kJarSuffix = ".jar"; - if (android::base::StartsWith(path, kFrameworksPrefix) - && android::base::EndsWith(path, kJarSuffix)) { - return true; + + for (const auto& frameworks_prefix : kFrameworksPrefix) { + if (android::base::StartsWith(path, frameworks_prefix) + && android::base::EndsWith(path, kJarSuffix)) { + return true; + } } // Jars from the ART APEX are allowed. diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 3d99b726e6fe..829e1f7d0d96 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -905,13 +905,8 @@ message GlobalSettingsProto { optional SettingProto storage_full_threshold_bytes = 4 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto storage_cache_percentage = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto storage_cache_max_bytes = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; - // System VDSO global setting. This links to the "sys.vdso" system property. - // The following values are supported: - // false -> both 32 and 64 bit vdso disabled - // 32 -> 32 bit vdso enabled - // 64 -> 64 bit vdso enabled - // Any other value defaults to both 32 bit and 64 bit true. - optional SettingProto vdso = 7 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Used to be sys_vdso + reserved 7; // UidCpuPower global setting. This links the sys.uidcpupower system property. // The following values are supported: // 0 -> /proc/uid_cpupower/* are disabled diff --git a/packages/Shell/res/layout/null_home_finishing_boot.xml b/core/res/res/layout/system_user_home.xml index 5f9563a5d25c..8afa42338e36 100644 --- a/packages/Shell/res/layout/null_home_finishing_boot.xml +++ b/core/res/res/layout/system_user_home.xml @@ -30,9 +30,9 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="40sp" + android:textSize="20sp" android:textColor="?android:attr/textColorPrimary" - android:text="@*android:string/android_start_title"/> + android:text="Framework Fallback Home"/> <ProgressBar style="@android:style/Widget.Material.ProgressBar.Horizontal" android:layout_width="match_parent" diff --git a/core/res/res/values-mcc334-mnc020/config.xml b/core/res/res/values-mcc334-mnc020/config.xml index 0970517835b6..82b3ee6448e3 100644 --- a/core/res/res/values-mcc334-mnc020/config.xml +++ b/core/res/res/values-mcc334-mnc020/config.xml @@ -18,4 +18,7 @@ --> <resources> <bool name="config_use_sim_language_file">false</bool> -</resources>
\ No newline at end of file + + <bool name="config_pdp_reject_enable_retry">true</bool> + <integer name="config_pdp_reject_retry_delay_ms">45000</integer> +</resources> diff --git a/core/res/res/values-mcc334-mnc020/strings.xml b/core/res/res/values-mcc334-mnc020/strings.xml new file mode 100644 index 000000000000..91b560aeef7e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title"></string> + <string name="config_pdp_reject_user_authentication_failed">AUTHENTICATION FAILURE -29-.</string> + <string name="config_pdp_reject_service_not_subscribed">NOT SUBSCRIBED TO SERVICE -33-.</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed">Multiple PDN connections for a given APN not allowed -55-.</string> +</resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2f301946402b..b908ab8b709e 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4742,7 +4742,7 @@ May be a string value, which is a comma-separated language tag list, such as "ja-JP,zh-CN". When not specified or an empty string is given, it will fallback to the default one. {@see android.os.LocaleList#forLanguageTags(String)} - {@see android.text.TextView#setTextLocales(android.os.LocaleList)} --> + {@see android.widget.TextView#setTextLocales(android.os.LocaleList)} --> <attr name="textLocale" format="string" /> <!-- Text color for links. --> <attr name="textColorLink" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d7ab426ec9dd..6551b28bd5a3 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -419,13 +419,14 @@ <!-- Regex of wired ethernet ifaces --> <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string> - - <!-- Configuration of Ethernet interfaces in the following format: <interface name|mac address>;[Network Capabilities];[IP config];[Override Transport] Where [Network Capabilities] Optional. A comma seprated list of network capabilities. - Values must be from NetworkCapabilities#NET_CAPABILITIES_* constants. + Values must be from NetworkCapabilities#NET_CAPABILITY_* constants. + The NOT_ROAMING, NOT_CONGESTED and NOT_SUSPENDED capabilities are always + added automatically because this configuration provides no way to update + them dynamically. [IP config] Optional. If empty or not specified - DHCP will be used, otherwise use the following format to specify static IP configuration: ip=<ip-address/mask> gateway=<ip-address> dns=<comma-sep-ip-addresses> @@ -451,10 +452,6 @@ --> </string-array> - <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] --> - <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastservice - </string> - <!-- 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. @@ -4367,4 +4364,9 @@ <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing check after reboot or airplane mode toggling --> <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool> + + <!-- pdp data retry for cause 29, 33 and 55--> + <bool name="config_pdp_reject_enable_retry">false</bool> + <!--pdp data reject retry delay in ms--> + <integer name="config_pdp_reject_retry_delay_ms">-1</integer> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7f463807e1e9..12fc1bb8553c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5653,4 +5653,10 @@ ul.</string> <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS">IMPI unlock successful.</string> <!-- Success message displayed on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS">Network subset service provider unlock successful.</string> + + <!-- pdp data reject dialog string for cause 29, 33 and 55--> + <string name="config_pdp_reject_dialog_title"></string> + <string name="config_pdp_reject_user_authentication_failed"></string> + <string name="config_pdp_reject_service_not_subscribed"></string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed"></string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 355186cc507b..3cee3407296c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -745,7 +745,6 @@ <java-symbol type="string" name="config_ethernet_iface_regex" /> <java-symbol type="array" name="config_ethernet_interfaces" /> <java-symbol type="array" name="config_wakeonlan_supported_interfaces" /> - <java-symbol type="string" name="cellbroadcast_default_package" /> <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" /> <java-symbol type="string" name="config_mms_user_agent" /> <java-symbol type="string" name="config_mms_user_agent_profile_url" /> @@ -1546,6 +1545,7 @@ <java-symbol type="layout" name="select_dialog" /> <java-symbol type="layout" name="simple_dropdown_hint" /> <java-symbol type="layout" name="status_bar_latest_event_content" /> + <java-symbol type="layout" name="system_user_home" /> <java-symbol type="layout" name="text_edit_action_popup_text" /> <java-symbol type="layout" name="text_drag_thumbnail" /> <java-symbol type="layout" name="typing_filter" /> @@ -3871,4 +3871,12 @@ <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" /> <java-symbol type="bool" name="reset_geo_fencing_check_after_boot_or_apm" /> + + <!-- For Pdn throttle feature --> + <java-symbol type="bool" name="config_pdp_reject_enable_retry" /> + <java-symbol type="integer" name="config_pdp_reject_retry_delay_ms" /> + <java-symbol type="string" name="config_pdp_reject_dialog_title" /> + <java-symbol type="string" name="config_pdp_reject_user_authentication_failed" /> + <java-symbol type="string" name="config_pdp_reject_service_not_subscribed" /> + <java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" /> </resources> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index 70917e76f8b4..d5733e34a8ef 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -39,7 +39,7 @@ <!-- Albania: 5 digits, known short codes listed --> <shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" /> - <!-- Argentia: 5 digits, known short codes listed --> + <!-- Argentina: 5 digits, known short codes listed --> <shortcode country="ar" pattern="\\d{5}" free="11711|28291" /> <!-- Armenia: 3-4 digits, emergency numbers 10[123] --> @@ -70,7 +70,7 @@ <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" /> <!-- Canada: 5-6 digits --> - <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" /> + <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" free="455677" /> <!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf --> <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075|30047" /> diff --git a/core/tests/PlatformCompatFramework/OWNERS b/core/tests/PlatformCompatFramework/OWNERS index 2b7cdb0cbce9..cfd0a4b079ad 100644 --- a/core/tests/PlatformCompatFramework/OWNERS +++ b/core/tests/PlatformCompatFramework/OWNERS @@ -2,6 +2,5 @@ platform-compat-eng+reviews@google.com andreionea@google.com -atrost@google.com mathewi@google.com satayev@google.com diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 802b106a107c..cb91db1934a4 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -454,7 +454,6 @@ public class SettingsBackupTest { Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES, Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES, Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, - Settings.Global.SYS_VDSO, Settings.Global.SYS_UIDCPUPOWER, Settings.Global.SYS_TRACED, Settings.Global.FPS_DEVISOR, diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp new file mode 100644 index 000000000000..2194d4b030ce --- /dev/null +++ b/core/tests/hdmitests/Android.bp @@ -0,0 +1,27 @@ +// 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. + +android_test { + name: "HdmiCecTests", + // Include all test java files + srcs: ["src/**/*.java"], + static_libs: [ + "androidx.test.rules", + "frameworks-base-testutils", + "truth-prebuilt", + ], + libs: ["android.test.runner"], + platform_apis: true, + certificate: "platform", +} diff --git a/core/tests/hdmitests/Android.mk b/core/tests/hdmitests/Android.mk deleted file mode 100644 index f155feba0588..000000000000 --- a/core/tests/hdmitests/Android.mk +++ /dev/null @@ -1,31 +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. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -# Include all test java files -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils truth-prebuilt - -LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_PACKAGE_NAME := HdmiCecTests -LOCAL_PRIVATE_PLATFORM_APIS := true - -LOCAL_CERTIFICATE := platform - -include $(BUILD_PACKAGE) diff --git a/core/tests/packagemanagertests/Android.bp b/core/tests/packagemanagertests/Android.bp new file mode 100644 index 000000000000..6f39af8bd468 --- /dev/null +++ b/core/tests/packagemanagertests/Android.bp @@ -0,0 +1,14 @@ +android_test { + name: "FrameworksCorePackageManagerTests", + // We only want this apk build for tests. + // Include all test java files. + srcs: ["src/**/*.java"], + static_libs: [ + "androidx.test.rules", + "frameworks-base-testutils", + "mockito-target-minus-junit4", + ], + libs: ["android.test.runner"], + platform_apis: true, + certificate: "platform", +} diff --git a/core/tests/packagemanagertests/Android.mk b/core/tests/packagemanagertests/Android.mk deleted file mode 100644 index 8c00d14ce856..000000000000 --- a/core/tests/packagemanagertests/Android.mk +++ /dev/null @@ -1,22 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# We only want this apk build for tests. -LOCAL_MODULE_TAGS := tests - -# Include all test java files. -LOCAL_SRC_FILES := \ - $(call all-java-files-under, src) - -LOCAL_STATIC_JAVA_LIBRARIES := \ - androidx.test.rules \ - frameworks-base-testutils \ - mockito-target-minus-junit4 - -LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_PACKAGE_NAME := FrameworksCorePackageManagerTests -LOCAL_PRIVATE_PLATFORM_APIS := true - -LOCAL_CERTIFICATE := platform - -include $(BUILD_PACKAGE) diff --git a/core/tests/privacytests/Android.bp b/core/tests/privacytests/Android.bp new file mode 100644 index 000000000000..7f5699287796 --- /dev/null +++ b/core/tests/privacytests/Android.bp @@ -0,0 +1,14 @@ +android_test { + name: "FrameworksPrivacyLibraryTests", + srcs: ["src/**/*.java"], + static_libs: [ + "junit", + "rappor-tests", + "androidx.test.rules", + "truth-prebuilt", + ], + libs: ["android.test.runner"], + platform_apis: true, + certificate: "platform", + test_suites: ["device-tests"], +} diff --git a/core/tests/privacytests/Android.mk b/core/tests/privacytests/Android.mk deleted file mode 100644 index 7765977c03e8..000000000000 --- a/core/tests/privacytests/Android.mk +++ /dev/null @@ -1,20 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# We only want this apk build for tests. -LOCAL_MODULE_TAGS := tests - -# Include all test java files. -LOCAL_SRC_FILES := \ - $(call all-java-files-under, src) - -LOCAL_STATIC_JAVA_LIBRARIES := junit rappor-tests androidx.test.rules truth-prebuilt - -LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_PACKAGE_NAME := FrameworksPrivacyLibraryTests -LOCAL_PRIVATE_PLATFORM_APIS := true - -LOCAL_CERTIFICATE := platform -LOCAL_COMPATIBILITY_SUITE := device-tests - -include $(BUILD_PACKAGE) diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp index ca655f18149c..4b43b4136076 100644 --- a/core/xsd/vts/Android.bp +++ b/core/xsd/vts/Android.bp @@ -40,3 +40,7 @@ cc_test { ], test_config: "vts_permission_validate_test.xml", } + +vts_config { + name: "VtsValidatePermission", +} diff --git a/core/xsd/vts/Android.mk b/core/xsd/vts/Android.mk deleted file mode 100644 index a5754a494d94..000000000000 --- a/core/xsd/vts/Android.mk +++ /dev/null @@ -1,22 +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. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := VtsValidatePermission -include test/vts/tools/build/Android.host_config.mk diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index a1c8e1366803..5b0ef8ef2130 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -291,6 +291,7 @@ applications that come with the platform <permission name="android.permission.MANAGE_DEVICE_ADMINS"/> <permission name="android.permission.MANAGE_USB"/> <permission name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"/> + <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/> <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.MOUNT_FORMAT_FILESYSTEMS"/> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp new file mode 100644 index 000000000000..94e6a8096849 --- /dev/null +++ b/data/fonts/Android.bp @@ -0,0 +1,36 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +prebuilt_font { + name: "DroidSansMono.ttf", + src: "DroidSansMono.ttf", + required: [ + "DroidSans.ttf", + "DroidSans-Bold.ttf", + ], +} + +prebuilt_font { + name: "AndroidClock.ttf", + src: "AndroidClock.ttf", +} + +///////////////////////////////// +// Copies the font configuration file into system/etc for the product as fonts.xml. +// Additional fonts should be installed to /product/fonts/ alongside a corresponding +// fonts_customiztion.xml in /product/etc/ +prebuilt_etc { + name: "fonts.xml", + src: "fonts.xml", +} diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk index 4226e0882538..e22b72346249 100644 --- a/data/fonts/Android.mk +++ b/data/fonts/Android.mk @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# We have to use BUILD_PREBUILT instead of PRODUCT_COPY_FIES, -# because MINIMAL_FONT_FOOTPRINT is only available in Android.mks. - LOCAL_PATH := $(call my-dir) ########################################## @@ -37,61 +34,7 @@ endef ########################################## $(eval $(call create-font-symlink,DroidSans.ttf,Roboto-Regular.ttf)) $(eval $(call create-font-symlink,DroidSans-Bold.ttf,Roboto-Bold.ttf)) -$(eval $(call create-font-symlink,DroidSerif-Regular.ttf,NotoSerif-Regular.ttf)) -$(eval $(call create-font-symlink,DroidSerif-Bold.ttf,NotoSerif-Bold.ttf)) -$(eval $(call create-font-symlink,DroidSerif-Italic.ttf,NotoSerif-Italic.ttf)) -$(eval $(call create-font-symlink,DroidSerif-BoldItalic.ttf,NotoSerif-BoldItalic.ttf)) - -extra_font_files := \ - DroidSans.ttf \ - DroidSans-Bold.ttf - -################################ -# Use DroidSansMono to hang extra_font_files on -include $(CLEAR_VARS) -LOCAL_MODULE := DroidSansMono.ttf -LOCAL_SRC_FILES := $(LOCAL_MODULE) -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts -LOCAL_REQUIRED_MODULES := $(extra_font_files) -include $(BUILD_PREBUILT) -extra_font_files := - -################################ -# Build the rest of font files as prebuilt. - -# $(1): The source file name in LOCAL_PATH. -# It also serves as the module name and the dest file name. -define build-one-font-module -$(eval include $(CLEAR_VARS))\ -$(eval LOCAL_MODULE := $(1))\ -$(eval LOCAL_SRC_FILES := $(1))\ -$(eval LOCAL_MODULE_CLASS := ETC)\ -$(eval LOCAL_MODULE_TAGS := optional)\ -$(eval LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts)\ -$(eval include $(BUILD_PREBUILT)) -endef - -font_src_files := \ - AndroidClock.ttf - -$(foreach f, $(font_src_files), $(call build-one-font-module, $(f))) - -build-one-font-module := -font_src_files := - -################################ -# Copies the font configuration file into system/etc for the product as fonts.xml. -# Additional fonts should be installed to /product/fonts/ alongside a corresponding -# fonts_customiztion.xml in /product/etc/ -include $(CLEAR_VARS) - -LOCAL_MODULE := fonts.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_PREBUILT_MODULE_FILE := frameworks/base/data/fonts/fonts.xml -include $(BUILD_PREBUILT) # Run sanity tests on fonts on checkbuild checkbuild: fontchain_lint diff --git a/data/keyboards/Vendor_0f0d_Product_00c1.kl b/data/keyboards/Vendor_0f0d_Product_00c1.kl new file mode 100644 index 000000000000..c74512a3a4b0 --- /dev/null +++ b/data/keyboards/Vendor_0f0d_Product_00c1.kl @@ -0,0 +1,55 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Device name: HORI CO.,LTD. HORIPAD S +# HORIPAD for Nintendo Switch, USB game controller +# https://hori.co.uk/horipad-for-nintendo-switch/ + +# Button labeled as "Y" but should really produce keycode "X" +key 0x130 BUTTON_X +# Button labeled as "B" but should really produce keycode "A" +key 0x131 BUTTON_A +# Button labeled as "A" but should really produce keycode "B" +key 0x132 BUTTON_B +# Button labeled as "X" but should really product keycode "Y" +key 0x133 BUTTON_Y + +key 0x134 BUTTON_L1 +key 0x135 BUTTON_R1 +key 0x136 BUTTON_L2 +key 0x137 BUTTON_R2 + +# Minus +key 0x138 BUTTON_SELECT +# Plus +key 0x139 BUTTON_START + +# Analog stick buttons +key 0x13a BUTTON_THUMBL +key 0x13b BUTTON_THUMBR + +# Home +key 0x13c HOME +# Capture +key 0x13d BUTTON_MODE + +# Left analog stick +axis 0x00 X +axis 0x01 Y +# Right analog stick +axis 0x02 Z +axis 0x05 RZ +# D-pad +axis 0x10 HAT_X +axis 0x11 HAT_Y diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index ae7fe6c46f2f..c3c56dbbc6aa 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -998,7 +998,7 @@ public final class RenderNode { * Sets the rotation value for the display list around the Z axis. * * @param rotation The rotation value of the display list, in degrees - * @see View#setRotationZ(float) + * @see View#setRotation(float) * @see #getRotationZ() * @return True if the value changed, false if the new value was the same as the previous value. */ diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index e70529b6cd1a..9cf12f121e0a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -617,7 +617,7 @@ public abstract class Drawable { * {@link #setTintList(ColorStateList) tint}. * </p> * - * @see {@link #setColorFilter(ColorFilter)} } + * @see #setColorFilter(ColorFilter) * @deprecated use {@link #setColorFilter(ColorFilter)} with an instance * of {@link android.graphics.BlendModeColorFilter} */ diff --git a/graphics/java/android/graphics/fonts/FontStyle.java b/graphics/java/android/graphics/fonts/FontStyle.java index af517d623b01..09799fdf5a13 100644 --- a/graphics/java/android/graphics/fonts/FontStyle.java +++ b/graphics/java/android/graphics/fonts/FontStyle.java @@ -217,7 +217,7 @@ public final class FontStyle { /** * Gets the weight value * - * @see FontStyle#setWeight(int) + * @see #FontStyle(int, int) * @return a weight value */ public @IntRange(from = 0, to = 1000) int getWeight() { diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java index 54622c5e74df..babcfc3815f4 100644 --- a/graphics/java/android/graphics/text/LineBreaker.java +++ b/graphics/java/android/graphics/text/LineBreaker.java @@ -320,7 +320,7 @@ public class LineBreaker { /** * Returns the array of tab stops in pixels. * - * @see #setTabStops(float[], int) + * @see #setTabStops */ public @Nullable float[] getTabStops() { return mVariableTabStops; @@ -329,7 +329,7 @@ public class LineBreaker { /** * Returns the default tab stops in pixels. * - * @see #setTabStop(float[], int) + * @see #setTabStops */ public @Px @FloatRange(from = 0) float getDefaultTabStop() { return mDefaultTabStop; diff --git a/identity/java/android/security/identity/AccessControlProfileId.java b/identity/java/android/security/identity/AccessControlProfileId.java index 3d5945065ad7..6caac0a8a065 100644 --- a/identity/java/android/security/identity/AccessControlProfileId.java +++ b/identity/java/android/security/identity/AccessControlProfileId.java @@ -25,6 +25,8 @@ public class AccessControlProfileId { /** * Constructs a new object holding a numerical identifier. * + * <p>The identifier must be a non-negative number and less than 32. + * * @param id the identifier. */ public AccessControlProfileId(int id) { diff --git a/identity/java/android/security/identity/IdentityCredentialStore.java b/identity/java/android/security/identity/IdentityCredentialStore.java index 4f834d2b87b5..3843d9279900 100644 --- a/identity/java/android/security/identity/IdentityCredentialStore.java +++ b/identity/java/android/security/identity/IdentityCredentialStore.java @@ -46,7 +46,7 @@ import java.lang.annotation.RetentionPolicy; * access control profile IDs. Names are strings and values are typed and can be any * value supported by <a href="http://cbor.io/">CBOR</a>.</li> * - * <li>A set of access control profiles, each with a profile ID and a specification + * <li>A set of access control profiles (up to 32), each with a profile ID and a specification * of the conditions which satisfy the profile's requirements.</li> * * <li>An asymmetric key pair which is used to authenticate the credential to the Issuing diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index e9bc8026d25e..d35642e362b1 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -1067,6 +1067,17 @@ public class KeyStore { return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); } + /** + * Notify keystore about the latest user locked state. This is to support keyguard-bound key. + */ + public void onUserLockedStateChanged(int userHandle, boolean locked) { + try { + mBinder.onKeyguardVisibilityChanged(locked, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed to update user locked state " + userHandle, e); + } + } + private class KeyAttestationCallbackResult { private KeystoreResponse keystoreResponse; private KeymasterCertificateChain certificateChain; diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index 91aac8367976..11775caa8ad4 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -17,11 +17,10 @@ package android.security.keystore; import android.annotation.Nullable; +import android.os.Build; import android.security.Credentials; -import android.security.GateKeeper; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore; -import android.security.KeyStoreException; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterCertificateChain; @@ -52,6 +51,7 @@ import libcore.util.EmptyArray; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -494,6 +494,20 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato if (challenge != null) { KeymasterArguments args = new KeymasterArguments(); args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge); + + if (mSpec.isDevicePropertiesAttestationIncluded()) { + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND, + Build.BRAND.getBytes(StandardCharsets.UTF_8)); + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE, + Build.DEVICE.getBytes(StandardCharsets.UTF_8)); + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT, + Build.PRODUCT.getBytes(StandardCharsets.UTF_8)); + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER, + Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8)); + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL, + Build.MODEL.getBytes(StandardCharsets.UTF_8)); + } + return getAttestationChain(privateKeyAlias, keyPair, args); } @@ -603,8 +617,14 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato private Iterable<byte[]> getAttestationChain(String privateKeyAlias, KeyPair keyPair, KeymasterArguments args) throws ProviderException { - KeymasterCertificateChain outChain = new KeymasterCertificateChain(); - int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain); + final KeymasterCertificateChain outChain = new KeymasterCertificateChain(); + final int errorCode; + if (mSpec.isDevicePropertiesAttestationIncluded() + && mSpec.getAttestationChallenge() == null) { + throw new ProviderException("An attestation challenge must be provided when requesting " + + "device properties attestation."); + } + errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain); if (errorCode != KeyStore.NO_ERROR) { throw new ProviderException("Failed to generate attestation certificate chain", KeyStore.getKeyStoreException(errorCode)); diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 630a6dd081a3..e7e410a9ddb3 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -24,6 +24,7 @@ import android.app.KeyguardManager; import android.compat.annotation.UnsupportedAppUsage; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; +import android.os.Build; import android.security.GateKeeper; import android.security.KeyStore; import android.text.TextUtils; @@ -264,6 +265,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private final int mUserAuthenticationValidityDurationSeconds; private final boolean mUserPresenceRequired; private final byte[] mAttestationChallenge; + private final boolean mDevicePropertiesAttestationIncluded; private final boolean mUniqueIdIncluded; private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mInvalidatedByBiometricEnrollment; @@ -301,6 +303,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu int userAuthenticationValidityDurationSeconds, boolean userPresenceRequired, byte[] attestationChallenge, + boolean devicePropertiesAttestationIncluded, boolean uniqueIdIncluded, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, @@ -350,6 +353,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUserPresenceRequired = userPresenceRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge); + mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded; mUniqueIdIncluded = uniqueIdIncluded; mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; @@ -644,6 +648,21 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * Returns {@code true} if attestation for the base device properties ({@link Build#BRAND}, + * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL}, {@link Build#PRODUCT}) + * was requested to be added in the attestation certificate for the generated key. + * + * {@link javax.crypto.KeyGenerator#generateKey()} will throw + * {@link java.security.ProviderException} if device properties attestation fails or is not + * supported. + * + * @see Builder#setDevicePropertiesAttestationIncluded(boolean) + */ + public boolean isDevicePropertiesAttestationIncluded() { + return mDevicePropertiesAttestationIncluded; + } + + /** * @hide This is a system-only API * * Returns {@code true} if the attestation certificate will contain a unique ID field. @@ -734,6 +753,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private int mUserAuthenticationValidityDurationSeconds = -1; private boolean mUserPresenceRequired = false; private byte[] mAttestationChallenge = null; + private boolean mDevicePropertiesAttestationIncluded = false; private boolean mUniqueIdIncluded = false; private boolean mUserAuthenticationValidWhileOnBody; private boolean mInvalidatedByBiometricEnrollment = true; @@ -797,6 +817,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu sourceSpec.getUserAuthenticationValidityDurationSeconds(); mUserPresenceRequired = sourceSpec.isUserPresenceRequired(); mAttestationChallenge = sourceSpec.getAttestationChallenge(); + mDevicePropertiesAttestationIncluded = + sourceSpec.isDevicePropertiesAttestationIncluded(); mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded(); mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody(); mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment(); @@ -1252,6 +1274,31 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * Sets whether to include the base device properties in the attestation certificate. + * + * <p>If {@code attestationChallenge} is not {@code null}, the public key certificate for + * this key pair will contain an extension that describes the details of the key's + * configuration and authorizations, including the device properties values (brand, device, + * manufacturer, model, product). These should be the same as in ({@link Build#BRAND}, + * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL}, + * {@link Build#PRODUCT}). The attestation certificate chain can + * be retrieved with {@link java.security.KeyStore#getCertificateChain(String)}. + * + * <p> If {@code attestationChallenge} is {@code null}, the public key certificate for + * this key pair will not contain the extension with the requested attested values. + * + * <p> {@link javax.crypto.KeyGenerator#generateKey()} will throw + * {@link java.security.ProviderException} if device properties attestation fails or is not + * supported. + */ + @NonNull + public Builder setDevicePropertiesAttestationIncluded( + boolean devicePropertiesAttestationIncluded) { + mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded; + return this; + } + + /** * @hide Only system apps can use this method. * * Sets whether to include a temporary unique ID field in the attestation certificate. @@ -1360,6 +1407,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUserAuthenticationValidityDurationSeconds, mUserPresenceRequired, mAttestationChallenge, + mDevicePropertiesAttestationIncluded, mUniqueIdIncluded, mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java index d8030fb8ab79..0518f45ae1bb 100644 --- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java @@ -16,8 +16,8 @@ package android.security.keystore; -import android.os.Parcelable; import android.os.Parcel; +import android.os.Parcelable; import java.math.BigInteger; import java.security.spec.AlgorithmParameterSpec; @@ -99,6 +99,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds()); out.writeBoolean(mSpec.isUserPresenceRequired()); out.writeByteArray(mSpec.getAttestationChallenge()); + out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded()); out.writeBoolean(mSpec.isUniqueIdIncluded()); out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody()); out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment()); @@ -154,6 +155,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { final int userAuthenticationValidityDurationSeconds = in.readInt(); final boolean userPresenceRequired = in.readBoolean(); final byte[] attestationChallenge = in.createByteArray(); + final boolean devicePropertiesAttestationIncluded = in.readBoolean(); final boolean uniqueIdIncluded = in.readBoolean(); final boolean userAuthenticationValidWhileOnBody = in.readBoolean(); final boolean invalidatedByBiometricEnrollment = in.readBoolean(); @@ -185,6 +187,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { userAuthenticationValidityDurationSeconds, userPresenceRequired, attestationChallenge, + devicePropertiesAttestationIncluded, uniqueIdIncluded, userAuthenticationValidWhileOnBody, invalidatedByBiometricEnrollment, diff --git a/lowpan/tests/Android.bp b/lowpan/tests/Android.bp new file mode 100644 index 000000000000..ad2bc27d1b39 --- /dev/null +++ b/lowpan/tests/Android.bp @@ -0,0 +1,41 @@ +// 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. + +// Make test APK +// ============================================================ +android_test { + name: "FrameworksLowpanApiTests", + srcs: ["**/*.java"], + // Filter all src files to just java files + jacoco: { + include_filter: ["android.net.lowpan.*"], + exclude_filter: [ + "android.net.lowpan.LowpanInterfaceTest*", + "android.net.lowpan.LowpanManagerTest*", + ], + }, + static_libs: [ + "androidx.test.rules", + "guava", + "mockito-target-minus-junit4", + "frameworks-base-testutils", + ], + libs: [ + "android.test.runner", + "android.test.base", + ], + platform_apis: true, + test_suites: ["device-tests"], + certificate: "platform", +} diff --git a/lowpan/tests/Android.mk b/lowpan/tests/Android.mk deleted file mode 100644 index 832ed2f53f7b..000000000000 --- a/lowpan/tests/Android.mk +++ /dev/null @@ -1,63 +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. - -LOCAL_PATH:= $(call my-dir) - -# Make test APK -# ============================================================ -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -# This list is generated from the java source files in this module -# The list is a comma separated list of class names with * matching zero or more characters. -# Example: -# Input files: src/com/android/server/lowpan/Test.java src/com/android/server/lowpan/AnotherTest.java -# Generated exclude list: com.android.server.lowpan.Test*,com.android.server.lowpan.AnotherTest* - -# Filter all src files to just java files -local_java_files := $(filter %.java,$(LOCAL_SRC_FILES)) -# Transform java file names into full class names. -# This only works if the class name matches the file name and the directory structure -# matches the package. -local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files))) -# Convert class name list to jacoco exclude list -# This appends a * to all classes and replace the space separators with commas. -# These patterns will match all classes in this module and their inner classes. -jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes))) - -jacoco_include := android.net.lowpan.* - -LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include) -LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude) - -LOCAL_STATIC_JAVA_LIBRARIES := \ - androidx.test.rules \ - guava \ - mockito-target-minus-junit4 \ - frameworks-base-testutils \ - -LOCAL_JAVA_LIBRARIES := \ - android.test.runner \ - android.test.base \ - -LOCAL_PACKAGE_NAME := FrameworksLowpanApiTests -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_COMPATIBILITY_SUITE := device-tests - -LOCAL_CERTIFICATE := platform -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -include $(BUILD_PACKAGE) diff --git a/media/Android.bp b/media/Android.bp index 43635684d9b3..a432c8d2a64d 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -26,8 +26,10 @@ java_library { installable: true, - // Make sure that the implementaion only relies on SDK or system APIs. + // TODO: build against stable API surface. Use core_platform for now to avoid + // link-check failure with exoplayer building against "current". sdk_version: "core_platform", + min_sdk_version: "29", libs: [ // The order matters. android_system_* library should come later. "framework_media_annotation", @@ -94,4 +96,5 @@ java_library { name: "framework_media_annotation", srcs: [":framework-media-annotation-srcs"], installable: false, + sdk_version: "core_current", } diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java index 4e7050129058..4c0850b675a8 100644 --- a/media/java/android/media/AudioFocusRequest.java +++ b/media/java/android/media/AudioFocusRequest.java @@ -80,9 +80,9 @@ import android.os.Looper; * <p>An {@code AudioFocusRequest} instance always contains one of the four types of requests * explained above. It is passed when building an {@code AudioFocusRequest} instance with its * builder in the {@link Builder} constructor - * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(int)}, or + * {@link AudioFocusRequest.Builder#Builder(int)}, or * with {@link AudioFocusRequest.Builder#setFocusGain(int)} after copying an existing instance with - * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(AudioFocusRequest)}. + * {@link AudioFocusRequest.Builder#Builder(AudioFocusRequest)}. * * <h3>Qualifying your focus request</h3> * <h4>Use case requiring a focus request</h4> diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 0ced68ef8695..babe0723dc01 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1098,7 +1098,7 @@ public class AudioTrack extends PlayerBase * Can only be called only if the AudioTrack is opened in offload mode * {@see Builder#setOffloadedPlayback(boolean)}. * Can only be called only if the AudioTrack is in state {@link #PLAYSTATE_PLAYING} - * {@see #getPlaystate()}. + * {@see #getPlayState()}. * Use this method in the same thread as any write() operation. */ public void setOffloadEndOfStream() { diff --git a/native/android/Android.bp b/native/android/Android.bp index ae8cb3a47a05..8f36decec400 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -137,4 +137,4 @@ filegroup { "aidl/com/android/internal/compat/IPlatformCompatNative.aidl", ], path: "aidl", -}
\ No newline at end of file +} diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java index 50542818e0d7..6fab9e4641b6 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java @@ -106,6 +106,7 @@ public class CaptivePortalLoginActivity extends Activity { webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); webSettings.setDomStorageEnabled(true); + webSettings.setAllowFileAccess(false); mWebViewClient = new MyWebViewClient(); mWebView.setWebViewClient(mWebViewClient); mWebView.setWebChromeClient(new MyWebChromeClient()); diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java index d48aa246ecba..231809bfece4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java +++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java @@ -242,7 +242,16 @@ public class ZoneGetter { final TimeZoneNames.NameType nameType = tz.inDaylightTime(now) ? TimeZoneNames.NameType.LONG_DAYLIGHT : TimeZoneNames.NameType.LONG_STANDARD; - return names.getDisplayName(tz.getID(), nameType, now.getTime()); + return names.getDisplayName(getCanonicalZoneId(tz), nameType, now.getTime()); + } + + private static String getCanonicalZoneId(TimeZone timeZone) { + final String id = timeZone.getID(); + final String canonicalId = android.icu.util.TimeZone.getCanonicalID(id); + if (canonicalId != null) { + return canonicalId; + } + return id; } private static void appendWithTtsSpan(SpannableStringBuilder builder, CharSequence content, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 21129f927873..65f68cc5c5b5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1352,9 +1352,6 @@ class SettingsProtoDumpUtil { Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, GlobalSettingsProto.Sys.STORAGE_CACHE_MAX_BYTES); dumpSetting(s, p, - Settings.Global.SYS_VDSO, - GlobalSettingsProto.Sys.VDSO); - dumpSetting(s, p, Settings.Global.SYS_UIDCPUPOWER, GlobalSettingsProto.Sys.UIDCPUPOWER); p.end(sysToken); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index ff91c797e9b1..c1ec9b0f3215 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -219,6 +219,9 @@ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/> + <!-- Permission required for CTS test - BatterySaverTest --> + <uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/> + <!-- Permission required for CTS test - UiModeManagerTest --> <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/> @@ -247,6 +250,9 @@ <!-- Permission required for testing system audio effect APIs. --> <uses-permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"/> + <!-- Permissions needed to test shared libraries --> + <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" @@ -293,22 +299,6 @@ android:excludeFromRecents="true" android:exported="false" /> - <!-- - The following is used as a no-op/null home activity when - no other MAIN/HOME activity is present (e.g., in CSI). - --> - <activity android:name=".NullHome" - android:excludeFromRecents="true" - android:label="" - android:screenOrientation="nosensor"> - <!-- The priority here is set to be lower than that for Settings --> - <intent-filter android:priority="-1100"> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.HOME" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - <receiver android:name=".BugreportReceiver" android:permission="android.permission.DUMP"> diff --git a/packages/Shell/src/com/android/shell/NullHome.java b/packages/Shell/src/com/android/shell/NullHome.java deleted file mode 100644 index bd975614a50a..000000000000 --- a/packages/Shell/src/com/android/shell/NullHome.java +++ /dev/null @@ -1,43 +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.shell; - -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; - -/** - * This covers the fallback case where no launcher is available. - * Usually Settings.apk has one fallback home activity. - * Settings.apk, however, is not part of CSI, which needs to be - * standalone (bootable and testable). - */ -public class NullHome extends Activity { - private static final String TAG = "NullHome"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Log.i(TAG, "onCreate"); - setContentView(R.layout.null_home_finishing_boot); - } - - protected void onDestroy() { - super.onDestroy(); - Log.i(TAG, "onDestroy"); - } -} diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index c8cf7f503468..304f81b4e77f 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -43,7 +43,7 @@ twickham@google.com winsonc@google.com #Android Auto -stenning@google.com +hseog@google.com #Android TV rgl@google.com diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 688e8eb8f2e3..7c49c3f961c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -566,6 +566,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated); mRoundnessManager.setOnRoundingChangedCallback(this::invalidate); addOnExpandedHeightChangedListener(mRoundnessManager::setExpanded); + mLockscreenUserManager.addUserChangedListener(userId -> + updateSensitiveness(false /* animated */)); setOutlineProvider(mOutlineProvider); // Blocking helper manager wants to know the expanded state, update as well. @@ -4602,7 +4604,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void setHideSensitive(boolean hideSensitive, boolean animate) { + private void updateSensitiveness(boolean animate) { + boolean hideSensitive = mLockscreenUserManager.isAnyProfilePublicMode(); if (hideSensitive != mAmbientState.isHideSensitive()) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -5306,7 +5309,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd SysuiStatusBarStateController state = (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class); - setHideSensitive(publicMode, state.goingToFullShade() /* animate */); + updateSensitiveness(state.goingToFullShade() /* animate */); setDimmed(onKeyguard, state.fromShadeLocked() /* animate */); setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = getActivatedChild(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 31054260eb15..f2ed3e648220 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -57,6 +57,8 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; @@ -119,6 +121,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private MetricsLogger mMetricsLogger; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + private UserChangedListener mUserChangedListener; private TestableNotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; @@ -137,7 +141,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectTestDependency( NotificationBlockingHelperManager.class, mBlockingHelperManager); - mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState); + mDependency.injectTestDependency(NotificationLockscreenUserManager.class, + mLockscreenUserManager); + mDependency.injectTestDependency(StatusBarStateController.class, mBarState); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager); @@ -152,6 +158,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { NotificationShelf notificationShelf = mock(NotificationShelf.class); + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); // The actual class under test. You may need to work with this class directly when // testing anonymous class members of mStackScroller, like mMenuEventListener, @@ -174,6 +182,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); mStackScroller.setIconAreaController(mNotificationIconAreaController); + verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture()); + mUserChangedListener = userChangedCaptor.getValue(); // Stub out functionality that isn't necessary to test. doNothing().when(mBar) @@ -247,6 +257,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testOnStatePostChange_verifyIfProfileIsPublic() { + mUserChangedListener.onUserChanged(0); + verify(mLockscreenUserManager).isAnyProfilePublicMode(); + } + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 27297c44573c..eb72b81fb766 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -27,7 +27,7 @@ java_defaults { "androidx.annotation_annotation", "netd_aidl_interface-V3-java", "netlink-client", - "networkstack-aidl-interfaces-unstable-java", + "networkstack-aidl-interfaces-java", "android.hardware.tetheroffload.config-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", "net-utils-framework-common", @@ -50,6 +50,11 @@ android_library { 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", ], @@ -108,6 +113,8 @@ android_app { 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 @@ -121,4 +128,5 @@ android_app { // 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/apex/Android.bp b/packages/Tethering/apex/Android.bp index 24df5f696077..67097a79e5c0 100644 --- a/packages/Tethering/apex/Android.bp +++ b/packages/Tethering/apex/Android.bp @@ -17,7 +17,7 @@ apex { name: "com.android.tethering", updatable: true, - min_sdk_version: "R", + min_sdk_version: "current", java_libs: ["framework-tethering"], apps: ["Tethering"], manifest: "manifest.json", @@ -36,3 +36,12 @@ 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/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index ee6b9f12f9d2..79a178297aa5 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -13,43 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -// AIDL interfaces between the core system and the tethering mainline module. -aidl_interface { - name: "tethering-aidl-interfaces", - unstable: true, - local_include_dir: "src", - include_dirs: ["frameworks/base/core/java"], // For framework parcelables. - srcs: [ - // @JavaOnlyStableParcelable aidl declarations must not be listed here, as this would cause - // compilation to fail (b/148001843). - "src/android/net/IIntResultListener.aidl", - "src/android/net/ITetheringConnector.aidl", - "src/android/net/ITetheringEventCallback.aidl", - "src/android/net/TetheringCallbackStartedParcel.aidl", - "src/android/net/TetheringConfigurationParcel.aidl", - "src/android/net/TetheringRequestParcel.aidl", - "src/android/net/TetherStatesParcel.aidl", - ], - backend: { - ndk: { - enabled: false, - }, - cpp: { - enabled: false, - }, - }, -} - java_library { name: "framework-tethering", sdk_version: "module_current", srcs: [ - "src/android/net/TetheredClient.java", - "src/android/net/TetheringManager.java", - "src/android/net/TetheringConstants.java", - ], - static_libs: [ - "tethering-aidl-interfaces-java", + ":framework-tethering-srcs", ], jarjar_rules: "jarjar-rules.txt", installable: true, @@ -67,6 +35,7 @@ java_library { stubs_defaults { name: "framework-tethering-stubs-defaults", srcs: [":framework-tethering-srcs"], + dist: { dest: "framework-tethering.txt" }, } filegroup { @@ -123,16 +92,19 @@ java_library { name: "framework-tethering-stubs-publicapi", srcs: [":framework-tethering-stubs-srcs-publicapi"], defaults: ["framework-module-stubs-lib-defaults-publicapi"], + dist: { dest: "framework-tethering.jar" }, } java_library { name: "framework-tethering-stubs-systemapi", srcs: [":framework-tethering-stubs-srcs-systemapi"], defaults: ["framework-module-stubs-lib-defaults-systemapi"], + dist: { dest: "framework-tethering.jar" }, } java_library { name: "framework-tethering-stubs-module_libs_api", srcs: [":framework-tethering-stubs-srcs-module_libs_api"], - defaults: ["framework-module-stubs-lib-defaults-systemapi"], + defaults: ["framework-module-stubs-lib-defaults-module_libs_api"], + dist: { dest: "framework-tethering.jar" }, } diff --git a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml index 2a7330098faf..d074f1569933 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (5030042590486713460) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (3843613362272973447) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) --> - <skip /> + <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-ta/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml index ea04821e33bd..f4b15aab19b7 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (5030042590486713460) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (3843613362272973447) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) --> - <skip /> + <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-rTW/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml index 05b90692ea7b..528a1e52925c 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml @@ -16,9 +16,9 @@ <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_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="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-mcc311-mnc480-ne/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml index 617c50dd0ce8..1503244f5000 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (611650570559011140) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (6508394877641864863) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) --> - <skip /> + <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-ta/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml index 0e437593ee87..2ea2467e5879 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (611650570559011140) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (6508394877641864863) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) --> - <skip /> + <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-rTW/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml index ea01b943fbe8..cd653df1dac6 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml @@ -16,9 +16,9 @@ <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_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="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-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml index 9d738a76eb0e..50a50bf7a996 100644 --- a/packages/Tethering/res/values-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-zh-rTW/strings.xml @@ -16,11 +16,11 @@ <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_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_title" msgid="3004509127903564191">"網路共用已停用"</string> <string name="disable_tether_notification_message" msgid="6717523799293901476">"詳情請洽你的管理員"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與數據連線狀態"</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> diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml index effc24ac4de5..3f5bc901d07b 100644 --- a/packages/Tethering/res/values/config.xml +++ b/packages/Tethering/res/values/config.xml @@ -55,6 +55,12 @@ <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> @@ -62,6 +68,13 @@ <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. diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml index 16ae8ade19da..4e2bb1e31b2a 100644 --- a/packages/Tethering/res/values/overlayable.xml +++ b/packages/Tethering/res/values/overlayable.xml @@ -23,7 +23,13 @@ <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="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 --> diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index 4f8ad8a221ef..4710a30b2998 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -173,6 +173,18 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { 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; diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index 83727bcdc67e..659d344acfcd 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -50,6 +50,7 @@ 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.Handler; import android.os.Looper; @@ -60,6 +61,7 @@ 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; @@ -115,6 +117,15 @@ public class IpServer extends StateMachine { private static final String ETHERNET_IFACE_ADDR = "192.168.50.1"; private static final int ETHERNET_IFACE_PREFIX_LENGTH = 24; + // TODO: remove this constant after introducing PrivateAddressCoordinator. + private static final List<IpPrefix> NCM_PREFIXES = Collections.unmodifiableList( + Arrays.asList( + new IpPrefix("192.168.42.0/24"), + new IpPrefix("192.168.51.0/24"), + new IpPrefix("192.168.52.0/24"), + new IpPrefix("192.168.53.0/24") + )); + // TODO: have PanService use some visible version of this constant private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24; @@ -212,6 +223,8 @@ public class IpServer extends StateMachine { 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; private final State mInitialState; private final State mLocalHotspotState; @@ -227,6 +240,7 @@ public class IpServer extends StateMachine { private final int mInterfaceType; private final LinkProperties mLinkProperties; private final boolean mUsingLegacyDhcp; + private final boolean mUsingBpfOffload; private final Dependencies mDeps; @@ -302,9 +316,12 @@ public class IpServer extends StateMachine { private final IpNeighborMonitor mIpNeighborMonitor; + // 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, Callback callback, boolean usingLegacyDhcp, Dependencies deps) { + INetd netd, Callback callback, boolean usingLegacyDhcp, boolean usingBpfOffload, + Dependencies deps) { super(ifaceName, looper); mLog = log.forSubComponent(ifaceName); mNetd = netd; @@ -314,6 +331,7 @@ public class IpServer extends StateMachine { mInterfaceType = interfaceType; mLinkProperties = new LinkProperties(); mUsingLegacyDhcp = usingLegacyDhcp; + mUsingBpfOffload = usingBpfOffload; mDeps = deps; resetLinkProperties(); mLastError = TetheringManager.TETHER_ERROR_NO_ERROR; @@ -321,7 +339,12 @@ public class IpServer extends StateMachine { mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog, new MyNeighborEventConsumer()); - if (!mIpNeighborMonitor.start()) { + + // 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); } @@ -452,7 +475,7 @@ public class IpServer extends StateMachine { handleError(); } } - }, new DhcpLeaseCallback()); + }, new DhcpEventCallback()); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -465,7 +488,7 @@ public class IpServer extends StateMachine { } } - private class DhcpLeaseCallback extends IDhcpEventCallbacks.Stub { + private class DhcpEventCallback extends IDhcpEventCallbacks.Stub { @Override public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) { final ArrayList<TetheredClient> leases = new ArrayList<>(); @@ -499,8 +522,9 @@ public class IpServer extends StateMachine { } @Override - public void onNewPrefixRequest(IpPrefix currentPrefix) { - //TODO: add specific implementation. + public void onNewPrefixRequest(@NonNull final IpPrefix currentPrefix) { + Objects.requireNonNull(currentPrefix); + sendMessage(CMD_NEW_PREFIX_REQUEST, currentPrefix); } @Override @@ -514,26 +538,38 @@ public class IpServer extends StateMachine { } } + 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 int prefixLen = serverLinkAddr.getPrefixLength(); final Inet4Address clientAddr = clientLinkAddr == null ? null : (Inet4Address) clientLinkAddr.getAddress(); - final DhcpServingParamsParcel params; - params = new DhcpServingParamsParcelExt() - .setDefaultRouters(addr) - .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) - .setDnsServers(addr) - .setServerAddr(serverLinkAddr) - .setMetered(true) - .setSingleClientAddr(clientAddr); - // TODO: also advertise link MTU - + final DhcpServingParamsParcel params = makeServingParams(addr /* defaultRouter */, + addr /* dnsServer */, serverLinkAddr, clientAddr); mDhcpServerStartIndex++; mDeps.makeDhcpServer( mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex)); @@ -560,7 +596,7 @@ public class IpServer extends StateMachine { }); mDhcpServer = null; } catch (RemoteException e) { - mLog.e("Error stopping DHCP", e); + mLog.e("Error stopping DHCP server", e); // Not much more we can do here } } @@ -642,31 +678,33 @@ public class IpServer extends StateMachine { return false; } - // Directly-connected route. - final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), - mIpv4Address.getPrefixLength()); - final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST); if (enabled) { mLinkProperties.addLinkAddress(mIpv4Address); - mLinkProperties.addRoute(route); + mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address)); } else { mLinkProperties.removeLinkAddress(mIpv4Address); - mLinkProperties.removeRoute(route); + mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address)); } - return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr); } - private String getRandomWifiIPv4Address() { + private Inet4Address getRandomIPv4Address(@NonNull final byte[] rawAddr) { + final byte[] ipv4Addr = rawAddr; + ipv4Addr[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF); try { - byte[] bytes = parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress(); - bytes[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF); - return InetAddress.getByAddress(bytes).getHostAddress(); - } catch (Exception e) { - return WIFI_HOST_IFACE_ADDR; + return (Inet4Address) InetAddress.getByAddress(ipv4Addr); + } catch (UnknownHostException e) { + mLog.e("Failed to construct Inet4Address from raw IPv4 addr"); + return null; } } + private String getRandomWifiIPv4Address() { + final Inet4Address ipv4Addr = + getRandomIPv4Address(parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress()); + return ipv4Addr != null ? ipv4Addr.getHostAddress() : WIFI_HOST_IFACE_ADDR; + } + private boolean startIPv6() { mInterfaceParams = mDeps.getInterfaceParams(mIfaceName); if (mInterfaceParams == null) { @@ -700,7 +738,7 @@ public class IpServer extends StateMachine { // // TODO: Evaluate using a data structure than is more directly suited to // communicating only the relevant information. - private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) { + private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) { if (mRaDaemon == null) return; // Avoid unnecessary work on spurious updates. @@ -715,15 +753,15 @@ public class IpServer extends StateMachine { final String upstreamIface = v6only.getInterfaceName(); params = new RaParams(); - // We advertise an mtu lower by 16, which is the closest multiple of 8 >= 14, - // the ethernet header size. This makes kernel ebpf tethering offload happy. - // This hack should be reverted once we have the kernel fixed up. + // When BPF offload is enabled, we advertise an mtu lower by 16, which is the closest + // multiple of 8 >= 14, the ethernet header size. This makes kernel ebpf tethering + // offload happy. This hack should be reverted once we have the kernel fixed up. // Note: this will automatically clamp to at least 1280 (ipv6 minimum mtu) // see RouterAdvertisementDaemon.java putMtu() - params.mtu = v6only.getMtu() - 16; + params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu(); params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); - if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface); + if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); for (LinkAddress linkAddr : v6only.getLinkAddresses()) { if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; @@ -751,21 +789,43 @@ public class IpServer extends StateMachine { mLastIPv6UpstreamIfindex = upstreamIfindex; } + 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()) { - final ArrayList<RouteInfo> toBeRemoved = - getLocalRoutesFor(mIfaceName, deprecatedPrefixes); - // Remove routes from local network. - 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); + removeRoutesFromLocalNetwork(getLocalRoutesFor(mIfaceName, deprecatedPrefixes)); } // [2] Add only the routes that have not previously been added. @@ -776,24 +836,7 @@ public class IpServer extends StateMachine { } if (!addedPrefixes.isEmpty()) { - final ArrayList<RouteInfo> toBeAdded = - getLocalRoutesFor(mIfaceName, addedPrefixes); - 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 IPv6 routes to local table: " + e); - } - } catch (ServiceSpecificException | RemoteException e) { - mLog.e("Failed to add " + mIfaceName + " to local table: ", e); - } - - for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); + addRoutesToLocalNetwork(getLocalRoutesFor(mIfaceName, addedPrefixes)); } } } @@ -844,6 +887,11 @@ public class IpServer extends StateMachine { } 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; + try { mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel()); mIpv6ForwardingRules.put(rule.address, rule); @@ -853,6 +901,11 @@ public class IpServer extends StateMachine { } private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) { + // 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; + try { mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel()); if (removeFromMap) { @@ -925,12 +978,85 @@ public class IpServer extends StateMachine { } } - private byte getHopLimit(String upstreamIface) { + // TODO: call PrivateAddressCoordinator.requestDownstreamAddress instead of this temporary + // logic. + private Inet4Address requestDownstreamAddress(@NonNull final IpPrefix currentPrefix) { + final int oldIndex = NCM_PREFIXES.indexOf(currentPrefix); + if (oldIndex == -1) { + mLog.e("current prefix isn't supported for NCM link: " + currentPrefix); + return null; + } + + final IpPrefix newPrefix = NCM_PREFIXES.get((oldIndex + 1) % NCM_PREFIXES.size()); + return getRandomIPv4Address(newPrefix.getRawAddress()); + } + + 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; + final Inet4Address srvAddr = requestDownstreamAddress(currentPrefix); + if (srvAddr == null) { + mLog.e("Fail to request a new downstream prefix"); + return; + } + mIpv4Address = new LinkAddress(srvAddr, currentPrefix.getPrefixLength()); + + // 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")); - // Add one hop to account for this forwarding device - upstreamHopLimit++; + upstreamHopLimit = upstreamHopLimit + adjustTTL; // Cap the hop limit to 255. return (byte) Integer.min(upstreamHopLimit, 255); } catch (Exception e) { @@ -1018,7 +1144,7 @@ public class IpServer extends StateMachine { transitionTo(mUnavailableState); break; case CMD_IPV6_TETHER_UPDATE: - updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); + updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); break; default: return NOT_HANDLED; @@ -1036,11 +1162,9 @@ public class IpServer extends StateMachine { } try { - final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), - mIpv4Address.getPrefixLength()); - NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix); + NetdUtils.tetherInterface(mNetd, mIfaceName, PrefixUtils.asIpPrefix(mIpv4Address)); } catch (RemoteException | ServiceSpecificException | IllegalStateException e) { - mLog.e("Error Tethering: " + e); + mLog.e("Error Tethering", e); mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; return; } @@ -1084,7 +1208,7 @@ public class IpServer extends StateMachine { if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); break; case CMD_IPV6_TETHER_UPDATE: - updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); + updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); sendLinkProperties(); break; case CMD_IP_FORWARDING_ENABLE_ERROR: @@ -1095,6 +1219,9 @@ public class IpServer extends StateMachine { mLastError = TetheringManager.TETHER_ERROR_INTERNAL_ERROR; transitionTo(mInitialState); break; + case CMD_NEW_PREFIX_REQUEST: + handleNewPrefixRequest((IpPrefix) message.obj); + break; default: return false; } diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java index 049a9f68bbd2..3c6e8d88ed13 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java @@ -37,6 +37,7 @@ 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; @@ -45,13 +46,12 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; import android.telephony.CarrierConfigManager; -import android.util.ArraySet; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.StateMachine; import java.io.PrintWriter; +import java.util.BitSet; /** * Re-check tethering provisioning for enabled downstream tether types. @@ -73,39 +73,39 @@ public class EntitlementManager { private final ComponentName mSilentProvisioningService; private static final int MS_PER_HOUR = 60 * 60 * 1000; + private static final int DUMP_TIMEOUT = 10_000; - // The ArraySet contains enabled downstream types, ex: + // 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 ArraySet<Integer> mCurrentTethers; + private final BitSet mCurrentDownstreams; + private final BitSet mExemptedDownstreams; private final Context mContext; - private final int mPermissionChangeMessageCode; private final SharedLog mLog; private final SparseIntArray mEntitlementCacheValue; private final Handler mHandler; - private final StateMachine mTetherMasterSM; // Key: TetheringManager.TETHERING_*(downstream). // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). - private final SparseIntArray mCellularPermitted; + private final SparseIntArray mCurrentEntitlementResults; + private final Runnable mPermissionChangeCallback; private PendingIntent mProvisioningRecheckAlarm; - private boolean mCellularUpstreamPermitted = true; + private boolean mLastCellularUpstreamPermitted = true; private boolean mUsingCellularAsUpstream = false; private boolean mNeedReRunProvisioningUi = false; private OnUiEntitlementFailedListener mListener; private TetheringConfigurationFetcher mFetcher; - public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, - int permissionChangeMessageCode) { - + public EntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { mContext = ctx; mLog = log.forSubComponent(TAG); - mCurrentTethers = new ArraySet<Integer>(); - mCellularPermitted = new SparseIntArray(); + mCurrentDownstreams = new BitSet(); + mExemptedDownstreams = new BitSet(); + mCurrentEntitlementResults = new SparseIntArray(); mEntitlementCacheValue = new SparseIntArray(); - mTetherMasterSM = tetherMasterSM; - mPermissionChangeMessageCode = permissionChangeMessageCode; - mHandler = tetherMasterSM.getHandler(); + mPermissionChangeCallback = callback; + mHandler = h; mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM), null, mHandler); mSilentProvisioningService = ComponentName.unflattenFromString( @@ -144,13 +144,35 @@ public class EntitlementManager { * Check if cellular upstream is permitted. */ public boolean isCellularUpstreamPermitted() { - // If provisioning is required and EntitlementManager don't know any downstream, - // cellular upstream should not be allowed. final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (mCurrentTethers.size() == 0 && isTetherProvisioningRequired(config)) { - return false; - } - return mCellularUpstreamPermitted; + + 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); } /** @@ -164,29 +186,24 @@ public class EntitlementManager { public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) { if (!isValidDownstreamType(downstreamType)) return; - if (!mCurrentTethers.contains(downstreamType)) mCurrentTethers.add(downstreamType); + mCurrentDownstreams.set(downstreamType, true); + + mExemptedDownstreams.set(downstreamType, false); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (isTetherProvisioningRequired(config)) { - // If provisioning is required and the result is not available yet, - // cellular upstream should not be allowed. - if (mCellularPermitted.size() == 0) { - mCellularUpstreamPermitted = false; - } - // If upstream is not cellular, provisioning app would not be launched - // till upstream change to cellular. - if (mUsingCellularAsUpstream) { - if (showProvisioningUi) { - runUiTetherProvisioning(downstreamType, config.activeDataSubId); - } else { - runSilentTetherProvisioning(downstreamType, config.activeDataSubId); - } - mNeedReRunProvisioningUi = false; + 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.activeDataSubId); } else { - mNeedReRunProvisioningUi |= showProvisioningUi; + runSilentTetherProvisioning(downstreamType, config.activeDataSubId); } + mNeedReRunProvisioningUi = false; } else { - mCellularUpstreamPermitted = true; + mNeedReRunProvisioningUi |= showProvisioningUi; } } @@ -195,14 +212,15 @@ public class EntitlementManager { * * @param type tethering type from TetheringManager.TETHERING_{@code *} */ - public void stopProvisioningIfNeeded(int type) { - if (!isValidDownstreamType(type)) return; + public void stopProvisioningIfNeeded(int downstreamType) { + if (!isValidDownstreamType(downstreamType)) return; - mCurrentTethers.remove(type); + 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(type); + removeDownstreamMapping(downstreamType); + mExemptedDownstreams.set(downstreamType, false); } /** @@ -213,7 +231,7 @@ public class EntitlementManager { public void notifyUpstream(boolean isCellular) { if (DBG) { mLog.i("notifyUpstream: " + isCellular - + ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted + + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi); } mUsingCellularAsUpstream = isCellular; @@ -231,7 +249,7 @@ public class EntitlementManager { } private void maybeRunProvisioning(final TetheringConfiguration config) { - if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) { + if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) { return; } @@ -239,8 +257,9 @@ public class EntitlementManager { // 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 (Integer downstream : mCurrentTethers) { - if (mCellularPermitted.indexOfKey(downstream) < 0) { + 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.activeDataSubId); @@ -286,7 +305,7 @@ public class EntitlementManager { mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread"); } mEntitlementCacheValue.clear(); - mCellularPermitted.clear(); + mCurrentEntitlementResults.clear(); // TODO: refine provisioning check to isTetherProvisioningRequired() ?? if (!config.hasMobileHotspotProvisionApp() @@ -410,26 +429,25 @@ public class EntitlementManager { } private void evaluateCellularPermission(final TetheringConfiguration config) { - final boolean oldPermitted = mCellularUpstreamPermitted; - mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config) - || mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1); + final boolean permitted = isCellularUpstreamPermitted(config); if (DBG) { - mLog.i("Cellular permission change from " + oldPermitted - + " to " + mCellularUpstreamPermitted); + mLog.i("Cellular permission change from " + mLastCellularUpstreamPermitted + + " to " + permitted); } - if (mCellularUpstreamPermitted != oldPermitted) { - mLog.log("Cellular permission change: " + mCellularUpstreamPermitted); - mTetherMasterSM.sendMessage(mPermissionChangeMessageCode); + 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 (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) { + if (permitted && mCurrentEntitlementResults.size() > 0) { scheduleProvisioningRechecks(config); } else { cancelTetherProvisioningRechecks(); } + mLastCellularUpstreamPermitted = permitted; } /** @@ -441,10 +459,10 @@ public class EntitlementManager { */ protected void addDownstreamMapping(int type, int resultCode) { mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode - + " ,TetherTypeRequested: " + mCurrentTethers.contains(type)); - if (!mCurrentTethers.contains(type)) return; + + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type)); + if (!mCurrentDownstreams.get(type)) return; - mCellularPermitted.put(type, resultCode); + mCurrentEntitlementResults.put(type, resultCode); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); evaluateCellularPermission(config); } @@ -455,7 +473,7 @@ public class EntitlementManager { */ protected void removeDownstreamMapping(int type) { mLog.i("removeDownstreamMapping: " + type); - mCellularPermitted.delete(type); + mCurrentEntitlementResults.delete(type); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); evaluateCellularPermission(config); } @@ -488,18 +506,33 @@ public class EntitlementManager { * @param pw {@link PrintWriter} is used to print formatted */ public void dump(PrintWriter pw) { - pw.print("mCellularUpstreamPermitted: "); - pw.println(mCellularUpstreamPermitted); - for (Integer type : mCurrentTethers) { - pw.print("Type: "); - pw.print(typeString(type)); - if (mCellularPermitted.indexOfKey(type) > -1) { - pw.print(", Value: "); - pw.println(errorString(mCellularPermitted.get(type))); - } else { - pw.println(", Value: empty"); + 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) { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java index d450c46de718..f3dcaa2529e7 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java @@ -161,11 +161,28 @@ public class IPv6TetheringCoordinator { private void updateIPv6TetheringInterfaces() { for (IpServer ipServer : mNotifyList) { final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer); - ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp); + 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; diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java index c007c174fe4f..88c77b07e7e3 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java @@ -23,8 +23,11 @@ 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; @@ -115,11 +118,31 @@ public class OffloadController { // 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) { + ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log, + @NonNull Dependencies deps) { mHandler = h; mHwInterface = hwi; mContentResolver = contentResolver; @@ -135,6 +158,7 @@ public class OffloadController { provider = null; } mStatsProvider = provider; + mDeps = deps; } /** Start hardware offload. */ @@ -240,6 +264,7 @@ public class OffloadController { mLog.log("tethering offload started"); mNatUpdateCallbacksReceived = 0; mNatUpdateNetlinkErrors = 0; + maybeSchedulePollingStats(); } return isStarted; } @@ -255,6 +280,9 @@ public class OffloadController { mHwInterface.stopOffloadControl(); mControlInitialized = false; mConfigInitialized = false; + if (mHandler.hasCallbacks(mScheduledPollingTask)) { + mHandler.removeCallbacks(mScheduledPollingTask); + } if (wasStarted) mLog.log("tethering offload stopped"); } @@ -345,6 +373,11 @@ public class OffloadController { @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(); + }); } } @@ -366,15 +399,70 @@ public class OffloadController { // 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())) { @@ -414,6 +502,8 @@ public class OffloadController { 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 diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java index c4a1078d0be0..fe92204c25c8 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java @@ -66,6 +66,7 @@ public class OffloadHardwareInterface { private final Handler mHandler; private final SharedLog mLog; + private final Dependencies mDeps; private IOffloadControl mOffloadControl; private TetheringOffloadCallback mTetheringOffloadCallback; private ControlCallback mControlCallback; @@ -126,8 +127,76 @@ public class OffloadHardwareInterface { } 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. */ @@ -141,13 +210,7 @@ public class OffloadHardwareInterface { * share them with offload management process. */ public boolean initOffloadConfig() { - IOffloadConfig offloadConfig; - try { - offloadConfig = IOffloadConfig.getService(true /*retry*/); - } catch (RemoteException | NoSuchElementException e) { - mLog.e("getIOffloadConfig error " + e); - return false; - } + final IOffloadConfig offloadConfig = mDeps.getOffloadConfig(); if (offloadConfig == null) { mLog.e("Could not find IOffloadConfig service"); return false; @@ -159,11 +222,11 @@ public class OffloadHardwareInterface { // // h2 provides a file descriptor bound to the following netlink groups // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY). - final NativeHandle h1 = createConntrackSocket( + final NativeHandle h1 = mDeps.createConntrackSocket( NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); if (h1 == null) return false; - final NativeHandle h2 = createConntrackSocket( + final NativeHandle h2 = mDeps.createConntrackSocket( NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); if (h2 == null) { closeFdInNativeHandle(h1); @@ -198,53 +261,12 @@ public class OffloadHardwareInterface { } } - private NativeHandle createConntrackSocket(final int groups) { - 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); - } - /** Initialize the tethering offload HAL. */ public boolean initOffloadControl(ControlCallback controlCb) { mControlCallback = controlCb; if (mOffloadControl == null) { - try { - mOffloadControl = IOffloadControl.getService(true /*retry*/); - } catch (RemoteException | NoSuchElementException e) { - mLog.e("tethering offload control not supported: " + e); - return false; - } + mOffloadControl = mDeps.getOffloadControl(); if (mOffloadControl == null) { mLog.e("tethering IOffloadControl.getService() returned null"); return false; @@ -308,7 +330,6 @@ public class OffloadHardwareInterface { return stats; } - mLog.log(logmsg + YIELDS + stats); return stats; } diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java index 44eacb410d10..3ce3b4506c3f 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -62,7 +62,6 @@ 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; @@ -110,8 +109,10 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceSpecificException; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -229,6 +230,7 @@ public class Tethering { private final ConnectedClientsTracker mConnectedClientsTracker; private final TetheringThreadExecutor mExecutor; private final TetheringNotificationUpdater mNotificationUpdater; + private final UserManager mUserManager; private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID; // All the usage of mTetheringEventCallback should run in the same thread. private ITetheringEventCallback mTetheringEventCallback = null; @@ -268,12 +270,15 @@ public class Tethering { mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps); mTetherMasterSM.start(); - final NetworkStatsManager statsManager = - (NetworkStatsManager) mContext.getSystemService(Context.NETWORK_STATS_SERVICE); mHandler = mTetherMasterSM.getHandler(); - mOffloadController = new OffloadController(mHandler, - mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), - statsManager, mLog); + mOffloadController = mDeps.getOffloadController(mHandler, mLog, + new OffloadController.Dependencies() { + + @Override + public TetheringConfiguration getTetherConfig() { + return mConfig; + } + }); mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK); mForwardedDownstreams = new LinkedHashSet<>(); @@ -282,8 +287,9 @@ public class Tethering { 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, mTetherMasterSM, mLog, - TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED); + mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog, + () -> mTetherMasterSM.sendMessage( + TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { mLog.log("OBSERVED UiEnitlementFailed"); stopTethering(downstream); @@ -302,23 +308,24 @@ public class Tethering { mStateReceiver = new StateReceiver(); - final UserManager userManager = (UserManager) mContext.getSystemService( - Context.USER_SERVICE); + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mTetheringRestriction = new UserRestrictionActionListener( - userManager, this, mNotificationUpdater); + mUserManager, this, mNotificationUpdater); mExecutor = new TetheringThreadExecutor(mHandler); mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); mNetdCallback = new NetdCallback(); // Load tethering configuration. updateConfiguration(); + + startStateMachineUpdaters(); } /** * Start to register callbacks. * Call this function when tethering is ready to handle callback events. */ - public void startStateMachineUpdaters() { + private void startStateMachineUpdaters() { try { mNetd.registerUnsolicitedEventListener(mNetdCallback); } catch (RemoteException e) { @@ -513,8 +520,12 @@ public class Tethering { } mActiveTetheringRequests.put(request.tetheringType, request); - mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, - request.showProvisioningUi); + if (request.exemptFromEntitlementCheck) { + mEntitlementMgr.setExemptedDownstreamType(request.tetheringType); + } else { + mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, + request.showProvisioningUi); + } enableTetheringInternal(request.tetheringType, true /* enabled */, listener); }); } @@ -772,7 +783,7 @@ public class Tethering { // TODO: Figure out how to update for local hotspot mode interfaces. private void sendTetherStateChangedBroadcast() { - if (!mDeps.isTetheringSupported()) return; + if (!isTetheringSupported()) return; final ArrayList<String> availableList = new ArrayList<>(); final ArrayList<String> tetherList = new ArrayList<>(); @@ -1013,14 +1024,14 @@ public class Tethering { @VisibleForTesting protected static class UserRestrictionActionListener { - private final UserManager mUserManager; + 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) { - mUserManager = um; + mUserMgr = um; mWrapper = wrapper; mNotificationUpdater = updater; mDisallowTethering = false; @@ -1030,7 +1041,7 @@ public class Tethering { // 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 = mUserManager.getUserRestrictions(); + final Bundle restrictions = mUserMgr.getUserRestrictions(); final boolean newlyDisallowed = restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING); final boolean prevDisallowed = mDisallowTethering; @@ -1981,7 +1992,7 @@ public class Tethering { mHandler.post(() -> { mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission)); final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel(); - parcel.tetheringSupported = mDeps.isTetheringSupported(); + parcel.tetheringSupported = isTetheringSupported(); parcel.upstreamNetwork = mTetherUpstream; parcel.config = mConfig.toStableParcelable(); parcel.states = @@ -2104,6 +2115,20 @@ public class Tethering { } } + // 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 = + SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1; + final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.TETHER_SUPPORTED, defaultVal) != 0; + final boolean tetherEnabledInSettings = tetherSupported + && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); + + return tetherEnabledInSettings && hasTetherableConfiguration(); + } + void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { // Binder.java closes the resource for us. @SuppressWarnings("resource") @@ -2289,7 +2314,7 @@ public class Tethering { final TetherState tetherState = new TetherState( new IpServer(iface, mLooper, interfaceType, mLog, mNetd, makeControlCallback(), mConfig.enableLegacyDhcpServer, - mDeps.getIpServerDependencies())); + mConfig.enableBpfOffload, mDeps.getIpServerDependencies())); mTetherStates.put(iface, tetherState); tetherState.ipServer.start(); } diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index aeac437e24e3..48a600dfe6e1 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -73,11 +73,23 @@ public class TetheringConfiguration { 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"; + /** + * 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[] tetherableWifiP2pRegexs; @@ -89,6 +101,8 @@ public class TetheringConfiguration { public final String[] legacyDhcpRanges; public final String[] defaultIPv4DNS; public final boolean enableLegacyDhcpServer; + // TODO: Add to TetheringConfigurationParcel if required. + public final boolean enableBpfOffload; public final String[] provisioningApp; public final String provisioningAppNoUi; @@ -96,6 +110,8 @@ public class TetheringConfiguration { public final int activeDataSubId; + private final int mOffloadPollInterval; + public TetheringConfiguration(Context ctx, SharedLog log, int id) { final SharedLog configLog = log.forSubComponent("config"); @@ -116,11 +132,12 @@ public class TetheringConfiguration { isDunRequired = checkDunRequired(ctx); chooseUpstreamAutomatically = getResourceBoolean( - res, R.bool.config_tether_upstream_automatic); + res, R.bool.config_tether_upstream_automatic, false /** defaultValue */); preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired); legacyDhcpRanges = getLegacyDhcpRanges(res); defaultIPv4DNS = copy(DEFAULT_IPV4_DNS); + enableBpfOffload = getEnableBpfOffload(res); enableLegacyDhcpServer = getEnableLegacyDhcpServer(res); provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app); @@ -129,6 +146,10 @@ public class TetheringConfiguration { R.integer.config_mobile_hotspot_provision_check_period, 0 /* No periodic re-check */); + mOffloadPollInterval = getResourceInteger(res, + R.integer.config_tether_offload_poll_interval, + DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + configLog.log(toString()); } @@ -189,10 +210,16 @@ public class TetheringConfiguration { 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(enableBpfOffload); + pw.print("enableLegacyDhcpServer: "); pw.println(enableLegacyDhcpServer); } @@ -208,10 +235,12 @@ public class TetheringConfiguration { 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", enableBpfOffload)); sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer)); return String.format("TetheringConfiguration{%s}", sj.toString()); } @@ -246,6 +275,10 @@ public class TetheringConfiguration { return (tm != null) ? tm.isTetheringApnRequired() : false; } + public int getOffloadPollInterval() { + return mOffloadPollInterval; + } + 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); @@ -312,11 +345,11 @@ public class TetheringConfiguration { } } - private static boolean getResourceBoolean(Resources res, int resId) { + private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) { try { return res.getBoolean(resId); } catch (Resources.NotFoundException e404) { - return false; + return defaultValue; } } @@ -337,14 +370,36 @@ public class TetheringConfiguration { } } + 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) - || getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER); + 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 boolean getDeviceConfigBoolean(final String name) { - return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, false /** defaultValue */); + protected String getDeviceConfigProperty(String name) { + return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name); } private Resources getResources(Context ctx, int subId) { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java index 9b54b5ff2403..ce546c701a61 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java @@ -16,6 +16,7 @@ package com.android.networkstack.tethering; +import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.net.INetd; @@ -47,6 +48,19 @@ public abstract class TetheringDependencies { } /** + * 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, @@ -82,9 +96,9 @@ public abstract class TetheringDependencies { /** * Get a reference to the EntitlementManager to be used by tethering. */ - public EntitlementManager getEntitlementManager(Context ctx, StateMachine target, - SharedLog log, int what) { - return new EntitlementManager(ctx, target, log, what); + public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { + return new EntitlementManager(ctx, h, log, callback); } /** diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java index c82e2be72ad2..c11e86258d3c 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java @@ -16,6 +16,8 @@ package com.android.networkstack.tethering; +import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.TETHER_PRIVILEGED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; @@ -38,15 +40,12 @@ import android.net.TetheringRequestParcel; import android.net.dhcp.DhcpServerCallbacks; import android.net.dhcp.DhcpServingParamsParcel; import android.net.ip.IpServer; -import android.net.util.SharedLog; import android.os.Binder; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.SystemProperties; -import android.os.UserManager; import android.provider.Settings; import android.util.Log; @@ -66,21 +65,14 @@ import java.io.PrintWriter; public class TetheringService extends Service { private static final String TAG = TetheringService.class.getSimpleName(); - private final SharedLog mLog = new SharedLog(TAG); private TetheringConnector mConnector; - private Context mContext; - private TetheringDependencies mDeps; - private Tethering mTethering; - private UserManager mUserManager; @Override public void onCreate() { - mLog.mark("onCreate"); - mDeps = getTetheringDependencies(); - mContext = mDeps.getContext(); - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - mTethering = makeTethering(mDeps); - mTethering.startStateMachineUpdaters(); + 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); } /** @@ -92,21 +84,10 @@ public class TetheringService extends Service { return new Tethering(deps); } - /** - * Create a binder connector for the system server to communicate with the tethering. - */ - private synchronized IBinder makeConnector() { - if (mConnector == null) { - mConnector = new TetheringConnector(mTethering, TetheringService.this); - } - return mConnector; - } - @NonNull @Override public IBinder onBind(Intent intent) { - mLog.mark("onBind"); - return makeConnector(); + return mConnector; } private static class TetheringConnector extends ITetheringConnector.Stub { @@ -151,7 +132,12 @@ public class TetheringService extends Service { @Override public void startTethering(TetheringRequestParcel request, String callerPkg, String callingAttributionTag, IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; + if (checkAndNotifyCommonError(callerPkg, + callingAttributionTag, + request.exemptFromEntitlementCheck /* onlyAllowPrivileged */, + listener)) { + return; + } mTethering.startTethering(request, listener); } @@ -179,7 +165,7 @@ public class TetheringService extends Service { public void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { try { - if (!mService.hasTetherAccessPermission()) { + if (!hasTetherAccessPermission()) { callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); return; } @@ -191,7 +177,7 @@ public class TetheringService extends Service { public void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { try { - if (!mService.hasTetherAccessPermission()) { + if (!hasTetherAccessPermission()) { callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); return; } @@ -226,14 +212,22 @@ public class TetheringService extends Service { mTethering.dump(fd, writer, args); } - private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag, - IIntResultListener listener) { + 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 (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) { + if (!hasTetherChangePermission(callerPkg, callingAttributionTag, + onlyAllowPrivileged)) { listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); return true; } - if (!mService.isTetheringSupported()) { + if (!mTethering.isTetheringSupported()) { listener.onResult(TETHER_ERROR_UNSUPPORTED); return true; } @@ -244,13 +238,14 @@ public class TetheringService extends Service { return false; } - private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag, - ResultReceiver receiver) { - if (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) { + 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 (!mService.isTetheringSupported()) { + if (!mTethering.isTetheringSupported()) { receiver.send(TETHER_ERROR_UNSUPPORTED, null); return true; } @@ -258,40 +253,31 @@ public class TetheringService extends Service { return false; } - } - - // if ro.tether.denied = true we default to no tethering - // gservices could set the secure setting to 1 though to enable it on a build where it - // had previously been turned off. - private boolean isTetheringSupported() { - final int defaultVal = - SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1; - final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TETHER_SUPPORTED, defaultVal) != 0; - final boolean tetherEnabledInSettings = tetherSupported - && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); - - return tetherEnabledInSettings && mTethering.hasTetherableConfiguration(); - } - - private boolean hasTetherChangePermission(String callerPkg, String callingAttributionTag) { - if (checkCallingOrSelfPermission( - android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { - return true; + private boolean hasTetherPrivilegedPermission() { + return mService.checkCallingOrSelfPermission(TETHER_PRIVILEGED) == PERMISSION_GRANTED; } - if (mTethering.isTetherProvisioningRequired()) return false; + private boolean hasTetherChangePermission(final String callerPkg, + final String callingAttributionTag, final boolean onlyAllowPrivileged) { + if (hasTetherPrivilegedPermission()) return true; + if (onlyAllowPrivileged || mTethering.isTetherProvisioningRequired()) return false; - int uid = Binder.getCallingUid(); - // If callerPkg's uid is not same as Binder.getCallingUid(), - // checkAndNoteWriteSettingsOperation will return false and the operation will be denied. - if (checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg, - callingAttributionTag, false /* throwException */)) { - return true; + 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 */); } - return false; + private boolean hasTetherAccessPermission() { + if (hasTetherPrivilegedPermission()) return true; + + return mService.checkCallingOrSelfPermission( + ACCESS_NETWORK_STATE) == PERMISSION_GRANTED; + } } /** @@ -300,114 +286,91 @@ public class TetheringService extends Service { * * @return {@code true} iff the package is allowed to write settings. */ - // TODO: Remove method and replace with direct call once R code is pushed to AOSP - private static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, + @VisibleForTesting + boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, boolean throwException) { return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, throwException); } - private boolean hasTetherAccessPermission() { - if (checkCallingOrSelfPermission( - android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { - return true; - } - - if (checkCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) { - return true; - } - - return false; - } - - /** * An injection method for testing. */ @VisibleForTesting - public TetheringDependencies getTetheringDependencies() { - if (mDeps == null) { - mDeps = 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(); - } + 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 boolean isTetheringSupported() { - return TetheringService.this.isTetheringSupported(); - } + @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 Context getContext() { + return TetheringService.this; + } - @Override - public IpServer.Dependencies getIpServerDependencies() { - return new IpServer.Dependencies() { - @Override - public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, - DhcpServerCallbacks cb) { + @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 { - 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) { } - } + 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); + // 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; } - } catch (InterruptedException e) { - Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector"); - return null; + Thread.sleep(200); } - return INetworkStackConnector.Stub.asInterface(connector); + } 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(); - } - }; - } - return mDeps; + @Override + public BluetoothAdapter getBluetoothAdapter() { + return BluetoothAdapter.getDefaultAdapter(); + } + }; } } diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp index 3305ed084481..ed69b7d63cb4 100644 --- a/packages/Tethering/tests/integration/Android.bp +++ b/packages/Tethering/tests/integration/Android.bp @@ -63,7 +63,6 @@ android_test { // NetworkStackTests. android_test { name: "TetheringCoverageTests", - certificate: "platform", platform_apis: true, test_suites: ["device-tests", "mts"], test_config: "AndroidTest_Coverage.xml", diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index 9b7d68309fbf..d1e8f5fc777d 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -82,7 +82,7 @@ android_library { android_test { name: "TetheringTests", - certificate: "platform", + platform_apis: true, test_suites: [ "device-tests", "mts", diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml index 31eaabff5274..355342f64371 100644 --- a/packages/Tethering/tests/unit/AndroidManifest.xml +++ b/packages/Tethering/tests/unit/AndroidManifest.xml @@ -16,9 +16,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.networkstack.tethering.tests.unit"> - <uses-permission android:name="android.permission.READ_PHONE_STATE"/> - <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/> - <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> <service diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index f9be7b9d3664..307ebf17d229 100644 --- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -17,7 +17,9 @@ 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; @@ -38,6 +40,7 @@ import static android.net.shared.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; @@ -67,10 +70,12 @@ import android.net.MacAddress; import android.net.RouteInfo; import android.net.TetherOffloadRuleParcel; 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.SharedLog; @@ -94,6 +99,7 @@ import org.mockito.MockitoAnnotations; import java.net.Inet4Address; import java.net.InetAddress; import java.util.Arrays; +import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest @@ -106,6 +112,7 @@ public class IpServerTest { private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.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 */); @@ -130,10 +137,11 @@ public class IpServerTest { private NeighborEventConsumer mNeighborEventConsumer; private void initStateMachine(int interfaceType) throws Exception { - initStateMachine(interfaceType, false /* usingLegacyDhcp */); + initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); } - private void initStateMachine(int interfaceType, boolean usingLegacyDhcp) throws Exception { + private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, + boolean usingBpfOffload) throws Exception { doAnswer(inv -> { final IDhcpServerCallbacks cb = inv.getArgument(2); new Thread(() -> { @@ -165,7 +173,7 @@ public class IpServerTest { mIpServer = new IpServer( IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, - mCallback, usingLegacyDhcp, mDependencies); + mCallback, usingLegacyDhcp, usingBpfOffload, mDependencies); mIpServer.start(); mNeighborEventConsumer = neighborCaptor.getValue(); @@ -179,17 +187,18 @@ public class IpServerTest { private void initTetheredStateMachine(int interfaceType, String upstreamIface) throws Exception { - initTetheredStateMachine(interfaceType, upstreamIface, false); + initTetheredStateMachine(interfaceType, upstreamIface, false, + DEFAULT_USING_BPF_OFFLOAD); } private void initTetheredStateMachine(int interfaceType, String upstreamIface, - boolean usingLegacyDhcp) throws Exception { - initStateMachine(interfaceType, usingLegacyDhcp); + 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); + dispatchTetherConnectionChanged(upstreamIface, lp, 0); } reset(mNetd, mCallback); } @@ -204,7 +213,8 @@ public class IpServerTest { when(mDependencies.getIpNeighborMonitor(any(), any(), any())) .thenReturn(mIpNeighborMonitor); mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog, - mNetd, mCallback, false /* usingLegacyDhcp */, mDependencies); + mNetd, mCallback, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD, + mDependencies); mIpServer.start(); mLooper.dispatchAll(); verify(mCallback).updateInterfaceState( @@ -493,8 +503,62 @@ public class IpServerTest { } @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")); + + // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals + // onNewPrefixRequest callback. + eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24")); + mLooper.dispatchAll(); + + final ArgumentCaptor<LinkProperties> lpCaptor = + ArgumentCaptor.forClass(LinkProperties.class); + InOrder inOrder = inOrder(mNetd, mCallback); + inOrder.verify(mCallback).updateInterfaceState( + mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); + inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); + 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(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 */); + initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */, + DEFAULT_USING_BPF_OFFLOAD); dispatchTetherConnectionChanged(UPSTREAM_IFACE); verify(mDependencies, never()).makeDhcpServer(any(), any(), any()); @@ -577,7 +641,8 @@ public class IpServerTest { @Test public void addRemoveipv6ForwardingRules() throws Exception { - initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */); + initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, + DEFAULT_USING_BPF_OFFLOAD); final int myIfindex = TEST_IFACE_PARAMS.index; final int notMyIfindex = myIfindex - 1; @@ -631,7 +696,7 @@ public class IpServerTest { InOrder inOrder = inOrder(mNetd); LinkProperties lp = new LinkProperties(); lp.setInterfaceName(UPSTREAM_IFACE2); - dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp); + dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB)); @@ -639,7 +704,7 @@ public class IpServerTest { reset(mNetd); // When the upstream is lost, rules are removed. - dispatchTetherConnectionChanged(null, null); + dispatchTetherConnectionChanged(null, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA)); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB)); reset(mNetd); @@ -652,19 +717,19 @@ public class IpServerTest { // Rules can be added again once upstream IPv6 connectivity is available. lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); + dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); // If upstream IPv6 connectivity is lost, rules are removed. reset(mNetd); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, null); + dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); // When the interface goes down, rules are removed. lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); + dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); @@ -678,19 +743,116 @@ public class IpServerTest { reset(mNetd); } - 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()); - final DhcpServingParamsParcel params = mDhcpParamsCaptor.getValue(); + @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"); + + reset(mNetd); + + // Expect that rules can be only added/removed when the BPF offload config is enabled. + // Note that the usingBpfOffload false 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 this test once we don't need this check anymore. + for (boolean usingBpfOffload : new boolean[]{true, false}) { + initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, + usingBpfOffload); + + // A neighbor is added. + recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA); + if (usingBpfOffload) { + verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neigh, macA)); + } else { + verify(mNetd, never()).tetherOffloadRuleAdd(any()); + } + reset(mNetd); + + // A neighbor is deleted. + recvDelNeigh(myIfindex, neigh, NUD_STALE, macA); + if (usingBpfOffload) { + verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neigh, macNull)); + } else { + verify(mNetd, never()).tetherOffloadRuleRemove(any()); + } + reset(mNetd); + } + } + + @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); + } + + private void assertDhcpServingParams(final DhcpServingParamsParcel params, + final IpPrefix prefix) { // Last address byte is random - assertTrue(expectedPrefix.contains(intToInet4AddressHTH(params.serverAddr))); - assertEquals(expectedPrefix.getPrefixLength(), params.serverAddrPrefixLength); + 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); } /** @@ -721,9 +883,10 @@ public class IpServerTest { * @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) { + private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, + int ttlAdjustment) { dispatchTetherConnectionChanged(upstreamIface); - mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp); + mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); mLooper.dispatchAll(); } 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 index 8bd0edc2490d..72fa916b9e42 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java @@ -37,6 +37,8 @@ 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; @@ -45,7 +47,7 @@ import android.content.Context; import android.content.res.Resources; import android.net.util.SharedLog; import android.os.Bundle; -import android.os.Message; +import android.os.Handler; import android.os.PersistableBundle; import android.os.ResultReceiver; import android.os.SystemProperties; @@ -56,26 +58,22 @@ import android.telephony.CarrierConfigManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; 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; -import java.util.ArrayList; - @RunWith(AndroidJUnit4.class) @SmallTest public final class EntitlementManagerTest { - private static final int EVENT_EM_UPDATE = 1; private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; @@ -90,8 +88,8 @@ public final class EntitlementManagerTest { private final PersistableBundle mCarrierConfig = new PersistableBundle(); private final TestLooper mLooper = new TestLooper(); private Context mMockContext; + private Runnable mPermissionChangeCallback; - private TestStateMachine mSM; private WrappedEntitlementManager mEnMgr; private TetheringConfiguration mConfig; private MockitoSession mMockingSession; @@ -112,9 +110,9 @@ public final class EntitlementManagerTest { public int uiProvisionCount = 0; public int silentProvisionCount = 0; - public WrappedEntitlementManager(Context ctx, StateMachine target, - SharedLog log, int what) { - super(ctx, target, log, what); + public WrappedEntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { + super(ctx, h, log, callback); } public void reset() { @@ -149,9 +147,8 @@ public final class EntitlementManagerTest { doReturn(false).when( () -> SystemProperties.getBoolean( eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean())); - doReturn(false).when( - () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean())); + doReturn(null).when( + () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), anyString())); when(mResources.getStringArray(R.array.config_tether_dhcp_range)) .thenReturn(new String[0]); @@ -169,8 +166,9 @@ public final class EntitlementManagerTest { when(mLog.forSubComponent(anyString())).thenReturn(mLog); mMockContext = new MockContext(mContext); - mSM = new TestStateMachine(); - mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE); + 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(() -> { @@ -180,10 +178,6 @@ public final class EntitlementManagerTest { @After public void tearDown() throws Exception { - if (mSM != null) { - mSM.quit(); - mSM = null; - } mMockingSession.finishMocking(); } @@ -350,68 +344,105 @@ public final class EntitlementManagerTest { 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()); - mLooper.dispatchAll(); + 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; @@ -421,16 +452,22 @@ public final class EntitlementManagerTest { 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(); @@ -438,44 +475,58 @@ public final class EntitlementManagerTest { 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(); } @@ -492,31 +543,32 @@ public final class EntitlementManagerTest { verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); } - public class TestStateMachine extends StateMachine { - public final ArrayList<Message> messages = new ArrayList<>(); - private final State - mLoggingState = new EntitlementManagerTest.TestStateMachine.LoggingState(); + @Test + public void testsetExemptedDownstreamType() throws Exception { + setupForRequiredProvisioning(); + // Cellular upstream is not permitted when no entitlement result. + assertFalse(mEnMgr.isCellularUpstreamPermitted()); - class LoggingState extends State { - @Override public void enter() { - messages.clear(); - } + // If there is exempted downstream and no other non-exempted downstreams, cellular is + // permitted. + mEnMgr.setExemptedDownstreamType(TETHERING_WIFI); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); - @Override public void exit() { - messages.clear(); - } + // 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()); - @Override public boolean processMessage(Message msg) { - messages.add(msg); - return false; - } - } + // 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()); - public TestStateMachine() { - super("EntitlementManagerTest.TestStateMachine", mLooper.getLooper()); - addState(mLoggingState); - setInitialState(mLoggingState); - super.start(); - } + 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 index 820f25514532..f2b5314e5a17 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java @@ -128,7 +128,7 @@ public class IPv6TetheringCoordinatorTest { 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(0), eq(0), + verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties v6OnlyLink = lp.getValue(); assertOnlyOneV6AddressAndNoV4(v6OnlyLink); @@ -140,7 +140,7 @@ public class IPv6TetheringCoordinatorTest { 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(0), eq(0), + verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties localOnlyLink = lp.getValue(); assertNotNull(localOnlyLink); 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 index 1c81c1247ded..071a290e657b 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java @@ -15,13 +15,20 @@ */ 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); @@ -35,6 +42,15 @@ public class MockTetheringService extends TetheringService { 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; } 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 index 65797200fa92..b291438937c7 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java @@ -29,15 +29,15 @@ 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.MiscAssertsKt.assertContainsAll; import static com.android.testutils.MiscAssertsKt.assertThrows; -import static com.android.testutils.NetworkStatsUtilsKt.orderInsensitiveEquals; +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.ArgumentMatchers.anyInt; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; @@ -63,10 +63,10 @@ import android.net.LinkProperties; import android.net.NetworkStats; import android.net.NetworkStats.Entry; import android.net.RouteInfo; -import android.net.netstats.provider.INetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.net.util.SharedLog; import android.os.Handler; -import android.os.Looper; +import android.os.test.TestLooper; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.test.mock.MockContentResolver; @@ -75,7 +75,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; -import com.android.testutils.HandlerUtilsKt; +import com.android.testutils.TestableNetworkStatsProviderCbBinder; import org.junit.After; import org.junit.Before; @@ -109,13 +109,22 @@ public class OffloadControllerTest { @Mock private ApplicationInfo mApplicationInfo; @Mock private Context mContext; @Mock private NetworkStatsManager mStatsManager; - @Mock private INetworkStatsProviderCallback mTetherStatsProviderCb; + @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); @@ -125,6 +134,7 @@ public class OffloadControllerTest { 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 { @@ -144,13 +154,17 @@ public class OffloadControllerTest { Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); } + private void setOffloadPollInterval(int interval) { + when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval); + } + private void waitForIdle() { - HandlerUtilsKt.waitForIdle(new Handler(Looper.getMainLooper()), WAIT_FOR_IDLE_TIMEOUT); + mTestLooper.dispatchAll(); } private OffloadController makeOffloadController() throws Exception { - OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()), - mHardware, mContentResolver, mStatsManager, new SharedLog("test")); + 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); @@ -158,6 +172,7 @@ public class OffloadControllerTest { tetherStatsProviderCaptor.capture()); mTetherStatsProvider = tetherStatsProviderCaptor.getValue(); assertNotNull(mTetherStatsProvider); + mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder(); mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb); return offload; } @@ -346,9 +361,9 @@ public class OffloadControllerTest { 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)); + RTN_UNICAST)); stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null, - RTN_UNICAST)); + RTN_UNICAST)); assertTrue(lp.addStackedLink(stacked)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). @@ -453,20 +468,12 @@ public class OffloadControllerTest { .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321)); - assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStats)); - assertTrue(orderInsensitiveEquals(expectedUidStats, uidStats)); - - final ArgumentCaptor<NetworkStats> ifaceStatsCaptor = ArgumentCaptor.forClass( - NetworkStats.class); - final ArgumentCaptor<NetworkStats> uidStatsCaptor = ArgumentCaptor.forClass( - NetworkStats.class); + assertNetworkStatsEquals(expectedIfaceStats, ifaceStats); + assertNetworkStatsEquals(expectedUidStats, uidStats); // Force pushing stats update to verify the stats reported. mTetherStatsProvider.pushTetherStats(); - verify(mTetherStatsProviderCb, times(1)) - .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture()); - assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStatsCaptor.getValue())); - assertTrue(orderInsensitiveEquals(expectedUidStats, uidStatsCaptor.getValue())); + mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats); when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( new ForwardedStats(100000, 100000)); @@ -492,11 +499,10 @@ public class OffloadControllerTest { .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321)); - assertTrue(orderInsensitiveEquals(expectedIfaceStatsAccu, ifaceStatsAccu)); - assertTrue(orderInsensitiveEquals(expectedUidStatsAccu, uidStatsAccu)); + assertNetworkStatsEquals(expectedIfaceStatsAccu, ifaceStatsAccu); + assertNetworkStatsEquals(expectedUidStatsAccu, uidStatsAccu); // Verify that only diff of stats is reported. - reset(mTetherStatsProviderCb); mTetherStatsProvider.pushTetherStats(); final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2) .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0)) @@ -505,10 +511,8 @@ public class OffloadControllerTest { final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2) .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000)); - verify(mTetherStatsProviderCb, times(1)) - .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture()); - assertTrue(orderInsensitiveEquals(expectedIfaceStatsDiff, ifaceStatsCaptor.getValue())); - assertTrue(orderInsensitiveEquals(expectedUidStatsDiff, uidStatsCaptor.getValue())); + mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff, + expectedUidStatsDiff); } @Test @@ -585,7 +589,7 @@ public class OffloadControllerTest { OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); callback.onStoppedLimitReached(); - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); } @Test @@ -689,8 +693,8 @@ public class OffloadControllerTest { verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); // TODO: verify the exact stats reported. - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); - verifyNoMoreInteractions(mTetherStatsProviderCb); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); + mTetherStatsProviderCb.assertNoCallback(); verifyNoMoreInteractions(mHardware); } @@ -754,8 +758,8 @@ public class OffloadControllerTest { // Verify forwarded stats behaviour. verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); - verifyNoMoreInteractions(mTetherStatsProviderCb); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); + mTetherStatsProviderCb.assertNoCallback(); // TODO: verify local prefixes and downstreams are also pushed to the HAL. verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); @@ -774,4 +778,50 @@ public class OffloadControllerTest { 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 new file mode 100644 index 000000000000..f8ff1cb29c23 --- /dev/null +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +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 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.util.SharedLog; +import android.os.Handler; +import android.os.NativeHandle; +import android.os.test.TestLooper; +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.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; + + 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))); + } + + 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/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java index 07ddea43f4e8..1999ad786ed4 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java @@ -30,7 +30,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess 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.eq; import static org.mockito.Mockito.when; @@ -109,12 +108,14 @@ public class TetheringConfigurationTest { .mockStatic(DeviceConfig.class) .strictness(Strictness.WARN) .startMocking(); - doReturn(false).when( - () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean())); + 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" }); @@ -125,6 +126,8 @@ public class TetheringConfigurationTest { .thenReturn(new String[0]); when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); + initializeBpfOffloadConfiguration(true, null /* unset */); + mHasTelephonyManager = true; mMockContext = new MockContext(mContext); mEnableLegacyDhcpServer = false; @@ -276,13 +279,57 @@ public class TetheringConfigurationTest { 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.enableBpfOffload); + } + + @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.enableBpfOffload); + } + } + + @Test + public void testBpfOffloadDisabledByResource() { + initializeBpfOffloadConfiguration(false, null /* unset */); + final TetheringConfiguration disableByRes = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertFalse(disableByRes.enableBpfOffload); + } + + @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.enableBpfOffload); + } + } + @Test public void testNewDhcpServerDisabled() { when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( true); - doReturn(false).when( - () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean())); + 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); @@ -290,9 +337,9 @@ public class TetheringConfigurationTest { when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); - doReturn(true).when( - () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean())); + 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); @@ -303,9 +350,9 @@ public class TetheringConfigurationTest { public void testNewDhcpServerEnabled() { when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); - doReturn(false).when( - () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY), - eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean())); + 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); @@ -314,6 +361,23 @@ public class TetheringConfigurationTest { } @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( 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 index 7df9fc685053..cf060ba95d25 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java @@ -16,20 +16,29 @@ 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; @@ -51,13 +60,14 @@ import org.mockito.MockitoAnnotations; @SmallTest public final class TetheringServiceTest { private static final String TEST_IFACE_NAME = "test_wlan0"; - private static final String TEST_CALLER_PKG = "test_pkg"; + 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. @@ -71,9 +81,26 @@ public final class TetheringServiceTest { } } + 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(), @@ -83,116 +110,364 @@ public final class TetheringServiceTest { mTetheringConnector = mockConnector.getTetheringConnector(); final MockTetheringService service = mockConnector.getService(); mTethering = service.getTethering(); - verify(mTethering).startStateMachineUpdaters(); - when(mTethering.hasTetherableConfiguration()).thenReturn(true); } @After public void tearDown() throws Exception { mServiceTestRule.unbindService(); + mUiAutomation.dropShellPermissionIdentity(); } - @Test - public void testTether() throws Exception { + 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); - final TestTetheringResult result = new TestTetheringResult(); mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).hasTetherableConfiguration(); + verify(mTethering).isTetheringSupported(); verify(mTethering).tether(TEST_IFACE_NAME); - verifyNoMoreInteractions(mTethering); result.assertResult(TETHER_ERROR_NO_ERROR); } @Test - public void testUntether() throws Exception { + 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); - final TestTetheringResult result = new TestTetheringResult(); mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).hasTetherableConfiguration(); + verify(mTethering).isTetheringSupported(); verify(mTethering).untether(TEST_IFACE_NAME); - verifyNoMoreInteractions(mTethering); result.assertResult(TETHER_ERROR_NO_ERROR); } @Test - public void testSetUsbTethering() throws Exception { + 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); - final TestTetheringResult result = new TestTetheringResult(); mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).hasTetherableConfiguration(); + verify(mTethering).isTetheringSupported(); verify(mTethering).setUsbTethering(true /* enable */); - verifyNoMoreInteractions(mTethering); 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 TestTetheringResult result = new TestTetheringResult(); final TetheringRequestParcel request = new TetheringRequestParcel(); request.tetheringType = TETHERING_WIFI; - mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result); - verify(mTethering).hasTetherableConfiguration(); - verify(mTethering).startTethering(eq(request), eq(result)); - verifyNoMoreInteractions(mTethering); + + 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(); + }); } @Test - public void testStopTethering() throws Exception { - final TestTetheringResult result = new TestTetheringResult(); - mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, - result); - verify(mTethering).hasTetherableConfiguration(); + public void testStartTetheringWithExemptFromEntitlementCheck() throws Exception { + final TetheringRequestParcel request = new TetheringRequestParcel(); + request.tetheringType = TETHERING_WIFI; + request.exemptFromEntitlementCheck = true; + + runAsTetherPrivileged((result) -> { + runStartTethering(result, request); + verifyNoMoreInteractionsForTethering(); + }); + + runAsWriteSettings((result) -> { + mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, + result); + result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); + verifyNoMoreInteractionsForTethering(); + }); + } + + 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); - verifyNoMoreInteractions(mTethering); result.assertResult(TETHER_ERROR_NO_ERROR); } @Test - public void testRequestLatestTetheringEntitlementResult() throws Exception { - final ResultReceiver result = new ResultReceiver(null); + 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).hasTetherableConfiguration(); + verify(mTethering).isTetheringSupported(); verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI), eq(result), eq(true) /* showEntitlementUi */); - verifyNoMoreInteractions(mTethering); } @Test - public void testRegisterTetheringEventCallback() throws Exception { + 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)); - verifyNoMoreInteractions(mTethering); } @Test - public void testUnregisterTetheringEventCallback() throws Exception { + 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)); - verifyNoMoreInteractions(mTethering); + verify(mTethering).unregisterTetheringEventCallback(eq(mITetheringEventCallback)); } @Test - public void testStopAllTethering() throws Exception { - final TestTetheringResult result = new TestTetheringResult(); + 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).hasTetherableConfiguration(); + verify(mTethering).isTetheringSupported(); verify(mTethering).untetherAll(); - verifyNoMoreInteractions(mTethering); result.assertResult(TETHER_ERROR_NO_ERROR); } @Test - public void testIsTetheringSupported() throws Exception { - final TestTetheringResult result = new TestTetheringResult(); + 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).hasTetherableConfiguration(); - verifyNoMoreInteractions(mTethering); + 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 index 4471f649691f..7734a3c61eaf 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -57,6 +57,7 @@ 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; @@ -150,6 +151,8 @@ 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; @@ -170,6 +173,8 @@ public class TetheringTest { private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0"; private static final String TEST_NCM_IFNAME = "test_ncm0"; 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; @@ -212,6 +217,9 @@ public class TetheringTest { private Tethering mTethering; private PhoneStateListener mPhoneStateListener; private InterfaceConfigurationParcel mInterfaceConfiguration; + private TetheringConfiguration mConfig; + private EntitlementManager mEntitleMgr; + private OffloadController mOffloadCtrl; private class TestContext extends BroadcastInterceptingContext { TestContext(Context base) { @@ -297,14 +305,15 @@ public class TetheringTest { } } - private class MockTetheringConfiguration extends TetheringConfiguration { - MockTetheringConfiguration(Context ctx, SharedLog log, int id) { + // 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 boolean getDeviceConfigBoolean(final String name) { - return false; + protected String getDeviceConfigProperty(final String name) { + return null; } @Override @@ -328,6 +337,15 @@ public class TetheringTest { } @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) { mUpstreamNetworkMonitorMasterSM = target; @@ -352,6 +370,13 @@ public class TetheringTest { } @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; } @@ -359,7 +384,8 @@ public class TetheringTest { @Override public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log, int subId) { - return new MockTetheringConfiguration(ctx, log, subId); + mConfig = spy(new MyTetheringConfiguration(ctx, log, subId)); + return mConfig; } @Override @@ -459,18 +485,6 @@ public class TetheringTest { MockitoAnnotations.initMocks(this); 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[] { "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(false); when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); when(mNetd.interfaceGetList()) @@ -489,6 +503,7 @@ public class TetheringTest { mServiceContext = new TestContext(mContext); mContentResolver = new MockContentResolver(mServiceContext); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); + setTetheringSupported(true /* supported */); mIntents = new Vector<>(); mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -499,7 +514,6 @@ public class TetheringTest { mServiceContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_TETHER_STATE_CHANGED)); mTethering = makeTethering(); - mTethering.startStateMachineUpdaters(); verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any()); verify(mNetd).registerUnsolicitedEventListener(any()); final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor = @@ -510,22 +524,47 @@ public class TetheringTest { 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); + return createTetheringRequestParcel(type, null, null, false); } private TetheringRequestParcel createTetheringRequestParcel(final int type, - final LinkAddress serverAddr, final LinkAddress clientAddr) { + 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 = false; + request.exemptFromEntitlementCheck = exempt; request.showProvisioningUi = false; return request; @@ -646,9 +685,7 @@ public class TetheringTest { } private void prepareUsbTethering(UpstreamNetworkState upstreamState) { - when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) - .thenReturn(upstreamState); + initTetheringUpstream(upstreamState); // Emulate pressing the USB tethering button in Settings UI. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null); @@ -674,7 +711,7 @@ public class TetheringTest { verify(mNetd, times(1)).interfaceGetList(); // UpstreamNetworkMonitor should receive selected upstream - verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any()); + verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream(); verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network); } @@ -846,8 +883,7 @@ public class TetheringTest { // Then 464xlat comes up upstreamState = buildMobile464xlatUpstreamState(); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) - .thenReturn(upstreamState); + initTetheringUpstream(upstreamState); // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES. mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage( @@ -1318,9 +1354,7 @@ public class TetheringTest { callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); // 2. Enable wifi tethering. UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState(); - when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) - .thenReturn(upstreamState); + initTetheringUpstream(upstreamState); when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); mLooper.dispatchAll(); @@ -1636,7 +1670,7 @@ public class TetheringTest { // Enable USB tethering and check that Tethering starts USB. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null), firstResult); + null, null, false), firstResult); mLooper.dispatchAll(); firstResult.assertHasResult(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); @@ -1644,7 +1678,7 @@ public class TetheringTest { // Enable USB tethering again with the same request and expect no change to USB. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null), secondResult); + null, null, false), secondResult); mLooper.dispatchAll(); secondResult.assertHasResult(); verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE); @@ -1653,7 +1687,7 @@ public class TetheringTest { // Enable USB tethering with a different request and expect that USB is stopped and // started. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr), thirdResult); + serverLinkAddr, clientLinkAddr, false), thirdResult); mLooper.dispatchAll(); thirdResult.assertHasResult(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE); @@ -1677,7 +1711,7 @@ public class TetheringTest { final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor = ArgumentCaptor.forClass(DhcpServingParamsParcel.class); mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr), null); + serverLinkAddr, clientLinkAddr, false), null); mLooper.dispatchAll(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); @@ -1697,7 +1731,7 @@ public class TetheringTest { final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM) mTetheringDependencies.mUpstreamNetworkMonitorMasterSM; final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState); + initTetheringUpstream(upstreamState); stateMachine.chooseUpstreamType(true); verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network)); @@ -1709,7 +1743,7 @@ public class TetheringTest { final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM) mTetheringDependencies.mUpstreamNetworkMonitorMasterSM; final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); - when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState); + initTetheringUpstream(upstreamState); stateMachine.chooseUpstreamType(true); stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState); @@ -1726,6 +1760,82 @@ public class TetheringTest { 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(); + } // TODO: Test that a request for hotspot mode doesn't interfere with an // already operating tethering mode interface. } diff --git a/services/Android.bp b/services/Android.bp index b4d8393683ba..0d221b930f5d 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -122,13 +122,13 @@ droidstubs { removed_api_file: "api/removed.txt", }, last_released: { - api_file: ":last-released-system-server-api", + api_file: ":android.api.system-server.latest", removed_api_file: "api/removed.txt", baseline_file: ":system-server-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-system-server-api", + new_since: ":android.api.system-server.latest", baseline_file: "api/lint-baseline.txt", }, }, diff --git a/services/core/Android.bp b/services/core/Android.bp index a2f73a6730b5..74fddb2b630e 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -28,7 +28,7 @@ java_library_static { "android.hardware.power-V1.0-java", "android.hardware.tv.cec-V1.0-java", "android.hardware.vibrator-java", - "android.net.ipsec.ike.stubs.module_libs_api", + "android.net.ipsec.ike.stubs.module_lib", "app-compat-annotations", "framework-tethering-stubs-module_libs_api", ], @@ -53,8 +53,8 @@ java_library_static { "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", - "dnsresolver_aidl_interface-V4-java", - "netd_event_listener_interface-java", + "dnsresolver_aidl_interface-java", + "netd_aidl_interfaces-platform-java", ], } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 58e06e00ef2d..4b66cea88ed0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2732,7 +2732,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the Messenger, but if this ever changes, not making a defensive copy // here will give attack vectors to clients using this code path. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(); + networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid); } updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); break; @@ -3079,30 +3079,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void notifyDataStallSuspected(DataStallReportParcelable p) { - final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, - p.detectionMethod, mNetId, p.timestampMillis); - - final PersistableBundle extras = new PersistableBundle(); - switch (p.detectionMethod) { - case DETECTION_METHOD_DNS_EVENTS: - extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); - break; - case DETECTION_METHOD_TCP_METRICS: - extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); - extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, - p.tcpMetricsCollectionPeriodMillis); - break; - default: - log("Unknown data stall detection method, ignoring: " + p.detectionMethod); - return; - } - msg.setData(new Bundle(extras)); - - // NetworkStateTrackerHandler currently doesn't take any actions based on data - // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid - // the cost of going through two handlers. - mConnectivityDiagnosticsHandler.sendMessage(msg); + ConnectivityService.this.notifyDataStallSuspected(p, mNetId); } @Override @@ -3116,6 +3093,37 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) { + log("Data stall detected with methods: " + p.detectionMethod); + + final PersistableBundle extras = new PersistableBundle(); + int detectionMethod = 0; + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { + extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); + detectionMethod |= DETECTION_METHOD_DNS_EVENTS; + } + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { + extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); + extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, + p.tcpMetricsCollectionPeriodMillis); + detectionMethod |= DETECTION_METHOD_TCP_METRICS; + } + + final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId, + p.timestampMillis); + msg.setData(new Bundle(extras)); + + // NetworkStateTrackerHandler currently doesn't take any actions based on data + // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid + // the cost of going through two handlers. + mConnectivityDiagnosticsHandler.sendMessage(msg); + } + + private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) { + return (p.detectionMethod & detectionMethod) != 0; + } + private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { return isPrivateDnsValidationRequired(nai.networkCapabilities); } @@ -5855,7 +5863,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never // sees capabilities that may be malicious, which might prevent mistakes in the future. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(); + networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid()); } else { enforceNetworkFactoryPermission(); } @@ -5868,7 +5876,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, mNMS, providerId); + this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid()); // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); @@ -5969,7 +5977,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Start or stop DNS64 detection and 464xlat according to network state. networkAgent.clatd.update(); notifyIfacesChangedForNetworkStats(); - networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp); + networkAgent.networkMonitor().notifyLinkPropertiesChanged( + new LinkProperties(newLp, true /* parcelSensitiveFields */)); if (networkAgent.everConnected) { notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED); } @@ -7123,6 +7132,14 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); if (!createNativeNetwork(networkAgent)) return; + if (networkAgent.isVPN()) { + // Initialize the VPN capabilities to their starting values according to the + // underlying networks. This will avoid a spurious callback to + // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as + // the VPN would switch from its default, blank capabilities to those + // that reflect the capabilities of its underlying networks. + updateAllVpnsCapabilities(); + } networkAgent.created = true; } @@ -7149,7 +7166,9 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkMonitor().setAcceptPartialConnectivity(); } networkAgent.networkMonitor().notifyNetworkConnected( - networkAgent.linkProperties, networkAgent.networkCapabilities); + new LinkProperties(networkAgent.linkProperties, + true /* parcelSensitiveFields */), + networkAgent.networkCapabilities); scheduleUnvalidatedPrompt(networkAgent); // Whether a particular NetworkRequest listen should cause signal strength thresholds to @@ -8147,4 +8166,41 @@ public class ConnectivityService extends IConnectivityManager.Stub 0, callback)); } + + @Override + public void simulateDataStall(int detectionMethod, long timestampMillis, + @NonNull Network network, @NonNull PersistableBundle extras) { + enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_STACK); + final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network); + if (!nc.hasTransport(TRANSPORT_TEST)) { + throw new SecurityException("Data Stall simluation is only possible for test networks"); + } + + final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); + if (nai == null || nai.creatorUid != Binder.getCallingUid()) { + throw new SecurityException("Data Stall simulation is only possible for network " + + "creators"); + } + + // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat + // this as a Data Stall received directly from NetworkMonitor. This requires wrapping the + // Data Stall information as a DataStallReportParcelable and passing to + // #notifyDataStallSuspected. This ensures that unknown Data Stall detection methods are + // still passed to ConnectivityDiagnostics (with new detection methods masked). + final DataStallReportParcelable p = new DataStallReportParcelable(); + p.timestampMillis = timestampMillis; + p.detectionMethod = detectionMethod; + + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { + p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS); + } + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { + p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE); + p.tcpMetricsCollectionPeriodMillis = extras.getInt( + KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS); + } + + notifyDataStallSuspected(p, network.netId); + } } diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 0ea73460e105..d6bd5a1d7c4c 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -317,39 +317,34 @@ class TestNetworkService extends ITestNetworkManager.Stub { "Cannot create network for non ipsec, non-testtun interface"); } - // Setup needs to be done with NETWORK_STACK privileges. - int callingUid = Binder.getCallingUid(); - Binder.withCleanCallingIdentity( - () -> { - try { - mNMS.setInterfaceUp(iface); - - // Synchronize all accesses to mTestNetworkTracker to prevent the case - // where: - // 1. TestNetworkAgent successfully binds to death of binder - // 2. Before it is added to the mTestNetworkTracker, binder dies, - // binderDied() is called (on a different thread) - // 3. This thread is pre-empted, put() is called after remove() - synchronized (mTestNetworkTracker) { - TestNetworkAgent agent = - registerTestNetworkAgent( - mHandler.getLooper(), - mContext, - iface, - lp, - isMetered, - callingUid, - administratorUids, - binder); - - mTestNetworkTracker.put(agent.getNetwork().netId, agent); - } - } catch (SocketException e) { - throw new UncheckedIOException(e); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - }); + try { + // This requires NETWORK_STACK privileges. + Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface)); + + // Synchronize all accesses to mTestNetworkTracker to prevent the case where: + // 1. TestNetworkAgent successfully binds to death of binder + // 2. Before it is added to the mTestNetworkTracker, binder dies, binderDied() is called + // (on a different thread) + // 3. This thread is pre-empted, put() is called after remove() + synchronized (mTestNetworkTracker) { + TestNetworkAgent agent = + registerTestNetworkAgent( + mHandler.getLooper(), + mContext, + iface, + lp, + isMetered, + Binder.getCallingUid(), + administratorUids, + binder); + + mTestNetworkTracker.put(agent.getNetwork().netId, agent); + } + } catch (SocketException e) { + throw new UncheckedIOException(e); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** Teardown a test network */ diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0ba41736ce15..0ba6a5536cbf 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -842,6 +842,15 @@ public final class ActiveServices { } } + void killMisbehavingService(ServiceRecord r, + int appUid, int appPid, String localPackageName) { + synchronized (mAm) { + stopServiceLocked(r); + mAm.crashApplication(appUid, appPid, localPackageName, -1, + "Bad notification for startForeground", true /*force*/); + } + } + IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) { ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), @@ -3946,7 +3955,7 @@ public final class ActiveServices { void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) { mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId, "Context.startForegroundService() did not then call Service.startForeground(): " - + serviceRecord); + + serviceRecord, false /*force*/); } void scheduleServiceTimeoutLocked(ProcessRecord proc) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b001e62a4684..166c4f3c749b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -456,6 +456,8 @@ public class ActivityManagerService extends IActivityManager.Stub static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; + static final String SYSTEM_USER_HOME_NEEDED = "ro.system_user_home_needed"; + public static final String ANR_TRACE_DIR = "/data/anr"; // Maximum number of receivers an app can register. @@ -3595,7 +3597,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void crashApplication(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: crashApplication() from pid=" @@ -3607,7 +3609,8 @@ public class ActivityManagerService extends IActivityManager.Stub } synchronized(this) { - mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message); + mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, + message, force); } } @@ -4786,7 +4789,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @GuardedBy("this") - private final boolean attachApplicationLocked(IApplicationThread thread, + private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { // Find the application record that is being attached... either via @@ -5209,6 +5212,9 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public final void attachApplication(IApplicationThread thread, long startSeq) { + if (thread == null) { + throw new SecurityException("Invalid application interface"); + } synchronized (this) { int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); @@ -9111,7 +9117,8 @@ public class ActivityManagerService extends IActivityManager.Stub // to handle home activity in this case. if (UserManager.isSplitSystemUser() && Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) { + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0 + || SystemProperties.getBoolean(SYSTEM_USER_HOME_NEEDED, false)) { ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, @@ -12850,7 +12857,9 @@ public class ActivityManagerService extends IActivityManager.Stub pw.print(" unmapped + "); pw.print(stringifyKBSize(ionPool)); pw.println(" pools)"); - kernelUsed += ionUnmapped; + // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being + // set on ION VMAs, therefore consider the entire ION heap as used kernel memory + kernelUsed += ionHeap; } final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() @@ -13587,7 +13596,9 @@ public class ActivityManagerService extends IActivityManager.Stub memInfoBuilder.append(" ION: "); memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool)); memInfoBuilder.append("\n"); - kernelUsed += ionUnmapped; + // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being + // set on ION VMAs, therefore consider the entire ION heap as used kernel memory + kernelUsed += ionHeap; } memInfoBuilder.append(" Used RAM: "); memInfoBuilder.append(stringifyKBSize( diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 5078b8a14eb2..5ab18d95b84d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -1058,7 +1058,7 @@ final class ActivityManagerShellCommand extends ShellCommand { } catch (NumberFormatException e) { packageName = arg; } - mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash"); + mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false); return 0; } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index a4c695067139..bbd2d34e92a6 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -314,20 +314,24 @@ class AppErrors { } void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { - app.setCrashing(false); - app.crashingReport = null; - app.setNotResponding(false); - app.notRespondingReport = null; if (app.anrDialog == fromDialog) { app.anrDialog = null; } if (app.waitDialog == fromDialog) { app.waitDialog = null; } + killAppImmediateLocked(app, "user-terminated", "user request after error"); + } + + private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { + app.setCrashing(false); + app.crashingReport = null; + app.setNotResponding(false); + app.notRespondingReport = null; if (app.pid > 0 && app.pid != MY_PID) { - handleAppCrashLocked(app, "user-terminated" /*reason*/, + handleAppCrashLocked(app, reason, null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); - app.kill("user request after error", true); + app.kill(killReason, true); } } @@ -341,7 +345,7 @@ class AppErrors { * @param message */ void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { ProcessRecord proc = null; // Figure out which process to kill. We don't trust that initialPid @@ -374,6 +378,14 @@ class AppErrors { } proc.scheduleCrash(message); + if (force) { + // If the app is responsive, the scheduled crash will happen as expected + // and then the delayed summary kill will be a no-op. + final ProcessRecord p = proc; + mService.mHandler.postDelayed( + () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), + 5000L); + } } /** diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index dee8e3b285a7..c408695bcb66 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -798,6 +798,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN final String localPackageName = packageName; final int localForegroundId = foregroundId; final Notification _foregroundNoti = foregroundNoti; + final ServiceRecord record = this; ams.mHandler.post(new Runnable() { public void run() { NotificationManagerInternal nm = LocalServices.getService( @@ -896,10 +897,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN Slog.w(TAG, "Error showing notification for service", e); // If it gave us a garbage notification, it doesn't // get to be foreground. - ams.setServiceForeground(instanceName, ServiceRecord.this, - 0, null, 0, 0); - ams.crashApplication(appUid, appPid, localPackageName, -1, - "Bad notification for startForeground: " + e); + ams.mServices.killMisbehavingService(record, + appUid, appPid, localPackageName); } } }); diff --git a/services/core/java/com/android/server/compat/OWNERS b/services/core/java/com/android/server/compat/OWNERS index 2b7cdb0cbce9..cfd0a4b079ad 100644 --- a/services/core/java/com/android/server/compat/OWNERS +++ b/services/core/java/com/android/server/compat/OWNERS @@ -2,6 +2,5 @@ platform-compat-eng+reviews@google.com andreionea@google.com -atrost@google.com mathewi@google.com satayev@google.com diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 34d0bed9a802..3091a7178377 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -198,6 +198,9 @@ public class Nat464Xlat extends BaseNetworkObserver { if (mPrefixDiscoveryRunning && !isPrefixDiscoveryNeeded()) { stopPrefixDiscovery(); } + if (!mPrefixDiscoveryRunning) { + setPrefix64(mNat64PrefixInUse); + } } /** @@ -221,6 +224,10 @@ public class Nat464Xlat extends BaseNetworkObserver { mIface = null; mBaseIface = null; + if (!mPrefixDiscoveryRunning) { + setPrefix64(null); + } + if (isPrefixDiscoveryNeeded()) { if (!mPrefixDiscoveryRunning) { startPrefixDiscovery(); @@ -308,6 +315,16 @@ public class Nat464Xlat extends BaseNetworkObserver { return requiresClat(mNetwork) && mNat64PrefixFromRa == null; } + private void setPrefix64(IpPrefix prefix) { + final String prefixString = (prefix != null) ? prefix.toString() : ""; + try { + mDnsResolver.setPrefix64(getNetId(), prefixString); + } catch (RemoteException | ServiceSpecificException e) { + Slog.e(TAG, "Error setting NAT64 prefix on netId " + getNetId() + " to " + + prefix + ": " + e); + } + } + private void maybeHandleNat64PrefixChange() { final IpPrefix newPrefix = selectNat64Prefix(); if (!Objects.equals(mNat64PrefixInUse, newPrefix)) { diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 2d1f553ab8cd..a9f62d91592d 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -168,6 +168,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // Obtained by ConnectivityService and merged into NetworkAgent-provided information. public CaptivePortalData captivePortalData; + // The UID of the remote entity that created this Network. + public final int creatorUid; + // Networks are lingered when they become unneeded as a result of their NetworkRequests being // satisfied by a higher-scoring network. so as to allow communication to wrap up before the // network is taken down. This usually only happens to the default network. Lingering ends with @@ -268,7 +271,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, - IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { + IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber, + int creatorUid) { this.messenger = messenger; asyncChannel = ac; network = net; @@ -282,6 +286,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { mHandler = handler; networkAgentConfig = config; this.factorySerialNumber = factorySerialNumber; + this.creatorUid = creatorUid; } /** diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 120e744a9740..730da28ba8a2 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -21,6 +21,7 @@ import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; @@ -64,6 +65,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkProvider; +import android.net.NetworkRequest; import android.net.RouteInfo; import android.net.UidRange; import android.net.VpnManager; @@ -317,8 +319,7 @@ public class Vpn { * * @param defaultNetwork underlying network for VPNs following platform's default */ - public synchronized NetworkCapabilities updateCapabilities( - @Nullable Network defaultNetwork) { + public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) { if (mConfig == null) { // VPN is not running. return null; @@ -350,11 +351,10 @@ public class Vpn { int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; - // VPN's meteredness is OR'd with isAlwaysMetered and meteredness of its underlying - // networks. - boolean metered = isAlwaysMetered; - boolean roaming = false; - boolean congested = false; + boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered + boolean roaming = false; // roaming if any underlying is roaming + boolean congested = false; // congested if any underlying is congested + boolean suspended = true; // suspended if all underlying are suspended boolean hadUnderlyingNetworks = false; if (null != underlyingNetworks) { @@ -367,15 +367,24 @@ public class Vpn { transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType); } - // When we have multiple networks, we have to assume the - // worst-case link speed and restrictions. + // Merge capabilities of this underlying network. For bandwidth, assume the + // worst case. downKbps = NetworkCapabilities.minBandwidth(downKbps, underlyingCaps.getLinkDownstreamBandwidthKbps()); upKbps = NetworkCapabilities.minBandwidth(upKbps, underlyingCaps.getLinkUpstreamBandwidthKbps()); + // If this underlying network is metered, the VPN is metered (it may cost money + // to send packets on this network). metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED); + // If this underlying network is roaming, the VPN is roaming (the billing structure + // is different than the usual, local one). roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING); + // If this underlying network is congested, the VPN is congested (the current + // condition of the network affects the performance of this network). congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); + // If this network is not suspended, the VPN is not suspended (the VPN + // is able to transfer some data). + suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); } } if (!hadUnderlyingNetworks) { @@ -383,6 +392,7 @@ public class Vpn { metered = true; roaming = false; congested = false; + suspended = false; } caps.setTransportTypes(transportTypes); @@ -391,6 +401,7 @@ public class Vpn { caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered); caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); + caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended); } /** @@ -1955,6 +1966,7 @@ public class Vpn { profile.ipsecCaCert = caCert; // Start VPN profile + profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore); return; case VpnProfile.TYPE_IKEV2_IPSEC_PSK: @@ -1963,6 +1975,7 @@ public class Vpn { Ikev2VpnProfile.encodeForIpsecSecret(profile.ipsecSecret.getBytes()); // Start VPN profile + profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore); return; case VpnProfile.TYPE_L2TP_IPSEC_PSK: @@ -2213,12 +2226,27 @@ public class Vpn { @Override public void run() { - // Explicitly use only the network that ConnectivityService thinks is the "best." In - // other words, only ever use the currently selected default network. This does mean - // that in both onLost() and onConnected(), any old sessions MUST be torn down. This - // does NOT include VPNs. + // Unless the profile is restricted to test networks, explicitly use only the network + // that ConnectivityService thinks is the "best." In other words, only ever use the + // currently selected default network. This does mean that in both onLost() and + // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs. + // + // When restricted to test networks, select any network with TRANSPORT_TEST. Since the + // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, + // this is considered safe. final ConnectivityManager cm = ConnectivityManager.from(mContext); - cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback); + final NetworkRequest req; + + if (mProfile.isRestrictedToTestNetworks()) { + req = new NetworkRequest.Builder() + .clearCapabilities() + .addTransportType(NetworkCapabilities.TRANSPORT_TEST) + .build(); + } else { + req = cm.getDefaultRequest(); + } + + cm.requestNetwork(req, mNetworkCallback); } private boolean isActiveNetwork(@Nullable Network network) { @@ -2359,7 +2387,7 @@ public class Vpn { final IkeSessionParams ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, network); final ChildSessionParams childSessionParams = - VpnIkev2Utils.buildChildSessionParams(); + VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms()); // TODO: Remove the need for adding two unused addresses with // IPsec tunnels. @@ -2856,6 +2884,11 @@ public class Vpn { verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); + if (profile.isRestrictedToTestNetworks) { + mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS, + "Test-mode profiles require the MANAGE_TEST_NETWORKS permission"); + } + final byte[] encodedProfile = profile.encode(); if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) { throw new IllegalArgumentException("Profile too big"); diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java index 3da304c07910..103f659cc258 100644 --- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java +++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java @@ -17,14 +17,12 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.NetworkCallback; -import static android.net.ipsec.ike.SaProposal.DH_GROUP_1024_BIT_MODP; import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8; import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96; -import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96; import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128; import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192; import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256; @@ -39,6 +37,7 @@ import android.content.Context; import android.net.Ikev2VpnProfile; import android.net.InetAddresses; import android.net.IpPrefix; +import android.net.IpSecAlgorithm; import android.net.IpSecTransform; import android.net.Network; import android.net.RouteInfo; @@ -83,6 +82,14 @@ import java.util.List; * @hide */ public class VpnIkev2Utils { + private static final String TAG = VpnIkev2Utils.class.getSimpleName(); + + // TODO: Use IKE library exposed constants when @SystemApi is updated. + /** IANA-defined 3072 group for use in IKEv2 */ + private static final int DH_GROUP_3072_BIT_MODP = 15; + /** IANA-defined 4096 group for use in IKEv2 */ + private static final int DH_GROUP_4096_BIT_MODP = 16; + static IkeSessionParams buildIkeSessionParams( @NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) { final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity()); @@ -103,11 +110,11 @@ public class VpnIkev2Utils { return ikeOptionsBuilder.build(); } - static ChildSessionParams buildChildSessionParams() { + static ChildSessionParams buildChildSessionParams(List<String> allowedAlgorithms) { final TunnelModeChildSessionParams.Builder childOptionsBuilder = new TunnelModeChildSessionParams.Builder(); - for (final ChildSaProposal childProposal : getChildSaProposals()) { + for (final ChildSaProposal childProposal : getChildSaProposals(allowedAlgorithms)) { childOptionsBuilder.addSaProposal(childProposal); } @@ -144,7 +151,7 @@ public class VpnIkev2Utils { } private static List<IkeSaProposal> getIkeSaProposals() { - // TODO: filter this based on allowedAlgorithms + // TODO: Add ability to filter this when IKEv2 API is made Public API final List<IkeSaProposal> proposals = new ArrayList<>(); // Encryption Algorithms: Currently only AES_CBC is supported. @@ -160,7 +167,6 @@ public class VpnIkev2Utils { normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96); - normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA1_96); // Add AEAD options final IkeSaProposal.Builder aeadBuilder = new IkeSaProposal.Builder(); @@ -176,8 +182,9 @@ public class VpnIkev2Utils { // Add dh, prf for both builders for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) { + builder.addDhGroup(DH_GROUP_4096_BIT_MODP); + builder.addDhGroup(DH_GROUP_3072_BIT_MODP); builder.addDhGroup(DH_GROUP_2048_BIT_MODP); - builder.addDhGroup(DH_GROUP_1024_BIT_MODP); builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC); builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1); } @@ -187,38 +194,59 @@ public class VpnIkev2Utils { return proposals; } - private static List<ChildSaProposal> getChildSaProposals() { - // TODO: filter this based on allowedAlgorithms + /** Builds a child SA proposal based on the allowed IPsec algorithms */ + private static List<ChildSaProposal> getChildSaProposals(List<String> allowedAlgorithms) { final List<ChildSaProposal> proposals = new ArrayList<>(); // Add non-AEAD options - final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder(); - - // Encryption Algorithms: Currently only AES_CBC is supported. - normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256); - normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192); - normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128); + if (Ikev2VpnProfile.hasNormalModeAlgorithms(allowedAlgorithms)) { + final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder(); + + // Encryption Algorithms: + // AES-CBC is currently the only supported encryption algorithm. + normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256); + normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192); + normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128); + + // Authentication/Integrity Algorithms: + // Guaranteed by Ikev2VpnProfile constructor to contain at least one of these. + if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA512)) { + normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); + } + if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA384)) { + normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); + } + if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA256)) { + normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); + } - // Authentication/Integrity Algorithms - normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); - normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); - normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); - normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA1_96); + ChildSaProposal proposal = normalModeBuilder.build(); + if (proposal.getIntegrityAlgorithms().isEmpty()) { + // Should be impossible; Verified in Ikev2VpnProfile. + Log.wtf(TAG, "Missing integrity algorithm when buildling Child SA proposal"); + } else { + proposals.add(normalModeBuilder.build()); + } + } // Add AEAD options - final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder(); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128); - aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128); + if (Ikev2VpnProfile.hasAeadAlgorithms(allowedAlgorithms)) { + final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder(); + + // AES-GCM is currently the only supported AEAD algorithm + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128); + aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128); + + proposals.add(aeadBuilder.build()); + } - proposals.add(normalModeBuilder.build()); - proposals.add(aeadBuilder.build()); return proposals; } diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 3006ef41931f..d7bf37db6afd 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -306,49 +306,6 @@ final class Constants { static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "persist.sys.hdmi.addr.playback"; static final String PROPERTY_PREFERRED_ADDRESS_TV = "persist.sys.hdmi.addr.tv"; - - // TODO(OEM): Set this to false to keep the playback device in sleep upon hotplug event. - // True by default. - static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug"; - - // TODO(OEM): Set this to true to enable 'Set Menu Language' feature. False by default. - static final String PROPERTY_SET_MENU_LANGUAGE = "ro.hdmi.set_menu_language"; - - /** - * Property to save the ARC port id on system audio device. - * <p>When ARC is initiated, this port will be used to turn on ARC. - */ - static final String PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT = - "ro.hdmi.property_sytem_audio_device_arc_port"; - - /** - * Property to disable muting logic in System Audio Control handling. Default is true. - * - * <p>True means enabling muting logic. - * <p>False means never mute device. - */ - static final String PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE = - "ro.hdmi.property_system_audio_mode_muting_enable"; - - /** - * When set to true the HdmiControlService will never request a Logical Address for the - * playback device type. Default is false. - * - * <p> This is useful when HDMI CEC multiple device types is not supported by the cec driver - */ - static final String PROPERTY_HDMI_CEC_NEVER_CLAIM_PLAYBACK_LOGICAL_ADDRESS = - "ro.hdmi.property_hdmi_cec_never_claim_playback_logical_address"; - - /** - * A comma separated list of logical addresses that HdmiControlService - * will never assign local CEC devices to. - * - * <p> This is useful when HDMI CEC hardware module can't assign multiple logical addresses - * in the range same range of 0-7 or 8-15. - */ - static final String PROPERTY_HDMI_CEC_NEVER_ASSIGN_LOGICAL_ADDRESSES = - "ro.hdmi.property_hdmi_cec_never_assign_logical_addresses"; - // Set to false to allow playback device to go to suspend mode even // when it's an active source. True by default. static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake"; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 9e2fd4e9e91e..496273b6bf0e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -35,6 +35,7 @@ import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager.TvInputCallback; import android.os.SystemProperties; import android.provider.Settings.Global; +import android.sysprop.HdmiProperties; import android.util.Slog; import android.util.SparseArray; @@ -90,8 +91,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { // If the current device uses TvInput for ARC. We assume all other inputs also use TvInput // when ARC is using TvInput. - private boolean mArcIntentUsed = SystemProperties - .get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, "0").contains("tvinput"); + private boolean mArcIntentUsed = HdmiProperties.arc_port().orElse("0").contains("tvinput"); // Keeps the mapping (HDMI port ID to TV input URI) to keep track of the TV inputs ready to // accept input switching request from HDMI devices. @@ -823,7 +823,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { private void enableAudioReturnChannel(boolean enabled) { assertRunOnServiceThread(); mService.enableAudioReturnChannel( - SystemProperties.getInt(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, 0), + Integer.parseInt(HdmiProperties.arc_port().orElse("0")), enabled); } @@ -895,9 +895,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { boolean currentMuteStatus = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC); if (currentMuteStatus == newSystemAudioMode) { - if (mService.readBooleanSystemProperty( - Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true) - || newSystemAudioMode) { + if (HdmiProperties.system_audio_mode_muting().orElse(true) || newSystemAudioMode) { mService.getAudioManager() .adjustStreamVolume( AudioManager.STREAM_MUSIC, @@ -1133,7 +1131,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { if (portId == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) { switchToHomeTvInput(); } else if (portId == Constants.CEC_SWITCH_ARC) { - switchToTvInput(SystemProperties.get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT)); + switchToTvInput(HdmiProperties.arc_port().orElse("0")); setLocalActivePort(portId); return; } else { diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 560f7a03b20f..603dfafc6ff5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -24,6 +24,7 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemProperties; import android.provider.Settings.Global; +import android.sysprop.HdmiProperties; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -43,11 +44,10 @@ import java.util.Locale; public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { private static final String TAG = "HdmiCecLocalDevicePlayback"; - private static final boolean WAKE_ON_HOTPLUG = - SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true); + private static final boolean WAKE_ON_HOTPLUG = false; private static final boolean SET_MENU_LANGUAGE = - SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false); + HdmiProperties.set_menu_language_enabled().orElse(false); // Used to keep the device awake while it is the active source. For devices that // cannot wake up via CEC commands, this address the inconvenience of having to diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java index ae008b4bfa7a..eb6612fffc0c 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java @@ -16,12 +16,10 @@ package com.android.server.hdmi; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; - import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.IHdmiControlCallback; -import android.os.SystemProperties; +import android.sysprop.HdmiProperties; import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -44,8 +42,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice { // Device has cec switch functionality or not. // Default is false. - protected boolean mIsSwitchDevice = SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + protected boolean mIsSwitchDevice = HdmiProperties.is_switch().orElse(false); // Routing port number used for Routing Control. // This records the default routing port or the previous valid routing port. diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 6a0cc2661f3d..51d363a41116 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -19,7 +19,6 @@ package com.android.server.hdmi; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static com.android.server.hdmi.Constants.DISABLED; import static com.android.server.hdmi.Constants.ENABLED; @@ -2520,8 +2519,7 @@ public class HdmiControlService extends SystemService { } boolean isSwitchDevice() { - return SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + return HdmiProperties.is_switch().orElse(false); } boolean isTvDeviceEnabled() { diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 75ffe35674d1..3dac106418c5 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -385,11 +385,10 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); } - // Filter out debug entries as that may lead to over counting. - delta.filterDebugEntries(); - // Update mTunAnd464xlatAdjustedStats with migrated delta. mTunAnd464xlatAdjustedStats.combineAllValues(delta); mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 26808587437c..5d1cc2a5c24a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -46,7 +46,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -67,9 +66,6 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; -import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; -import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -123,7 +119,6 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -133,9 +128,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -166,6 +159,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -184,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; private static final int MSG_UPDATE_IFACES = 3; + // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent + // deadlock. + private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -206,7 +203,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; - private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -231,12 +227,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String PREFIX_UID_TAG = "uid_tag"; /** - * Virtual network interface for video telephony. This is for VT data usage counting purpose. - */ - // TODO: Remove this after no one is using it. - public static final String VT_INTERFACE = NetworkStats.IFACE_VT; - - /** * Settings that can be changed externally. */ public interface NetworkStatsSettings { @@ -308,8 +298,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new DropBoxNonMonotonicObserver(); private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100; - private final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList = - new RemoteCallbackList<>(); + private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList = + new CopyOnWriteArrayList<>(); /** Semaphore used to wait for stats provider to respond to request stats update. */ private final Semaphore mStatsProviderSem = new Semaphore(0, true); @@ -352,6 +342,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Dependencies mDeps; + @NonNull + private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -390,6 +383,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerGlobalAlert(); break; } + case MSG_BROADCAST_NETWORK_STATS_UPDATED: { + final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); + updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); + break; + } } } } @@ -401,8 +401,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), + final NetworkStatsService service = new NetworkStatsService(context, networkManager, + alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -416,16 +416,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir, @NonNull Dependencies deps) { + NetworkStatsSettings settings, NetworkStatsFactory factory, + NetworkStatsObservers statsObservers, File systemDir, File baseDir, + @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + "missing INetworkManagementService"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); - mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager"); mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); mStatsFactory = Objects.requireNonNull(factory, "missing factory"); mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); @@ -437,7 +436,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); - mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); + mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, + new HandlerExecutor(mHandler), this); } /** @@ -453,6 +453,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public HandlerThread makeHandlerThread() { return new HandlerThread(TAG); } + + /** + * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change + * event in NetworkStatsService. + */ + @NonNull + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, + @NonNull Executor executor, @NonNull NetworkStatsService service) { + // TODO: Update RatType passively in NSS, instead of querying into the monitor + // when forceUpdateIface. + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> + service.handleOnCollapsedRatTypeChanged()); + } } private void registerLocalService() { @@ -517,11 +530,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: 1. listen to changes from all subscriptions. - // 2. listen to settings changed to support dynamically enable/disable. + // TODO: listen to settings changed to support dynamically enable/disable. // watch for networkType changes if (!mSettings.getCombineSubtypeEnabled()) { - mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + mNetworkStatsSubscriptionsMonitor.start(); } registerGlobalAlert(); @@ -544,7 +556,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!mSettings.getCombineSubtypeEnabled()) { + mNetworkStatsSubscriptionsMonitor.stop(); + } final long currentTime = mClock.millis(); @@ -1197,35 +1211,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** - * Receiver that watches for {@link TelephonyManager} changes, such as - * transitioning between Radio Access Technology(RAT) types. + * Handle collapsed RAT type changed event. */ - @NonNull - private final NetworkTypeListener mPhoneListener; - - class NetworkTypeListener extends PhoneStateListener { - private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; - - NetworkTypeListener(@NonNull Executor executor) { - super(executor); - } - - @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); - final int collapsedRatType = getCollapsedRatType(networkType); - if (collapsedRatType == mLastCollapsedRatType) return; - - if (LOGD) { - Log.d(TAG, "subtype changed for mobile: " - + mLastCollapsedRatType + " -> " + collapsedRatType); - } - // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); - mLastCollapsedRatType = collapsedRatType; - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); - } + @VisibleForTesting + public void handleOnCollapsedRatTypeChanged() { + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } private void updateIfaces( @@ -1352,8 +1345,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return 0; } - // TODO: return different subType for different subscriptions. - return mPhoneListener.mLastCollapsedRatType; + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); } private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet( @@ -1463,10 +1455,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; // Request asynchronous stats update from all providers for next poll. And wait a bit of - // time to allow providers report-in given that normally binder call should be fast. + // time to allow providers report-in given that normally binder call should be fast. Note + // that size of list might be changed because addition/removing at the same time. For + // addition, the stats of the missed provider can only be collected in next poll; + // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS + // once that happened. // TODO: request with a valid token. Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); - final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); + final int registeredCallbackCount = mStatsProviderCbList.size(); mStatsProviderSem.drainPermits(); invokeForAllStatsProviderCallbacks( (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); @@ -1520,10 +1516,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // finally, dispatch updated event to any listeners - final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); - updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, - READ_NETWORK_USAGE_HISTORY); + mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); Trace.traceEnd(TRACE_TAG_NETWORK); } @@ -1643,7 +1636,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); + if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); } } @@ -1934,7 +1927,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( tag, provider, mStatsProviderSem, mAlertObserver, mStatsProviderCbList); - mStatsProviderCbList.register(callback); + mStatsProviderCbList.add(callback); Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + getCallingUid() + "/" + getCallingPid()); return callback; @@ -1958,20 +1951,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void invokeForAllStatsProviderCallbacks( @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) { - synchronized (mStatsLock) { - final int length = mStatsProviderCbList.beginBroadcast(); + for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) { try { - for (int i = 0; i < length; i++) { - final NetworkStatsProviderCallbackImpl cb = - mStatsProviderCbList.getBroadcastItem(i); - try { - task.accept(cb); - } catch (RemoteException e) { - Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); - } - } - } finally { - mStatsProviderCbList.finishBroadcast(); + task.accept(cb); + } catch (RemoteException e) { + Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); } } } @@ -1983,7 +1967,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull final INetworkStatsProvider mProvider; @NonNull private final Semaphore mSemaphore; @NonNull final INetworkManagementEventObserver mAlertObserver; - @NonNull final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList; + @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList; @NonNull private final Object mProviderStatsLock = new Object(); @@ -1997,7 +1981,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull String tag, @NonNull INetworkStatsProvider provider, @NonNull Semaphore semaphore, @NonNull INetworkManagementEventObserver alertObserver, - @NonNull RemoteCallbackList<NetworkStatsProviderCallbackImpl> cbList) + @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList) throws RemoteException { mTag = tag; mProvider = provider; @@ -2054,13 +2038,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void binderDied() { Log.d(TAG, mTag + ": binderDied"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } @Override public void unregister() { Log.d(TAG, mTag + ": unregister"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index a2f191444b63..2d39e9169245 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -920,7 +920,7 @@ public class NotificationManagerService extends SystemService { () -> mAm.crashApplication(uid, initialPid, pkg, -1, "Bad notification(tag=" + tag + ", id=" + id + ") posted from package " + pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): " - + message)); + + message, true /* force */)); } } diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 341a88dd0a87..4bb17a2c298e 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -33,9 +33,9 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.os.Binder; import android.os.Environment; import android.os.RemoteException; -import android.os.ServiceManager; import android.sysprop.ApexProperties; import android.util.Slog; @@ -73,12 +73,7 @@ abstract class ApexManager { */ static ApexManager create(Context systemContext) { if (ApexProperties.updatable().orElse(false)) { - try { - return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface( - ServiceManager.getServiceOrThrow("apexservice"))); - } catch (ServiceManager.ServiceNotFoundException e) { - throw new IllegalStateException("Required service apexservice not available"); - } + return new ApexManagerImpl(systemContext); } else { return new ApexManagerFlattenedApex(); } @@ -247,8 +242,7 @@ abstract class ApexManager { * APEX packages. */ @VisibleForTesting - static class ApexManagerImpl extends ApexManager { - private final IApexService mApexService; + protected static class ApexManagerImpl extends ApexManager { private final Context mContext; private final Object mLock = new Object(); /** @@ -261,9 +255,8 @@ abstract class ApexManager { @GuardedBy("mLock") private List<PackageInfo> mAllPackagesCache; - ApexManagerImpl(Context context, IApexService apexService) { + ApexManagerImpl(Context context) { mContext = context; - mApexService = apexService; } /** @@ -286,10 +279,23 @@ abstract class ApexManager { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + /** + * Retrieve the service from ServiceManager. If the service is not running, it will be + * started, and this function will block until it is ready. + */ + @VisibleForTesting + protected IApexService waitForApexService() { + try { + return IApexService.Stub.asInterface(Binder.waitForService("apexservice")); + } catch (RemoteException e) { + throw new IllegalStateException("Required service apexservice not available"); + } + } + @Override List<ActiveApexInfo> getActiveApexInfos() { try { - return Arrays.stream(mApexService.getActivePackages()) + return Arrays.stream(waitForApexService().getActivePackages()) .map(apexInfo -> new ActiveApexInfo( new File( Environment.getApexDirectory() + File.separator @@ -324,7 +330,7 @@ abstract class ApexManager { mAllPackagesCache = new ArrayList<>(); HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>(); - final ApexInfo[] allPkgs = mApexService.getAllPackages(); + final ApexInfo[] allPkgs = waitForApexService().getAllPackages(); for (ApexInfo ai : allPkgs) { // If the device is using flattened APEX, don't report any APEX // packages since they won't be managed or updated by PackageManager. @@ -431,7 +437,8 @@ abstract class ApexManager { @Override @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { try { - ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId); + ApexSessionInfo apexSessionInfo = + waitForApexService().getStagedSessionInfo(sessionId); if (apexSessionInfo.isUnknown) { return null; } @@ -450,7 +457,7 @@ abstract class ApexManager { ApexSessionParams params = new ApexSessionParams(); params.sessionId = sessionId; params.childSessionIds = childSessionIds; - mApexService.submitStagedSession(params, apexInfoList); + waitForApexService().submitStagedSession(params, apexInfoList); return apexInfoList; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); @@ -465,7 +472,7 @@ abstract class ApexManager { @Override void markStagedSessionReady(int sessionId) throws PackageManagerException { try { - mApexService.markStagedSessionReady(sessionId); + waitForApexService().markStagedSessionReady(sessionId); } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); throw new RuntimeException(re); @@ -479,7 +486,7 @@ abstract class ApexManager { @Override void markStagedSessionSuccessful(int sessionId) { try { - mApexService.markStagedSessionSuccessful(sessionId); + waitForApexService().markStagedSessionSuccessful(sessionId); } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); throw new RuntimeException(re); @@ -498,7 +505,7 @@ abstract class ApexManager { @Override boolean revertActiveSessions() { try { - mApexService.revertActiveSessions(); + waitForApexService().revertActiveSessions(); return true; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); @@ -512,7 +519,7 @@ abstract class ApexManager { @Override boolean abortStagedSession(int sessionId) throws PackageManagerException { try { - mApexService.abortStagedSession(sessionId); + waitForApexService().abortStagedSession(sessionId); return true; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); @@ -527,7 +534,7 @@ abstract class ApexManager { @Override boolean uninstallApex(String apexPackagePath) { try { - mApexService.unstagePackages(Collections.singletonList(apexPackagePath)); + waitForApexService().unstagePackages(Collections.singletonList(apexPackagePath)); return true; } catch (Exception e) { return false; @@ -578,7 +585,7 @@ abstract class ApexManager { ipw.increaseIndent(); ipw.println("APEX session state:"); ipw.increaseIndent(); - final ApexSessionInfo[] sessions = mApexService.getSessions(); + final ApexSessionInfo[] sessions = waitForApexService().getSessions(); for (ApexSessionInfo si : sessions) { ipw.println("Session ID: " + si.sessionId); ipw.increaseIndent(); diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 0d7494cfbeab..6fdde7a196cc 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -30,7 +30,7 @@ per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google. per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com -per-file UserManagerService.java = omakoto@google.com, yamasani@google.com +per-file UserManagerService.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e82102f3379d..50bbfa96bfab 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3004,8 +3004,7 @@ public class PackageManagerService extends IPackageManager.Stub mWellbeingPackage = getWellbeingPackageName(); mDocumenterPackage = getDocumenterPackageName(); - mConfiguratorPackage = - mContext.getString(R.string.config_deviceConfiguratorPackageName); + mConfiguratorPackage = getDeviceConfiguratorPackageName(); mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); mTelephonyPackages = getTelephonyPackageNames(); @@ -20537,7 +20536,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getSystemTextClassifierPackageName() { - return mContext.getString(R.string.config_defaultTextClassifierPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_defaultTextClassifierPackage)); } @Override @@ -20547,7 +20547,7 @@ public class PackageManagerService extends IPackageManager.Stub if (flattenedComponentName != null) { ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName); if (componentName != null && componentName.getPackageName() != null) { - return componentName.getPackageName(); + return ensureSystemPackageName(componentName.getPackageName()); } } return null; @@ -20572,9 +20572,15 @@ public class PackageManagerService extends IPackageManager.Stub } } + @Nullable + private String getDeviceConfiguratorPackageName() { + return ensureSystemPackageName(mContext.getString( + R.string.config_deviceConfiguratorPackageName)); + } + @Override public String getWellbeingPackageName() { - return mContext.getString(R.string.config_defaultWellbeingPackage); + return ensureSystemPackageName(mContext.getString(R.string.config_defaultWellbeingPackage)); } @Override @@ -20589,7 +20595,7 @@ public class PackageManagerService extends IPackageManager.Stub if (appPredictionServiceComponentName == null) { return null; } - return appPredictionServiceComponentName.getPackageName(); + return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName()); } @Override @@ -20606,11 +20612,33 @@ public class PackageManagerService extends IPackageManager.Stub if (systemCaptionsServiceComponentName == null) { return null; } - return systemCaptionsServiceComponentName.getPackageName(); + return ensureSystemPackageName(systemCaptionsServiceComponentName.getPackageName()); } public String getIncidentReportApproverPackageName() { - return mContext.getString(R.string.config_incidentReportApproverPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_incidentReportApproverPackage)); + } + + @Nullable + private String ensureSystemPackageName(@Nullable String packageName) { + if (packageName == null) { + return null; + } + long token = Binder.clearCallingIdentity(); + try { + if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) { + PackageInfo packageInfo = getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM); + if (packageInfo != null) { + EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid, + ""); + } + return null; + } + } finally { + Binder.restoreCallingIdentity(token); + } + return packageName; } @Override diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index f78d2639df1a..add0b01f1879 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -19,8 +19,6 @@ package com.android.server.policy.keyguard; import android.app.ActivityManager; import android.content.Context; import android.os.RemoteException; -import android.os.ServiceManager; -import android.security.keystore.IKeystoreService; import android.util.Slog; import com.android.internal.policy.IKeyguardService; @@ -53,16 +51,11 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { private final LockPatternUtils mLockPatternUtils; private final StateCallback mCallback; - IKeystoreService mKeystoreService; - public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) { mLockPatternUtils = new LockPatternUtils(context); mCurrentUserId = ActivityManager.getCurrentUser(); mCallback = callback; - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - try { service.addStateMonitorCallback(this); } catch (RemoteException e) { @@ -95,23 +88,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mIsShowing = showing; mCallback.onShowingChanged(); - int retry = 2; - while (retry > 0) { - try { - mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId); - break; - } catch (RemoteException e) { - if (retry == 2) { - Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died" - + " -> refreshing service token and retrying"); - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - } else { - Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e); - } - --retry; - } - } } @Override // Binder interface @@ -123,10 +99,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mCurrentUserId = userId; } - private synchronized int getCurrentUser() { - return mCurrentUserId; - } - @Override // Binder interface public void onInputRestrictedStateChanged(boolean inputRestricted) { mInputRestricted = inputRestricted; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 7408dd40b5ca..5f5cd3c46117 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -53,6 +53,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.KeyStore; import android.service.trust.TrustAgentService; import android.text.TextUtils; import android.util.ArrayMap; @@ -135,6 +136,33 @@ public class TrustManagerService extends SystemService { @GuardedBy("mUserIsTrusted") private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray(); + /** + * Stores the locked state for users on the device. There are three different type of users + * which are handled slightly differently: + * <ul> + * <li> Users with real keyguard + * These are users who can be switched to ({@link UserInfo#supportsSwitchToByUser()}). Their + * locked state is derived by a combination of user secure state, keyguard state, trust agent + * decision and biometric authentication result. These are updated via + * {@link #refreshDeviceLockedForUser(int)} and result stored in {@link #mDeviceLockedForUser}. + * <li> Managed profiles with unified challenge + * Managed profile with unified challenge always shares the same locked state as their parent, + * so their locked state is not recorded in {@link #mDeviceLockedForUser}. Instead, + * {@link ITrustManager#isDeviceLocked(int)} always resolves their parent user handle and + * queries its locked state instead. + * <li> Managed profiles with separate challenge + * Locked state for profile with separate challenge is determined by other parts of the + * framework (mostly PowerManager) and pushed to TrustManagerService via + * {@link ITrustManager#setDeviceLockedForUser(int, boolean)}. Although in a corner case when + * the profile has a separate but empty challenge, setting its {@link #mDeviceLockedForUser} to + * {@code false} is actually done by {@link #refreshDeviceLockedForUser(int)}. + * </ul> + * TODO: Rename {@link ITrustManager#setDeviceLockedForUser(int, boolean)} to + * {@code setDeviceLockedForProfile} to better reflect its purpose. Unifying + * {@code setDeviceLockedForProfile} and {@link #setDeviceLockedForUser} would also be nice. + * At the moment they both update {@link #mDeviceLockedForUser} but have slightly different + * side-effects: one notifies trust agents while the other sends out a broadcast. + */ @GuardedBy("mDeviceLockedForUser") private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray(); @@ -601,6 +629,10 @@ public class TrustManagerService extends SystemService { } } + /** + * Update the user's locked state. Only applicable to users with a real keyguard + * ({@link UserInfo#supportsSwitchToByUser}) and unsecured managed profiles. + */ private void refreshDeviceLockedForUser(int userId) { if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) { Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle," @@ -661,6 +693,15 @@ public class TrustManagerService extends SystemService { } if (changed) { dispatchDeviceLocked(userId, locked); + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + // Also update the user's profiles who have unified challenge, since they + // share the same unlocked state (see {@link #isDeviceLocked(int)}) + for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) { + if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) { + KeyStore.getInstance().onUserLockedStateChanged(profileHandle, locked); + } + } } } @@ -1194,6 +1235,10 @@ public class TrustManagerService extends SystemService { return "0x" + Integer.toHexString(i); } + /** + * Changes the lock status for the given user. This is only applicable to managed profiles, + * other users should be handled by Keyguard. + */ @Override public void setDeviceLockedForUser(int userId, boolean locked) { enforceReportPermission(); @@ -1204,6 +1249,9 @@ public class TrustManagerService extends SystemService { synchronized (mDeviceLockedForUser) { mDeviceLockedForUser.put(userId, locked); } + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + if (locked) { try { ActivityManager.getService().notifyLockedProfile(userId); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 848971d3b044..1592f239fd2e 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4268,6 +4268,11 @@ class ActivityStack extends ConfigurationContainer { final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData) { + if (!srec.attachedToProcess()) { + // Nothing to do if the caller is not attached, because this method should be called + // from an alive activity. + return false; + } final TaskRecord task = srec.getTaskRecord(); final ArrayList<ActivityRecord> activities = task.mActivities; final int start = activities.indexOf(srec); @@ -4321,14 +4326,14 @@ class ActivityStack extends ConfigurationContainer { } if (parent != null && foundParentInTask) { + final int callingUid = srec.info.applicationInfo.uid; final int parentLaunchMode = parent.info.launchMode; final int destIntentFlags = destIntent.getFlags(); if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { - parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent, - srec.packageName); + parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName); } else { try { ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( @@ -4341,10 +4346,10 @@ class ActivityStack extends ConfigurationContainer { .setActivityInfo(aInfo) .setResultTo(parent.appToken) .setCallingPid(-1) - .setCallingUid(parent.launchedFromUid) - .setCallingPackage(parent.launchedFromPackage) + .setCallingUid(callingUid) + .setCallingPackage(srec.packageName) .setRealCallingPid(-1) - .setRealCallingUid(parent.launchedFromUid) + .setRealCallingUid(callingUid) .setComponentSpecified(true) .execute(); foundParentInTask = res == ActivityManager.START_SUCCESS; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5b697ee89602..f37698de34d5 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2763,6 +2763,11 @@ class ActivityStarter { return mRequest.intent; } + @VisibleForTesting + int getCallingUid() { + return mRequest.callingUid; + } + ActivityStarter setReason(String reason) { mRequest.reason = reason; return this; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index 72fc18937ece..9d56263740ed 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -28,12 +28,14 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.os.Process; import android.os.SystemClock; +import android.os.UserManagerInternal; import android.util.ArraySet; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.AtomicFile; +import com.android.server.LocalServices; import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; import java.io.File; @@ -73,6 +75,7 @@ class TaskSnapshotPersister { private boolean mStarted; private final Object mLock = new Object(); private final DirectoryResolver mDirectoryResolver; + private final UserManagerInternal mUserManagerInternal; private final float mReducedScale; /** @@ -84,6 +87,7 @@ class TaskSnapshotPersister { TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) { mDirectoryResolver = resolver; + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); if (service.mLowRamTaskSnapshotsAndRecents) { // Use very low res snapshots if we are using Go version of recents. mReducedScale = LOW_RAM_RECENTS_REDUCED_SCALE; @@ -172,7 +176,7 @@ class TaskSnapshotPersister { return; } } - SystemClock.sleep(100); + SystemClock.sleep(DELAY_MS); } } @@ -218,7 +222,7 @@ class TaskSnapshotPersister { private boolean createDirectory(int userId) { final File dir = getDirectory(userId); - return dir.exists() || dir.mkdirs(); + return dir.exists() || dir.mkdir(); } private void deleteSnapshot(int taskId, int userId) { @@ -243,18 +247,26 @@ class TaskSnapshotPersister { android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); while (true) { WriteQueueItem next; + boolean isReadyToWrite = false; synchronized (mLock) { if (mPaused) { next = null; } else { next = mWriteQueue.poll(); if (next != null) { - next.onDequeuedLocked(); + if (next.isReady()) { + isReadyToWrite = true; + next.onDequeuedLocked(); + } else { + mWriteQueue.addLast(next); + } } } } if (next != null) { - next.write(); + if (isReadyToWrite) { + next.write(); + } SystemClock.sleep(DELAY_MS); } synchronized (mLock) { @@ -274,6 +286,13 @@ class TaskSnapshotPersister { }; private abstract class WriteQueueItem { + /** + * @return {@code true} if item is ready to have {@link WriteQueueItem#write} called + */ + boolean isReady() { + return true; + } + abstract void write(); /** @@ -313,6 +332,11 @@ class TaskSnapshotPersister { } @Override + boolean isReady() { + return mUserManagerInternal.isUserUnlocked(mUserId); + } + + @Override void write() { if (!createDirectory(mUserId)) { Slog.e(TAG, "Unable to create snapshot directory for user dir=" diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e1f85446de7b..404863af800f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7717,14 +7717,19 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void syncInputTransactions() { - waitForAnimationsToComplete(); + long token = Binder.clearCallingIdentity(); + try { + waitForAnimationsToComplete(); - synchronized (mGlobalLock) { - mWindowPlacerLocked.performSurfacePlacementIfScheduled(); - mRoot.forAllDisplays(displayContent -> + synchronized (mGlobalLock) { + mWindowPlacerLocked.performSurfacePlacementIfScheduled(); + mRoot.forAllDisplays(displayContent -> displayContent.getInputMonitor().updateInputWindowsImmediately()); + } + new SurfaceControl.Transaction().syncInputWindows().apply(true); + } finally { + Binder.restoreCallingIdentity(token); } - new SurfaceControl.Transaction().syncInputWindows().apply(true); } private void waitForAnimationsToComplete() { diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp index e79612fbf3d3..a99c0a3fa23e 100644 --- a/services/core/jni/com_android_server_AlarmManagerService.cpp +++ b/services/core/jni/com_android_server_AlarmManagerService.cpp @@ -40,6 +40,7 @@ #include <linux/rtc.h> #include <array> +#include <limits> #include <memory> namespace android { @@ -213,22 +214,20 @@ int AlarmImpl::waitForAlarm() static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis) { AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); - struct timeval tv; - int ret; - if (millis <= 0 || millis / 1000LL >= INT_MAX) { + if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) { return -1; } - tv.tv_sec = (time_t) (millis / 1000LL); - tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); - - ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); + struct timeval tv; + tv.tv_sec = (millis / 1000LL); + tv.tv_usec = ((millis % 1000LL) * 1000LL); - ret = impl->setTime(&tv); + ALOGD("Setting time of day to sec=%ld", tv.tv_sec); - if(ret < 0) { - ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); + int ret = impl->setTime(&tv); + if (ret < 0) { + ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno)); ret = -1; } return ret; diff --git a/services/core/jni/com_android_server_SerialService.cpp b/services/core/jni/com_android_server_SerialService.cpp index aef0b25503c8..c9459994a658 100644 --- a/services/core/jni/com_android_server_SerialService.cpp +++ b/services/core/jni/com_android_server_SerialService.cpp @@ -48,6 +48,7 @@ static jobject android_server_SerialService_open(JNIEnv *env, jobject /* thiz */ jobject fileDescriptor = jniCreateFileDescriptor(env, fd); if (fileDescriptor == NULL) { + close(fd); return NULL; } return env->NewObject(gParcelFileDescriptorOffsets.mClass, diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp index ff1ec04cb23e..72dce4dca0da 100644 --- a/services/core/jni/com_android_server_UsbDeviceManager.cpp +++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp @@ -19,6 +19,7 @@ #include "jni.h" #include <nativehelper/JNIHelp.h> +#include <nativehelper/ScopedUtfChars.h> #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "MtpDescriptors.h" @@ -88,6 +89,7 @@ static jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobjec } jobject fileDescriptor = jniCreateFileDescriptor(env, fd); if (fileDescriptor == NULL) { + close(fd); return NULL; } return env->NewObject(gParcelFileDescriptorOffsets.mClass, @@ -120,35 +122,30 @@ static jint android_server_UsbDeviceManager_getAudioMode(JNIEnv* /* env */, jobj } static jobject android_server_UsbDeviceManager_openControl(JNIEnv *env, jobject /* thiz */, jstring jFunction) { - const char *function = env->GetStringUTFChars(jFunction, NULL); + ScopedUtfChars function(env, jFunction); bool ptp = false; int fd = -1; - if (!strcmp(function, "ptp")) { + if (!strcmp(function.c_str(), "ptp")) { ptp = true; } - if (!strcmp(function, "mtp") || ptp) { + if (!strcmp(function.c_str(), "mtp") || ptp) { fd = TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP0 : FFS_MTP_EP0, O_RDWR)); if (fd < 0) { - ALOGE("could not open control for %s %s", function, strerror(errno)); - goto error; + ALOGE("could not open control for %s %s", function.c_str(), strerror(errno)); + return NULL; } if (!writeDescriptors(fd, ptp)) { - goto error; + close(fd); + return NULL; } } - if (function != NULL) { - env->ReleaseStringUTFChars(jFunction, function); - } - return jniCreateFileDescriptor(env, fd); -error: - if (fd != -1) { + jobject jifd = jniCreateFileDescriptor(env, fd); + if (jifd == NULL) { + // OutOfMemoryError will be pending. close(fd); } - if (function != NULL) { - env->ReleaseStringUTFChars(jFunction, function); - } - return NULL; + return jifd; } static const JNINativeMethod method_table[] = { diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index 24f2014afa30..a40bcd0d7c07 100644 --- a/services/core/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp @@ -134,6 +134,7 @@ static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /* jobject fileDescriptor = jniCreateFileDescriptor(env, newFD); if (fileDescriptor == NULL) { + close(newFD); return NULL; } return env->NewObject(gParcelFileDescriptorOffsets.mClass, diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbMidiDevice.cpp index 79d935fe610c..8ac2c4f37ecd 100644 --- a/services/core/jni/com_android_server_UsbMidiDevice.cpp +++ b/services/core/jni/com_android_server_UsbMidiDevice.cpp @@ -20,6 +20,7 @@ #include "jni.h" #include <nativehelper/JNIHelp.h> +#include <nativehelper/ScopedLocalRef.h> #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" @@ -99,24 +100,45 @@ android_server_UsbMidiDevice_open(JNIEnv *env, jobject thiz, jint card, jint dev int fd = open(path, O_RDWR); if (fd < 0) { ALOGE("open failed on %s for index %d", path, i); - return NULL; + goto release_fds; } - - jobject fileDescriptor = jniCreateFileDescriptor(env, fd); - env->SetObjectArrayElement(fds, i, fileDescriptor); - env->DeleteLocalRef(fileDescriptor); + ScopedLocalRef<jobject> jifd(env, jniCreateFileDescriptor(env, fd)); + if (jifd.get() == NULL) { + goto release_fds; + } + env->SetObjectArrayElement(fds, i, jifd.get()); } // create a pipe to use for unblocking our input thread - int pipeFD[2]; - pipe(pipeFD); - jobject fileDescriptor = jniCreateFileDescriptor(env, pipeFD[0]); - env->SetObjectArrayElement(fds, subdevice_count, fileDescriptor); - env->DeleteLocalRef(fileDescriptor); - // store our end of the pipe in mPipeFD - env->SetIntField(thiz, sPipeFDField, pipeFD[1]); + { + int pipeFD[2]; + if (pipe(pipeFD) == -1) { + ALOGE("pipe() failed, errno = %d", errno); + goto release_fds; + } + ScopedLocalRef<jobject> jifd(env, jniCreateFileDescriptor(env, pipeFD[0])); + if (jifd.get() == NULL) { + close(pipeFD[0]); + close(pipeFD[1]); + goto release_fds; + } + env->SetObjectArrayElement(fds, subdevice_count, jifd.get()); + // store our end of the pipe in mPipeFD + env->SetIntField(thiz, sPipeFDField, pipeFD[1]); + } return fds; + +release_fds: + for (int i = 0; i < subdevice_count + 1; ++i) { + ScopedLocalRef<jobject> jifd(env, env->GetObjectArrayElement(fds, i)); + if (jifd.get() == NULL) { + break; + } + int fd = jniGetFDFromFileDescriptor(env, jifd.get()); + close(fd); + } + return NULL; } static void diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 0167a3b0aebe..23b1512081da 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -165,6 +165,8 @@ import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; +import libcore.timezone.ZoneInfoDb; + import dalvik.system.VMRuntime; import java.io.File; @@ -395,8 +397,9 @@ public final class SystemServer { // Default the timezone property to GMT if not set. // String timezoneProperty = SystemProperties.get("persist.sys.timezone"); - if (timezoneProperty == null || timezoneProperty.isEmpty()) { - Slog.w(TAG, "Timezone not set; setting to GMT."); + if (!isValidTimeZoneId(timezoneProperty)) { + Slog.w(TAG, "persist.sys.timezone is not valid (" + timezoneProperty + + "); setting to GMT."); SystemProperties.set("persist.sys.timezone", "GMT"); } @@ -564,6 +567,12 @@ public final class SystemServer { throw new RuntimeException("Main thread loop unexpectedly exited"); } + private static boolean isValidTimeZoneId(String timezoneProperty) { + return timezoneProperty != null + && !timezoneProperty.isEmpty() + && ZoneInfoDb.getInstance().hasTimeZone(timezoneProperty); + } + private boolean isFirstBootOrUpgrade() { return mPackageManagerService.isFirstBoot() || mPackageManagerService.isDeviceUpgrading(); } diff --git a/services/net/Android.bp b/services/net/Android.bp index bb5409b3e032..8b444b0fed41 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -12,8 +12,7 @@ java_library_static { ":services.net-sources", ], static_libs: [ - "dnsresolver_aidl_interface-V4-java", - "netd_aidl_interface-V3-java", + "netd_aidl_interfaces-platform-java", "netlink-client", "networkstack-client", "net-utils-services-common", @@ -44,7 +43,8 @@ java_library { "framework-wifi-util-lib", ], static_libs: [ - "dnsresolver_aidl_interface-V2-java", + // All the classes in netd_aidl_interface must be jarjar so they do not conflict with the + // classes generated by netd_aidl_interfaces-platform-java above. "netd_aidl_interface-V3-java", "netlink-client", "networkstack-client", diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index 163832983b5b..3465ea99bdae 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -73,7 +73,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { private static final int HDMI_3_PHYSICAL_ADDRESS = 0x2300; private int mInvokeDeviceEventState; private HdmiDeviceInfo mDeviceInfo; - private boolean mMutingEnabled; private boolean mArcSupport; private HdmiPortInfo[] mHdmiPortInfo; @@ -154,8 +153,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Override boolean readBooleanSystemProperty(String key, boolean defVal) { switch (key) { - case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE: - return mMutingEnabled; case Constants.PROPERTY_ARC_SUPPORT: return mArcSupport; default: @@ -209,7 +206,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); mNativeWrapper.clearResultMessages(); - mMutingEnabled = true; mArcSupport = true; mInvokeDeviceEventState = 0; mDeviceInfo = null; diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java index 30d103576c99..c08671825b09 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,7 +70,9 @@ public class ApexManagerTest { @Before public void setUp() throws RemoteException { mContext = InstrumentationRegistry.getInstrumentation().getContext(); - mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService); + ApexManager.ApexManagerImpl managerImpl = spy(new ApexManager.ApexManagerImpl(mContext)); + doReturn(mApexService).when(managerImpl).waitForApexService(); + mApexManager = managerImpl; } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index bde0ef6aa39e..ff27b9bb1c9e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -28,7 +28,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; @@ -54,8 +54,11 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import android.app.ActivityManager; +import android.app.IApplicationThread; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.os.UserHandle; @@ -82,8 +85,9 @@ public class ActivityStackTests extends ActivityTestsBase { @Before public void setUp() throws Exception { mDefaultDisplay = mRootActivityContainer.getDefaultDisplay(); - mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, - true /* onTop */)); + mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + spyOn(mStack); mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); } @@ -1078,6 +1082,37 @@ public class ActivityStackTests extends ActivityTestsBase { assertTrue(listener.mChanged); } + @Test + public void testNavigateUpTo() { + final ActivityStartController controller = mock(ActivityStartController.class); + final ActivityStarter starter = new ActivityStarter(controller, + mService, mService.mStackSupervisor, mock(ActivityStartInterceptor.class)); + doReturn(controller).when(mService).getActivityStartController(); + spyOn(starter); + doReturn(ActivityManager.START_SUCCESS).when(starter).execute(); + + final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); + final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask) + .setUid(firstActivity.getUid() + 1).build(); + doReturn(starter).when(controller).obtainStarter(eq(firstActivity.intent), anyString()); + + final IApplicationThread thread = secondActivity.app.getThread(); + secondActivity.app.setThread(null); + // This should do nothing from a non-attached caller. + assertFalse(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + + secondActivity.app.setThread(thread); + assertTrue(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + // The firstActivity uses default launch mode, so the activities between it and itself will + // be finished. + assertTrue(secondActivity.finishing); + assertTrue(firstActivity.finishing); + // The calling uid of the new activity should be the current real caller. + assertEquals(secondActivity.getUid(), starter.getCallingUid()); + } + private void verifyShouldSleepActivities(boolean focusedStack, boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { final ActivityDisplay display = mock(ActivityDisplay.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 84bdecb86826..f94f00203521 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -290,6 +290,7 @@ class ActivityTestsBase { aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; aInfo.packageName = mComponent.getPackageName(); + aInfo.name = mComponent.getClassName(); if (mTargetActivity != null) { aInfo.targetActivity = mTargetActivity; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java index e004cd3fb0c4..f25110f549df 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java @@ -23,6 +23,9 @@ import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.app.ActivityManager.TaskSnapshot; import android.content.ComponentName; import android.graphics.Canvas; @@ -32,9 +35,14 @@ import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.UserManager; +import android.os.UserManagerInternal; + +import com.android.server.LocalServices; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import java.io.File; @@ -50,10 +58,26 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase { TaskSnapshotLoader mLoader; int mTestUserId; + @BeforeClass + public static void setUpOnce() { + final UserManagerInternal userManager = mock(UserManagerInternal.class); + LocalServices.addService(UserManagerInternal.class, userManager); + } + + @AfterClass + public static void tearDownOnce() { + LocalServices.removeServiceForTest(UserManagerInternal.class); + } + @Before public void setUp() { final UserManager um = UserManager.get(getInstrumentation().getTargetContext()); mTestUserId = um.getUserHandle(); + + final UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true); + mPersister = new TaskSnapshotPersister(mWm, userId -> FILES_DIR); mLoader = new TaskSnapshotLoader(mPersister); mPersister.start(); diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 4e14fd3d59a1..d9605522b3b0 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -106,6 +106,7 @@ public abstract class Conference extends Conferenceable { private int mCallerDisplayNamePresentation; private int mCallDirection; private boolean mRingbackRequested = false; + private boolean mIsMultiparty = true; private final Connection.Listener mConnectionDeathListener = new Connection.Listener() { @Override @@ -998,8 +999,8 @@ public abstract class Conference extends Conferenceable { public void onExtrasChanged(Bundle extras) {} /** - * Set whether Telecom should treat this {@link Conference} as a conference call or if it - * should treat it as a single-party call. + * Set whether Telecom should treat this {@link Conference} as a multiparty conference call or + * if it should treat it as a single-party call. * This method is used as part of a workaround regarding IMS conference calls and user * expectation. In IMS, once a conference is formed, the UE is connected to an IMS conference * server. If all participants of the conference drop out of the conference except for one, the @@ -1020,6 +1021,7 @@ public abstract class Conference extends Conferenceable { @TestApi @RequiresPermission(MODIFY_PHONE_STATE) public void setConferenceState(boolean isConference) { + mIsMultiparty = isConference; for (Listener l : mListeners) { l.onConferenceStateChanged(this, isConference); } @@ -1043,6 +1045,20 @@ public abstract class Conference extends Conferenceable { } } + /** + * Determines if the {@link Conference} is considered "multiparty" or not. By default all + * conferences are considered multiparty. A multiparty conference is one where there are + * multiple conference participants (other than the host) in the conference. + * This is tied to {@link #setConferenceState(boolean)}, which is used for some use cases to + * have a conference appear as if it is a standalone call, in which case the conference will + * no longer be multiparty. + * @return {@code true} if conference is treated as a conference (i.e. it is multiparty), + * {@code false} if it should emulate a standalone call (i.e. not multiparty). + * @hide + */ + public boolean isMultiparty() { + return mIsMultiparty; + } /** * Sets the address of this {@link Conference}. Used when {@link #setConferenceState(boolean)} diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 73296986d82e..1b60e4820ad0 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -2505,6 +2505,11 @@ public abstract class ConnectionService extends Service { mAdapter.addConferenceCall(id, parcelableConference); mAdapter.setVideoProvider(id, conference.getVideoProvider()); mAdapter.setVideoState(id, conference.getVideoState()); + // In some instances a conference can start its life as a standalone call with just a + // single participant; ensure we signal to Telecom in this case. + if (!conference.isMultiparty()) { + mAdapter.setConferenceState(id, conference.isMultiparty()); + } // Go through any child calls and set the parent. for (Connection connection : conference.getConnections()) { diff --git a/telecomm/java/android/telecom/GatewayInfo.java b/telecomm/java/android/telecom/GatewayInfo.java index 0faa4fd2027a..31c24d54918a 100644 --- a/telecomm/java/android/telecom/GatewayInfo.java +++ b/telecomm/java/android/telecom/GatewayInfo.java @@ -111,7 +111,7 @@ public class GatewayInfo implements Parcelable { @Override public void writeToParcel(Parcel destination, int flags) { destination.writeString(mGatewayProviderPackageName); - mGatewayAddress.writeToParcel(destination, 0); - mOriginalAddress.writeToParcel(destination, 0); + Uri.writeToParcel(destination, mGatewayAddress); + Uri.writeToParcel(destination, mOriginalAddress); } } diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index 415a817b58d5..182dc8bb8325 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -629,7 +629,7 @@ public final class ParcelableCall implements Parcelable { int capabilities = source.readInt(); int properties = source.readInt(); long connectTimeMillis = source.readLong(); - Uri handle = source.readParcelable(classLoader); + Uri handle = Uri.CREATOR.createFromParcel(source); int handlePresentation = source.readInt(); String callerDisplayName = source.readString(); int callerDisplayNamePresentation = source.readInt(); @@ -711,7 +711,7 @@ public final class ParcelableCall implements Parcelable { destination.writeInt(mCapabilities); destination.writeInt(mProperties); destination.writeLong(mConnectTimeMillis); - destination.writeParcelable(mHandle, 0); + Uri.writeToParcel(destination, mHandle); destination.writeInt(mHandlePresentation); destination.writeString(mCallerDisplayName); destination.writeInt(mCallerDisplayNamePresentation); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 8d53158b9f32..ce71511c0361 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -398,7 +398,7 @@ public class TelecomManager { * Optional extra for communicating the call network technology used by a * {@link android.telecom.Connection} to Telecom and InCallUI. * - * @see {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}. + * {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}. */ public static final String EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE"; diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt deleted file mode 100644 index 892bd03a562e..000000000000 --- a/telephony/api/system-current.txt +++ /dev/null @@ -1,2140 +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 isIncomingSilenceDetected(); - method public boolean isOutgoingSilenceDetected(); - 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 DisconnectCause { - field public static final int ALREADY_DIALING = 72; // 0x48 - field public static final int ANSWERED_ELSEWHERE = 52; // 0x34 - field public static final int BUSY = 4; // 0x4 - field public static final int CALLING_DISABLED = 74; // 0x4a - field public static final int CALL_BARRED = 20; // 0x14 - field public static final int CALL_PULLED = 51; // 0x33 - field public static final int CANT_CALL_WHILE_RINGING = 73; // 0x49 - field public static final int CDMA_ACCESS_BLOCKED = 35; // 0x23 - field public static final int CDMA_ACCESS_FAILURE = 32; // 0x20 - field public static final int CDMA_ALREADY_ACTIVATED = 49; // 0x31 - field public static final int CDMA_DROP = 27; // 0x1b - field public static final int CDMA_INTERCEPT = 28; // 0x1c - field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 26; // 0x1a - field public static final int CDMA_NOT_EMERGENCY = 34; // 0x22 - field public static final int CDMA_PREEMPTED = 33; // 0x21 - field public static final int CDMA_REORDER = 29; // 0x1d - field public static final int CDMA_RETRY_ORDER = 31; // 0x1f - field public static final int CDMA_SO_REJECT = 30; // 0x1e - field public static final int CONGESTION = 5; // 0x5 - field public static final int CS_RESTRICTED = 22; // 0x16 - field public static final int CS_RESTRICTED_EMERGENCY = 24; // 0x18 - field public static final int CS_RESTRICTED_NORMAL = 23; // 0x17 - field public static final int DATA_DISABLED = 54; // 0x36 - field public static final int DATA_LIMIT_REACHED = 55; // 0x37 - field public static final int DIALED_CALL_FORWARDING_WHILE_ROAMING = 57; // 0x39 - field public static final int DIALED_MMI = 39; // 0x27 - field public static final int DIAL_LOW_BATTERY = 62; // 0x3e - field public static final int DIAL_MODIFIED_TO_DIAL = 48; // 0x30 - field public static final int DIAL_MODIFIED_TO_DIAL_VIDEO = 66; // 0x42 - field public static final int DIAL_MODIFIED_TO_SS = 47; // 0x2f - field public static final int DIAL_MODIFIED_TO_USSD = 46; // 0x2e - field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL = 69; // 0x45 - field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70; // 0x46 - field public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67; // 0x43 - field public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68; // 0x44 - field public static final int EMERGENCY_PERM_FAILURE = 64; // 0x40 - field public static final int EMERGENCY_TEMP_FAILURE = 63; // 0x3f - field public static final int ERROR_UNSPECIFIED = 36; // 0x24 - field public static final int FDN_BLOCKED = 21; // 0x15 - field public static final int ICC_ERROR = 19; // 0x13 - field public static final int IMEI_NOT_ACCEPTED = 58; // 0x3a - field public static final int IMS_ACCESS_BLOCKED = 60; // 0x3c - field public static final int IMS_MERGED_SUCCESSFULLY = 45; // 0x2d - field public static final int IMS_SIP_ALTERNATE_EMERGENCY_CALL = 71; // 0x47 - field public static final int INCOMING_AUTO_REJECTED = 81; // 0x51 - field public static final int INCOMING_MISSED = 1; // 0x1 - field public static final int INCOMING_REJECTED = 16; // 0x10 - field public static final int INVALID_CREDENTIALS = 10; // 0xa - field public static final int INVALID_NUMBER = 7; // 0x7 - field public static final int LIMIT_EXCEEDED = 15; // 0xf - field public static final int LOCAL = 3; // 0x3 - field public static final int LOST_SIGNAL = 14; // 0xe - field public static final int LOW_BATTERY = 61; // 0x3d - field public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53; // 0x35 - field public static final int MMI = 6; // 0x6 - field public static final int NORMAL = 2; // 0x2 - field public static final int NORMAL_UNSPECIFIED = 65; // 0x41 - field public static final int NOT_DISCONNECTED = 0; // 0x0 - field public static final int NOT_VALID = -1; // 0xffffffff - field public static final int NO_PHONE_NUMBER_SUPPLIED = 38; // 0x26 - field public static final int NUMBER_UNREACHABLE = 8; // 0x8 - field public static final int OTASP_PROVISIONING_IN_PROCESS = 76; // 0x4c - field public static final int OUTGOING_CANCELED = 44; // 0x2c - field public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; // 0x50 - field public static final int OUTGOING_FAILURE = 43; // 0x2b - field public static final int OUT_OF_NETWORK = 11; // 0xb - field public static final int OUT_OF_SERVICE = 18; // 0x12 - field public static final int POWER_OFF = 17; // 0x11 - field public static final int SERVER_ERROR = 12; // 0xc - field public static final int SERVER_UNREACHABLE = 9; // 0x9 - field public static final int TIMED_OUT = 13; // 0xd - field public static final int TOO_MANY_ONGOING_CALLS = 75; // 0x4b - field public static final int UNOBTAINABLE_NUMBER = 25; // 0x19 - field public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50; // 0x32 - field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28 - field public static final int WIFI_LOST = 59; // 0x3b - } - - 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 ModemActivityInfo implements android.os.Parcelable { - ctor public ModemActivityInfo(long, int, int, @NonNull int[], int); - method public int describeContents(); - method public int getIdleTimeMillis(); - method public int getReceiveTimeMillis(); - method public int getSleepTimeMillis(); - method public long getTimestamp(); - method @NonNull public java.util.List<android.telephony.ModemActivityInfo.TransmitPower> getTransmitPowerInfo(); - method public boolean isValid(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; - field public static final int TX_POWER_LEVELS = 5; // 0x5 - field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 - field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 - field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 - field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 - field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 - } - - public class ModemActivityInfo.TransmitPower { - method @NonNull public android.util.Range<java.lang.Integer> getPowerRangeInDbm(); - method public int getTimeInMillis(); - } - - public final class NetworkRegistrationInfo implements android.os.Parcelable { - method @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 @Nullable public android.net.LinkProperties getDataConnectionLinkProperties(); - method @Deprecated public int getDataConnectionNetworkType(); - method @Deprecated public int getDataConnectionState(); - } - - 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 public void fillInNotifierBundle(@NonNull android.os.Bundle); - 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); - method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle); - field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2 - field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3 - field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0 - field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1 - } - - public class SignalStrength implements android.os.Parcelable { - ctor public SignalStrength(@NonNull android.telephony.SignalStrength); - } - - 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 @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean copyMessageToIcc(@Nullable byte[], @NonNull byte[], int); - method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int); - method public boolean disableCellBroadcastRange(int, int, int); - method public boolean enableCellBroadcastRange(int, int, int); - method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public java.util.List<android.telephony.SmsMessage> getMessagesFromIcc(); - 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 public int[] getActiveAndHiddenSubscriptionIdList(); - method @NonNull 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 @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 int setDisplayName(@Nullable String, int, int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setIconTint(int, 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 class TelephonyFrameworkInitializer { - method public static void registerServiceWrappers(); - method public static void setTelephonyServiceManager(@NonNull android.os.TelephonyServiceManager); - } - - 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 isInEmergencySmsMode(); - 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 void notifyUserActivity(); - 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 boolean setAlwaysAllowMmsData(boolean); - 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_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"; - field public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE"; - field public static final String ACTION_CARRIER_SIGNAL_REDIRECTED = "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED"; - field public static final String ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED = "com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED"; - field public static final String ACTION_CARRIER_SIGNAL_RESET = "com.android.internal.telephony.CARRIER_SIGNAL_RESET"; - 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_SERVICE_PROVIDERS_UPDATED = "android.telephony.action.SERVICE_PROVIDERS_UPDATED"; - 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 CARD_POWER_DOWN = 0; // 0x0 - field public static final int CARD_POWER_UP = 1; // 0x1 - field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2 - 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 @Deprecated public static final String EXTRA_APN_PROTOCOL = "apnProto"; - field public static final String EXTRA_APN_PROTOCOL_INT = "apnProtoInt"; - field @Deprecated public static final String EXTRA_APN_TYPE = "apnType"; - field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt"; - field public static final String EXTRA_DATA_SPN = "android.telephony.extra.DATA_SPN"; - field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable"; - field public static final String EXTRA_ERROR_CODE = "errorCode"; - field public static final String EXTRA_PCO_ID = "pcoId"; - field public static final String EXTRA_PCO_VALUE = "pcoValue"; - 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_PLMN = "android.telephony.extra.PLMN"; - field public static final String EXTRA_REDIRECTION_URL = "redirectionUrl"; - field public static final String EXTRA_SHOW_PLMN = "android.telephony.extra.SHOW_PLMN"; - field public static final String EXTRA_SHOW_SPN = "android.telephony.extra.SHOW_SPN"; - field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; - field public static final String EXTRA_SPN = "android.telephony.extra.SPN"; - 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 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 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 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_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 boolean isCapable(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/common/com/android/internal/telephony/CellBroadcastUtils.java b/telephony/common/com/android/internal/telephony/CellBroadcastUtils.java new file mode 100644 index 000000000000..6c6375586225 --- /dev/null +++ b/telephony/common/com/android/internal/telephony/CellBroadcastUtils.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.provider.Telephony; +import android.text.TextUtils; +import android.util.Log; + +/** + * This class provides utility functions related to CellBroadcast. + */ +public class CellBroadcastUtils { + private static final String TAG = "CellBroadcastUtils"; + private static final boolean VDBG = false; + + /** + * Utility method to query the default CBR's package name. + */ + public static String getDefaultCellBroadcastReceiverPackageName(Context context) { + PackageManager packageManager = context.getPackageManager(); + ResolveInfo resolveInfo = packageManager.resolveActivity( + new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION), + PackageManager.MATCH_SYSTEM_ONLY); + String packageName; + + if (resolveInfo == null) { + Log.e(TAG, "getDefaultCellBroadcastReceiverPackageName: no package found"); + return null; + } + + packageName = resolveInfo.activityInfo.applicationInfo.packageName; + + if (VDBG) { + Log.d(TAG, "getDefaultCellBroadcastReceiverPackageName: found package: " + packageName); + } + + if (TextUtils.isEmpty(packageName) || packageManager.checkPermission( + android.Manifest.permission.READ_CELL_BROADCASTS, packageName) + == PackageManager.PERMISSION_DENIED) { + Log.e(TAG, "getDefaultCellBroadcastReceiverPackageName: returning null; " + + "permission check failed for : " + packageName); + return null; + } + + return packageName; + } +} diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 726d250c49d0..4d15a93c2dbe 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2512,6 +2512,16 @@ public class CarrierConfigManager { "parameters_use_for_5g_nr_signal_bar_int"; /** + * There are two signal strengths, NR and LTE signal strength, during NR (non-standalone). + * Boolean indicating whether to use LTE signal strength as primary during NR (non-standalone). + * By default this value is true. + * + * @hide + */ + public static final String KEY_SIGNAL_STRENGTH_NR_NSA_USE_LTE_AS_PRIMARY_BOOL = + "signal_strength_nr_nsa_use_lte_as_primary_bool"; + + /** * String array of default bandwidth values per network type. * The entries should be of form "network_name:downstream,upstream", with values in Kbps. * @hide @@ -3015,19 +3025,95 @@ public class CarrierConfigManager { public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string"; /** - * Timeout in seconds for displaying 5G icon, default value is 0 which means the timer is - * disabled. + * This configuration allows the system UI to determine how long to continue to display 5G icons + * when the device switches between different 5G scenarios. * - * System UI will show the 5G icon and start a timer with the timeout from this config when the - * device connects to a 5G cell. System UI stops displaying 5G icon when both the device - * disconnects from 5G cell and the timer is expired. + * There are seven 5G scenarios: + * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using + * millimeter wave. + * 2. connected: device currently connected to 5G cell as the secondary cell but not using + * millimeter wave. + * 3. not_restricted_rrc_idle: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in IDLE state. + * 4. not_restricted_rrc_con: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in CONNECTED state. + * 5. restricted: device camped on a network that has 5G capability (not necessary to connect a + * 5G cell as a secondary cell) but the use of 5G is restricted. + * 6. legacy: device is not camped on a network that has 5G capability + * 7. any: any of the above scenarios + * + * The configured string contains various timer rules separated by a semicolon. + * Each rule will have three items: prior 5G scenario, current 5G scenario, and grace period + * in seconds before changing the icon. When the 5G state changes from the prior to the current + * 5G scenario, the system UI will continue to show the icon for the prior 5G scenario (defined + * in {@link #KEY_5G_ICON_CONFIGURATION_STRING}) for the amount of time specified by the grace + * period. If the prior 5G scenario is reestablished, the timer will reset and start again if + * the UE changes 5G scenarios again. Defined states (5G scenarios #1-5) take precedence over + * 'any' (5G scenario #6), and unspecified transitions have a default grace period of 0. + * The order of rules in the configuration determines the priority (the first applicable timer + * rule will be used). + * + * Here is an example: "connected_mmwave,connected,30;connected_mmwave,any,10;connected,any,10" + * This configuration defines 3 timers: + * 1. When UE goes from 'connected_mmwave' to 'connected', system UI will continue to display + * the 5G icon for 'connected_mmwave' for 30 seconds. + * 2. When UE goes from 'connected_mmwave' to any other state (except for connected, since + * rule 1 would be used instead), system UI will continue to display the 5G icon for + * 'connected_mmwave' for 10 seconds. + * 3. When UE goes from 'connected' to any other state, system UI will continue to display the + * 5G icon for 'connected' for 10 seconds. * - * If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next - * lost. Allows us to momentarily lose 5G without blinking the icon. * @hide */ - public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = - "5g_icon_display_grace_period_sec_int"; + public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING = + "5g_icon_display_grace_period_string"; + + /** + * This configuration extends {@link #KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING} to allow the + * system UI to continue displaying 5G icons after the initial timer expires. + * + * There are seven 5G scenarios: + * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using + * millimeter wave. + * 2. connected: device currently connected to 5G cell as the secondary cell but not using + * millimeter wave. + * 3. not_restricted_rrc_idle: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in IDLE state. + * 4. not_restricted_rrc_con: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in CONNECTED state. + * 5. restricted: device camped on a network that has 5G capability (not necessary to connect a + * 5G cell as a secondary cell) but the use of 5G is restricted. + * 6. legacy: device is not camped on a network that has 5G capability + * 7. any: any of the above scenarios + * + * The configured string contains various timer rules separated by a semicolon. + * Each rule will have three items: primary 5G scenario, secondary 5G scenario, and + * grace period in seconds before changing the icon. When the timer for the primary 5G timer + * expires, the system UI will continue to show the icon for the primary 5G scenario (defined + * in {@link #KEY_5G_ICON_CONFIGURATION_STRING}) for the amount of time specified by the grace + * period. If the primary 5G scenario is reestablished, the timers will reset and the system UI + * will continue to display the icon for the primary 5G scenario without interruption. If the + * secondary 5G scenario is lost, the timer will reset and the icon will reflect the true state. + * Defined states (5G scenarios #1-5) take precedence over 'any' (5G scenario #6), and + * unspecified transitions have a default grace period of 0. The order of rules in the + * configuration determines the priority (the first applicable timer rule will be used). + * + * Here is an example: "connected,not_restricted_rrc_idle,30" + * This configuration defines a secondary timer that extends the primary 'connected' timer. + * When the primary 'connected' timer expires while the UE is in the 'not_restricted_rrc_idle' + * 5G state, system UI will continue to display the 5G icon for 'connected' for 30 seconds. + * If the 5G state returns to 'connected', the timer will be reset without change to the icon, + * and if the 5G state changes to neither 'connected' not 'not_restricted_rrc_idle', the icon + * will change to reflect the true state. + * + * @hide + */ + public static final String KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING = + "5g_icon_display_secondary_grace_period_string"; /** * Controls time in milliseconds until DcTracker reevaluates 5G connection state. @@ -3058,6 +3144,38 @@ public class CarrierConfigManager { public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool"; /** + * Whether NR (non-standalone) should be unmetered when the device is roaming. + * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL}, + * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL}, + * and unmetered {@link SubscriptionPlan} will be ignored. + * @hide + */ + public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL = + "unmetered_nr_nsa_when_roaming_bool"; + + /** + * Whether NR (standalone) should be unmetered for all frequencies. + * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or + * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored. + * @hide + */ + public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool"; + + /** + * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered. + * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. + * @hide + */ + public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool"; + + /** + * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered. + * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. + * @hide + */ + public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool"; + + /** * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable * this feature. * @hide @@ -3587,6 +3705,17 @@ public class CarrierConfigManager { public static final String KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY = "missed_incoming_call_sms_originator_string_array"; + + /** + * String array of Apn Type configurations. + * The entries should be of form "APN_TYPE_NAME:priority". + * priority is an integer that is sorted from highest to lowest. + * example: cbs:5 + * + * @hide + */ + public static final String KEY_APN_PRIORITY_STRING_ARRAY = "apn_priority_string_array"; + /** * The patterns of missed incoming call sms. This is the regular expression used for * matching the missed incoming call's date, time, and caller id. The pattern should match @@ -3979,10 +4108,10 @@ public class CarrierConfigManager { }); sDefaults.putIntArray(KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY, new int[] { - -19, /* SIGNAL_STRENGTH_POOR */ + -20, /* SIGNAL_STRENGTH_POOR */ -17, /* SIGNAL_STRENGTH_MODERATE */ -14, /* SIGNAL_STRENGTH_GOOD */ - -12 /* SIGNAL_STRENGTH_GREAT */ + -11 /* SIGNAL_STRENGTH_GREAT */ }); sDefaults.putIntArray(KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY, new int[] { @@ -4010,9 +4139,9 @@ public class CarrierConfigManager { // Boundaries: [-20 dB, -3 dB] new int[] { -16, /* SIGNAL_STRENGTH_POOR */ - -11, /* SIGNAL_STRENGTH_MODERATE */ + -12, /* SIGNAL_STRENGTH_MODERATE */ -9, /* SIGNAL_STRENGTH_GOOD */ - -7 /* SIGNAL_STRENGTH_GREAT */ + -6 /* SIGNAL_STRENGTH_GREAT */ }); sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY, // Boundaries: [-23 dB, 40 dB] @@ -4024,10 +4153,11 @@ public class CarrierConfigManager { }); sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, CellSignalStrengthNr.USE_SSRSRP); + sDefaults.putBoolean(KEY_SIGNAL_STRENGTH_NR_NSA_USE_LTE_AS_PRIMARY_BOOL, true); sDefaults.putStringArray(KEY_BANDWIDTH_STRING_ARRAY, new String[]{ "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA-IS95A:14,14", "CDMA-IS95B:14,14", "1xRTT:30,30", "EvDo-rev.0:750,48", "EvDo-rev.A:950,550", "HSDPA:4300,620", - "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550:", "eHRPD:750,48", + "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550", "eHRPD:750,48", "HSPAP:13000,3400", "TD-SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,15000", "NR_NSA_MMWAVE:145000,15000", "NR_SA:145000,15000"}); sDefaults.putBoolean(KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL, false); @@ -4046,12 +4176,17 @@ public class CarrierConfigManager { sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING, "connected_mmwave:5G,connected:5G,not_restricted_rrc_idle:5G," + "not_restricted_rrc_con:5G"); - sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0); + sDefaults.putString(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING, ""); + sDefaults.putString(KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING, ""); /* Default value is 1 hour. */ sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000); sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false); sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false); sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false); + sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false); + sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false); + sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false); + sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false); sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false); sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false); /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */ @@ -4112,6 +4247,10 @@ public class CarrierConfigManager { sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, TimeUnit.DAYS.toMillis(1)); sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY, new String[0]); + sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] { + "default:0", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2", + "ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3" + }); sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]); } diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java index 33a43c1e0319..1e5ce05ff28a 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -211,7 +211,7 @@ public abstract class CellIdentity implements Parcelable { } /** @hide */ - protected String getPlmn() { + public @Nullable String getPlmn() { if (mMccStr == null || mMncStr == null) return null; return mMccStr + mMncStr; } diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java index f21277cdd83c..68c833c37c99 100644 --- a/telephony/java/android/telephony/CellIdentityCdma.java +++ b/telephony/java/android/telephony/CellIdentityCdma.java @@ -279,6 +279,7 @@ public final class CellIdentityCdma extends CellIdentity { mLongitude = in.readInt(); mLatitude = in.readInt(); + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java index 1a913105db2e..849c613da748 100644 --- a/telephony/java/android/telephony/CellIdentityGsm.java +++ b/telephony/java/android/telephony/CellIdentityGsm.java @@ -323,6 +323,7 @@ public final class CellIdentityGsm extends CellIdentity { mBsic = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index 13a8273d64d4..1993550d52b8 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -403,6 +403,8 @@ public final class CellIdentityLte extends CellIdentity { mBandwidth = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index f0d878001bf4..8dd7bdd57841 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -273,6 +273,8 @@ public final class CellIdentityNr extends CellIdentity { mBands = in.createIntArray(); mNci = in.readLong(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); + + updateGlobalCellId(); } /** Implement the Parcelable interface */ diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java index 6dffe922ffd1..e74b70939d14 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -321,6 +321,8 @@ public final class CellIdentityTdscdma extends CellIdentity { mUarfcn = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java index eab174ade3b7..40cb27e95151 100644 --- a/telephony/java/android/telephony/CellIdentityWcdma.java +++ b/telephony/java/android/telephony/CellIdentityWcdma.java @@ -336,6 +336,8 @@ public final class CellIdentityWcdma extends CellIdentity { mUarfcn = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index 8562df1d015f..95fe90a47654 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -57,9 +57,9 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa // Boundaries: [-20 dB, -3 dB] private int[] mSsRsrqThresholds = new int[] { -16, /* SIGNAL_STRENGTH_POOR */ - -11, /* SIGNAL_STRENGTH_MODERATE */ + -12, /* SIGNAL_STRENGTH_MODERATE */ -9, /* SIGNAL_STRENGTH_GOOD */ - -7 /* SIGNAL_STRENGTH_GREAT */ + -6 /* SIGNAL_STRENGTH_GREAT */ }; // Lifted from Default carrier configs and max range of SSSINR diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index 0ad572412309..bf21bb7c2a35 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -22,6 +22,8 @@ import android.compat.annotation.UnsupportedAppUsage; /** * Describes the cause of a disconnected call. Those disconnect causes can be converted into a more * generic {@link android.telecom.DisconnectCause} object. + * + * Used in {@link PhoneStateListener#onCallDisconnectCauseChanged}. */ public final class DisconnectCause { @@ -333,20 +335,17 @@ public final class DisconnectCause { /** * Indicates that the call is dropped due to RTCP inactivity, primarily due to media path * disruption. - * @hide */ public static final int MEDIA_TIMEOUT = 77; /** * Indicates that an emergency call cannot be placed over WFC because the service is not * available in the current location. - * @hide */ public static final int EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 78; /** * Indicates that WiFi calling service is not available in the current location. - * @hide */ public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79; diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index 45deea206cfc..3d96fc634d6a 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -231,6 +231,8 @@ public class MbmsDownloadSession implements AutoCloseable { private static final String DESTINATION_SANITY_CHECK_FILE_NAME = "destinationSanityCheckFile"; + private static final int MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE = 10 * 1024; // 10KB + private static AtomicBoolean sIsInitialized = new AtomicBoolean(false); private final Context mContext; @@ -318,6 +320,16 @@ public class MbmsDownloadSession implements AutoCloseable { return session; } + /** + * Returns the maximum size of the service announcement file that can be provided via + * {@link #addServiceAnnouncementFile} + * @return The maximum length of the byte array passed as an argument to + * {@link #addServiceAnnouncementFile}. + */ + public static int getMaximumServiceAnnouncementFileSize() { + return MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE; + } + private int bindAndInitialize() { mServiceConnection = new ServiceConnection() { @Override @@ -424,6 +436,60 @@ public class MbmsDownloadSession implements AutoCloseable { } /** + * Inform the middleware of a service announcement file received from a group communication + * server. + * + * When participating in a group call via the {@link MbmsGroupCallSession} API, applications may + * receive a service announcement file from the group call server that informs them of + * files that may be relevant to users communicating on the group call. + * + * After supplying the service announcement file received from the server to the middleware via + * this API, applications will receive information on the available files via + * {@link MbmsDownloadSessionCallback#onFileServicesUpdated}, and the available files will be + * downloadable via {@link MbmsDownloadSession#download} like other files published via + * {@link MbmsDownloadSessionCallback#onFileServicesUpdated}. + * + * Asynchronous error codes via the {@link MbmsDownloadSessionCallback#onError(int, String)} + * callback may include any of the errors that are not specific to the streaming use-case. + * + * May throw an {@link IllegalStateException} when the middleware has not yet been bound, + * or an {@link IllegalArgumentException} if the file is too large. + * + * @param fileContents The contents of the service announcement file received from the group + * call server. If the size of this array is greater than the value of + * {@link #getMaximumServiceAnnouncementFileSize()}, an + * {@link IllegalArgumentException} will be thrown. + */ + public void addServiceAnnouncementFile(@NonNull byte[] fileContents) { + IMbmsDownloadService downloadService = mService.get(); + if (downloadService == null) { + throw new IllegalStateException("Middleware not yet bound"); + } + + if (fileContents.length > MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE) { + throw new IllegalArgumentException("File too large"); + } + + try { + int returnCode = downloadService.addServiceAnnouncementFile( + mSubscriptionId, fileContents); + if (returnCode == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } + if (returnCode != MbmsErrors.SUCCESS) { + sendErrorToApp(returnCode, null); + } + } catch (RemoteException e) { + Log.w(LOG_TAG, "Remote process died"); + mService.set(null); + sIsInitialized.set(false); + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + } + } + + /** * Sets the temp file root for downloads. * All temp files created for the middleware to write to will be contained in the specified * directory. Applications that wish to specify a location only need to call this method once diff --git a/telephony/java/android/telephony/PinResult.java b/telephony/java/android/telephony/PinResult.java index 68c9d998ba92..d9b5de5f878a 100644 --- a/telephony/java/android/telephony/PinResult.java +++ b/telephony/java/android/telephony/PinResult.java @@ -37,6 +37,7 @@ public final class PinResult implements Parcelable { PIN_RESULT_TYPE_SUCCESS, PIN_RESULT_TYPE_INCORRECT, PIN_RESULT_TYPE_FAILURE, + PIN_RESULT_TYPE_ABORTED, }) public @interface PinResultType {} @@ -55,6 +56,11 @@ public final class PinResult implements Parcelable { */ public static final int PIN_RESULT_TYPE_FAILURE = PhoneConstants.PIN_GENERAL_FAILURE; + /** + * Indicates that the pin attempt was aborted. + */ + public static final int PIN_RESULT_TYPE_ABORTED = PhoneConstants.PIN_OPERATION_ABORTED; + private static final PinResult sFailedResult = new PinResult(PinResult.PIN_RESULT_TYPE_FAILURE, -1); diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index a269bd1809d4..5c84297d3b86 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1392,15 +1392,16 @@ public class ServiceState implements Parcelable { /** @hide */ public boolean isUsingCarrierAggregation() { + boolean isUsingCa = false; NetworkRegistrationInfo nri = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (nri != null) { DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo(); if (dsri != null) { - return dsri.isUsingCarrierAggregation(); + isUsingCa = dsri.isUsingCarrierAggregation(); } } - return false; + return isUsingCa || getCellBandwidths().length > 1; } /** @hide */ diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java index 16fbd07f9495..5f09ca203dd9 100644 --- a/telephony/java/android/telephony/SignalStrength.java +++ b/telephony/java/android/telephony/SignalStrength.java @@ -83,6 +83,8 @@ public class SignalStrength implements Parcelable { // Effectively final. Timestamp is set during construction of SignalStrength private long mTimestampMillis; + private boolean mLteAsPrimaryInNrNsa = true; + CellSignalStrengthCdma mCdma; CellSignalStrengthGsm mGsm; CellSignalStrengthWcdma mWcdma; @@ -190,12 +192,16 @@ public class SignalStrength implements Parcelable { private CellSignalStrength getPrimary() { // This behavior is intended to replicate the legacy behavior of getLevel() by prioritizing // newer faster RATs for default/for display purposes. + + if (mLteAsPrimaryInNrNsa) { + if (mLte.isValid()) return mLte; + } + if (mNr.isValid()) return mNr; if (mLte.isValid()) return mLte; if (mCdma.isValid()) return mCdma; if (mTdscdma.isValid()) return mTdscdma; if (mWcdma.isValid()) return mWcdma; if (mGsm.isValid()) return mGsm; - if (mNr.isValid()) return mNr; return mLte; } @@ -270,6 +276,10 @@ public class SignalStrength implements Parcelable { /** @hide */ public void updateLevel(PersistableBundle cc, ServiceState ss) { + if (cc != null) { + mLteAsPrimaryInNrNsa = cc.getBoolean( + CarrierConfigManager.KEY_SIGNAL_STRENGTH_NR_NSA_USE_LTE_AS_PRIMARY_BOOL, true); + } mCdma.updateLevel(cc, ss); mGsm.updateLevel(cc, ss); mWcdma.updateLevel(cc, ss); diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java index 2c4d5ae3b82b..3d5c6aad1042 100644 --- a/telephony/java/android/telephony/TelephonyDisplayInfo.java +++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java @@ -62,8 +62,6 @@ public final class TelephonyDisplayInfo implements Parcelable { * {@link TelephonyManager#NETWORK_TYPE_LTE} network and has E-UTRA-NR Dual Connectivity(EN-DC) * capability or is currently connected to the secondary * {@link TelephonyManager#NETWORK_TYPE_NR} cellular network on millimeter wave bands. - * - * @see AccessNetworkConstants.NgranBands#FREQUENCY_RANGE_GROUP_2 */ public static final int OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE = 4; @@ -154,7 +152,14 @@ public final class TelephonyDisplayInfo implements Parcelable { return Objects.hash(mNetworkType, mOverrideNetworkType); } - private static String overrideNetworkTypeToString(@OverrideNetworkType int type) { + /** + * Convert override network type to string. + * + * @param type Override network type + * @return Override network type in string format + * @hide + */ + public static String overrideNetworkTypeToString(@OverrideNetworkType int type) { switch (type) { case OVERRIDE_NETWORK_TYPE_NONE: return "NONE"; case OVERRIDE_NETWORK_TYPE_LTE_CA: return "LTE_CA"; @@ -168,6 +173,6 @@ public final class TelephonyDisplayInfo implements Parcelable { @Override public String toString() { return "TelephonyDisplayInfo {network=" + TelephonyManager.getNetworkTypeName(mNetworkType) - + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType); + + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType) + "}"; } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 74339e9833a1..7d1398b51ec8 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -10314,7 +10314,7 @@ public class TelephonyManager { * <p>To recognize a carrier (including MVNO) as a first-class identity, Android assigns each * carrier with a canonical integer a.k.a. carrier id. The carrier ID is an Android * platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in - * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> + * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a> * * <p>Apps which have carrier-specific configurations or business logic can use the carrier id * as an Android platform-wide identifier for carriers. @@ -10376,7 +10376,7 @@ public class TelephonyManager { * * <p>For carriers without fine-grained specific carrier ids, return {@link #getSimCarrierId()} * <p>Specific carrier ids are defined in the same way as carrier id - * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> + * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a> * except each with a "parent" id linking to its top-level carrier id. * * @return Returns fine-grained carrier id of the current subscription. @@ -10425,7 +10425,7 @@ public class TelephonyManager { * This is used for fallback when configurations/logic for exact carrier id * {@link #getSimCarrierId()} are not found. * - * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> + * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a> * can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier * was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id * by default. After carrier id table update, a new carrier id was assigned. If apps don't @@ -10452,7 +10452,7 @@ public class TelephonyManager { * used for fallback when configurations/logic for exact carrier id {@link #getSimCarrierId()} * are not found. * - * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> + * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a> * can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier * was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id * by default. After carrier id table update, a new carrier id was assigned. If apps don't @@ -12977,4 +12977,21 @@ public class TelephonyManager { } return 0; } + + /** + * Whether device can connect to 5G network when two SIMs are active. + * @hide + * TODO b/153669716: remove or make system API. + */ + public boolean canConnectTo5GInDsdsMode() { + ITelephony telephony = getITelephony(); + if (telephony == null) return true; + try { + return telephony.canConnectTo5GInDsdsMode(); + } catch (RemoteException ex) { + return true; + } catch (NullPointerException ex) { + return true; + } + } } diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 44b0968eaa90..5500d635d2ff 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -269,10 +269,10 @@ public class EuiccManager { * only contains {@link #OPERATION_DOWNLOAD} and ErrorCode is 0 implies this is an unknown * Download error. * - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE} + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE */ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; @@ -552,7 +552,7 @@ public class EuiccManager { /** * List of OperationCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}'s - * value, an integer. @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * value, an integer. @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE * * @hide */ @@ -575,44 +575,44 @@ public class EuiccManager { /** * Internal system error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SYSTEM = 1; /** * SIM slot error. Failed to switch slot, failed to access the physical slot etc. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SIM_SLOT = 2; /** * eUICC card error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_EUICC_CARD = 3; /** * Generic switching profile error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SWITCH = 4; /** * Download profile error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_DOWNLOAD = 5; /** * Subscription's metadata error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_METADATA = 6; /** * eUICC returned an error defined in GSMA (SGP.22 v2.2) while running one of the ES10x * functions. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_EUICC_GSMA = 7; @@ -620,13 +620,13 @@ public class EuiccManager { * The exception of failing to execute an APDU command. It can be caused by an error * happening on opening the basic or logical channel, or the response of the APDU command is * not success (0x9000). - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_APDU = 8; /** * SMDX(SMDP/SMDS) error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SMDX = 9; @@ -655,19 +655,19 @@ public class EuiccManager { * Thus the integer stored in {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} is * 0xA8B1051(176885841) * - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10; /** * HTTP error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_HTTP = 11; /** * List of ErrorCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -695,56 +695,56 @@ public class EuiccManager { /** * Operation such as downloading/switching to another profile failed due to device being * carrier locked. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CARRIER_LOCKED = 10000; /** * The activation code(SGP.22 v2.2 section[4.1]) is invalid. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_ACTIVATION_CODE = 10001; /** * The confirmation code(SGP.22 v2.2 section[4.7]) is invalid. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002; /** * The profile's carrier is incompatible with the LPA. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INCOMPATIBLE_CARRIER = 10003; /** * There is no more space available on the eUICC for new profiles. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004; /** * Timed out while waiting for an operation to complete. i.e restart, disable, * switch reset etc. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_TIME_OUT = 10005; /** * eUICC is missing or defective on the device. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_EUICC_MISSING = 10006; /** * The eUICC card(hardware) version is incompatible with the software - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_UNSUPPORTED_VERSION = 10007; /** * No SIM card is available in the device. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_SIM_MISSING = 10008; @@ -754,52 +754,52 @@ public class EuiccManager { * 2. GSMA(.22 v2.2) Profile Install Result - installFailedDueToDataMismatch * 3. operation was interrupted * 4. SIMalliance error in PEStatus(SGP.22 v2.2 section 2.5.6.1) - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INSTALL_PROFILE = 10009; /** * Failed to load profile onto eUICC due to Profile Poicly Rules. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_DISALLOWED_BY_PPR = 10010; /** * Address is missing e.g SMDS/SMDP address is missing. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_ADDRESS_MISSING = 10011; /** * Certificate needed for authentication is not valid or missing. E.g SMDP/SMDS authentication * failed. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CERTIFICATE_ERROR = 10012; /** * No profiles available. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_NO_PROFILES_AVAILABLE = 10013; /** * Failure to create a connection. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CONNECTION_ERROR = 10014; /** * Response format is invalid. e.g SMDP/SMDS response contains invalid json, header or/and ASN1. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_RESPONSE = 10015; /** * The operation is currently busy, try again later. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_OPERATION_BUSY = 10016; diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 95ebbf39e944..872f49d65d25 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -141,8 +141,7 @@ public class ImsMmTelManager implements RegistrationManager { } /** - * Receives IMS capability status updates from the ImsService. This information is also - * available via the {@see #isAvailable(int, int)} method below. + * Receives IMS capability status updates from the ImsService. * * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) @@ -195,8 +194,6 @@ public class ImsMmTelManager implements RegistrationManager { * If unavailable, the feature is not able to support the unavailable capability at this * time. * - * This information can also be queried using the {@see #isAvailable(int, int)} API. - * * @param capabilities The new availability of the capabilities. */ public void onCapabilitiesStatusChanged( @@ -497,8 +494,7 @@ public class ImsMmTelManager implements RegistrationManager { /** * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service * availability updates for the subscription specified in - * {@link ImsManager#getImsMmTelManager(int)}. The method {@see #isAvailable(int, int)} - * can also be used to query this information at any time. + * {@link ImsManager#getImsMmTelManager(int)}. * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call @@ -640,7 +636,6 @@ public class ImsMmTelManager implements RegistrationManager { * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL - * @see #setAdvancedCallingSettingEnabled(boolean) * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for advanced calling is enabled, false otherwise. @@ -859,7 +854,6 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user’s “Video Calling” setting is currently enabled. - * @see #setVtSettingEnabled(boolean) */ @RequiresPermission(anyOf = { android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, @@ -934,7 +928,6 @@ public class ImsMmTelManager implements RegistrationManager { * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. - * @see #setVoWiFiSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1012,7 +1005,6 @@ public class ImsMmTelManager implements RegistrationManager { * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for Voice over WiFi while roaming is enabled, false * if disabled. - * @see #setVoWiFiRoamingSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1131,7 +1123,6 @@ public class ImsMmTelManager implements RegistrationManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} - * @see #setVoWiFiSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1316,7 +1307,6 @@ public class ImsMmTelManager implements RegistrationManager { * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. - * @see android.telecom.TelecomManager#getCurrentTtyMode * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index ed9b94b3d85e..71bc68e4b4c4 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -49,7 +49,7 @@ import java.util.function.Consumer; * * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager. */ -public class ImsRcsManager implements RegistrationManager { +public class ImsRcsManager { private static final String TAG = "ImsRcsManager"; /** @@ -173,11 +173,11 @@ public class ImsRcsManager implements RegistrationManager { /** * @hide */ - @Override + // @Override add back to RegistrationManager interface once public. @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback( @NonNull @CallbackExecutor Executor executor, - @NonNull RegistrationCallback c) + @NonNull RegistrationManager.RegistrationCallback c) throws ImsException { if (c == null) { throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); @@ -204,7 +204,7 @@ public class ImsRcsManager implements RegistrationManager { /** * @hide */ - @Override + // @Override add back to RegistrationManager interface once public. @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback( @NonNull RegistrationManager.RegistrationCallback c) { @@ -228,10 +228,10 @@ public class ImsRcsManager implements RegistrationManager { /** * @hide */ - @Override + // @Override add back to RegistrationManager interface once public. @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, - @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) { + @NonNull @RegistrationManager.ImsRegistrationState Consumer<Integer> stateCallback) { if (stateCallback == null) { throw new IllegalArgumentException("Must include a non-null stateCallback."); } @@ -260,7 +260,6 @@ public class ImsRcsManager implements RegistrationManager { /** * @hide */ - @Override @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, @NonNull @AccessNetworkConstants.TransportType @@ -347,8 +346,7 @@ public class ImsRcsManager implements RegistrationManager { * inactive subscription, it will result in a no-op. * @param c The RCS {@link AvailabilityCallback} to be removed. * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) - * @throws ImsException if the IMS service is not available when calling this method - * {@link ImsRcsController#unregisterRcsAvailabilityCallback()}. + * @throws ImsException if the IMS service is not available when calling this method. * See {@link ImsException#getCode()} for more information on the error codes. * @hide */ @@ -390,8 +388,7 @@ public class ImsRcsManager implements RegistrationManager { * rather the subscription is capable of this service over IMS. * @see #isAvailable(int) * @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL - * @throws ImsException if the IMS service is not available when calling this method - * {@link ImsRcsController#isCapable(int, int)}. + * @throws ImsException if the IMS service is not available when calling this method. * See {@link ImsException#getCode()} for more information on the error codes. * @hide */ @@ -424,9 +421,8 @@ public class ImsRcsManager implements RegistrationManager { * @return true if the RCS capability is currently available for the associated subscription, * false otherwise. If the capability is available, IMS is registered and the service is * currently available over IMS. - * @see #isCapable(int) - * @throws ImsException if the IMS service is not available when calling this method - * {@link ImsRcsController#isAvailable(int, int)}. + * @see #isCapable(int, int) + * @throws ImsException if the IMS service is not available when calling this method. * See {@link ImsException#getCode()} for more information on the error codes. * @hide */ diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index 1dbaff5df802..e085dec10546 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -270,7 +270,7 @@ public interface RegistrationManager { * inactive subscription, it will result in a no-op. * * @param c The {@link RegistrationCallback} to be removed. - * @see SubscriptionManager.OnSubscriptionsChangedListener + * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index a3ce1b585f76..6840e8eed318 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -218,13 +218,7 @@ public class MmTelFeature extends ImsFeature { * {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}. * - * The capabilities of this MmTelFeature will be set by the framework and can be queried with - * {@see #queryCapabilityStatus()}. - * - * This MmTelFeature can then return the status of each of these capabilities (enabled or not) - * by sending a {@see #notifyCapabilitiesStatusChanged} callback to the framework. The current - * status can also be queried using {@see #queryCapabilityStatus()}. - * @see #isCapable(int) + * The capabilities of this MmTelFeature will be set by the framework. */ public static class MmTelCapabilities extends Capabilities { @@ -436,7 +430,6 @@ public class MmTelFeature extends ImsFeature { /** * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and * notifies the framework. - * @hide */ private void setListener(IImsMmTelListener listener) { synchronized (mLock) { @@ -448,6 +441,16 @@ public class MmTelFeature extends ImsFeature { } /** + * @return the listener associated with this MmTelFeature. May be null if it has not been set + * by the framework yet. + */ + private IImsMmTelListener getListener() { + synchronized (mLock) { + return mListener; + } + } + + /** * The current capability status that this MmTelFeature has defined is available. This * configuration will be used by the platform to figure out which capabilities are CURRENTLY * available to be used. @@ -495,15 +498,14 @@ public class MmTelFeature extends ImsFeature { throw new IllegalArgumentException("ImsCallSessionImplBase and Bundle can not be " + "null."); } - synchronized (mLock) { - if (mListener == null) { - throw new IllegalStateException("Session is not available."); - } - try { - mListener.onIncomingCall(c.getServiceImpl(), extras); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + IImsMmTelListener listener = getListener(); + if (listener == null) { + throw new IllegalStateException("Session is not available."); + } + try { + listener.onIncomingCall(c.getServiceImpl(), extras); + } catch (RemoteException e) { + throw new RuntimeException(e); } } @@ -522,15 +524,14 @@ public class MmTelFeature extends ImsFeature { throw new IllegalArgumentException("ImsCallProfile and ImsReasonInfo must not be " + "null."); } - synchronized (mLock) { - if (mListener == null) { - throw new IllegalStateException("Session is not available."); - } - try { - mListener.onRejectedCall(callProfile, reason); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + IImsMmTelListener listener = getListener(); + if (listener == null) { + throw new IllegalStateException("Session is not available."); + } + try { + listener.onRejectedCall(callProfile, reason); + } catch (RemoteException e) { + throw new RuntimeException(e); } } @@ -539,15 +540,14 @@ public class MmTelFeature extends ImsFeature { * @hide */ public final void notifyIncomingCallSession(IImsCallSession c, Bundle extras) { - synchronized (mLock) { - if (mListener == null) { - throw new IllegalStateException("Session is not available."); - } - try { - mListener.onIncomingCall(c, extras); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + IImsMmTelListener listener = getListener(); + if (listener == null) { + throw new IllegalStateException("Session is not available."); + } + try { + listener.onIncomingCall(c, extras); + } catch (RemoteException e) { + throw new RuntimeException(e); } } @@ -558,15 +558,14 @@ public class MmTelFeature extends ImsFeature { */ @SystemApi @TestApi public final void notifyVoiceMessageCountUpdate(int count) { - synchronized (mLock) { - if (mListener == null) { - throw new IllegalStateException("Session is not available."); - } - try { - mListener.onVoiceMessageCountUpdate(count); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + IImsMmTelListener listener = getListener(); + if (listener == null) { + throw new IllegalStateException("Session is not available."); + } + try { + listener.onVoiceMessageCountUpdate(count); + } catch (RemoteException e) { + throw new RuntimeException(e); } } diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java index ce9a73a21657..a9a33c0e1507 100644 --- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java @@ -403,8 +403,7 @@ public class ImsSmsImplBase { message.mWrappedSmsMessage.mMessageRef, STATUS_REPORT_STATUS_ERROR); } else { - Log.w(LOG_TAG, - "onSmsStatusReportReceivedWithoutMessageRef: Invalid pdu entered."); + Log.w(LOG_TAG, "onSmsStatusReportReceived: Invalid pdu entered."); acknowledgeSmsReport(token, 0, STATUS_REPORT_STATUS_ERROR); } } diff --git a/telephony/java/android/telephony/mbms/MbmsErrors.java b/telephony/java/android/telephony/mbms/MbmsErrors.java index 52e4d333b29d..8611d26bc85b 100644 --- a/telephony/java/android/telephony/mbms/MbmsErrors.java +++ b/telephony/java/android/telephony/mbms/MbmsErrors.java @@ -16,8 +16,12 @@ package android.telephony.mbms; +import android.annotation.IntDef; import android.telephony.MbmsStreamingSession; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public class MbmsErrors { /** * Indicates that the middleware has sent an error code that is not defined in the version of @@ -138,6 +142,13 @@ public class MbmsErrors { /** Indicates the the middleware has no record of the supplied {@link FileInfo} */ public static final int ERROR_UNKNOWN_FILE_INFO = 403; + + /** + * Indicates that the service announcement file passed via + * {@link android.telephony.MbmsDownloadSession#addServiceAnnouncementFile(byte[])} + * is malformed. + */ + public static final int ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE = 404; } /** @@ -156,5 +167,35 @@ public class MbmsErrors { public static final int ERROR_DUPLICATE_START_GROUP_CALL = 502; } + /** @hide */ + @IntDef(value = { + SUCCESS, + ERROR_NO_UNIQUE_MIDDLEWARE, + ERROR_MIDDLEWARE_NOT_BOUND, + ERROR_MIDDLEWARE_LOST, + InitializationErrors.ERROR_DUPLICATE_INITIALIZE, + InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED, + InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY, + GeneralErrors.ERROR_OUT_OF_MEMORY, + GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE, + GeneralErrors.ERROR_IN_E911, + GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE, + GeneralErrors.ERROR_UNABLE_TO_READ_SIM, + GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED, + StreamingErrors.ERROR_CONCURRENT_SERVICE_LIMIT_REACHED, + StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, + StreamingErrors.ERROR_DUPLICATE_START_STREAM, + DownloadErrors.ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT, + DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST, + DownloadErrors.ERROR_UNKNOWN_FILE_INFO, + DownloadErrors.ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE, + GroupCallErrors.ERROR_UNABLE_TO_START_SERVICE, + GroupCallErrors.ERROR_DUPLICATE_START_GROUP_CALL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MbmsError { + } + private MbmsErrors() {} } diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl index 445087fb78d5..36136ab280c4 100755 --- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl +++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl @@ -35,6 +35,8 @@ interface IMbmsDownloadService int setTempFileRootDirectory(int subId, String rootDirectoryPath); + int addServiceAnnouncementFile(int subId, in byte[] fileContents); + int download(in DownloadRequest downloadRequest); int addStatusListener(in DownloadRequest downloadRequest, diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java index 9f22d0a49806..3279ce66cd17 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java @@ -216,6 +216,28 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub { } /** + * Called when the client application wishes to receive file information according to a + * service announcement file received from a group call server. + * + * The service announcement file is in the format of a multipart MIME file with XML parts, + * though no validation is performed on the contents of the {@code fileContents} argument -- + * implementing middleware applications should perform their own validation and return + * {@link MbmsErrors.DownloadErrors#ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE} if the file is + * malformed. + * + * @param subscriptionId The subscription id the service announcement applies to. + * @param fileContents The contents of the service announcement file. + * @return {@link MbmsErrors#SUCCESS}, or + * {@link MbmsErrors.DownloadErrors#ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE} + */ + // TODO: are there any public specifications of what the file format is that I can link to? + @Override + public @MbmsErrors.MbmsError int addServiceAnnouncementFile( + int subscriptionId, @NonNull byte[] fileContents) { + return 0; + } + + /** * Issues a request to download a set of files. * * The middleware should expect that {@link #setTempFileRootDirectory(int, String)} has been diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 18e25921555a..76fc4f7d0519 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -109,11 +109,10 @@ public class DctConstants { public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49; public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50; public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51; - public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52; - public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53; - public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54; - public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55; - public static final int EVENT_SIM_STATE_UPDATED = BASE + 56; + public static final int EVENT_TELEPHONY_DISPLAY_INFO_CHANGED = BASE + 52; + public static final int EVENT_NR_TIMER_WATCHDOG = BASE + 53; + public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 54; + public static final int EVENT_SIM_STATE_UPDATED = BASE + 55; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 1face6c4f4cd..5293efa6bce7 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2248,4 +2248,9 @@ interface ITelephony { int setIccLockEnabled(int subId, boolean enabled, String password); int changeIccLockPassword(int subId, String oldPassword, String newPassword); + + /** + * Whether device can connect to 5G network when two SIMs are active. + */ + boolean canConnectTo5GInDsdsMode(); } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index 6eea88f4c103..db9fdf54852d 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -111,6 +111,7 @@ public class PhoneConstants { public static final int PIN_RESULT_SUCCESS = 0; public static final int PIN_PASSWORD_INCORRECT = 1; public static final int PIN_GENERAL_FAILURE = 2; + public static final int PIN_OPERATION_ABORTED = 3; /** * Return codes for <code>enableApnType()</code> diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index ff70f8ba3936..29286e8f429e 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -240,5 +240,5 @@ public interface TelephonyProperties * two. * Type: int */ - static final String PROPERTY_MAX_ACTIVE_MODEMS = "ro.telephony.max.active.modems"; + static final String PROPERTY_MAX_ACTIVE_MODEMS = "telephony.active_modems.max_count"; } diff --git a/test-base/api/lint-baseline.txt b/test-base/api/lint-baseline.txt new file mode 100644 index 000000000000..86c8a910d20a --- /dev/null +++ b/test-base/api/lint-baseline.txt @@ -0,0 +1,3 @@ +// Baseline format: 1.0 +MissingNullability: junit.framework.ComparisonFailure#getMessage(): + Missing nullability on method `getMessage` return diff --git a/test-mock/api/lint-baseline.txt b/test-mock/api/lint-baseline.txt new file mode 100644 index 000000000000..c6ba3f5d8fd8 --- /dev/null +++ b/test-mock/api/lint-baseline.txt @@ -0,0 +1,143 @@ +// Baseline format: 1.0 +ArrayReturn: android.test.mock.MockContentProvider#bulkInsert(android.net.Uri, android.content.ContentValues[]) parameter #1: + Method parameter should be Collection<ContentValues> (or subclass) instead of raw array; was `android.content.ContentValues[]` +ArrayReturn: android.test.mock.MockResources#getTextArray(int): + Method should return Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]` + + +MissingNullability: android.test.mock.MockApplication#onConfigurationChanged(android.content.res.Configuration) parameter #0: + Missing nullability on parameter `newConfig` in method `onConfigurationChanged` +MissingNullability: android.test.mock.MockContentProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #0: + Missing nullability on parameter `context` in method `attachInfo` +MissingNullability: android.test.mock.MockContentProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #1: + Missing nullability on parameter `info` in method `attachInfo` +MissingNullability: android.test.mock.MockContentProvider#bulkInsert(android.net.Uri, android.content.ContentValues[]) parameter #0: + Missing nullability on parameter `uri` in method `bulkInsert` +MissingNullability: android.test.mock.MockContentProvider#bulkInsert(android.net.Uri, android.content.ContentValues[]) parameter #1: + Missing nullability on parameter `values` in method `bulkInsert` +MissingNullability: android.test.mock.MockContentProvider#getStreamTypes(android.net.Uri, String): + Missing nullability on method `getStreamTypes` return +MissingNullability: android.test.mock.MockContentProvider#getStreamTypes(android.net.Uri, String) parameter #0: + Missing nullability on parameter `url` in method `getStreamTypes` +MissingNullability: android.test.mock.MockContentProvider#getStreamTypes(android.net.Uri, String) parameter #1: + Missing nullability on parameter `mimeTypeFilter` in method `getStreamTypes` +MissingNullability: android.test.mock.MockContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean) parameter #0: + Missing nullability on parameter `uri` in method `notifyChange` +MissingNullability: android.test.mock.MockContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean) parameter #1: + Missing nullability on parameter `observer` in method `notifyChange` +MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #0: + Missing nullability on parameter `service` in method `bindIsolatedService` +MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #2: + Missing nullability on parameter `instanceName` in method `bindIsolatedService` +MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #3: + Missing nullability on parameter `executor` in method `bindIsolatedService` +MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #4: + Missing nullability on parameter `conn` in method `bindIsolatedService` +MissingNullability: android.test.mock.MockContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #0: + Missing nullability on parameter `service` in method `bindService` +MissingNullability: android.test.mock.MockContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #2: + Missing nullability on parameter `executor` in method `bindService` +MissingNullability: android.test.mock.MockContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #3: + Missing nullability on parameter `conn` in method `bindService` +MissingNullability: android.test.mock.MockContext#getMainExecutor(): + Missing nullability on method `getMainExecutor` return +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #0: + Missing nullability on parameter `intent` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #1: + Missing nullability on parameter `receiverPermission` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #2: + Missing nullability on parameter `receiverAppOp` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #3: + Missing nullability on parameter `resultReceiver` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #4: + Missing nullability on parameter `scheduler` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #6: + Missing nullability on parameter `initialData` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #7: + Missing nullability on parameter `initialExtras` in method `sendOrderedBroadcast` +MissingNullability: android.test.mock.MockContext#updateServiceGroup(android.content.ServiceConnection, int, int) parameter #0: + Missing nullability on parameter `conn` in method `updateServiceGroup` +MissingNullability: android.test.mock.MockCursor#getNotificationUris(): + Missing nullability on method `getNotificationUris` return +MissingNullability: android.test.mock.MockCursor#setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>) parameter #0: + Missing nullability on parameter `cr` in method `setNotificationUris` +MissingNullability: android.test.mock.MockCursor#setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>) parameter #1: + Missing nullability on parameter `uris` in method `setNotificationUris` +MissingNullability: android.test.mock.MockPackageManager#getPackageArchiveInfo(String, int): + Missing nullability on method `getPackageArchiveInfo` return +MissingNullability: android.test.mock.MockPackageManager#getPackageArchiveInfo(String, int) parameter #0: + Missing nullability on parameter `archiveFilePath` in method `getPackageArchiveInfo` +MissingNullability: android.test.mock.MockPackageManager#hasSigningCertificate(String, byte[], int) parameter #0: + Missing nullability on parameter `packageName` in method `hasSigningCertificate` +MissingNullability: android.test.mock.MockPackageManager#hasSigningCertificate(String, byte[], int) parameter #1: + Missing nullability on parameter `certificate` in method `hasSigningCertificate` +MissingNullability: android.test.mock.MockPackageManager#hasSigningCertificate(int, byte[], int) parameter #1: + Missing nullability on parameter `certificate` in method `hasSigningCertificate` +MissingNullability: android.test.mock.MockResources#getAnimation(int): + Missing nullability on method `getAnimation` return +MissingNullability: android.test.mock.MockResources#getConfiguration(): + Missing nullability on method `getConfiguration` return +MissingNullability: android.test.mock.MockResources#getDisplayMetrics(): + Missing nullability on method `getDisplayMetrics` return +MissingNullability: android.test.mock.MockResources#getIdentifier(String, String, String) parameter #0: + Missing nullability on parameter `name` in method `getIdentifier` +MissingNullability: android.test.mock.MockResources#getIdentifier(String, String, String) parameter #1: + Missing nullability on parameter `defType` in method `getIdentifier` +MissingNullability: android.test.mock.MockResources#getIdentifier(String, String, String) parameter #2: + Missing nullability on parameter `defPackage` in method `getIdentifier` +MissingNullability: android.test.mock.MockResources#getIntArray(int): + Missing nullability on method `getIntArray` return +MissingNullability: android.test.mock.MockResources#getLayout(int): + Missing nullability on method `getLayout` return +MissingNullability: android.test.mock.MockResources#getQuantityString(int, int): + Missing nullability on method `getQuantityString` return +MissingNullability: android.test.mock.MockResources#getQuantityString(int, int, java.lang.Object...): + Missing nullability on method `getQuantityString` return +MissingNullability: android.test.mock.MockResources#getQuantityString(int, int, java.lang.Object...) parameter #2: + Missing nullability on parameter `formatArgs` in method `getQuantityString` +MissingNullability: android.test.mock.MockResources#getQuantityText(int, int): + Missing nullability on method `getQuantityText` return +MissingNullability: android.test.mock.MockResources#getResourceEntryName(int): + Missing nullability on method `getResourceEntryName` return +MissingNullability: android.test.mock.MockResources#getResourceName(int): + Missing nullability on method `getResourceName` return +MissingNullability: android.test.mock.MockResources#getResourcePackageName(int): + Missing nullability on method `getResourcePackageName` return +MissingNullability: android.test.mock.MockResources#getResourceTypeName(int): + Missing nullability on method `getResourceTypeName` return +MissingNullability: android.test.mock.MockResources#getString(int): + Missing nullability on method `getString` return +MissingNullability: android.test.mock.MockResources#getString(int, java.lang.Object...): + Missing nullability on method `getString` return +MissingNullability: android.test.mock.MockResources#getString(int, java.lang.Object...) parameter #1: + Missing nullability on parameter `formatArgs` in method `getString` +MissingNullability: android.test.mock.MockResources#getStringArray(int): + Missing nullability on method `getStringArray` return +MissingNullability: android.test.mock.MockResources#getText(int): + Missing nullability on method `getText` return +MissingNullability: android.test.mock.MockResources#getText(int, CharSequence): + Missing nullability on method `getText` return +MissingNullability: android.test.mock.MockResources#getText(int, CharSequence) parameter #1: + Missing nullability on parameter `def` in method `getText` +MissingNullability: android.test.mock.MockResources#getTextArray(int): + Missing nullability on method `getTextArray` return +MissingNullability: android.test.mock.MockResources#getValue(String, android.util.TypedValue, boolean) parameter #0: + Missing nullability on parameter `name` in method `getValue` +MissingNullability: android.test.mock.MockResources#getValue(String, android.util.TypedValue, boolean) parameter #1: + Missing nullability on parameter `outValue` in method `getValue` +MissingNullability: android.test.mock.MockResources#getValue(int, android.util.TypedValue, boolean) parameter #1: + Missing nullability on parameter `outValue` in method `getValue` +MissingNullability: android.test.mock.MockResources#getXml(int): + Missing nullability on method `getXml` return +MissingNullability: android.test.mock.MockResources#obtainAttributes(android.util.AttributeSet, int[]): + Missing nullability on method `obtainAttributes` return +MissingNullability: android.test.mock.MockResources#obtainAttributes(android.util.AttributeSet, int[]) parameter #0: + Missing nullability on parameter `set` in method `obtainAttributes` +MissingNullability: android.test.mock.MockResources#obtainAttributes(android.util.AttributeSet, int[]) parameter #1: + Missing nullability on parameter `attrs` in method `obtainAttributes` +MissingNullability: android.test.mock.MockResources#obtainTypedArray(int): + Missing nullability on method `obtainTypedArray` return +MissingNullability: android.test.mock.MockResources#openRawResource(int): + Missing nullability on method `openRawResource` return +MissingNullability: android.test.mock.MockResources#openRawResourceFd(int): + Missing nullability on method `openRawResourceFd` return diff --git a/test-mock/api/system-lint-baseline.txt b/test-mock/api/system-lint-baseline.txt new file mode 100644 index 000000000000..466bc5376ed6 --- /dev/null +++ b/test-mock/api/system-lint-baseline.txt @@ -0,0 +1,15 @@ +// Baseline format: 1.0 +IntentBuilderName: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler): + Methods creating an Intent should be named `create<Foo>Intent()`, was `registerReceiverForAllUsers` + + +MissingNullability: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler): + Missing nullability on method `registerReceiverForAllUsers` return +MissingNullability: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) parameter #0: + Missing nullability on parameter `receiver` in method `registerReceiverForAllUsers` +MissingNullability: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) parameter #1: + Missing nullability on parameter `filter` in method `registerReceiverForAllUsers` +MissingNullability: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) parameter #2: + Missing nullability on parameter `broadcastPermission` in method `registerReceiverForAllUsers` +MissingNullability: android.test.mock.MockContext#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) parameter #3: + Missing nullability on parameter `scheduler` in method `registerReceiverForAllUsers` diff --git a/test-runner/api/lint-baseline.txt b/test-runner/api/lint-baseline.txt new file mode 100644 index 000000000000..54947fe687c0 --- /dev/null +++ b/test-runner/api/lint-baseline.txt @@ -0,0 +1,173 @@ +// Baseline format: 1.0 +GenericException: android.test.ActivityInstrumentationTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ActivityInstrumentationTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ActivityInstrumentationTestCase2#runTest(): + Methods must not throw generic exceptions (`java.lang.Throwable`) +GenericException: android.test.ActivityInstrumentationTestCase2#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ActivityInstrumentationTestCase2#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ActivityUnitTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ActivityUnitTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ApplicationTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ApplicationTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ProviderTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ProviderTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ProviderTestCase2#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ProviderTestCase2#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ServiceTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.ServiceTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.SingleLaunchActivityTestCase#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.SingleLaunchActivityTestCase#tearDown(): + Methods must not throw generic exceptions (`java.lang.Exception`) +GenericException: android.test.SyncBaseInstrumentation#setUp(): + Methods must not throw generic exceptions (`java.lang.Exception`) + + +IntentBuilderName: android.test.IsolatedContext#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter): + Methods creating an Intent should be named `create<Foo>Intent()`, was `registerReceiver` + + +MissingNullability: android.test.ComparisonFailure#getMessage(): + Missing nullability on method `getMessage` return +MissingNullability: android.test.InstrumentationTestRunner#onCreate(android.os.Bundle) parameter #0: + Missing nullability on parameter `arguments` in method `onCreate` +MissingNullability: android.test.IsolatedContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #0: + Missing nullability on parameter `service` in method `bindIsolatedService` +MissingNullability: android.test.IsolatedContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #2: + Missing nullability on parameter `instanceName` in method `bindIsolatedService` +MissingNullability: android.test.IsolatedContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #3: + Missing nullability on parameter `executor` in method `bindIsolatedService` +MissingNullability: android.test.IsolatedContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #4: + Missing nullability on parameter `conn` in method `bindIsolatedService` +MissingNullability: android.test.IsolatedContext#bindService(android.content.Intent, android.content.ServiceConnection, int) parameter #0: + Missing nullability on parameter `service` in method `bindService` +MissingNullability: android.test.IsolatedContext#bindService(android.content.Intent, android.content.ServiceConnection, int) parameter #1: + Missing nullability on parameter `conn` in method `bindService` +MissingNullability: android.test.IsolatedContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #0: + Missing nullability on parameter `service` in method `bindService` +MissingNullability: android.test.IsolatedContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #2: + Missing nullability on parameter `executor` in method `bindService` +MissingNullability: android.test.IsolatedContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #3: + Missing nullability on parameter `conn` in method `bindService` +MissingNullability: android.test.IsolatedContext#checkUriPermission(android.net.Uri, String, String, int, int, int) parameter #0: + Missing nullability on parameter `uri` in method `checkUriPermission` +MissingNullability: android.test.IsolatedContext#checkUriPermission(android.net.Uri, String, String, int, int, int) parameter #1: + Missing nullability on parameter `readPermission` in method `checkUriPermission` +MissingNullability: android.test.IsolatedContext#checkUriPermission(android.net.Uri, String, String, int, int, int) parameter #2: + Missing nullability on parameter `writePermission` in method `checkUriPermission` +MissingNullability: android.test.IsolatedContext#checkUriPermission(android.net.Uri, int, int, int) parameter #0: + Missing nullability on parameter `uri` in method `checkUriPermission` +MissingNullability: android.test.IsolatedContext#getContentResolver(): + Missing nullability on method `getContentResolver` return +MissingNullability: android.test.IsolatedContext#getFilesDir(): + Missing nullability on method `getFilesDir` return +MissingNullability: android.test.IsolatedContext#getSystemService(String): + Missing nullability on method `getSystemService` return +MissingNullability: android.test.IsolatedContext#getSystemService(String) parameter #0: + Missing nullability on parameter `name` in method `getSystemService` +MissingNullability: android.test.IsolatedContext#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter): + Missing nullability on method `registerReceiver` return +MissingNullability: android.test.IsolatedContext#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter) parameter #0: + Missing nullability on parameter `receiver` in method `registerReceiver` +MissingNullability: android.test.IsolatedContext#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter) parameter #1: + Missing nullability on parameter `filter` in method `registerReceiver` +MissingNullability: android.test.IsolatedContext#sendBroadcast(android.content.Intent) parameter #0: + Missing nullability on parameter `intent` in method `sendBroadcast` +MissingNullability: android.test.IsolatedContext#sendOrderedBroadcast(android.content.Intent, String) parameter #0: + Missing nullability on parameter `intent` in method `sendOrderedBroadcast` +MissingNullability: android.test.IsolatedContext#sendOrderedBroadcast(android.content.Intent, String) parameter #1: + Missing nullability on parameter `receiverPermission` in method `sendOrderedBroadcast` +MissingNullability: android.test.IsolatedContext#unregisterReceiver(android.content.BroadcastReceiver) parameter #0: + Missing nullability on parameter `receiver` in method `unregisterReceiver` +MissingNullability: android.test.RenamingDelegatingContext#databaseList(): + Missing nullability on method `databaseList` return +MissingNullability: android.test.RenamingDelegatingContext#deleteDatabase(String) parameter #0: + Missing nullability on parameter `name` in method `deleteDatabase` +MissingNullability: android.test.RenamingDelegatingContext#deleteFile(String) parameter #0: + Missing nullability on parameter `name` in method `deleteFile` +MissingNullability: android.test.RenamingDelegatingContext#fileList(): + Missing nullability on method `fileList` return +MissingNullability: android.test.RenamingDelegatingContext#getCacheDir(): + Missing nullability on method `getCacheDir` return +MissingNullability: android.test.RenamingDelegatingContext#getDatabasePath(String): + Missing nullability on method `getDatabasePath` return +MissingNullability: android.test.RenamingDelegatingContext#getDatabasePath(String) parameter #0: + Missing nullability on parameter `name` in method `getDatabasePath` +MissingNullability: android.test.RenamingDelegatingContext#getFileStreamPath(String): + Missing nullability on method `getFileStreamPath` return +MissingNullability: android.test.RenamingDelegatingContext#getFileStreamPath(String) parameter #0: + Missing nullability on parameter `name` in method `getFileStreamPath` +MissingNullability: android.test.RenamingDelegatingContext#openFileInput(String): + Missing nullability on method `openFileInput` return +MissingNullability: android.test.RenamingDelegatingContext#openFileInput(String) parameter #0: + Missing nullability on parameter `name` in method `openFileInput` +MissingNullability: android.test.RenamingDelegatingContext#openFileOutput(String, int): + Missing nullability on method `openFileOutput` return +MissingNullability: android.test.RenamingDelegatingContext#openFileOutput(String, int) parameter #0: + Missing nullability on parameter `name` in method `openFileOutput` +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory): + Missing nullability on method `openOrCreateDatabase` return +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory) parameter #0: + Missing nullability on parameter `name` in method `openOrCreateDatabase` +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory) parameter #2: + Missing nullability on parameter `factory` in method `openOrCreateDatabase` +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler): + Missing nullability on method `openOrCreateDatabase` return +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler) parameter #0: + Missing nullability on parameter `name` in method `openOrCreateDatabase` +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler) parameter #2: + Missing nullability on parameter `factory` in method `openOrCreateDatabase` +MissingNullability: android.test.RenamingDelegatingContext#openOrCreateDatabase(String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler) parameter #3: + Missing nullability on parameter `errorHandler` in method `openOrCreateDatabase` + + +ProtectedMember: android.test.ActivityInstrumentationTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.ActivityInstrumentationTestCase.setUp()} +ProtectedMember: android.test.ActivityInstrumentationTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.ActivityInstrumentationTestCase.tearDown()} +ProtectedMember: android.test.ActivityInstrumentationTestCase2#runTest(): + Protected methods not allowed; must be public: method android.test.ActivityInstrumentationTestCase2.runTest()} +ProtectedMember: android.test.ActivityInstrumentationTestCase2#setUp(): + Protected methods not allowed; must be public: method android.test.ActivityInstrumentationTestCase2.setUp()} +ProtectedMember: android.test.ActivityInstrumentationTestCase2#tearDown(): + Protected methods not allowed; must be public: method android.test.ActivityInstrumentationTestCase2.tearDown()} +ProtectedMember: android.test.ActivityUnitTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.ActivityUnitTestCase.setUp()} +ProtectedMember: android.test.ActivityUnitTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.ActivityUnitTestCase.tearDown()} +ProtectedMember: android.test.ApplicationTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.ApplicationTestCase.setUp()} +ProtectedMember: android.test.ApplicationTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.ApplicationTestCase.tearDown()} +ProtectedMember: android.test.ProviderTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.ProviderTestCase.setUp()} +ProtectedMember: android.test.ProviderTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.ProviderTestCase.tearDown()} +ProtectedMember: android.test.ProviderTestCase2#setUp(): + Protected methods not allowed; must be public: method android.test.ProviderTestCase2.setUp()} +ProtectedMember: android.test.ProviderTestCase2#tearDown(): + Protected methods not allowed; must be public: method android.test.ProviderTestCase2.tearDown()} +ProtectedMember: android.test.ServiceTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.ServiceTestCase.setUp()} +ProtectedMember: android.test.ServiceTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.ServiceTestCase.tearDown()} +ProtectedMember: android.test.SingleLaunchActivityTestCase#setUp(): + Protected methods not allowed; must be public: method android.test.SingleLaunchActivityTestCase.setUp()} +ProtectedMember: android.test.SingleLaunchActivityTestCase#tearDown(): + Protected methods not allowed; must be public: method android.test.SingleLaunchActivityTestCase.tearDown()} +ProtectedMember: android.test.SyncBaseInstrumentation#setUp(): + Protected methods not allowed; must be public: method android.test.SyncBaseInstrumentation.setUp()} diff --git a/tests/GamePerformance/Android.bp b/tests/GamePerformance/Android.bp new file mode 100644 index 000000000000..648fd8151b4e --- /dev/null +++ b/tests/GamePerformance/Android.bp @@ -0,0 +1,32 @@ +// 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. + +android_test_helper_app { + name: "GamePerformance", + // Don't include this package in any target + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, + srcs: ["src/**/*.java"], + static_libs: ["android-support-test"], + libs: [ + "android.test.base", + "android.test.runner", + ], + platform_apis: true, + certificate: "platform", +} diff --git a/tests/GamePerformance/Android.mk b/tests/GamePerformance/Android.mk deleted file mode 100644 index 58654de34029..000000000000 --- a/tests/GamePerformance/Android.mk +++ /dev/null @@ -1,39 +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. - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -# Don't include this package in any target -LOCAL_MODULE_TAGS := tests - -LOCAL_DEX_PREOPT := false - -LOCAL_PROGUARD_ENABLED := disabled - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_STATIC_JAVA_LIBRARIES := android-support-test - -LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner - -LOCAL_PACKAGE_NAME := GamePerformance - -LOCAL_PRIVATE_PLATFORM_APIS := true - -LOCAL_CERTIFICATE := platform - - -include $(BUILD_PACKAGE) diff --git a/tests/NullHomeTest/Android.bp b/tests/NullHomeTest/Android.bp new file mode 100644 index 000000000000..99248bfe1da1 --- /dev/null +++ b/tests/NullHomeTest/Android.bp @@ -0,0 +1,22 @@ +// Copyright 2020 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +android_test { + name: "NullHomeTest", + srcs: ["src/**/*.java"], + certificate: "platform", + platform_apis: true, + static_libs: ["android-support-test"], + test_suites: ["device-tests"], +} diff --git a/tests/NullHomeTest/AndroidManifest.xml b/tests/NullHomeTest/AndroidManifest.xml new file mode 100644 index 000000000000..dc6402e03b5a --- /dev/null +++ b/tests/NullHomeTest/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.test.nullhome" + android:sharedUserId="android.uid.system" > + + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" /> + + <instrumentation + android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.test.nullhome" + android:label="Check if no null Home exists/is enabled" /> + + <application android:label="Null Home Test"> + <uses-library android:name="android.test.runner" /> + </application> +</manifest> diff --git a/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java new file mode 100644 index 000000000000..1d77cdc51187 --- /dev/null +++ b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.nullhome; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.support.test.InstrumentationRegistry; +import android.util.Log; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.ArrayList; +import java.util.List; + +/* + * Check if NullHome/SystemUserHome activity does not exist/is disabled. + * + * SystemUserHome is only enabled in bootable CSI (csi_x86, csi_arm64) + * products and should not be enabled in other products. + * + * Shell's NullHome is empty and caused issues in sevaral manual GUI tests + * that try to select/use it, and should be removed. + * + * Settings' FallbackHome is fine because it's specially handled by Settings. + * + */ + +@RunWith(JUnit4.class) +public class NullHomeTest { + private static final String TAG = "NullHomeTest"; + private Context mContext; + private PackageManager mPm; + + @Before + public void before() { + Log.d(TAG, "beforeClass()"); + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + mPm = mContext.getPackageManager(); + } + + @Test + public void checkNullHome() { + final List<ResolveInfo> homeActivities = new ArrayList<>(); + + mPm.getHomeActivities(homeActivities); + for (ResolveInfo activity : homeActivities) { + Log.d(TAG, "Home activity: " + activity.activityInfo.packageName); + Assert.assertNotEquals(activity.activityInfo.packageName, + "com.android.internal.app.SystemUserHomeActivity"); + Assert.assertNotEquals(activity.activityInfo.packageName, + "com.android.shell"); + } + } +} diff --git a/tests/ProtoInputStreamTests/Android.bp b/tests/ProtoInputStreamTests/Android.bp new file mode 100644 index 000000000000..ecc405664128 --- /dev/null +++ b/tests/ProtoInputStreamTests/Android.bp @@ -0,0 +1,33 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +android_test { + name: "ProtoInputStreamTests", + proto: { + type: "nano", + }, + srcs: [ + "src/**/*.java", + "src/**/*.proto", + ], + platform_apis: true, + certificate: "platform", + test_suites: ["device-tests"], + libs: ["android.test.runner"], + static_libs: [ + "androidx.test.rules", + "frameworks-base-testutils", + "mockito-target-minus-junit4", + ], +} diff --git a/tests/ProtoInputStreamTests/Android.mk b/tests/ProtoInputStreamTests/Android.mk deleted file mode 100644 index eb747cc2cdcc..000000000000 --- a/tests/ProtoInputStreamTests/Android.mk +++ /dev/null @@ -1,34 +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. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_PACKAGE_NAME := ProtoInputStreamTests -LOCAL_PROTOC_OPTIMIZE_TYPE := nano -LOCAL_MODULE_TAGS := tests optional -LOCAL_SRC_FILES := \ - $(call all-java-files-under, src) \ - $(call all-proto-files-under, src) -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform -LOCAL_COMPATIBILITY_SUITE := device-tests - -LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_STATIC_JAVA_LIBRARIES := \ - androidx.test.rules \ - frameworks-base-testutils \ - mockito-target-minus-junit4 - -include $(BUILD_PACKAGE)
\ No newline at end of file diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt index ef15b668e24c..a50f0461fae6 100644 --- a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt +++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt @@ -39,12 +39,12 @@ class MatchAllNetworkSpecifierTest { } @Test(expected = IllegalStateException::class) - fun testSatisfiedBy() { + fun testCanBeSatisfiedBy() { val specifier = MatchAllNetworkSpecifier() val discoverySession = Mockito.mock(DiscoverySession::class.java) val peerHandle = Mockito.mock(PeerHandle::class.java) val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle).build() - specifier.satisfiedBy(wifiAwareNetworkSpecifier) + specifier.canBeSatisfiedBy(wifiAwareNetworkSpecifier) } } diff --git a/tests/net/integration/AndroidManifest.xml b/tests/net/integration/AndroidManifest.xml index 09c0e4826075..f5a4234ede9e 100644 --- a/tests/net/integration/AndroidManifest.xml +++ b/tests/net/integration/AndroidManifest.xml @@ -16,50 +16,55 @@ * limitations under the License. */ --> + <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.server.net.integrationtests"> + package="com.android.server.net.integrationtests"> <!-- For ConnectivityService registerReceiverAsUser (receiving broadcasts) --> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> <!-- PermissionMonitor sets network permissions for each user --> - <uses-permission android:name="android.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.MANAGE_USERS"/> <!-- ConnectivityService sends notifications to BatteryStats --> - <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> + <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/> <!-- Reading network status --> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <uses-permission android:name="android.permission.NETWORK_FACTORY" /> - <uses-permission android:name="android.permission.NETWORK_STACK" /> - <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" /> - <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <uses-permission android:name="android.permission.NETWORK_FACTORY"/> + <!-- Obtain LinkProperties callbacks with sensitive fields --> + <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> + <uses-permission android:name="android.permission.NETWORK_STACK"/> + <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY"/> + <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <!-- Reading DeviceConfig flags --> - <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/> <application android:debuggable="true"> - <uses-library android:name="android.test.runner" /> + <uses-library android:name="android.test.runner"/> <!-- This manifest is merged with the base manifest of the real NetworkStack app. - Remove the NetworkStackService from the base (real) manifest, and replace with a test - service that responds to the same intent --> + Remove the NetworkStackService from the base (real) manifest, and replace with a test + service that responds to the same intent --> <service android:name=".TestNetworkStackService" - android:process="com.android.server.net.integrationtests.testnetworkstack"> + android:process="com.android.server.net.integrationtests.testnetworkstack" + android:exported="true"> <intent-filter> <action android:name="android.net.INetworkStackConnector.Test"/> </intent-filter> </service> <service android:name=".NetworkStackInstrumentationService" - android:process="com.android.server.net.integrationtests.testnetworkstack"> + android:process="com.android.server.net.integrationtests.testnetworkstack" + android:exported="true"> <intent-filter> <action android:name=".INetworkStackInstrumentation"/> </intent-filter> </service> <service android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService" - android:process="com.android.server.net.integrationtests.testnetworkstack" - android:permission="android.permission.BIND_JOB_SERVICE"/> + android:process="com.android.server.net.integrationtests.testnetworkstack" + android:permission="android.permission.BIND_JOB_SERVICE"/> </application> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.server.net.integrationtests" - android:label="Frameworks Net Integration Tests" /> + android:targetPackage="com.android.server.net.integrationtests" + android:label="Frameworks Net Integration Tests"/> </manifest> diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index c4801aab5c32..bc069e148b99 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt @@ -28,10 +28,13 @@ import android.net.INetd import android.net.INetworkPolicyManager import android.net.INetworkStatsService import android.net.LinkProperties +import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET +import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED import android.net.NetworkCapabilities.TRANSPORT_CELLULAR import android.net.NetworkRequest import android.net.TestNetworkStackClient +import android.net.Uri import android.net.metrics.IpConnectivityLog import android.os.ConditionVariable import android.os.IBinder @@ -64,6 +67,8 @@ import org.mockito.Mockito.spy import org.mockito.MockitoAnnotations import org.mockito.Spy import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNotNull import kotlin.test.assertTrue import kotlin.test.fail @@ -110,6 +115,10 @@ class ConnectivityServiceIntegrationTest { private val bindingCondition = ConditionVariable(false) private val realContext get() = InstrumentationRegistry.getInstrumentation().context + private val httpProbeUrl get() = + realContext.getResources().getString(R.string.config_captive_portal_http_url) + private val httpsProbeUrl get() = + realContext.getResources().getString(R.string.config_captive_portal_https_url) private class InstrumentationServiceConnection : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { @@ -188,12 +197,8 @@ class ConnectivityServiceIntegrationTest { val testCallback = TestableNetworkCallback() cm.registerNetworkCallback(request, testCallback) - nsInstrumentation.addHttpResponse(HttpResponse( - "http://test.android.com", - responseCode = 204, contentLength = 42, redirectUrl = null)) - nsInstrumentation.addHttpResponse(HttpResponse( - "https://secure.test.android.com", - responseCode = 204, contentLength = 42, redirectUrl = null)) + nsInstrumentation.addHttpResponse(HttpResponse(httpProbeUrl, responseCode = 204)) + nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204)) val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), context) networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS) @@ -204,4 +209,52 @@ class ConnectivityServiceIntegrationTest { testCallback.expectAvailableThenValidatedCallbacks(na.network, TEST_TIMEOUT_MS) assertEquals(2, nsInstrumentation.getRequestUrls().size) } + + @Test + fun testCapportApi() { + val request = NetworkRequest.Builder() + .clearCapabilities() + .addCapability(NET_CAPABILITY_INTERNET) + .build() + val testCb = TestableNetworkCallback() + val apiUrl = "https://capport.android.com" + + cm.registerNetworkCallback(request, testCb) + nsInstrumentation.addHttpResponse(HttpResponse( + apiUrl, + """ + |{ + | "captive": true, + | "user-portal-url": "https://login.capport.android.com", + | "venue-info-url": "https://venueinfo.capport.android.com" + |} + """.trimMargin())) + + // Tests will fail if a non-mocked query is received: mock the HTTPS probe, but not the + // HTTP probe as it should not be sent. + // Even if the HTTPS probe succeeds, a portal should be detected as the API takes precedence + // in that case. + nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204)) + + val lp = LinkProperties() + lp.captivePortalApiUrl = Uri.parse(apiUrl) + val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, lp, context) + networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS) + + na.addCapability(NET_CAPABILITY_INTERNET) + na.connect() + + testCb.expectAvailableCallbacks(na.network, validated = false, tmt = TEST_TIMEOUT_MS) + + val capportData = testCb.expectLinkPropertiesThat(na, TEST_TIMEOUT_MS) { + it.captivePortalData != null + }.lp.captivePortalData + assertNotNull(capportData) + assertTrue(capportData.isCaptive) + assertEquals(Uri.parse("https://login.capport.android.com"), capportData.userPortalUrl) + assertEquals(Uri.parse("https://venueinfo.capport.android.com"), capportData.venueInfoUrl) + + val nc = testCb.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, na, TEST_TIMEOUT_MS) + assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED)) + } }
\ No newline at end of file diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt b/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt index 45073d8df3f7..e2063138fef1 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt @@ -22,16 +22,21 @@ import android.os.Parcelable data class HttpResponse( val requestUrl: String, val responseCode: Int, - val contentLength: Long, - val redirectUrl: String? + val content: String = "", + val redirectUrl: String? = null ) : Parcelable { - constructor(p: Parcel): this(p.readString(), p.readInt(), p.readLong(), p.readString()) + constructor(p: Parcel): this(p.readString(), p.readInt(), p.readString(), p.readString()) + constructor(requestUrl: String, contentBody: String): this( + requestUrl, + responseCode = 200, + content = contentBody, + redirectUrl = null) override fun writeToParcel(dest: Parcel, flags: Int) { with(dest) { writeString(requestUrl) writeInt(responseCode) - writeLong(contentLength) + writeString(content) writeString(redirectUrl) } } diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt index 4827d2997d93..e807952cec11 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt @@ -65,6 +65,9 @@ class NetworkStackInstrumentationService : Service() { * * <p>For any subsequent HTTP/HTTPS query, the first response with a matching URL will be * used to mock the query response. + * + * <p>All requests that are expected to be sent must have a mock response: if an unexpected + * request is seen, the test will fail. */ override fun addHttpResponse(response: HttpResponse) { httpResponses.getValue(response.requestUrl).add(response) diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index eec3cdbe8d7f..a44ad1e05259 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -33,9 +33,11 @@ import com.android.server.net.integrationtests.NetworkStackInstrumentationServic import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.spy +import java.io.ByteArrayInputStream import java.net.HttpURLConnection import java.net.URL import java.net.URLConnection +import java.nio.charset.StandardCharsets private const val TEST_NETID = 42 @@ -52,7 +54,7 @@ class TestNetworkStackService : Service() { doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE) } - private class TestPermissionChecker : NetworkStackConnector.PermissionChecker() { + private class TestPermissionChecker : NetworkStackService.PermissionChecker() { override fun enforceNetworkStackCallingPermission() = Unit } @@ -62,8 +64,8 @@ class TestNetworkStackService : Service() { override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit } - private inner class TestNetworkStackConnector(context: Context) : - NetworkStackConnector(context, TestPermissionChecker()) { + private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector( + context, TestPermissionChecker(), NetworkStackService.Dependencies()) { private val network = Network(TEST_NETID) private val privateDnsBypassNetwork = TestNetwork(TEST_NETID) @@ -71,11 +73,13 @@ class TestNetworkStackService : Service() { private inner class TestNetwork(netId: Int) : Network(netId) { override fun openConnection(url: URL): URLConnection { val response = InstrumentationConnector.processRequest(url) + val responseBytes = response.content.toByteArray(StandardCharsets.UTF_8) val connection = mock(HttpURLConnection::class.java) doReturn(response.responseCode).`when`(connection).responseCode - doReturn(response.contentLength).`when`(connection).contentLengthLong + doReturn(responseBytes.size.toLong()).`when`(connection).contentLengthLong doReturn(response.redirectUrl).`when`(connection).getHeaderField("location") + doReturn(ByteArrayInputStream(responseBytes)).`when`(connection).inputStream return connection } } diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index a35fb407bca9..0ffafd45613a 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -92,6 +92,9 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { break; case TRANSPORT_VPN: mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); + // VPNs deduce the SUSPENDED capability from their underlying networks and there + // is no public API to let VPN services set it. + mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); mScore = ConnectivityConstants.VPN_DEFAULT_SCORE; break; default: diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java index 2273bc61225c..ada5494efd60 100644 --- a/tests/net/java/android/net/Ikev2VpnProfileTest.java +++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java @@ -40,7 +40,10 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.List; import java.util.concurrent.TimeUnit; import javax.security.auth.x500.X500Principal; @@ -106,6 +109,7 @@ public class Ikev2VpnProfileTest { assertTrue(profile.isBypassable()); assertTrue(profile.isMetered()); assertEquals(TEST_MTU, profile.getMaxMtu()); + assertEquals(Ikev2VpnProfile.DEFAULT_ALGORITHMS, profile.getAllowedAlgorithms()); } @Test @@ -160,6 +164,78 @@ public class Ikev2VpnProfileTest { } @Test + public void testBuildWithAllowedAlgorithmsAead() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + builder.setAuthPsk(PSK_BYTES); + + List<String> allowedAlgorithms = Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); + builder.setAllowedAlgorithms(allowedAlgorithms); + + final Ikev2VpnProfile profile = builder.build(); + assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); + } + + @Test + public void testBuildWithAllowedAlgorithmsNormal() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + builder.setAuthPsk(PSK_BYTES); + + List<String> allowedAlgorithms = + Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA512, IpSecAlgorithm.CRYPT_AES_CBC); + builder.setAllowedAlgorithms(allowedAlgorithms); + + final Ikev2VpnProfile profile = builder.build(); + assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); + } + + @Test + public void testSetAllowedAlgorithmsEmptyList() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + + try { + builder.setAllowedAlgorithms(new ArrayList<>()); + fail("Expected exception due to no valid algorithm set"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testSetAllowedAlgorithmsInvalidList() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + List<String> allowedAlgorithms = new ArrayList<>(); + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA256)); + fail("Expected exception due to missing encryption"); + } catch (IllegalArgumentException expected) { + } + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.CRYPT_AES_CBC)); + fail("Expected exception due to missing authentication"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testSetAllowedAlgorithmsInsecureAlgorithm() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + List<String> allowedAlgorithms = new ArrayList<>(); + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_MD5)); + fail("Expected exception due to insecure algorithm"); + } catch (IllegalArgumentException expected) { + } + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA1)); + fail("Expected exception due to insecure algorithm"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void testBuildNoAuthMethodSet() throws Exception { final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java index ceca6f028866..e5daa71c30ea 100644 --- a/tests/net/java/com/android/internal/net/VpnProfileTest.java +++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java @@ -33,7 +33,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** Unit tests for {@link VpnProfile}. */ @SmallTest @@ -41,6 +43,9 @@ import java.util.Arrays; public class VpnProfileTest { private static final String DUMMY_PROFILE_KEY = "Test"; + private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; + private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; + @Test public void testDefaults() throws Exception { final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); @@ -67,10 +72,11 @@ public class VpnProfileTest { assertFalse(p.isMetered); assertEquals(1360, p.maxMtu); assertFalse(p.areAuthParamsInline); + assertFalse(p.isRestrictedToTestNetworks); } private VpnProfile getSampleIkev2Profile(String key) { - final VpnProfile p = new VpnProfile(key); + final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */); p.name = "foo"; p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; @@ -116,7 +122,7 @@ public class VpnProfileTest { @Test public void testParcelUnparcel() { - assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22); + assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); } @Test @@ -159,14 +165,41 @@ public class VpnProfileTest { assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); } + private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { + // Sort to ensure when we remove, we can do it from greatest first. + Arrays.sort(missingIndices); + + final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); + final List<String> parts = + new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); + + // Remove from back first to ensure indexing is consistent. + for (int i = missingIndices.length - 1; i >= 0; i--) { + parts.remove(missingIndices[i]); + } + + return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); + } + @Test public void testEncodeDecodeInvalidNumberOfValues() { - final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - final String encoded = new String(profile.encode()); - final byte[] tooFewValues = - encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes(); + final String tooFewValues = + getEncodedDecodedIkev2ProfileMissingValues( + ENCODED_INDEX_AUTH_PARAMS_INLINE, + ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); - assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues)); + assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); + } + + @Test + public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { + final String tooFewValues = + getEncodedDecodedIkev2ProfileMissingValues( + ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); + + // Verify decoding without isRestrictedToTestNetworks defaults to false + final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); + assertFalse(decoded.isRestrictedToTestNetworks); } @Test diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 656fe489d8b8..ea4982ed7c7d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -75,6 +75,7 @@ import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.RouteInfo.RTN_UNREACHABLE; +import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType; @@ -5394,8 +5395,6 @@ public class ConnectivityServiceTest { // Even though the VPN is unvalidated, it becomes the default network for our app. callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); - // TODO: this looks like a spurious callback. - callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); callback.assertNoCallback(); assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore()); @@ -5425,6 +5424,47 @@ public class ConnectivityServiceTest { } @Test + public void testVpnStartsWithUnderlyingCaps() throws Exception { + final int uid = Process.myUid(); + + final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); + final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .addTransportType(TRANSPORT_VPN) + .build(); + mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); + vpnNetworkCallback.assertNoCallback(); + + // Connect cell. It will become the default network, and in the absence of setting + // underlying networks explicitly it will become the sole underlying network for the vpn. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); + final ArraySet<UidRange> ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); + mMockVpn.setNetworkAgent(vpnNetworkAgent); + mMockVpn.connect(); + mMockVpn.setUids(ranges); + vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, + false /* isStrictMode */); + + vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(), + false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS, + nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)); + + final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED)); + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + } + + @Test public void testVpnSetUnderlyingNetworks() throws Exception { final int uid = Process.myUid(); @@ -5454,9 +5494,12 @@ public class ConnectivityServiceTest { assertFalse(nc.hasTransport(TRANSPORT_WIFI)); // For safety reasons a VPN without underlying networks is considered metered. assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + // A VPN without underlying networks is not suspended. + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Connect cell and use it as an underlying network. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mCellNetworkAgent.connect(true); mService.setUnderlyingNetworksForVpn( @@ -5465,10 +5508,12 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mWiFiNetworkAgent.connect(true); mService.setUnderlyingNetworksForVpn( @@ -5477,7 +5522,8 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Don't disconnect, but note the VPN is not using wifi any more. mService.setUnderlyingNetworksForVpn( @@ -5486,16 +5532,36 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + + // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent); + + // Add NOT_SUSPENDED again and observe VPN is no longer suspended. + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent); - // Use Wifi but not cell. Note the VPN is now unmetered. + // Use Wifi but not cell. Note the VPN is now unmetered and not suspended. mService.setUnderlyingNetworksForVpn( new Network[] { mWiFiNetworkAgent.getNetwork() }); vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Use both again. mService.setUnderlyingNetworksForVpn( @@ -5504,7 +5570,37 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + + // Cell is suspended again. As WiFi is not, this should not cause a callback. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.assertNoCallback(); + + // Stop using WiFi. The VPN is suspended again. + mService.setUnderlyingNetworksForVpn( + new Network[] { mCellNetworkAgent.getNetwork() }); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + // While the SUSPENDED callback should in theory be sent here, it is not. This is + // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never + // been public and are deprecated and slated for removal, there is no sense in spending + // resources fixing this bug now. + + // Use both again. + mService.setUnderlyingNetworksForVpn( + new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); + + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + // As above, the RESUMED callback not being sent here is a bug, but not a bug that's + // worth anybody's time to fix. // Disconnect cell. Receive update without even removing the dead network from the // underlying networks – it's dead anyway. Not metered any more. @@ -6226,6 +6322,7 @@ public class ConnectivityServiceTest { int netId = network.getNetId(); callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); callback.assertNoCallback(); assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); @@ -6235,6 +6332,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, null); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and @@ -6244,6 +6342,7 @@ public class ConnectivityServiceTest { expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS // discovery has succeeded. @@ -6251,6 +6350,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, null); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, @@ -6258,13 +6358,40 @@ public class ConnectivityServiceTest { expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); - // If the RA prefix reappears, clatd is restarted and prefix discovery is stopped. + // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix + // discovery is not stopped, and there are no callbacks. + lp.setNat64Prefix(pref64FromDns); + mCellNetworkAgent.sendLinkProperties(lp); + callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + + // If the RA is later withdrawn, nothing happens again. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + + // If the RA prefix changes, clatd is restarted and prefix discovery is stopped. lp.setNat64Prefix(pref64FromRa); mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); inOrder.verify(mMockNetd).clatdStop(iface); inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + + // Stopping prefix discovery results in a prefix removed notification. + mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */, + pref64FromDnsStr, 96); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); // If the RA prefix changes, clatd is restarted and prefix discovery is not started. @@ -6272,7 +6399,9 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); @@ -6285,11 +6414,45 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties. + // If the same prefix is learned first by DNS and then by RA, and clat is later stopped, + // (e.g., because the network disconnects) setPrefix64(netid, "") is never called. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, null); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); + inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); + mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, + pref64FromDnsStr, 96); + expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any()); + + lp.setNat64Prefix(pref64FromDns); + mCellNetworkAgent.sendLinkProperties(lp); callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + + // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but + // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that + // clat has been stopped, or the test will be flaky. + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.disconnect(); + callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + waitFor(cv); + + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + mCm.unregisterNetworkCallback(callback); } @@ -6953,7 +7116,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission( android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); @@ -6969,7 +7132,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); @@ -6985,7 +7148,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); @@ -7002,7 +7165,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, network, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); @@ -7036,7 +7199,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, - mService, null, null, null, 0); + mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); @@ -7058,7 +7221,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, - mService, null, null, null, 0); + mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt index 42d4cf3c382b..a10a3c81bc86 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -14,6 +14,11 @@ * limitations under the License. */ +// Don't warn about deprecated types anywhere in this test, because LegacyTypeTracker's very reason +// for existence is to power deprecated APIs. The annotation has to apply to the whole file because +// otherwise warnings will be generated by the imports of deprecated constants like TYPE_xxx. +@file:Suppress("DEPRECATION") + package com.android.server import android.net.ConnectivityManager.TYPE_ETHERNET diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 24a87177224e..aafa18a532fa 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -38,6 +38,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; +import android.os.Binder; import android.os.INetworkManagementService; import android.text.format.DateUtils; @@ -354,7 +355,7 @@ public class LingerMonitorTest { caps.addTransportType(transport); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, - NetworkProvider.ID_NONE); + NetworkProvider.ID_NONE, Binder.getCallingUid()); nai.everValidated = true; return nai; } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 1994d1f2ed45..f8d8a56b57c0 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; @@ -606,6 +607,7 @@ public class VpnTest { .addCapability(NET_CAPABILITY_NOT_METERED) .addCapability(NET_CAPABILITY_NOT_ROAMING) .addCapability(NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NET_CAPABILITY_NOT_SUSPENDED) .setLinkUpstreamBandwidthKbps(20)); setMockedNetworks(networks); @@ -621,6 +623,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, @@ -635,6 +638,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */); @@ -646,6 +650,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */); @@ -657,6 +662,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, @@ -671,6 +677,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); } /** diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java index 28785f7c9726..3aafe0b075f2 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java @@ -41,6 +41,7 @@ abstract class NetworkStatsBaseTest { static final String TEST_IFACE = "test0"; static final String TEST_IFACE2 = "test1"; static final String TUN_IFACE = "test_nss_tun0"; + static final String TUN_IFACE2 = "test_nss_tun1"; static final int UID_RED = 1001; static final int UID_BLUE = 1002; @@ -107,10 +108,14 @@ abstract class NetworkStatsBaseTest { assertEquals("unexpected operations", operations, entry.operations); } - VpnInfo createVpnInfo(String[] underlyingIfaces) { + static VpnInfo createVpnInfo(String[] underlyingIfaces) { + return createVpnInfo(TUN_IFACE, underlyingIfaces); + } + + static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) { VpnInfo info = new VpnInfo(); info.ownerUid = UID_VPN; - info.vpnIface = TUN_IFACE; + info.vpnIface = vpnIface; info.underlyingIfaces = underlyingIfaces; return info; } diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java index a21f5095c746..4473492d7972 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -104,7 +104,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnRewriteTrafficThroughItself() throws Exception { + public void testVpnRewriteTrafficThroughItself() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -133,7 +133,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithClat() throws Exception { + public void testVpnWithClat() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); mFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE); @@ -166,7 +166,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIface() throws Exception { + public void testVpnWithOneUnderlyingIface() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -189,7 +189,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception { + public void testVpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -217,7 +217,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIface_withCompression() throws Exception { + public void testVpnWithOneUnderlyingIface_withCompression() throws Exception { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -238,7 +238,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { + public void testVpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is duplicating traffic across both WiFi and Cell. @@ -264,7 +264,47 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { + public void testConcurrentVpns() throws Exception { + // Assume two VPNs are connected on two different network interfaces. VPN1 is using + // TEST_IFACE and VPN2 is using TEST_IFACE2. + final VpnInfo[] vpnInfos = new VpnInfo[] { + createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}), + createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})}; + mFactory.updateVpnInfos(vpnInfos); + + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED + // over VPN1. + // 700 bytes (70 packets) were sent, and 3000 bytes (300 packets) were received by UID_RED + // over VPN2. + // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE + // over VPN1. + // 250 bytes (25 packets) were sent, and 500 bytes (50 packets) were received by UID_BLUE + // over VPN2. + // VPN1 sent 1650 bytes (150 packets), and received 3300 (300 packets) over TEST_IFACE. + // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes + // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. + // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes + // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. + // VPN2 sent 1045 bytes (95 packets), and received 3850 (350 packets) over TEST_IFACE2. + // Of 1045 bytes sent over Cell, expect 700 bytes attributed to UID_RED, 250 bytes + // attributed to UID_BLUE, and 95 bytes attributed to UID_VPN. + // Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes + // attributed to UID_BLUE, and 350 bytes attributed to UID_VPN. + final NetworkStats tunStats = + parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn); + + assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); + assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); + assertValues(tunStats, TEST_IFACE2, UID_RED, 3000L, 300L, 700L, 70L); + assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 250L, 25L); + assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); + assertValues(tunStats, TEST_IFACE2, UID_VPN, 350L, 0L, 95L, 0L); + } + + @Test + public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell. @@ -291,7 +331,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { + public void testVpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell. @@ -314,7 +354,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithIncorrectUnderlyingIface() throws Exception { + public void testVpnWithIncorrectUnderlyingIface() throws Exception { // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2), // but has declared only WiFi (TEST_IFACE) in its underlying network set. VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 1db90b71e2b1..a1bb0d586916 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -60,14 +60,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; import android.content.Context; @@ -95,8 +94,6 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.SimpleClock; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; @@ -126,6 +123,7 @@ import java.io.File; import java.time.Clock; import java.time.ZoneOffset; import java.util.Objects; +import java.util.concurrent.Executor; /** * Tests for {@link NetworkStatsService}. @@ -168,14 +166,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private @Mock NetworkStatsSettings mSettings; private @Mock IBinder mBinder; private @Mock AlarmManager mAlarmManager; - private @Mock TelephonyManager mTelephonyManager; + @Mock + private NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; private HandlerThread mHandlerThread; private NetworkStatsService mService; private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; - @Nullable - private PhoneStateListener mPhoneStateListener; private final Clock mClock = new SimpleClock(ZoneOffset.UTC) { @Override @@ -203,8 +200,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mHandlerThread = new HandlerThread("HandlerThread"); final NetworkStatsService.Dependencies deps = makeDependencies(); mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, - mClock, mTelephonyManager, mSettings, - mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps); + mClock, mSettings, mStatsFactory, new NetworkStatsObservers(), mStatsDir, + getBaseDir(mStatsDir), deps); mElapsedRealtime = 0L; @@ -224,12 +221,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { ArgumentCaptor.forClass(INetworkManagementEventObserver.class); verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - - // Capture the phone state listener that created by service. - final ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt()); - mPhoneStateListener = phoneStateListenerCaptor.getValue(); } @NonNull @@ -239,6 +230,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public HandlerThread makeHandlerThread() { return mHandlerThread; } + + @Override + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor( + @NonNull Context context, @NonNull Executor executor, + @NonNull NetworkStatsService service) { + + return mNetworkStatsSubscriptionsMonitor; + } }; } @@ -678,10 +677,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // TODO: support per IMSI state private void setMobileRatTypeAndWaitForIdle(int ratType) { - final ServiceState mockSs = mock(ServiceState.class); - when(mockSs.getDataNetworkType()).thenReturn(ratType); - mPhoneStateListener.onServiceStateChanged(mockSs); - + when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString())) + .thenReturn(ratType); + mService.handleOnCollapsedRatTypeChanged(); HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); } diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn new file mode 100644 index 000000000000..eb0513b10049 --- /dev/null +++ b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn @@ -0,0 +1,9 @@ +idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets +2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 +3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 +4 test_nss_tun1 0x0 1001 0 3000 300 700 70 0 0 0 0 0 0 0 0 0 0 0 0 +5 test_nss_tun1 0x0 1002 0 500 50 250 25 0 0 0 0 0 0 0 0 0 0 0 0 +6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 +8 test1 0x0 1004 0 3850 350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +9 test1 0x0 1004 1 0 0 1045 95 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java index 8d99ac7100eb..7218ae3550c6 100644 --- a/tests/testables/src/android/testing/TestableLooper.java +++ b/tests/testables/src/android/testing/TestableLooper.java @@ -222,6 +222,10 @@ public class TestableLooper { return sLoopers.get(test); } + public static void remove(Object test) { + sLoopers.remove(test); + } + static class LooperFrameworkMethod extends FrameworkMethod { private HandlerThread mHandlerThread; diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index f354bb610224..7afb0000aea1 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1659,13 +1659,24 @@ class Linker { return 1; } - // First extract the Package name without modifying it (via --rename-manifest-package). + // First extract the package name without modifying it (via --rename-manifest-package). if (Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) { + // Extract the package name from the manifest ignoring the value of --rename-manifest-package. const AppInfo& app_info = maybe_app_info.value(); context_->SetCompilationPackage(app_info.package); } + // Determine the package name under which to merge resources. + if (options_.rename_resources_package) { + if (!options_.custom_java_package) { + // Generate the R.java under the original package name instead of the package name specified + // through --rename-resources-package. + options_.custom_java_package = context_->GetCompilationPackage(); + } + context_->SetCompilationPackage(options_.rename_resources_package.value()); + } + // Now that the compilation package is set, load the dependencies. This will also extract // the Android framework's versionCode and versionName, if they exist. if (!LoadSymbolsFromIncludePaths()) { diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 7c583858ee1d..e62e0a6b9f62 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -43,6 +43,7 @@ struct LinkOptions { bool output_to_directory = false; bool auto_add_overlay = false; OutputFormat output_format = OutputFormat::kApk; + Maybe<std::string> rename_resources_package; // Java/Proguard options. Maybe<std::string> generate_java_class_path; @@ -244,10 +245,16 @@ class LinkCommand : public Command { &options_.auto_add_overlay); AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.", &options_.manifest_fixer_options.rename_manifest_package); + AddOptionalFlag("--rename-resources-package", "Renames the package in resources table", + &options_.rename_resources_package); AddOptionalFlag("--rename-instrumentation-target-package", "Changes the name of the target package for instrumentation. Most useful\n" "when used in conjunction with --rename-manifest-package.", &options_.manifest_fixer_options.rename_instrumentation_target_package); + AddOptionalFlag("--rename-overlay-target-package", + "Changes the name of the target package for overlay. Most useful\n" + "when used in conjunction with --rename-manifest-package.", + &options_.manifest_fixer_options.rename_overlay_target_package); AddOptionalFlagList("-0", "File extensions not to compress.", &options_.extensions_to_not_compress); AddOptionalSwitch("--no-compress", "Do not compress any resources.", diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 49909f6e2b8e..06303c273261 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -236,6 +236,16 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, } } + if (options_.rename_overlay_target_package) { + if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) { + diag->Error(DiagMessage() + << "invalid overlay target package override '" + << options_.rename_overlay_target_package.value() + << "'"); + return false; + } + } + // Common <intent-filter> actions. xml::XmlNodeAction intent_filter_action; intent_filter_action["action"].Action(RequiredNameIsNotEmpty); @@ -337,7 +347,17 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, manifest_action["instrumentation"]["meta-data"] = meta_data_action; manifest_action["original-package"]; - manifest_action["overlay"]; + manifest_action["overlay"].Action([&](xml::Element* el) -> bool { + if (!options_.rename_overlay_target_package) { + return true; + } + + if (xml::Attribute* attr = + el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) { + attr->value = options_.rename_overlay_target_package.value(); + } + return true; + }); manifest_action["protected-broadcast"]; manifest_action["adopt-permissions"]; manifest_action["uses-permission"]; diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h index 3ef57d0d0e42..ec4367b450fb 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -44,6 +44,10 @@ struct ManifestFixerOptions { // <instrumentation>. Maybe<std::string> rename_instrumentation_target_package; + // The Android package to use instead of the one defined in 'android:targetPackage' in + // <overlay>. + Maybe<std::string> rename_overlay_target_package; + // The version name to set if 'android:versionName' is not defined in <manifest> or if // replace_version is set. Maybe<std::string> version_name_default; diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 3f1ee36dea4a..3aba4e2ec49f 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -325,6 +325,32 @@ TEST_F(ManifestFixerTest, EXPECT_THAT(attr->value, StrEq("com.android")); } +TEST_F(ManifestFixerTest, + RenameManifestOverlayPackageAndFullyQualifyTarget) { + ManifestFixerOptions options; + options.rename_overlay_target_package = std::string("com.android"); + + std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android"> + <overlay android:targetName="Customization" android:targetPackage="android" /> + </manifest>)EOF", + options); + ASSERT_THAT(doc, NotNull()); + + xml::Element* manifest_el = doc->root.get(); + ASSERT_THAT(manifest_el, NotNull()); + + xml::Element* overlay_el = + manifest_el->FindChild({}, "overlay"); + ASSERT_THAT(overlay_el, NotNull()); + + xml::Attribute* attr = + overlay_el->FindAttribute(xml::kSchemaAndroid, "targetPackage"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("com.android")); +} + TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { ManifestFixerOptions options; options.version_name_default = std::string("Beta"); diff --git a/tools/bit/adb.cpp b/tools/bit/adb.cpp index fa7d3d4031d4..f521a63255e1 100644 --- a/tools/bit/adb.cpp +++ b/tools/bit/adb.cpp @@ -200,7 +200,7 @@ skip_bytes(int fd, ssize_t size, char* scratch, int scratchSize) static int skip_unknown_field(int fd, uint64_t tag, char* scratch, int scratchSize) { - bool done; + bool done = false; int err; uint64_t size; switch (tag & 0x7) { diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index 0b2077d9bba0..de6b4785ec37 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -18,10 +18,10 @@ Generate API lists for non-SDK API enforcement. """ import argparse from collections import defaultdict +import functools import os -import sys import re -import functools +import sys # Names of flags recognized by the `hiddenapi` tool. FLAG_WHITELIST = "whitelist" @@ -30,6 +30,7 @@ FLAG_BLACKLIST = "blacklist" FLAG_GREYLIST_MAX_O = "greylist-max-o" FLAG_GREYLIST_MAX_P = "greylist-max-p" FLAG_GREYLIST_MAX_Q = "greylist-max-q" +FLAG_GREYLIST_MAX_R = "greylist-max-r" FLAG_CORE_PLATFORM_API = "core-platform-api" FLAG_PUBLIC_API = "public-api" FLAG_SYSTEM_API = "system-api" @@ -43,13 +44,14 @@ FLAGS_API_LIST = [ FLAG_GREYLIST_MAX_O, FLAG_GREYLIST_MAX_P, FLAG_GREYLIST_MAX_Q, + FLAG_GREYLIST_MAX_R, ] ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API, FLAG_PUBLIC_API, FLAG_SYSTEM_API, FLAG_TEST_API, - ] +] FLAGS_API_LIST_SET = set(FLAGS_API_LIST) ALL_FLAGS_SET = set(ALL_FLAGS) diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index 91f875ed9918..ba1267b28fbb 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -368,10 +368,13 @@ static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination // Don't generate a variable twice if (!hasDefaultFlags[i]) variableNames[fieldName] = false; } + // hasDefaultFlags[i] has been initialized in the above for-loop, + // but clang-tidy analyzer still report uninitized values. + // So we use NOLINT to suppress those false positives. bool allDefaults = true; for (size_t i=0; i<fieldsInOrder.size(); i++) { - allDefaults &= hasDefaultFlags[i]; + allDefaults &= hasDefaultFlags[i]; // NOLINT(clang-analyzer-core.uninitialized.Assign) } parents->erase(messageName); // erase the message type name when exit the message. @@ -384,7 +387,7 @@ static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination printf("Privacy* %s[] = {\n", messageName.c_str()); for (size_t i=0; i<fieldsInOrder.size(); i++) { const FieldDescriptor* field = fieldsInOrder[i]; - if (hasDefaultFlags[i]) continue; + if (hasDefaultFlags[i]) continue; // NOLINT(clang-analyzer-core.uninitialized.Branch) printf(" &%s,\n", getFieldName(field).c_str()); policyCount++; } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 47d8f13bf9ef..29e09a11590b 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -892,7 +892,7 @@ public class WifiManager { * The RSSI (signal strength) has changed. * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE - * @see {@link #EXTRA_NEW_RSSI} + * @see #EXTRA_NEW_RSSI */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java index 00cb243efcaa..689ace5bf5b9 100644 --- a/wifi/java/android/net/wifi/WpsInfo.java +++ b/wifi/java/android/net/wifi/WpsInfo.java @@ -22,7 +22,7 @@ import android.os.Parcelable; /** * A class representing Wi-Fi Protected Setup * - * {@see WifiP2pConfig} + * {@see android.net.wifi.p2p.WifiP2pConfig} */ public class WpsInfo implements Parcelable { |