diff options
868 files changed, 17975 insertions, 5189 deletions
diff --git a/Android.bp b/Android.bp index 82915b5e753a..88ed676aae69 100644 --- a/Android.bp +++ b/Android.bp @@ -25,6 +25,44 @@ // // READ ME: ######################################################## +package { + default_applicable_licenses: ["frameworks_base_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "frameworks_base_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + "SPDX-license-identifier-CC-BY", + "SPDX-license-identifier-CPL-1.0", + "SPDX-license-identifier-GPL", + "SPDX-license-identifier-GPL-2.0", + "SPDX-license-identifier-MIT", + "SPDX-license-identifier-Unicode-DFS", + "SPDX-license-identifier-W3C", + "legacy_unencumbered", + ], + license_text: [ + "NOTICE", + ], +} + filegroup { name: "framework-core-sources", srcs: [ @@ -363,6 +401,7 @@ filegroup { ":framework-statsd-sources", ":framework-tethering-srcs", ":framework-wifi-updatable-sources", + ":ike-srcs", ":updatable-media-srcs", ], visibility: ["//visibility:private"], @@ -371,6 +410,7 @@ filegroup { java_library { name: "framework-updatable-stubs-module_libs_api", static_libs: [ + "android.net.ipsec.ike.stubs.module_lib", "framework-media.stubs.module_lib", "framework-mediaprovider.stubs.module_lib", "framework-permission.stubs.module_lib", @@ -387,6 +427,7 @@ java_library { name: "framework-all", installable: false, static_libs: [ + "android.net.ipsec.ike.impl", "framework-minus-apex", "framework-mediaprovider.impl", "framework-permission.impl", @@ -484,6 +525,7 @@ java_library { "android.hardware.vibrator-V1.3-java", "android.security.apc-java", "android.security.authorization-java", + "android.security.usermanager-java", "android.system.keystore2-V1-java", "android.system.suspend.control.internal-java", "devicepolicyprotosnano", diff --git a/StubLibraries.bp b/StubLibraries.bp index 367b427d8207..6cece60c484c 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -303,6 +303,7 @@ java_library_static { name: "android_stubs_current", srcs: [ ":api-stubs-docs-non-updatable" ], static_libs: [ + "android.net.ipsec.ike.stubs", "art.module.public.api.stubs", "conscrypt.module.public.api.stubs", "framework-media.stubs", @@ -322,6 +323,7 @@ java_library_static { name: "android_system_stubs_current", srcs: [ ":system-api-stubs-docs-non-updatable" ], static_libs: [ + "android.net.ipsec.ike.stubs.system", "art.module.public.api.stubs", "conscrypt.module.public.api.stubs", "framework-media.stubs.system", @@ -357,6 +359,7 @@ java_library_static { static_libs: [ // Modules do not have test APIs, but we want to include their SystemApis, like we include // the SystemApi of framework-non-updatable-sources. + "android.net.ipsec.ike.stubs.system", "art.module.public.api.stubs", "conscrypt.module.public.api.stubs", "framework-media.stubs.system", diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp index 65c28fb4d0a7..82e29da0a077 100644 --- a/apct-tests/perftests/autofill/Android.bp +++ b/apct-tests/perftests/autofill/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AutofillPerfTests", srcs: ["src/**/*.java"], diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp index be5072ce3d9d..1b0b078a4472 100644 --- a/apct-tests/perftests/blobstore/Android.bp +++ b/apct-tests/perftests/blobstore/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BlobStorePerfTests", srcs: ["src/**/*.java"], @@ -25,4 +34,4 @@ android_test { platform_apis: true, test_suites: ["device-tests"], certificate: "platform", -}
\ No newline at end of file +} diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index 984893a25605..277ad7e265c7 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CorePerfTests", diff --git a/apct-tests/perftests/core/apps/overlay/Android.bp b/apct-tests/perftests/core/apps/overlay/Android.bp index 7bee30ee9cb4..646530788907 100644 --- a/apct-tests/perftests/core/apps/overlay/Android.bp +++ b/apct-tests/perftests/core/apps/overlay/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "Overlay0", aaptflags: [ @@ -185,4 +194,4 @@ java_library { ":LargeOverlay8", ":LargeOverlay9", ], -}
\ No newline at end of file +} diff --git a/apct-tests/perftests/core/apps/reources_manager/Android.bp b/apct-tests/perftests/core/apps/reources_manager/Android.bp index 451613236140..85dd0c4be48d 100644 --- a/apct-tests/perftests/core/apps/reources_manager/Android.bp +++ b/apct-tests/perftests/core/apps/reources_manager/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "LargeResourcesCompressed", static_libs: [ "androidx.appcompat_appcompat" ], @@ -31,4 +40,4 @@ java_library { ":LargeResourcesCompressed", ":LargeResourcesUncompressed", ], -}
\ No newline at end of file +} diff --git a/apct-tests/perftests/core/jni/Android.bp b/apct-tests/perftests/core/jni/Android.bp index d160d48538c3..1e4405dea2d2 100644 --- a/apct-tests/perftests/core/jni/Android.bp +++ b/apct-tests/perftests/core/jni/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libperftestscore_jni", sdk_version: "21", diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp index 04432f25e337..91e207433f3d 100644 --- a/apct-tests/perftests/multiuser/Android.bp +++ b/apct-tests/perftests/multiuser/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "MultiUserPerfTests", srcs: ["src/**/*.java"], diff --git a/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp b/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp index 08c54a60a290..892c14006f87 100644 --- a/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp +++ b/apct-tests/perftests/multiuser/apps/dummyapp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "MultiUserPerfDummyApp", diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp index 17033e048c7d..dbb8a2e0acc0 100644 --- a/apct-tests/perftests/packagemanager/Android.bp +++ b/apct-tests/perftests/packagemanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PackageManagerPerfTests", diff --git a/apct-tests/perftests/packagemanager/apps/query-all/Android.bp b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp index 3cb1589bc376..b2339d5965a0 100644 --- a/apct-tests/perftests/packagemanager/apps/query-all/Android.bp +++ b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "QueriesAll0", aaptflags: [ diff --git a/apct-tests/perftests/textclassifier/Android.bp b/apct-tests/perftests/textclassifier/Android.bp index 49952dc1d009..ce57bd5f2774 100644 --- a/apct-tests/perftests/textclassifier/Android.bp +++ b/apct-tests/perftests/textclassifier/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TextClassifierPerfTests", srcs: ["src/**/*.java"], diff --git a/apct-tests/perftests/utils/Android.bp b/apct-tests/perftests/utils/Android.bp index be85816629c1..6c46a9b58f06 100644 --- a/apct-tests/perftests/utils/Android.bp +++ b/apct-tests/perftests/utils/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "apct-perftests-utils", static_libs: [ diff --git a/apct-tests/perftests/windowmanager/Android.bp b/apct-tests/perftests/windowmanager/Android.bp index f02cbcfc4daf..1d78f6585dcb 100644 --- a/apct-tests/perftests/windowmanager/Android.bp +++ b/apct-tests/perftests/windowmanager/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "WmPerfTests", srcs: ["src/**/*.java"], diff --git a/apex/Android.bp b/apex/Android.bp index 8310ba769f55..f3a936233ae8 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -14,4 +14,10 @@ package { default_visibility: [":__subpackages__"], + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], } diff --git a/apex/blobstore/framework/Android.bp b/apex/blobstore/framework/Android.bp index 349955368b17..1cb295ba0822 100644 --- a/apex/blobstore/framework/Android.bp +++ b/apex/blobstore/framework/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-blobstore-sources", srcs: [ diff --git a/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp index f6cbac1628da..49cfd07443db 100644 --- a/apex/blobstore/service/Android.bp +++ b/apex/blobstore/service/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "service-blobstore", installable: true, diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp index 23f5614f018c..70f7fe9acac4 100644 --- a/apex/jobscheduler/framework/Android.bp +++ b/apex/jobscheduler/framework/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-jobscheduler-sources", srcs: [ diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp index 6ddba690bd6f..bb86341119e0 100644 --- a/apex/jobscheduler/service/Android.bp +++ b/apex/jobscheduler/service/Android.bp @@ -1,5 +1,14 @@ // Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex. // service-jobscheduler needs to be added to PRODUCT_SYSTEM_SERVER_JARS. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "service-jobscheduler", installable: true, diff --git a/apex/media/Android.bp b/apex/media/Android.bp index 5f1bd374df00..308741a6733d 100644 --- a/apex/media/Android.bp +++ b/apex/media/Android.bp @@ -17,4 +17,10 @@ package { "//frameworks/av/apex", "//frameworks/av/apex/testing", ], + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], } diff --git a/apex/media/aidl/Android.bp b/apex/media/aidl/Android.bp index 409a04897f56..5bf32717fac0 100644 --- a/apex/media/aidl/Android.bp +++ b/apex/media/aidl/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "stable-mediasession2-aidl-srcs", srcs: ["stable/**/*.aidl"], diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index 0ff6d4428c27..65f07c2d9d32 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "updatable-media", diff --git a/api/Android.bp b/api/Android.bp index fdfef4cb8a74..2c2bb65402ea 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -14,6 +14,14 @@ package { default_visibility: ["//visibility:private"], + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], } genrule { @@ -28,6 +36,7 @@ genrule { genrule { name: "frameworks-base-api-current.txt", srcs: [ + ":android.net.ipsec.ike{.public.api.txt}", ":art.module.public.api{.public.api.txt}", ":conscrypt.module.public.api{.public.api.txt}", ":framework-media{.public.api.txt}", @@ -59,8 +68,25 @@ genrule { } genrule { + name: "frameworks-base-api-current-compat", + srcs: [ + ":android.api.public.latest", + ":android-incompatibilities.api.public.latest", + ":frameworks-base-api-current.txt", + ], + out: ["stdout.txt"], + tools: ["metalava"], + cmd: "$(location metalava) --no-banner --format=v2 " + + "--check-compatibility:api:released $(location :android.api.public.latest) " + + "--baseline:compatibility:released $(location :android-incompatibilities.api.public.latest) " + + "$(location :frameworks-base-api-current.txt) " + + "> $(genDir)/stdout.txt", +} + +genrule { name: "frameworks-base-api-current.srcjar", srcs: [ + ":android.net.ipsec.ike{.public.stubs.source}", ":api-stubs-docs-non-updatable", ":art.module.public.api{.public.stubs.source}", ":conscrypt.module.public.api{.public.stubs.source}", @@ -82,6 +108,7 @@ genrule { genrule { name: "frameworks-base-api-removed.txt", srcs: [ + ":android.net.ipsec.ike{.public.removed-api.txt}", ":art.module.public.api{.public.removed-api.txt}", ":conscrypt.module.public.api{.public.removed-api.txt}", ":framework-media{.public.removed-api.txt}", @@ -114,6 +141,7 @@ genrule { genrule { name: "frameworks-base-api-system-current.txt", srcs: [ + ":android.net.ipsec.ike{.system.api.txt}", ":framework-media{.system.api.txt}", ":framework-mediaprovider{.system.api.txt}", ":framework-permission{.system.api.txt}", @@ -142,8 +170,27 @@ genrule { } genrule { + name: "frameworks-base-api-system-current-compat", + srcs: [ + ":android.api.system.latest", + ":android-incompatibilities.api.system.latest", + ":frameworks-base-api-current.txt", + ":frameworks-base-api-system-current.txt", + ], + out: ["stdout.txt"], + tools: ["metalava"], + cmd: "$(location metalava) --no-banner --format=v2 " + + "--check-compatibility:api:released $(location :android.api.system.latest) " + + "--check-compatibility:base $(location :frameworks-base-api-current.txt) " + + "--baseline:compatibility:released $(location :android-incompatibilities.api.system.latest) " + + "$(location :frameworks-base-api-system-current.txt) " + + "> $(genDir)/stdout.txt", +} + +genrule { name: "frameworks-base-api-system-removed.txt", srcs: [ + ":android.net.ipsec.ike{.system.removed-api.txt}", ":framework-media{.system.removed-api.txt}", ":framework-mediaprovider{.system.removed-api.txt}", ":framework-permission{.system.removed-api.txt}", @@ -174,6 +221,7 @@ genrule { genrule { name: "frameworks-base-api-module-lib-current.txt", srcs: [ + ":android.net.ipsec.ike{.module-lib.api.txt}", ":framework-media{.module-lib.api.txt}", ":framework-mediaprovider{.module-lib.api.txt}", ":framework-permission{.module-lib.api.txt}", @@ -201,8 +249,30 @@ genrule { } genrule { + name: "frameworks-base-api-module-lib-current-compat", + srcs: [ + ":android.api.module-lib.latest", + ":android-incompatibilities.api.module-lib.latest", + ":frameworks-base-api-current.txt", + ":frameworks-base-api-module-lib-current.txt", + ], + out: ["stdout.txt"], + tools: ["metalava"], + cmd: "$(location metalava) --no-banner --format=v2 " + + "--check-compatibility:api:released $(location :android.api.module-lib.latest) " + + // Note: having "public" be the base of module-lib is not perfect -- it should + // ideally be a merged public+system), but this will help when migrating from + // MODULE_LIBS -> public. + "--check-compatibility:base $(location :frameworks-base-api-current.txt) " + + "--baseline:compatibility:released $(location :android-incompatibilities.api.module-lib.latest) " + + "$(location :frameworks-base-api-module-lib-current.txt) " + + "> $(genDir)/stdout.txt", +} + +genrule { name: "frameworks-base-api-module-lib-removed.txt", srcs: [ + ":android.net.ipsec.ike{.module-lib.removed-api.txt}", ":framework-media{.module-lib.removed-api.txt}", ":framework-mediaprovider{.module-lib.removed-api.txt}", ":framework-permission{.module-lib.removed-api.txt}", diff --git a/boot/Android.bp b/boot/Android.bp index dd4066a7d151..4f7c44eca818 100644 --- a/boot/Android.bp +++ b/boot/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + boot_image { name: "framework-boot-image", image_name: "boot", diff --git a/cmds/am/Android.bp b/cmds/am/Android.bp index ed73d5596859..7bb9675ede37 100644 --- a/cmds/am/Android.bp +++ b/cmds/am/Android.bp @@ -1,6 +1,23 @@ // Copyright 2008 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_am_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_am_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_host_static { name: "libinstrumentation", srcs: ["**/*.proto"], diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index 14ebb713b6ae..4e5b3bac5713 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_base_cmds_app_process_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_app_process_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_binary { name: "app_process", diff --git a/cmds/appops/Android.bp b/cmds/appops/Android.bp index 9f330fa3bb51..80f8ec679247 100644 --- a/cmds/appops/Android.bp +++ b/cmds/appops/Android.bp @@ -1,5 +1,22 @@ // Copyright 2014 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_base_cmds_appops_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_appops_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + sh_binary { name: "appops", src: "appops", diff --git a/cmds/appwidget/Android.bp b/cmds/appwidget/Android.bp index 487d3e1fc25f..8049038de809 100644 --- a/cmds/appwidget/Android.bp +++ b/cmds/appwidget/Android.bp @@ -1,5 +1,22 @@ // Copyright 2014 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_base_cmds_appwidget_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_appwidget_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "appwidget", wrapper: "appwidget", diff --git a/cmds/backup/Android.bp b/cmds/backup/Android.bp index 287c23b27fbb..5e2a56e6a9cd 100644 --- a/cmds/backup/Android.bp +++ b/cmds/backup/Android.bp @@ -1,5 +1,22 @@ // Copyright 2009 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_base_cmds_backup_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_backup_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_binary { name: "btool", diff --git a/cmds/bmgr/Android.bp b/cmds/bmgr/Android.bp index b64923bcbe1b..14beb5561dba 100644 --- a/cmds/bmgr/Android.bp +++ b/cmds/bmgr/Android.bp @@ -1,6 +1,23 @@ // Copyright 2007 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_bmgr_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_bmgr_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "bmgr", wrapper: "bmgr", diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp index 757c2b2a4cfa..2ecbd75866ec 100644 --- a/cmds/bootanimation/Android.bp +++ b/cmds/bootanimation/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "bootanimation_defaults", diff --git a/cmds/bu/Android.bp b/cmds/bu/Android.bp index 0866ee053107..5b4ec3197cdd 100644 --- a/cmds/bu/Android.bp +++ b/cmds/bu/Android.bp @@ -1,6 +1,23 @@ // Copyright 2011 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_bu_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_bu_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "bu", wrapper: "bu", diff --git a/cmds/content/Android.bp b/cmds/content/Android.bp index 96d14696d0a2..c70d01ec8f0b 100644 --- a/cmds/content/Android.bp +++ b/cmds/content/Android.bp @@ -1,5 +1,22 @@ // Copyright 2012 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_base_cmds_content_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_content_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "content", wrapper: "content", diff --git a/cmds/device_config/Android.bp b/cmds/device_config/Android.bp index 67e014a20506..69572d8690c4 100644 --- a/cmds/device_config/Android.bp +++ b/cmds/device_config/Android.bp @@ -1,6 +1,17 @@ // Copyright 2018 The Android Open Source Project // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + sh_binary { name: "device_config", src: "device_config", diff --git a/cmds/dpm/Android.bp b/cmds/dpm/Android.bp index 753121e6d886..665abcd7314d 100644 --- a/cmds/dpm/Android.bp +++ b/cmds/dpm/Android.bp @@ -1,6 +1,23 @@ // Copyright 2014 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_dpm_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_dpm_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "dpm", wrapper: "dpm", diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp index 54c8bf3ef34c..295c71c65368 100644 --- a/cmds/hid/Android.bp +++ b/cmds/hid/Android.bp @@ -1,6 +1,23 @@ // Copyright 2015 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_hid_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_hid_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "hid", wrapper: "hid", diff --git a/cmds/hid/OWNERS b/cmds/hid/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/cmds/hid/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/cmds/hid/jni/Android.bp b/cmds/hid/jni/Android.bp index 2c07de04b6a7..11d92909e44a 100644 --- a/cmds/hid/jni/Android.bp +++ b/cmds/hid/jni/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_cmds_hid_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_cmds_hid_license"], +} + cc_library_shared { name: "libhidcommand_jni", diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index e21a6b288fb3..5212d8081401 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "idmap2_defaults", tidy: true, @@ -26,10 +35,24 @@ cc_defaults { tidy_checks_as_errors: [ "modernize-*", "-modernize-avoid-c-arrays", + "-modernize-pass-by-value", + "-modernize-replace-disallow-copy-and-assign-macro", + "-modernize-use-equals-default", + "-modernize-use-nodiscard", + "-modernize-use-override", "-modernize-use-trailing-return-type", + "-modernize-use-using", "android-*", "misc-*", + "-misc-non-private-member-variables-in-classes", "readability-*", + "-readability-braces-around-statements", + "-readability-const-return-type", + "-readability-convert-member-functions-to-static", + "-readability-else-after-return", + "-readability-named-parameter", + "-readability-redundant-access-specifiers", + "-readability-uppercase-literal-suffix", ], tidy_flags: [ "-system-headers", @@ -132,9 +155,6 @@ cc_test { "tests/XmlParserTests.cpp", "tests/ZipFileTests.cpp", ], - required: [ - "idmap2", - ], static_libs: ["libgmock"], target: { android: { @@ -163,9 +183,19 @@ cc_test { shared_libs: [ "libz", ], + data: [ + ":libz", + ":idmap2", + ], }, }, - data: ["tests/data/**/*.apk"], + data: [ + "tests/data/**/*.apk", + ], + compile_multilib: "first", + test_options: { + unit_test: true, + }, } cc_binary { diff --git a/cmds/idmap2/AndroidTest.xml b/cmds/idmap2/AndroidTest.xml deleted file mode 100644 index 5147f4e6cb4c..000000000000 --- a/cmds/idmap2/AndroidTest.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> -<configuration description="Config for idmap2_tests"> - <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> - <option name="cleanup" value="true" /> - <option name="push" value="idmap2_tests->/data/local/tmp/idmap2_tests" /> - </target_preparer> - <option name="test-suite-tag" value="idmap2_tests" /> - <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/local/tmp" /> - <option name="module-name" value="idmap2_tests" /> - </test> -</configuration> diff --git a/cmds/ime/Android.bp b/cmds/ime/Android.bp index 76a16c81ca38..6dd3ba1ca7ef 100644 --- a/cmds/ime/Android.bp +++ b/cmds/ime/Android.bp @@ -1,6 +1,23 @@ // Copyright 2007 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_ime_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_ime_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + sh_binary { name: "ime", src: "ime", diff --git a/cmds/incident/Android.bp b/cmds/incident/Android.bp index 94855aa0311f..147885f029c2 100644 --- a/cmds/incident/Android.bp +++ b/cmds/incident/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary { name: "incident", diff --git a/cmds/incident_helper/Android.bp b/cmds/incident_helper/Android.bp index f07743ec2ee6..5b819ebc3dfd 100644 --- a/cmds/incident_helper/Android.bp +++ b/cmds/incident_helper/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary { name: "incident-helper-cmd", wrapper: "incident_helper_cmd", diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp index c47526abad53..b0b23f569664 100644 --- a/cmds/incidentd/Android.bp +++ b/cmds/incidentd/Android.bp @@ -16,6 +16,15 @@ // incidentd // ========= +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary { name: "incidentd", diff --git a/cmds/input/Android.bp b/cmds/input/Android.bp index a0ebde63eb6e..f41a95eb380f 100644 --- a/cmds/input/Android.bp +++ b/cmds/input/Android.bp @@ -1,6 +1,23 @@ // Copyright 2008 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_input_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_input_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "input", wrapper: "input", diff --git a/cmds/interrupter/Android.bp b/cmds/interrupter/Android.bp index d68e7fe37535..d7f744d0834e 100644 --- a/cmds/interrupter/Android.bp +++ b/cmds/interrupter/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "interrupter", host_supported: true, diff --git a/cmds/locksettings/Android.bp b/cmds/locksettings/Android.bp index 59ccc5cd082e..3869c8fcdabc 100644 --- a/cmds/locksettings/Android.bp +++ b/cmds/locksettings/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary { name: "locksettings", wrapper: "locksettings", diff --git a/cmds/pm/Android.bp b/cmds/pm/Android.bp index 0644f6efcb8a..847dbabdf4c0 100644 --- a/cmds/pm/Android.bp +++ b/cmds/pm/Android.bp @@ -1,6 +1,23 @@ // Copyright 2007 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_pm_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_pm_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + sh_binary { name: "pm", src: "pm", diff --git a/cmds/requestsync/Android.bp b/cmds/requestsync/Android.bp index ef2a8a6be3ca..57e8dd355b26 100644 --- a/cmds/requestsync/Android.bp +++ b/cmds/requestsync/Android.bp @@ -1,6 +1,23 @@ // Copyright 2012 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_requestsync_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_requestsync_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "requestsync", wrapper: "requestsync", diff --git a/cmds/screencap/Android.bp b/cmds/screencap/Android.bp index 248c67589696..7b61bef5031c 100644 --- a/cmds/screencap/Android.bp +++ b/cmds/screencap/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary { name: "screencap", diff --git a/cmds/settings/Android.bp b/cmds/settings/Android.bp index 8a78e5420a5f..cc730062f9df 100644 --- a/cmds/settings/Android.bp +++ b/cmds/settings/Android.bp @@ -1,6 +1,17 @@ // Copyright 2011 The Android Open Source Project // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + sh_binary { name: "settings", src: "settings", diff --git a/cmds/sm/Android.bp b/cmds/sm/Android.bp index 11e4e72b435b..ecfacaeecfd9 100644 --- a/cmds/sm/Android.bp +++ b/cmds/sm/Android.bp @@ -1,6 +1,23 @@ // Copyright 2015 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_sm_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_sm_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "sm", wrapper: "sm", diff --git a/cmds/svc/Android.bp b/cmds/svc/Android.bp index 68b48f11e5a6..41a3ebd2f514 100644 --- a/cmds/svc/Android.bp +++ b/cmds/svc/Android.bp @@ -1,6 +1,23 @@ // Copyright 2007 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_svc_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_svc_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "svc", wrapper: "svc", diff --git a/cmds/telecom/Android.bp b/cmds/telecom/Android.bp index 56e147c5c8ca..4da79c54477b 100644 --- a/cmds/telecom/Android.bp +++ b/cmds/telecom/Android.bp @@ -1,6 +1,23 @@ // Copyright 2015 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_telecom_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_telecom_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "telecom", wrapper: "telecom", diff --git a/cmds/uiautomator/Android.bp b/cmds/uiautomator/Android.bp index f9cb3dd38897..a0bf624c6455 100644 --- a/cmds/uiautomator/Android.bp +++ b/cmds/uiautomator/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + genrule { name: "uiautomator-last-released-api", srcs: ["api/*.txt"], diff --git a/cmds/uiautomator/cmds/uiautomator/Android.bp b/cmds/uiautomator/cmds/uiautomator/Android.bp index 68cc5a339107..56e2e70958fa 100644 --- a/cmds/uiautomator/cmds/uiautomator/Android.bp +++ b/cmds/uiautomator/cmds/uiautomator/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary { name: "uiautomator", wrapper: "uiautomator", diff --git a/cmds/uiautomator/instrumentation/Android.bp b/cmds/uiautomator/instrumentation/Android.bp index 477f0d1f6e10..50e223425f14 100644 --- a/cmds/uiautomator/instrumentation/Android.bp +++ b/cmds/uiautomator/instrumentation/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test { name: "uiautomator-instrumentation", diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp index 14b74da0c616..469b45201337 100644 --- a/cmds/uiautomator/library/Android.bp +++ b/cmds/uiautomator/library/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + droidstubs { name: "uiautomator-stubs", srcs: [ diff --git a/cmds/vr/Android.bp b/cmds/vr/Android.bp index cb129bdf6853..893649155fd8 100644 --- a/cmds/vr/Android.bp +++ b/cmds/vr/Android.bp @@ -1,6 +1,23 @@ // Copyright 2017 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_vr_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_vr_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_binary { name: "vr", wrapper: "vr", diff --git a/cmds/wm/Android.bp b/cmds/wm/Android.bp index 609f84b89bd8..cf6b0193fe87 100644 --- a/cmds/wm/Android.bp +++ b/cmds/wm/Android.bp @@ -1,6 +1,23 @@ // Copyright 2013 The Android Open Source Project // +package { + default_applicable_licenses: ["frameworks_base_cmds_wm_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_cmds_wm_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + sh_binary { name: "wm", src: "wm", diff --git a/config/Android.bp b/config/Android.bp index 8dd409b51eee..6a6f848b7d52 100644 --- a/config/Android.bp +++ b/config/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_base_config_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_config_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "copyright-header", + ], +} + filegroup { name: "preloaded-classes-denylist", srcs: ["preloaded-classes-denylist"], diff --git a/core/api/Android.bp b/core/api/Android.bp index 00b901992b90..170febb4f766 100644 --- a/core/api/Android.bp +++ b/core/api/Android.bp @@ -14,6 +14,14 @@ package { default_visibility: ["//visibility:private"], + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], } filegroup { diff --git a/core/api/current.txt b/core/api/current.txt index 976ec5608d5a..cfb503757de1 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -11922,6 +11922,7 @@ package android.content.pm { method public void setAutoRevokePermissionsMode(boolean); method public void setInstallLocation(int); method public void setInstallReason(int); + method public void setInstallScenario(int); method public void setMultiPackage(); method public void setOriginatingUid(int); method public void setOriginatingUri(@Nullable android.net.Uri); @@ -12134,6 +12135,7 @@ package android.content.pm { field public static final String FEATURE_INPUT_METHODS = "android.software.input_methods"; field public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels"; field public static final String FEATURE_IRIS = "android.hardware.biometrics.iris"; + field public static final String FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key"; field public static final String FEATURE_KEYSTORE_LIMITED_USE_KEY = "android.hardware.keystore.limited_use_key"; field public static final String FEATURE_KEYSTORE_SINGLE_USE_KEY = "android.hardware.keystore.single_use_key"; field public static final String FEATURE_LEANBACK = "android.software.leanback"; @@ -12236,6 +12238,10 @@ package android.content.pm { field public static final int INSTALL_REASON_POLICY = 1; // 0x1 field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0 field public static final int INSTALL_REASON_USER = 4; // 0x4 + field public static final int INSTALL_SCENARIO_BULK = 2; // 0x2 + field public static final int INSTALL_SCENARIO_BULK_SECONDARY = 3; // 0x3 + field public static final int INSTALL_SCENARIO_DEFAULT = 0; // 0x0 + field public static final int INSTALL_SCENARIO_FAST = 1; // 0x1 field public static final int MATCH_ALL = 131072; // 0x20000 field public static final int MATCH_APEX = 1073741824; // 0x40000000 field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 @@ -26092,6 +26098,55 @@ package android.net.sip { } +package android.net.vcn { + + public final class VcnConfig implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.Set<android.net.vcn.VcnGatewayConnectionConfig> getGatewayConnectionConfigs(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnConfig> CREATOR; + } + + public static final class VcnConfig.Builder { + ctor public VcnConfig.Builder(@NonNull android.content.Context); + method @NonNull public android.net.vcn.VcnConfig.Builder addGatewayConnectionConfig(@NonNull android.net.vcn.VcnGatewayConnectionConfig); + method @NonNull public android.net.vcn.VcnConfig build(); + } + + public abstract class VcnControlPlaneConfig { + } + + public final class VcnControlPlaneIkeConfig extends android.net.vcn.VcnControlPlaneConfig { + ctor public VcnControlPlaneIkeConfig(@NonNull android.net.ipsec.ike.IkeSessionParams, @NonNull android.net.ipsec.ike.TunnelModeChildSessionParams); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams getChildSessionParams(); + method @NonNull public android.net.ipsec.ike.IkeSessionParams getIkeSessionParams(); + } + + public final class VcnGatewayConnectionConfig { + method @NonNull public int[] getExposedCapabilities(); + method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu(); + method @NonNull public int[] getRequiredUnderlyingCapabilities(); + method @NonNull public long[] getRetryInterval(); + } + + public static final class VcnGatewayConnectionConfig.Builder { + ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addRequiredUnderlyingCapability(int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build(); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeRequiredUnderlyingCapability(int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryInterval(@NonNull long[]); + } + + public class VcnManager { + method @RequiresPermission("carrier privileges") public void clearVcnConfig(@NonNull android.os.ParcelUuid) throws java.io.IOException; + method @RequiresPermission("carrier privileges") public void setVcnConfig(@NonNull android.os.ParcelUuid, @NonNull android.net.vcn.VcnConfig) throws java.io.IOException; + } + +} + package android.nfc { public class FormatException extends java.lang.Exception { @@ -29604,8 +29659,8 @@ package android.os { } public final class BugreportManager { - method public void cancelBugreport(); - method public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback); + method @WorkerThread public void cancelBugreport(); + method @WorkerThread public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback); } public abstract static class BugreportManager.BugreportCallback { @@ -34350,30 +34405,18 @@ package android.provider { public static final class SimPhonebookContract.SimRecords { method @NonNull public static android.net.Uri getContentUri(int, int); + method @WorkerThread public static int getEncodedNameLength(@NonNull android.content.ContentResolver, @NonNull String); method @NonNull public static android.net.Uri getItemUri(int, int, int); - method @NonNull @WorkerThread public static android.provider.SimPhonebookContract.SimRecords.NameValidationResult validateName(@NonNull android.content.ContentResolver, int, int, @NonNull String); field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sim-contact_v2"; field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/sim-contact_v2"; field public static final String ELEMENTARY_FILE_TYPE = "elementary_file_type"; + field public static final int ERROR_NAME_UNSUPPORTED = -1; // 0xffffffff field public static final String NAME = "name"; field public static final String PHONE_NUMBER = "phone_number"; field public static final String RECORD_NUMBER = "record_number"; field public static final String SUBSCRIPTION_ID = "subscription_id"; } - public static final class SimPhonebookContract.SimRecords.NameValidationResult implements android.os.Parcelable { - ctor public SimPhonebookContract.SimRecords.NameValidationResult(@NonNull String, @NonNull String, int, int); - method public int describeContents(); - method public int getEncodedLength(); - method public int getMaxEncodedLength(); - method @NonNull public String getName(); - method @NonNull public String getSanitizedName(); - method public boolean isSupportedCharacter(int); - method public boolean isValid(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.provider.SimPhonebookContract.SimRecords.NameValidationResult> CREATOR; - } - public class SyncStateContract { ctor public SyncStateContract(); } @@ -35970,6 +36013,19 @@ package android.se.omapi { package android.security { + public final class AppUriAuthenticationPolicy implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.Map<java.lang.String,java.util.Map<android.net.Uri,java.lang.String>> getAppAndUriMappings(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.security.AppUriAuthenticationPolicy> CREATOR; + } + + public static final class AppUriAuthenticationPolicy.Builder { + ctor public AppUriAuthenticationPolicy.Builder(); + method @NonNull public android.security.AppUriAuthenticationPolicy.Builder addAppAndUriMapping(@NonNull String, @NonNull android.net.Uri, @NonNull String); + method @NonNull public android.security.AppUriAuthenticationPolicy build(); + } + public final class AttestedKeyPair { ctor public AttestedKeyPair(@Nullable java.security.KeyPair, @NonNull java.util.List<java.security.cert.Certificate>); method @NonNull public java.util.List<java.security.cert.Certificate> getAttestationRecord(); @@ -36017,6 +36073,7 @@ package android.security { method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable String, int, @Nullable String); method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable android.net.Uri, @Nullable String); method @NonNull public static android.content.Intent createInstallIntent(); + method @NonNull public static android.content.Intent createManageCredentialsIntent(@NonNull android.security.AppUriAuthenticationPolicy); method @Nullable @WorkerThread public static java.security.cert.X509Certificate[] getCertificateChain(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException; method @Nullable @WorkerThread public static java.security.PrivateKey getPrivateKey(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException; method @Deprecated public static boolean isBoundKeyAlgorithm(@NonNull String); @@ -36243,6 +36300,7 @@ package android.security.keystore { public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec { method @Nullable public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec(); + method @Nullable public String getAttestKeyAlias(); method public byte[] getAttestationChallenge(); method @NonNull public String[] getBlockModes(); method @NonNull public java.util.Date getCertificateNotAfter(); @@ -36277,6 +36335,7 @@ package android.security.keystore { ctor public KeyGenParameterSpec.Builder(@NonNull String, int); method @NonNull public android.security.keystore.KeyGenParameterSpec build(); method public android.security.keystore.KeyGenParameterSpec.Builder setAlgorithmParameterSpec(@NonNull java.security.spec.AlgorithmParameterSpec); + method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestKeyAlias(@Nullable String); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestationChallenge(byte[]); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setBlockModes(java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateNotAfter(@NonNull java.util.Date); @@ -36374,6 +36433,7 @@ package android.security.keystore { field public static final int ORIGIN_SECURELY_IMPORTED = 8; // 0x8 field public static final int ORIGIN_UNKNOWN = 4; // 0x4 field public static final int PURPOSE_AGREE_KEY = 64; // 0x40 + field public static final int PURPOSE_ATTEST_KEY = 128; // 0x80 field public static final int PURPOSE_DECRYPT = 2; // 0x2 field public static final int PURPOSE_ENCRYPT = 1; // 0x1 field public static final int PURPOSE_SIGN = 4; // 0x4 @@ -41974,7 +42034,11 @@ package android.telephony.ims { } public class ImsRcsManager { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter(); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_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"; } @@ -42162,6 +42226,15 @@ package android.telephony.ims { field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 } + public final class ImsRegistrationAttributes implements android.os.Parcelable { + method public int describeContents(); + method public int getAttributeFlags(); + method @NonNull public java.util.Set<java.lang.String> getFeatureTags(); + method public int getTransportType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsRegistrationAttributes> CREATOR; + } + public class RcsUceAdapter { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException; } @@ -42178,8 +42251,10 @@ package android.telephony.ims { public static class RegistrationManager.RegistrationCallback { ctor public RegistrationManager.RegistrationCallback(); - method public void onRegistered(int); - method public void onRegistering(int); + method @Deprecated public void onRegistered(int); + method public void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes); + method @Deprecated public void onRegistering(int); + method public void onRegistering(@NonNull android.telephony.ims.ImsRegistrationAttributes); method public void onTechnologyChangeFailed(int, @NonNull android.telephony.ims.ImsReasonInfo); method public void onUnregistered(@NonNull android.telephony.ims.ImsReasonInfo); } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index ab9799ff6272..374c1c74d8e5 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -15,6 +15,7 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); } @@ -35,6 +36,14 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } + public class NetworkWatchlistManager { + method @Nullable public byte[] getWatchlistConfigHash(); + } + + public final class Proxy { + method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo); + } + public final class TcpRepairWindow { ctor public TcpRepairWindow(int, int, int, int, int, int); field public final int maxWindow; @@ -59,6 +68,7 @@ package android.net { method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>); method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder); method public void teardownTestNetwork(@NonNull android.net.Network); + field public static final String TEST_TAP_PREFIX = "testtap"; } public final class UnderlyingNetworkInfo implements android.os.Parcelable { @@ -71,6 +81,14 @@ package android.net { field @NonNull public final java.util.List<java.lang.String> underlyingIfaces; } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { + ctor public VpnTransportInfo(int); + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR; + field public final int type; + } + } package android.os { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 5fb898a282a8..7f0578aec671 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -74,6 +74,7 @@ package android { field public static final String CONTROL_DISPLAY_SATURATION = "android.permission.CONTROL_DISPLAY_SATURATION"; field public static final String CONTROL_INCALL_EXPERIENCE = "android.permission.CONTROL_INCALL_EXPERIENCE"; field public static final String CONTROL_KEYGUARD_SECURE_NOTIFICATIONS = "android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"; + field public static final String CONTROL_OEM_PAID_NETWORK_PREFERENCE = "android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE"; field public static final String CONTROL_VPN = "android.permission.CONTROL_VPN"; field public static final String CREATE_USERS = "android.permission.CREATE_USERS"; field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER"; @@ -238,6 +239,7 @@ package android { field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS"; field public static final String USER_ACTIVITY = "android.permission.USER_ACTIVITY"; field public static final String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK"; + field public static final String UWB_PRIVILEGED = "android.permission.UWB_PRIVILEGED"; field public static final String WHITELIST_AUTO_REVOKE_PERMISSIONS = "android.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS"; field public static final String WHITELIST_RESTRICTED_PERMISSIONS = "android.permission.WHITELIST_RESTRICTED_PERMISSIONS"; field public static final String WIFI_ACCESS_COEX_UNSAFE_CHANNELS = "android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS"; @@ -1544,6 +1546,10 @@ package android.bluetooth { field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; } + public final class BluetoothMapClient implements android.bluetooth.BluetoothProfile { + method @RequiresPermission(android.Manifest.permission.SEND_SMS) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent); + } + public final class BluetoothPan implements android.bluetooth.BluetoothProfile { method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); @@ -1576,6 +1582,7 @@ package android.bluetooth { field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0 field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff field public static final int HEADSET_CLIENT = 16; // 0x10 + field public static final int MAP_CLIENT = 18; // 0x12 field public static final int PAN = 5; // 0x5 field public static final int PBAP_CLIENT = 17; // 0x11 field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0 @@ -6006,11 +6013,15 @@ package android.net { method public long getExpiryTimeMillis(); method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); + method public int getUserPortalUrlSource(); method @Nullable public String getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); + method public int getVenueInfoUrlSource(); method public boolean isCaptive(); method public boolean isSessionExtendable(); method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0 + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1 field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR; } @@ -6024,8 +6035,10 @@ package android.net { method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long); method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); } public class ConnectivityManager { @@ -6039,6 +6052,7 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); @@ -6060,6 +6074,10 @@ package android.net { field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd } + public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { + method public void onComplete(); + } + @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); method @Deprecated public void onTetheringFailed(); @@ -6144,6 +6162,7 @@ package android.net { method public void close(); method @NonNull public String getInterfaceName(); method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void setUnderlyingNetwork(@NonNull android.net.Network) throws java.io.IOException; } public static class IpSecTransform.Builder { @@ -6287,6 +6306,7 @@ package android.net { method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); + method public boolean isPrivateDnsBroken(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 @@ -6301,6 +6321,7 @@ package android.net { method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder clearAll(); method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); @@ -6416,6 +6437,26 @@ package android.net { ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long); } + public final class OemNetworkPreferences implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getNetworkPreferences(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.OemNetworkPreferences> CREATOR; + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; // 0x1 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; // 0x2 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; // 0x3 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; // 0x4 + field public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; // 0x0 + } + + public static final class OemNetworkPreferences.Builder { + ctor public OemNetworkPreferences.Builder(); + ctor public OemNetworkPreferences.Builder(@NonNull android.net.OemNetworkPreferences); + method @NonNull public android.net.OemNetworkPreferences.Builder addNetworkPreference(@NonNull String, int); + method @NonNull public android.net.OemNetworkPreferences build(); + method @NonNull public android.net.OemNetworkPreferences.Builder clearNetworkPreference(@NonNull String); + } + public abstract class QosCallback { ctor public QosCallback(); method public void onError(@NonNull android.net.QosCallbackException); @@ -6809,6 +6850,28 @@ package android.net.util { } +package android.net.vcn { + + public class VcnManager { + method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.vcn.VcnNetworkPolicyResult applyVcnNetworkPolicy(@NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties); + method public void removeVcnNetworkPolicyListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener); + } + + public static interface VcnManager.VcnNetworkPolicyListener { + method public void onPolicyChanged(); + } + + public final class VcnNetworkPolicyResult implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public boolean isTeardownRequested(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnNetworkPolicyResult> CREATOR; + } + +} + package android.net.wifi { public final class WifiMigration { @@ -7149,7 +7212,7 @@ package android.os { public final class BugreportManager { method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence); - method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback); + method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback); } public final class BugreportParams { @@ -7504,6 +7567,7 @@ package android.os { public class SystemConfigManager { method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + method @NonNull @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public int[] getSystemPermissionUids(@NonNull String); } public class SystemProperties { @@ -8292,22 +8356,8 @@ package android.provider { method @RequiresPermission(android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, boolean); } - public final class SimPhonebookContract { - method @NonNull public static String getEfUriPath(int); - field public static final String SUBSCRIPTION_ID_PATH_SEGMENT = "subid"; - } - - public static final class SimPhonebookContract.ElementaryFiles { - field public static final String EF_ADN_PATH_SEGMENT = "adn"; - field public static final String EF_FDN_PATH_SEGMENT = "fdn"; - field public static final String EF_SDN_PATH_SEGMENT = "sdn"; - field public static final String ELEMENTARY_FILES_PATH_SEGMENT = "elementary_files"; - } - public static final class SimPhonebookContract.SimRecords { - field public static final String EXTRA_NAME_VALIDATION_RESULT = "android.provider.extra.NAME_VALIDATION_RESULT"; field public static final String QUERY_ARG_PIN2 = "android:query-arg-pin2"; - field public static final String VALIDATE_NAME_PATH_SEGMENT = "validate_name"; } public static final class Telephony.Carriers implements android.provider.BaseColumns { @@ -8429,10 +8479,12 @@ package android.security.keystore { } public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec { + method @Nullable public int[] getAttestationIds(); method public int getNamespace(); } public static final class KeyGenParameterSpec.Builder { + method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestationIds(@NonNull int[]); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setNamespace(int); method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int); } @@ -10730,35 +10782,6 @@ package android.telephony.cdma { package android.telephony.data { - public final class ApnThrottleStatus implements android.os.Parcelable { - method public int describeContents(); - method public int getApnType(); - method public int getRetryType(); - method public int getSlotIndex(); - method public long getThrottleExpiryTimeMillis(); - method public int getThrottleType(); - method public int getTransportType(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.ApnThrottleStatus> CREATOR; - field public static final int RETRY_TYPE_HANDOVER = 3; // 0x3 - field public static final int RETRY_TYPE_NEW_CONNECTION = 2; // 0x2 - field public static final int RETRY_TYPE_NONE = 1; // 0x1 - field public static final int THROTTLE_TYPE_ELAPSED_TIME = 2; // 0x2 - field public static final int THROTTLE_TYPE_NONE = 1; // 0x1 - } - - public static final class ApnThrottleStatus.Builder { - ctor public ApnThrottleStatus.Builder(); - method @NonNull public android.telephony.data.ApnThrottleStatus build(); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setApnType(int); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setNoThrottle(); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setRetryType(int); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setSlotIndex(int); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setThrottleExpiryTimeMillis(long); - method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setTransportType(int); - field public static final long NO_THROTTLE_EXPIRY_TIME = -1L; // 0xffffffffffffffffL - } - public final class DataCallResponse implements android.os.Parcelable { method public int describeContents(); method @NonNull public java.util.List<android.net.LinkAddress> getAddresses(); @@ -10928,7 +10951,7 @@ package android.telephony.data { ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int); method public abstract void close(); method public final int getSlotIndex(); - method public void reportApnThrottleStatusChanged(@NonNull java.util.List<android.telephony.data.ApnThrottleStatus>); + method public void reportThrottleStatusChanged(@NonNull java.util.List<android.telephony.data.ThrottleStatus>); method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>); } @@ -10958,6 +10981,34 @@ package android.telephony.data { method @NonNull public android.telephony.data.SliceInfo.Builder setSliceServiceType(int); } + public final class ThrottleStatus implements android.os.Parcelable { + method public int describeContents(); + method public int getApnType(); + method public int getRetryType(); + method public int getSlotIndex(); + method public long getThrottleExpiryTimeMillis(); + method public int getThrottleType(); + method public int getTransportType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.ThrottleStatus> CREATOR; + field public static final int RETRY_TYPE_HANDOVER = 3; // 0x3 + field public static final int RETRY_TYPE_NEW_CONNECTION = 2; // 0x2 + field public static final int RETRY_TYPE_NONE = 1; // 0x1 + field public static final int THROTTLE_TYPE_ELAPSED_TIME = 2; // 0x2 + field public static final int THROTTLE_TYPE_NONE = 1; // 0x1 + } + + public static final class ThrottleStatus.Builder { + ctor public ThrottleStatus.Builder(); + method @NonNull public android.telephony.data.ThrottleStatus build(); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setApnType(int); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setNoThrottle(); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setRetryType(int); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setSlotIndex(int); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setThrottleExpiryTimeMillis(long); + method @NonNull public android.telephony.data.ThrottleStatus.Builder setTransportType(int); + } + } package android.telephony.euicc { @@ -11545,12 +11596,35 @@ package android.telephony.ims { @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); + method @Deprecated public void onRegistered(int); + method @Deprecated public void onRegistering(int); + } + + public class ImsRcsManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addOnAvailabilityChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsRcsManager.OnAvailabilityChangedListener) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeOnAvailabilityChangedListener(@NonNull android.telephony.ims.ImsRcsManager.OnAvailabilityChangedListener); + } + + public static interface ImsRcsManager.OnAvailabilityChangedListener { + method public void onAvailabilityChanged(int); } public final class ImsReasonInfo implements android.os.Parcelable { field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; } + public final class ImsRegistrationAttributes implements android.os.Parcelable { + method public int getRegistrationTechnology(); + } + + public static final class ImsRegistrationAttributes.Builder { + ctor public ImsRegistrationAttributes.Builder(int); + method @NonNull public android.telephony.ims.ImsRegistrationAttributes build(); + method @NonNull public android.telephony.ims.ImsRegistrationAttributes.Builder setFeatureTags(@NonNull java.util.Set<java.lang.String>); + } + public class ImsService extends android.app.Service { ctor public ImsService(); method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); @@ -12187,20 +12261,39 @@ package android.telephony.ims.feature { ctor public RcsFeature(@NonNull java.util.concurrent.Executor); method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener); + method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities); method public void onFeatureReady(); method public void onFeatureRemoved(); + method public boolean queryCapabilityConfiguration(int, int); + method @NonNull public final android.telephony.ims.feature.RcsFeature.RcsImsCapabilities queryCapabilityStatus(); method public void removeCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase); } + public static class RcsFeature.RcsImsCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities { + ctor public RcsFeature.RcsImsCapabilities(int); + method public void addCapabilities(int); + method public boolean isCapable(int); + method public void removeCapabilities(int); + field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 + field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 + field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 + } + } package android.telephony.ims.stub { public interface CapabilityExchangeEventListener { + method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException; method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException; method public void onUnpublish() throws android.telephony.ims.ImsException; } + public static interface CapabilityExchangeEventListener.OptionsRequestCallback { + method public default void onRespondToCapabilityRequest(@NonNull android.telephony.ims.RcsContactUceCapability, boolean); + method public void onRespondToCapabilityRequestWithError(@IntRange(from=100, to=699) int, @NonNull String); + } + public interface DelegateConnectionMessageCallback { method public void onMessageReceived(@NonNull android.telephony.ims.SipMessage); method public void onMessageSendFailure(@NonNull String, int); @@ -12321,7 +12414,9 @@ package android.telephony.ims.stub { ctor public ImsRegistrationImplBase(); method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); method public final void onRegistered(int); + method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes); method public final void onRegistering(int); + method public final void onRegistering(@NonNull android.telephony.ims.ImsRegistrationAttributes); method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]); method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String); @@ -12384,6 +12479,7 @@ package android.telephony.ims.stub { public class RcsCapabilityExchangeImplBase { ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor); method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback); + method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback); method public void subscribeForCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback); field public static final int COMMAND_CODE_FETCH_ERROR = 3; // 0x3 field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1 @@ -12398,6 +12494,11 @@ package android.telephony.ims.stub { field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0 } + public static interface RcsCapabilityExchangeImplBase.OptionsResponseCallback { + method public void onCommandError(int) throws android.telephony.ims.ImsException; + method public void onNetworkResponse(int, @NonNull String, @NonNull java.util.List<java.lang.String>) throws android.telephony.ims.ImsException; + } + public static interface RcsCapabilityExchangeImplBase.PublishResponseCallback { method public void onCommandError(int) throws android.telephony.ims.ImsException; method public void onNetworkResponse(@IntRange(from=100, to=699) int, @NonNull String) throws android.telephony.ims.ImsException; @@ -12634,10 +12735,10 @@ package android.uwb { } public final class RangingSession implements java.lang.AutoCloseable { - method public void close(); - method public void reconfigure(@NonNull android.os.PersistableBundle); - method public void start(@NonNull android.os.PersistableBundle); - method public void stop(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void close(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void reconfigure(@NonNull android.os.PersistableBundle); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void start(@NonNull android.os.PersistableBundle); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void stop(); } public static interface RangingSession.Callback { @@ -12673,18 +12774,18 @@ package android.uwb { } public final class UwbManager { - method public long elapsedRealtimeResolutionNanos(); - method public int getAngleOfArrivalSupport(); - method public int getMaxRemoteDevicesPerInitiatorSession(); - method public int getMaxRemoteDevicesPerResponderSession(); - method public int getMaxSimultaneousSessions(); - method @NonNull public android.os.PersistableBundle getSpecificationInfo(); - method @NonNull public java.util.List<java.lang.Integer> getSupportedChannelNumbers(); - method @NonNull public java.util.Set<java.lang.Integer> getSupportedPreambleCodeIndices(); - method public boolean isRangingSupported(); - method @NonNull public AutoCloseable openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback); - method public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback); - method public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getAngleOfArrivalSupport(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerInitiatorSession(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerResponderSession(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxSimultaneousSessions(); + method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo(); + method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.List<java.lang.Integer> getSupportedChannelNumbers(); + method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.Set<java.lang.Integer> getSupportedPreambleCodeIndices(); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public boolean isRangingSupported(); + method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public AutoCloseable openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback); + method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback); field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2; // 0x2 field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3; // 0x3 field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4; // 0x4 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 668b5883cbfb..68721418b407 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -12,6 +12,7 @@ package android { field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"; field public static final String CONTROL_DEVICE_LIGHTS = "android.permission.CONTROL_DEVICE_LIGHTS"; field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; + field public static final String KEEP_UNINSTALLED_PACKAGES = "android.permission.KEEP_UNINSTALLED_PACKAGES"; field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; @@ -989,6 +990,12 @@ package android.net { field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0 } + public class NetworkPolicyManager { + method public boolean getRestrictBackground(); + method @NonNull public static String resolveNetworkId(@NonNull android.net.wifi.WifiConfiguration); + method public void setRestrictBackground(boolean); + } + public class NetworkStack { method public static void setServiceForTest(@Nullable android.os.IBinder); } diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt index f5ab40abdf37..b3636b9b765d 100644 --- a/core/api/test-lint-baseline.txt +++ b/core/api/test-lint-baseline.txt @@ -483,6 +483,8 @@ GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored(): GetterSetterNames: android.location.LocationRequest#isLowPowerMode(): +GetterSetterNames: android.net.NetworkPolicyManager#getRestrictBackground(): + Symmetric method for `setRestrictBackground` must be named `isRestrictBackground`; was `getRestrictBackground` GetterSetterNames: android.os.IncidentReportArgs#isAll(): GetterSetterNames: android.service.notification.NotificationStats#setDirectReplied(): diff --git a/core/java/Android.bp b/core/java/Android.bp index af5df769ffad..2fdf9c146ff6 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-BSD + // legacy_unencumbered + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "IKeyAttestationApplicationIdProvider.aidl", srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"], diff --git a/core/java/android/accounts/OWNERS b/core/java/android/accounts/OWNERS index ea5fd36702f9..8dcc04a27af6 100644 --- a/core/java/android/accounts/OWNERS +++ b/core/java/android/accounts/OWNERS @@ -3,7 +3,6 @@ dementyev@google.com sandrakwan@google.com hackbod@google.com svetoslavganov@google.com -moltmann@google.com fkupolov@google.com yamasani@google.com omakoto@google.com diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index bfde2d5d3d29..b99d5cd13a77 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -88,7 +88,6 @@ import android.graphics.ImageDecoder; import android.hardware.display.DisplayManagerGlobal; import android.inputmethodservice.InputMethodService; import android.net.ConnectivityManager; -import android.net.IConnectivityManager; import android.net.Proxy; import android.net.Uri; import android.os.AsyncTask; @@ -6546,25 +6545,6 @@ public final class ActivityThread extends ClientTransactionHandler { HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE); HardwareRenderer.setPackageName(data.appInfo.packageName); - /** - * Initialize the default http proxy in this process for the reasons we set the time zone. - */ - Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies"); - final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - if (b != null) { - // In pre-boot mode (doing initial launch to collect password), not - // all system is up. This includes the connectivity service, so don't - // crash if we can't get it. - final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); - try { - Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null)); - } catch (RemoteException e) { - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - throw e.rethrowFromSystemServer(); - } - } - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - // Instrumentation info affects the class loader, so load it before // setting up the app context. final InstrumentationInfo ii; @@ -6603,6 +6583,23 @@ public final class ActivityThread extends ClientTransactionHandler { updateLocaleListFromAppContext(appContext, mResourcesManager.getConfiguration().getLocales()); + // Initialize the default http proxy in this process. + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies"); + try { + // In pre-boot mode (doing initial launch to collect password), not all system is up. + // This includes the connectivity service, so trying to obtain ConnectivityManager at + // that point would return null. Check whether the ConnectivityService is available, and + // avoid crashing with a NullPointerException if it is not. + final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + if (b != null) { + final ConnectivityManager cm = + appContext.getSystemService(ConnectivityManager.class); + Proxy.setHttpProxyConfiguration(cm.getDefaultProxy()); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + if (!Process.isIsolated()) { final int oldMask = StrictMode.allowThreadDiskWritesMask(); try { @@ -7429,8 +7426,8 @@ public final class ActivityThread extends ClientTransactionHandler { } public static void updateHttpProxy(@NonNull Context context) { - final ConnectivityManager cm = ConnectivityManager.from(context); - Proxy.setHttpProxySystemProperty(cm.getDefaultProxy()); + final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); + Proxy.setHttpProxyConfiguration(cm.getDefaultProxy()); } @UnsupportedAppUsage diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 31ab2248236d..797253af394b 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1136,9 +1136,16 @@ public class AppOpsManager { // TODO: Add as AppProtoEnums public static final int OP_RECORD_AUDIO_HOTWORD = 102; + /** + * Manage credentials in the system KeyChain. + * + * @hide + */ + public static final int OP_MANAGE_CREDENTIALS = AppProtoEnums.APP_OP_MANAGE_CREDENTIALS; + /** @hide */ @UnsupportedAppUsage - public static final int _NUM_OP = 104; + public static final int _NUM_OP = 105; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -1485,6 +1492,13 @@ public class AppOpsManager { */ public static final String OPSTR_RECORD_AUDIO_HOTWORD = "android:record_audio_hotword"; + /** + * Manage credentials in the system KeyChain. + * + * @hide + */ + public static final String OPSTR_MANAGE_CREDENTIALS = "android:manage_credentials"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -1679,6 +1693,7 @@ public class AppOpsManager { OP_PHONE_CALL_CAMERA, // OP_PHONE_CALL_CAMERA OP_RECORD_AUDIO_HOTWORD, // RECORD_AUDIO_HOTWORD OP_MANAGE_ONGOING_CALLS, // MANAGE_ONGOING_CALLS + OP_MANAGE_CREDENTIALS, // MANAGE_CREDENTIALS }; /** @@ -1789,6 +1804,7 @@ public class AppOpsManager { OPSTR_PHONE_CALL_CAMERA, OPSTR_RECORD_AUDIO_HOTWORD, OPSTR_MANAGE_ONGOING_CALLS, + OPSTR_MANAGE_CREDENTIALS, }; /** @@ -1900,6 +1916,7 @@ public class AppOpsManager { "PHONE_CALL_CAMERA", "RECORD_AUDIO_HOTWORD", "MANAGE_ONGOING_CALLS", + "MANAGE_CREDENTIALS", }; /** @@ -2012,6 +2029,7 @@ public class AppOpsManager { null, // no permission for OP_PHONE_CALL_CAMERA null, // no permission for OP_RECORD_AUDIO_HOTWORD Manifest.permission.MANAGE_ONGOING_CALLS, + null, // no permission for OP_MANAGE_CREDENTIALS }; /** @@ -2124,6 +2142,7 @@ public class AppOpsManager { null, // PHONE_CALL_MICROPHONE null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS + null, // MANAGE_CREDENTIALS }; /** @@ -2235,6 +2254,7 @@ public class AppOpsManager { null, // PHONE_CALL_CAMERA null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS + null, // MANAGE_CREDENTIALS }; /** @@ -2345,6 +2365,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // PHONE_CALL_CAMERA AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS + AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS }; /** @@ -2459,6 +2480,7 @@ public class AppOpsManager { false, // PHONE_CALL_CAMERA false, // RECORD_AUDIO_HOTWORD true, // MANAGE_ONGOING_CALLS + false, // MANAGE_CREDENTIALS }; /** diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index 69d5c8d0d2ff..854f5a4ab724 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -428,6 +428,13 @@ public final class ApplicationExitInfo implements Parcelable { */ private IAppTraceRetriever mAppTraceRetriever; + /** + * ParcelFileDescriptor pointing to a native tombstone. + * + * @see #getTraceInputStream + */ + private IParcelFileDescriptorRetriever mNativeTombstoneRetriever; + /** @hide */ @IntDef(prefix = { "REASON_" }, value = { REASON_UNKNOWN, @@ -603,22 +610,38 @@ public final class ApplicationExitInfo implements Parcelable { * prior to the death of the process; typically it'll be available when * the reason is {@link #REASON_ANR}, though if the process gets an ANR * but recovers, and dies for another reason later, this trace will be included - * in the record of {@link ApplicationExitInfo} still. + * in the record of {@link ApplicationExitInfo} still. Beginning with API 31, + * tombstone traces will be returned for + * {@link #REASON_CRASH_NATIVE}, with an InputStream containing a protobuf with + * <a href="https://android.googlesource.com/platform/system/core/+/refs/heads/master/debuggerd/proto/tombstone.proto">this schema</a>. + * Note thatbecause these traces are kept in a separate global circular buffer, crashes may be + * overwritten by newer crashes (including from other applications), so this may still return + * null. * * @return The input stream to the traces that was taken by the system * prior to the death of the process. */ public @Nullable InputStream getTraceInputStream() throws IOException { - if (mAppTraceRetriever == null) { + if (mAppTraceRetriever == null && mNativeTombstoneRetriever == null) { return null; } + try { - final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor( - mPackageName, mPackageUid, mPid); - if (fd == null) { - return null; + if (mNativeTombstoneRetriever != null) { + final ParcelFileDescriptor pfd = mNativeTombstoneRetriever.getPfd(); + if (pfd == null) { + return null; + } + + return new ParcelFileDescriptor.AutoCloseInputStream(pfd); + } else { + final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor( + mPackageName, mPackageUid, mPid); + if (fd == null) { + return null; + } + return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd)); } - return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd)); } catch (RemoteException e) { return null; } @@ -849,6 +872,15 @@ public final class ApplicationExitInfo implements Parcelable { mAppTraceRetriever = retriever; } + /** + * @see mNativeTombstoneRetriever + * + * @hide + */ + public void setNativeTombstoneRetriever(final IParcelFileDescriptorRetriever retriever) { + mNativeTombstoneRetriever = retriever; + } + @Override public int describeContents() { return 0; @@ -878,6 +910,12 @@ public final class ApplicationExitInfo implements Parcelable { } else { dest.writeInt(0); } + if (mNativeTombstoneRetriever != null) { + dest.writeInt(1); + dest.writeStrongBinder(mNativeTombstoneRetriever.asBinder()); + } else { + dest.writeInt(0); + } } /** @hide */ @@ -906,6 +944,7 @@ public final class ApplicationExitInfo implements Parcelable { mState = other.mState; mTraceFile = other.mTraceFile; mAppTraceRetriever = other.mAppTraceRetriever; + mNativeTombstoneRetriever = other.mNativeTombstoneRetriever; } private ApplicationExitInfo(@NonNull Parcel in) { @@ -928,6 +967,10 @@ public final class ApplicationExitInfo implements Parcelable { if (in.readInt() == 1) { mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder()); } + if (in.readInt() == 1) { + mNativeTombstoneRetriever = IParcelFileDescriptorRetriever.Stub.asInterface( + in.readStrongBinder()); + } } public @NonNull static final Creator<ApplicationExitInfo> CREATOR = @@ -986,6 +1029,7 @@ public final class ApplicationExitInfo implements Parcelable { sb.append(" state=").append(ArrayUtils.isEmpty(mState) ? "empty" : Integer.toString(mState.length) + " bytes"); sb.append(" trace=").append(mTraceFile); + return sb.toString(); } diff --git a/core/java/android/app/IParcelFileDescriptorRetriever.aidl b/core/java/android/app/IParcelFileDescriptorRetriever.aidl new file mode 100644 index 000000000000..7e808e74bd5d --- /dev/null +++ b/core/java/android/app/IParcelFileDescriptorRetriever.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.os.ParcelFileDescriptor; + +/** + * An interface used to lazily provide a ParcelFileDescriptor to apps. + * + * @hide + */ +interface IParcelFileDescriptorRetriever { + /** + * Retrieve the ParcelFileDescriptor. + */ + ParcelFileDescriptor getPfd(); +} diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index d151526612f0..d7eded201740 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -116,11 +116,13 @@ import android.net.EthernetManager; import android.net.IEthernetManager; import android.net.IIpSecService; import android.net.INetworkPolicyManager; +import android.net.IVpnManager; import android.net.IpSecManager; import android.net.NetworkPolicyManager; import android.net.NetworkScoreManager; import android.net.NetworkWatchlistManager; import android.net.TetheringManager; +import android.net.VpnManager; import android.net.lowpan.ILowpanManager; import android.net.lowpan.LowpanManager; import android.net.nsd.INsdManager; @@ -358,6 +360,15 @@ public final class SystemServiceRegistry { ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE)); }}); + registerService(Context.VPN_MANAGEMENT_SERVICE, VpnManager.class, + new CachedServiceFetcher<VpnManager>() { + @Override + public VpnManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE); + IVpnManager service = IVpnManager.Stub.asInterface(b); + return new VpnManager(ctx, service); + }}); + registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class, new CachedServiceFetcher<VcnManager>() { @Override diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java index 28b73406b877..ab38832458d6 100644 --- a/core/java/android/app/compat/CompatChanges.java +++ b/core/java/android/app/compat/CompatChanges.java @@ -20,8 +20,16 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.Compatibility; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; +import com.android.internal.compat.CompatibilityOverrideConfig; +import com.android.internal.compat.IPlatformCompat; + +import java.util.Map; + /** * CompatChanges APIs - to be used by platform code only (including mainline * modules). @@ -89,4 +97,25 @@ public final class CompatChanges { return QUERY_CACHE.query(ChangeIdStateQuery.byUid(changeId, uid)); } + /** + * Set an app compat override for a given package. This will check whether the caller is allowed + * to perform this operation on the given apk and build. Only the installer package is allowed + * to set overrides on a non-debuggable final build and a non-test apk. + * + * @param packageName The package name of the app in question. + * @param overrides A map from changeId to the override applied for this change id. + * @hide + */ + @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG) + public static void setPackageOverride(String packageName, + Map<Long, PackageOverride> overrides) { + IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface( + ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides); + try { + platformCompat.setOverridesFromInstaller(config, packageName); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/compat/OWNERS b/core/java/android/app/compat/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/core/java/android/app/compat/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/core/java/android/app/compat/PackageOverride.java b/core/java/android/app/compat/PackageOverride.java new file mode 100644 index 000000000000..9f97cd41128a --- /dev/null +++ b/core/java/android/app/compat/PackageOverride.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.compat; + +import android.annotation.IntDef; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * An app compat override applied to a given package and change id pairing. + * + * A package override contains a list of version ranges with the desired boolean value of + * the override for the app in this version range. Ranges can be open ended in either direction. + * An instance of PackageOverride gets created via {@link Builder} and is immutable once created. + * + * @hide + */ +public class PackageOverride implements Parcelable { + + @IntDef({ + VALUE_UNDEFINED, + VALUE_ENABLED, + VALUE_DISABLED + }) + @Retention(RetentionPolicy.SOURCE) + /** @hide */ + public @interface EvaluatedOverride { + } + + /** + * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that + * this PackageOverride does not define the value of the override for the given version. + * @hide + */ + public static final int VALUE_UNDEFINED = 0; + /** + * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that + * the override evaluates to {@code true} for the given version. + * @hide + */ + public static final int VALUE_ENABLED = 1; + /** + * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that + * the override evaluates to {@code fakse} for the given version. + * @hide + */ + public static final int VALUE_DISABLED = 2; + + private final long mMinVersionCode; + private final long mMaxVersionCode; + private final boolean mEnabled; + + private PackageOverride(long minVersionCode, + long maxVersionCode, + boolean enabled) { + this.mMinVersionCode = minVersionCode; + this.mMaxVersionCode = maxVersionCode; + this.mEnabled = enabled; + } + + private PackageOverride(Parcel in) { + this(in.readLong(), in.readLong(), in.readBoolean()); + } + + /** + * Evaluate the override for the given {@code versionCode}. If no override is defined for + * the specified version code, {@link #VALUE_UNDEFINED} is returned. + * @hide + */ + public @EvaluatedOverride int evaluate(long versionCode) { + if (versionCode >= mMinVersionCode && versionCode <= mMaxVersionCode) { + return mEnabled ? VALUE_ENABLED : VALUE_DISABLED; + } + return VALUE_UNDEFINED; + } + + /** + * Evaluate the override independent of version code, i.e. only return an evaluated value if + * this range covers all versions, otherwise {@link #VALUE_UNDEFINED} is returned. + * @hide + */ + public int evaluateForAllVersions() { + if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) { + return mEnabled ? VALUE_ENABLED : VALUE_DISABLED; + } + return VALUE_UNDEFINED; + } + + /** Returns the minimum version code the override applies to. */ + public long getMinVersionCode() { + return mMinVersionCode; + } + + /** Returns the minimum version code the override applies from. */ + public long getMaxVersionCode() { + return mMaxVersionCode; + } + + /** Returns the enabled value for the override. */ + public boolean getEnabled() { + return mEnabled; + } + + /** @hide */ + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mMinVersionCode); + dest.writeLong(mMaxVersionCode); + dest.writeBoolean(mEnabled); + } + + /** @hide */ + @Override + public String toString() { + if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) { + return Boolean.toString(mEnabled); + } + return String.format("[%d,%d,%b]", mMinVersionCode, mMaxVersionCode, mEnabled); + } + + /** @hide */ + public static final Creator<PackageOverride> CREATOR = + new Creator<PackageOverride>() { + + @Override + public PackageOverride createFromParcel(Parcel in) { + return new PackageOverride(in); + } + + @Override + public PackageOverride[] newArray(int size) { + return new PackageOverride[size]; + } + }; + + /** + * Builder to construct a PackageOverride. + */ + public static class Builder { + private long mMinVersionCode = Long.MIN_VALUE; + private long mMaxVersionCode = Long.MAX_VALUE; + private boolean mEnabled; + + /** + * Sets the minimum version code the override should apply from. + * + * default value: {@code Long.MIN_VALUE}. + */ + public Builder setMinVersionCode(long minVersionCode) { + mMinVersionCode = minVersionCode; + return this; + } + + /** + * Sets the maximum version code the override should apply to. + * + * default value: {@code Long.MAX_VALUE}. + */ + public Builder setMaxVersionCode(long maxVersionCode) { + mMaxVersionCode = maxVersionCode; + return this; + } + + /** + * Sets whether the override should be enabled for the given version range. + * + * default value: {@code false}. + */ + public Builder setEnabled(boolean enabled) { + mEnabled = enabled; + return this; + } + + /** + * Build the {@link PackageOverride}. + * + * @throws IllegalArgumentException if {@code minVersionCode} is larger than + * {@code maxVersionCode}. + */ + public PackageOverride build() { + if (mMinVersionCode > mMaxVersionCode) { + throw new IllegalArgumentException("minVersionCode must not be larger than " + + "maxVersionCode"); + } + return new PackageOverride(mMinVersionCode, mMaxVersionCode, mEnabled); + } + }; +} diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index b7203e3e36bf..cc0b22afe38d 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -3565,12 +3565,12 @@ public final class BluetoothAdapter { } @Override - public void onDeviceDisconnected(BluetoothDevice device) { + public void onDeviceDisconnected(BluetoothDevice device, int hciReason) { for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry: mBluetoothConnectionCallbackExecutorMap.entrySet()) { BluetoothConnectionCallback callback = callbackExecutorEntry.getKey(); Executor executor = callbackExecutorEntry.getValue(); - executor.execute(() -> callback.onDeviceDisconnected(device)); + executor.execute(() -> callback.onDeviceDisconnected(device, hciReason)); } } }; @@ -3665,7 +3665,7 @@ public final class BluetoothAdapter { * * @hide */ - public abstract class BluetoothConnectionCallback { + public abstract static class BluetoothConnectionCallback { /** * Callback triggered when a bluetooth device (classic or BLE) is connected * @param device is the connected bluetooth device @@ -3675,8 +3675,155 @@ public final class BluetoothAdapter { /** * Callback triggered when a bluetooth device (classic or BLE) is disconnected * @param device is the disconnected bluetooth device + * @param reason is the disconnect reason */ - public void onDeviceDisconnected(BluetoothDevice device) {} + public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {} + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "REASON_" }, value = { + REASON_UNKNOWN, + REASON_LOCAL_REQUEST, + REASON_REMOTE_REQUEST, + REASON_LOCAL_ERROR, + REASON_REMOTE_ERROR, + REASON_TIMEOUT, + REASON_SECURITY, + REASON_SYSTEM_POLICY, + REASON_RESOURCE_LIMIT_REACHED, + REASON_CONNECTION_EXISTS, + REASON_BAD_PARAMETERS}) + public @interface DisconnectReason {} + + /** + * Indicates that the ACL disconnected due to an unknown reason. + */ + public static final int REASON_UNKNOWN = 0; + + /** + * Indicates that the ACL disconnected due to an explicit request from the local device. + * <p> + * Example cause: This is a normal disconnect reason, e.g., user/app initiates + * disconnection. + */ + public static final int REASON_LOCAL_REQUEST = 1; + + /** + * Indicates that the ACL disconnected due to an explicit request from the remote device. + * <p> + * Example cause: This is a normal disconnect reason, e.g., user/app initiates + * disconnection. + * <p> + * Example solution: The app can also prompt the user to check their remote device. + */ + public static final int REASON_REMOTE_REQUEST = 2; + + /** + * Generic disconnect reason indicating the ACL disconnected due to an error on the local + * device. + * <p> + * Example solution: Prompt the user to check their local device (e.g., phone, car + * headunit). + */ + public static final int REASON_LOCAL_ERROR = 3; + + /** + * Generic disconnect reason indicating the ACL disconnected due to an error on the remote + * device. + * <p> + * Example solution: Prompt the user to check their remote device (e.g., headset, car + * headunit, watch). + */ + public static final int REASON_REMOTE_ERROR = 4; + + /** + * Indicates that the ACL disconnected due to a timeout. + * <p> + * Example cause: remote device might be out of range. + * <p> + * Example solution: Prompt user to verify their remote device is on or in + * connection/pairing mode. + */ + public static final int REASON_TIMEOUT = 5; + + /** + * Indicates that the ACL disconnected due to link key issues. + * <p> + * Example cause: Devices are either unpaired or remote device is refusing our pairing + * request. + * <p> + * Example solution: Prompt user to unpair and pair again. + */ + public static final int REASON_SECURITY = 6; + + /** + * Indicates that the ACL disconnected due to the local device's system policy. + * <p> + * Example cause: privacy policy, power management policy, permissions, etc. + * <p> + * Example solution: Prompt the user to check settings, or check with their system + * administrator (e.g. some corp-managed devices do not allow OPP connection). + */ + public static final int REASON_SYSTEM_POLICY = 7; + + /** + * Indicates that the ACL disconnected due to resource constraints, either on the local + * device or the remote device. + * <p> + * Example cause: controller is busy, memory limit reached, maximum number of connections + * reached. + * <p> + * Example solution: The app should wait and try again. If still failing, prompt the user + * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device. + */ + public static final int REASON_RESOURCE_LIMIT_REACHED = 8; + + /** + * Indicates that the ACL disconnected because another ACL connection already exists. + */ + public static final int REASON_CONNECTION_EXISTS = 9; + + /** + * Indicates that the ACL disconnected due to incorrect parameters passed in from the app. + * <p> + * Example solution: Change parameters and try again. If error persists, the app can report + * telemetry and/or log the error in a bugreport. + */ + public static final int REASON_BAD_PARAMETERS = 10; + + /** + * Returns human-readable strings corresponding to {@link DisconnectReason}. + */ + public static String disconnectReasonText(@DisconnectReason int reason) { + switch (reason) { + case REASON_UNKNOWN: + return "Reason unknown"; + case REASON_LOCAL_REQUEST: + return "Local request"; + case REASON_REMOTE_REQUEST: + return "Remote request"; + case REASON_LOCAL_ERROR: + return "Local error"; + case REASON_REMOTE_ERROR: + return "Remote error"; + case REASON_TIMEOUT: + return "Timeout"; + case REASON_SECURITY: + return "Security"; + case REASON_SYSTEM_POLICY: + return "System policy"; + case REASON_RESOURCE_LIMIT_REACHED: + return "Resource constrained"; + case REASON_CONNECTION_EXISTS: + return "Connection already exists"; + case REASON_BAD_PARAMETERS: + return "Bad parameters"; + default: + return "Unrecognized disconnect reason: " + reason; + } + } } /** diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index ff6cffb272a5..0312a2190a4b 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -18,7 +18,9 @@ package android.bluetooth; import android.Manifest; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -30,6 +32,7 @@ import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -37,44 +40,60 @@ import java.util.List; * * @hide */ +@SystemApi public final class BluetoothMapClient implements BluetoothProfile { private static final String TAG = "BluetoothMapClient"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); + /** @hide */ public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED"; + /** @hide */ public static final String ACTION_MESSAGE_RECEIVED = "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED"; /* Actions to be used for pending intents */ + /** @hide */ public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY = "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY"; + /** @hide */ public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY = "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY"; /** * Action to notify read status changed + * + * @hide */ public static final String ACTION_MESSAGE_READ_STATUS_CHANGED = "android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED"; /** * Action to notify deleted status changed + * + * @hide */ public static final String ACTION_MESSAGE_DELETED_STATUS_CHANGED = "android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED"; - /* Extras used in ACTION_MESSAGE_RECEIVED intent. - * NOTE: HANDLE is only valid for a single session with the device. */ + /** + * Extras used in ACTION_MESSAGE_RECEIVED intent. + * NOTE: HANDLE is only valid for a single session with the device. + */ + /** @hide */ public static final String EXTRA_MESSAGE_HANDLE = "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE"; + /** @hide */ public static final String EXTRA_MESSAGE_TIMESTAMP = "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP"; + /** @hide */ public static final String EXTRA_MESSAGE_READ_STATUS = "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS"; + /** @hide */ public static final String EXTRA_SENDER_CONTACT_URI = "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI"; + /** @hide */ public static final String EXTRA_SENDER_CONTACT_NAME = "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME"; @@ -84,6 +103,8 @@ public final class BluetoothMapClient implements BluetoothProfile { * Possible values are: * true: deleted * false: undeleted + * + * @hide */ public static final String EXTRA_MESSAGE_DELETED_STATUS = "android.bluetooth.mapmce.profile.extra.MESSAGE_DELETED_STATUS"; @@ -93,24 +114,42 @@ public final class BluetoothMapClient implements BluetoothProfile { * Possible values are: * 0: failure * 1: success + * + * @hide */ public static final String EXTRA_RESULT_CODE = "android.bluetooth.device.extra.RESULT_CODE"; - /** There was an error trying to obtain the state */ + /** + * There was an error trying to obtain the state + * @hide + */ public static final int STATE_ERROR = -1; + /** @hide */ public static final int RESULT_FAILURE = 0; + /** @hide */ public static final int RESULT_SUCCESS = 1; - /** Connection canceled before completion. */ + /** + * Connection canceled before completion. + * @hide + */ public static final int RESULT_CANCELED = 2; - + /** @hide */ private static final int UPLOADING_FEATURE_BITMASK = 0x08; - /** Parameters in setMessageStatus */ + /* + * UNREAD, READ, UNDELETED, DELETED are passed as parameters + * to setMessageStatus to indicate the messages new state. + */ + + /** @hide */ public static final int UNREAD = 0; + /** @hide */ public static final int READ = 1; + /** @hide */ public static final int UNDELETED = 2; + /** @hide */ public static final int DELETED = 3; private BluetoothAdapter mAdapter; @@ -132,19 +171,12 @@ public final class BluetoothMapClient implements BluetoothProfile { mProfileConnector.connect(context, listener); } - protected void finalize() throws Throwable { - try { - close(); - } finally { - super.finalize(); - } - } - /** * Close the connection to the backing service. * Other public functions of BluetoothMap will return default error * results once close() has been called. Multiple invocations of close() * are ok. + * @hide */ public void close() { mProfileConnector.disconnect(); @@ -158,6 +190,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * Returns true if the specified Bluetooth device is connected. * Returns false if not connected, or if this proxy object is not * currently connected to the Map service. + * @hide */ public boolean isConnected(BluetoothDevice device) { if (VDBG) Log.d(TAG, "isConnected(" + device + ")"); @@ -225,6 +258,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * Get the list of connected devices. Currently at most one. * * @return list of connected devices + * @hide */ @Override public List<BluetoothDevice> getConnectedDevices() { @@ -246,6 +280,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * Get the list of devices matching specified states. Currently at most one. * * @return list of matching devices + * @hide */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @@ -267,6 +302,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * Get connection state of device * * @return device connection state + * @hide */ @Override public int getConnectionState(BluetoothDevice device) { @@ -383,11 +419,44 @@ public final class BluetoothMapClient implements BluetoothProfile { * Send an SMS message to either the contacts primary number or the telephone number specified. * * @param device Bluetooth device + * @param contacts Uri Collection of the contacts + * @param message Message to be sent + * @param sentIntent intent issued when message is sent + * @param deliveredIntent intent issued when message is delivered + * @return true if the message is enqueued, false on error + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.SEND_SMS) + public boolean sendMessage(@NonNull BluetoothDevice device, @NonNull Collection<Uri> contacts, + @NonNull String message, @Nullable PendingIntent sentIntent, + @Nullable PendingIntent deliveredIntent) { + if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); + final IBluetoothMapClient service = getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.sendMessage(device, contacts.toArray(new Uri[contacts.size()]), + message, sentIntent, deliveredIntent); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + return false; + } + + /** + * Send a message. + * + * Send an SMS message to either the contacts primary number or the telephone number specified. + * + * @param device Bluetooth device * @param contacts Uri[] of the contacts * @param message Message to be sent * @param sentIntent intent issued when message is sent * @param deliveredIntent intent issued when message is delivered * @return true if the message is enqueued, false on error + * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message, @@ -410,6 +479,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * * @param device Bluetooth device * @return true if the message is enqueued, false on error + * @hide */ public boolean getUnreadMessages(BluetoothDevice device) { if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")"); @@ -431,6 +501,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * @param device The Bluetooth device to get this value for. * @return Returns true if the Uploading bit value in SDP record's * MapSupportedFeatures field is set. False is returned otherwise. + * @hide */ public boolean isUploadingSupported(BluetoothDevice device) { final IBluetoothMapClient service = getService(); @@ -457,7 +528,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * "read", <code>UNDELETED</code> for "undeleted", <code>DELETED</code> for * "deleted", otherwise return error * @return <code>true</code> if request has been sent, <code>false</code> on error - * + * @hide */ @RequiresPermission(Manifest.permission.READ_SMS) public boolean setMessageStatus(BluetoothDevice device, String handle, int status) { diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index c31b04e81456..201d6c495d98 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -186,6 +186,7 @@ public interface BluetoothProfile { * * @hide */ + @SystemApi int MAP_CLIENT = 18; /** diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index a6089c31b140..32aa0377cd5f 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -64,7 +64,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.storage.StorageManager; -import android.system.Int32Ref; +import android.system.Int64Ref; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -4040,7 +4040,7 @@ public abstract class ContentResolver implements ContentInterface { // Convert to Point, since that's what the API is defined as final Bundle opts = new Bundle(); opts.putParcelable(EXTRA_SIZE, Point.convert(size)); - final Int32Ref orientation = new Int32Ref(0); + final Int64Ref orientation = new Int64Ref(0); Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> { final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts, diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 005c7ce9d949..08d8da389110 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1990,6 +1990,13 @@ public class PackageInstaller { this.forceQueryableOverride = true; } + /** + * Sets the install scenario for this session, which describes the expected user journey. + */ + public void setInstallScenario(@InstallScenario int installScenario) { + this.installScenario = installScenario; + } + /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 04e0468fde90..443ae358b8cd 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1059,15 +1059,11 @@ public abstract class PackageManager { /** * A value to indicate the lack of CUJ information, disabling all installation scenario logic. - * - * @hide */ public static final int INSTALL_SCENARIO_DEFAULT = 0; /** * Installation scenario providing the fastest “install button to launch" experience possible. - * - * @hide */ public static final int INSTALL_SCENARIO_FAST = 1; @@ -1084,8 +1080,6 @@ public abstract class PackageManager { * less optimized applications. The device state (e.g. memory usage or battery status) should * not be considered when making this decision as those factors are taken into account by the * Package Manager when acting on the installation scenario. - * - * @hide */ public static final int INSTALL_SCENARIO_BULK = 2; @@ -1096,8 +1090,6 @@ public abstract class PackageManager { * operation that are marked BULK_SECONDARY, the faster the entire bulk operation will be. * * See the comments for INSTALL_SCENARIO_BULK for more information. - * - * @hide */ public static final int INSTALL_SCENARIO_BULK_SECONDARY = 3; @@ -3280,6 +3272,15 @@ public abstract class PackageManager { public static final String FEATURE_KEYSTORE_LIMITED_USE_KEY = "android.hardware.keystore.limited_use_key"; + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has + * a Keystore implementation that can create application-specific attestation keys. + * See {@link android.security.keystore.KeyGenParameterSpec.Builder#setAttestKeyAlias}. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_KEYSTORE_APP_ATTEST_KEY = + "android.hardware.keystore.app_attest_key"; + /** @hide */ public static final boolean APP_ENUMERATION_ENABLED_BY_DEFAULT = true; diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java index 982fce918366..8b65d2410066 100644 --- a/core/java/android/content/pm/dex/DexMetadataHelper.java +++ b/core/java/android/content/pm/dex/DexMetadataHelper.java @@ -22,17 +22,26 @@ import static android.content.pm.PackageParser.APK_FILE_EXTENSION; import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; +import android.os.SystemProperties; import android.util.ArrayMap; import android.util.jar.StrictJarFile; +import android.util.JsonReader; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; /** * Helper class used to compute and validate the location of dex metadata files. @@ -40,6 +49,12 @@ import java.util.Map; * @hide */ public class DexMetadataHelper { + public static final String TAG = "DexMetadataHelper"; + /** $> adb shell 'setprop log.tag.DexMetadataHelper VERBOSE' */ + public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + /** $> adb shell 'setprop pm.dexopt.dm.require_manifest true' */ + private static String PROPERTY_DM_JSON_MANIFEST_REQUIRED = "pm.dexopt.dm.require_manifest"; + private static final String DEX_METADATA_FILE_EXTENSION = ".dm"; private DexMetadataHelper() {} @@ -147,14 +162,31 @@ public class DexMetadataHelper { /** * Validate that the given file is a dex metadata archive. - * This is just a validation that the file is a zip archive. + * This is just a validation that the file is a zip archive that contains a manifest.json + * with the package name and version code. * * @throws PackageParserException if the file is not a .dm file. */ - public static void validateDexMetadataFile(String dmaPath) throws PackageParserException { + public static void validateDexMetadataFile(String dmaPath, String packageName, long versionCode) + throws PackageParserException { + validateDexMetadataFile(dmaPath, packageName, versionCode, + SystemProperties.getBoolean(PROPERTY_DM_JSON_MANIFEST_REQUIRED, false)); + } + + @VisibleForTesting + public static void validateDexMetadataFile(String dmaPath, String packageName, long versionCode, + boolean requireManifest) throws PackageParserException { StrictJarFile jarFile = null; + + if (DEBUG) { + Log.v(TAG, "validateDexMetadataFile: " + dmaPath + ", " + packageName + + ", " + versionCode); + } + try { jarFile = new StrictJarFile(dmaPath, false, false); + validateDexMetadataManifest(dmaPath, jarFile, packageName, versionCode, + requireManifest); } catch (IOException e) { throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, "Error opening " + dmaPath, e); @@ -168,6 +200,72 @@ public class DexMetadataHelper { } } + /** Ensure that packageName and versionCode match the manifest.json in the .dm file */ + private static void validateDexMetadataManifest(String dmaPath, StrictJarFile jarFile, + String packageName, long versionCode, boolean requireManifest) + throws IOException, PackageParserException { + if (!requireManifest) { + if (DEBUG) { + Log.v(TAG, "validateDexMetadataManifest: " + dmaPath + + " manifest.json check skipped"); + } + return; + } + + ZipEntry zipEntry = jarFile.findEntry("manifest.json"); + if (zipEntry == null) { + throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, + "Missing manifest.json in " + dmaPath); + } + InputStream inputStream = jarFile.getInputStream(zipEntry); + + JsonReader reader; + try { + reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, + "Error opening manifest.json in " + dmaPath, e); + } + String jsonPackageName = null; + long jsonVersionCode = -1; + + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + if (name.equals("packageName")) { + jsonPackageName = reader.nextString(); + } else if (name.equals("versionCode")) { + jsonVersionCode = reader.nextLong(); + } else { + reader.skipValue(); + } + } + reader.endObject(); + + if (jsonPackageName == null || jsonVersionCode == -1) { + throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, + "manifest.json in " + dmaPath + + " is missing 'packageName' and/or 'versionCode'"); + } + + if (!jsonPackageName.equals(packageName)) { + throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, + "manifest.json in " + dmaPath + " has invalid packageName: " + jsonPackageName + + ", expected: " + packageName); + } + + if (versionCode != jsonVersionCode) { + throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA, + "manifest.json in " + dmaPath + " has invalid versionCode: " + jsonVersionCode + + ", expected: " + versionCode); + } + + if (DEBUG) { + Log.v(TAG, "validateDexMetadataManifest: " + dmaPath + ", " + packageName + + ", " + versionCode + ": successful"); + } + } + /** * Validates that all dex metadata paths in the given list have a matching apk. * (for any foo.dm there should be either a 'foo' of a 'foo.apk' file). diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS index cde7b2ac1898..d302b0ae1ea8 100644 --- a/core/java/android/content/pm/permission/OWNERS +++ b/core/java/android/content/pm/permission/OWNERS @@ -3,7 +3,6 @@ toddke@android.com toddke@google.com patb@google.com -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com zhanghai@google.com diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 3295042b0b35..2b4e4a106cec 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -3,3 +3,6 @@ per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhen # Sensor Privacy per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS + +# Sensors framework +per-file *Sensor*,*Trigger* = file:platform/frameworks/native:/services/sensorservice/OWNERS diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS index 25e02e1aa6f3..c390b33fa174 100644 --- a/core/java/android/hardware/input/OWNERS +++ b/core/java/android/hardware/input/OWNERS @@ -1,6 +1,3 @@ # Bug component: 136048 include /services/core/java/com/android/server/input/OWNERS - -michaelwr@google.com -svv@google.com diff --git a/core/java/android/hardware/location/OWNERS b/core/java/android/hardware/location/OWNERS index 383321bc3d69..bd40409f71c6 100644 --- a/core/java/android/hardware/location/OWNERS +++ b/core/java/android/hardware/location/OWNERS @@ -4,3 +4,6 @@ mstogaitis@google.com wyattriley@google.com etn@google.com weiwa@google.com + +# ContextHub team +per-file *ContextHub*,*NanoApp* = file:platform/system/chre:/OWNERS diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS index 8f2b39da4f63..8f5c2a025672 100644 --- a/core/java/android/hardware/usb/OWNERS +++ b/core/java/android/hardware/usb/OWNERS @@ -1,4 +1,3 @@ # Bug component: 175220 -moltmann@google.com badhri@google.com diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityMetricsEvent.aidl b/core/java/android/net/ConnectivityMetricsEvent.aidl index 1c541dc4c8cc..1c541dc4c8cc 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityMetricsEvent.aidl +++ b/core/java/android/net/ConnectivityMetricsEvent.aidl diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d6774d47b49e..933256a3b475 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -58,6 +58,9 @@ interface IIpSecService in LinkAddress localAddr, in String callingPackage); + void setNetworkForTunnelInterface( + int tunnelResourceId, in Network underlyingNetwork, in String callingPackage); + void deleteTunnelInterface(int resourceId, in String callingPackage); IpSecTransformResponse createTransform( diff --git a/core/java/android/net/IOnSetOemNetworkPreferenceListener.aidl b/core/java/android/net/IOnSetOemNetworkPreferenceListener.aidl new file mode 100644 index 000000000000..7979afc54f90 --- /dev/null +++ b/core/java/android/net/IOnSetOemNetworkPreferenceListener.aidl @@ -0,0 +1,23 @@ +/** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +oneway interface IOnSetOemNetworkPreferenceListener { + void onComplete(); +} diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl new file mode 100644 index 000000000000..271efe41a9ef --- /dev/null +++ b/core/java/android/net/IVpnManager.aidl @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.Network; + +import com.android.internal.net.LegacyVpnInfo; +import com.android.internal.net.VpnConfig; +import com.android.internal.net.VpnProfile; + +/** + * Interface that manages VPNs. + */ +/** {@hide} */ +interface IVpnManager { + /** VpnService APIs */ + boolean prepareVpn(String oldPackage, String newPackage, int userId); + void setVpnPackageAuthorization(String packageName, int userId, int vpnType); + ParcelFileDescriptor establishVpn(in VpnConfig config); + boolean addVpnAddress(String address, int prefixLength); + boolean removeVpnAddress(String address, int prefixLength); + boolean setUnderlyingNetworksForVpn(in Network[] networks); + + /** VpnManager APIs */ + boolean provisionVpnProfile(in VpnProfile profile, String packageName); + void deleteVpnProfile(String packageName); + void startVpnProfile(String packageName); + void stopVpnProfile(String packageName); + + /** Always-on VPN APIs */ + boolean isAlwaysOnVpnPackageSupported(int userId, String packageName); + boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown, + in List<String> lockdownAllowlist); + String getAlwaysOnVpnPackage(int userId); + boolean isVpnLockdownEnabled(int userId); + List<String> getVpnLockdownAllowlist(int userId); + boolean isCallerCurrentAlwaysOnVpnApp(); + boolean isCallerCurrentAlwaysOnVpnLockdownApp(); + + /** Legacy VPN APIs */ + void startLegacyVpn(in VpnProfile profile); + LegacyVpnInfo getLegacyVpnInfo(int userId); + boolean updateLockdownVpn(); + + /** General system APIs */ + VpnConfig getVpnConfig(int userId); + void factoryReset(); +} diff --git a/packages/Connectivity/framework/src/android/net/InterfaceConfiguration.aidl b/core/java/android/net/InterfaceConfiguration.aidl index 8aa5e3452853..8aa5e3452853 100644 --- a/packages/Connectivity/framework/src/android/net/InterfaceConfiguration.aidl +++ b/core/java/android/net/InterfaceConfiguration.aidl diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 70bca3019818..98acd98cc465 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -782,6 +782,42 @@ public final class IpSecManager { } } + /** + * Update the underlying network for this IpSecTunnelInterface. + * + * <p>This new underlying network will be used for all transforms applied AFTER this call is + * complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to + * this tunnel interface, traffic will still use the old SA, and be routed on the old + * underlying network. + * + * <p>To migrate IPsec tunnel mode traffic, a caller should: + * + * <ol> + * <li>Update the IpSecTunnelInterface’s underlying network. + * <li>Apply {@link IpSecTransform}(s) with matching addresses to this + * IpSecTunnelInterface. + * </ol> + * + * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. + * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise + * this method will throw an {@link IllegalArgumentException}. + */ + // TODO: b/169171001 Update the documentation when transform migration is supported. + // The purpose of making updating network and applying transforms separate is to leave open + // the possibility to support lossless migration procedures. To do that, Android platform + // will need to support multiple inbound tunnel mode transforms, just like it can support + // multiple transport mode transforms. + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) + public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException { + try { + mService.setNetworkForTunnelInterface( + mResourceId, underlyingNetwork, mOpPackageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java index e01e5aecc7e6..f7c1c4bb6d96 100644 --- a/core/java/android/net/LocalSocketImpl.java +++ b/core/java/android/net/LocalSocketImpl.java @@ -19,7 +19,6 @@ package android.net; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.system.ErrnoException; -import android.system.Int32Ref; import android.system.Os; import android.system.OsConstants; import android.system.StructLinger; @@ -65,14 +64,11 @@ class LocalSocketImpl public int available() throws IOException { FileDescriptor myFd = fd; if (myFd == null) throw new IOException("socket closed"); - - Int32Ref avail = new Int32Ref(0); try { - Os.ioctlInt(myFd, OsConstants.FIONREAD, avail); + return Os.ioctlInt(myFd, OsConstants.FIONREAD); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } - return avail.value; } /** {@inheritDoc} */ @@ -134,7 +130,7 @@ class LocalSocketImpl public void write (byte[] b) throws IOException { write(b, 0, b.length); } - + /** {@inheritDoc} */ @Override public void write (byte[] b, int off, int len) throws IOException { @@ -255,7 +251,7 @@ class LocalSocketImpl /** note timeout presently ignored */ protected void connect(LocalSocketAddress address, int timeout) throws IOException - { + { if (fd == null) { throw new IOException("socket not created"); } @@ -339,7 +335,7 @@ class LocalSocketImpl * @throws IOException if socket has been closed or cannot be created. */ protected OutputStream getOutputStream() throws IOException - { + { if (fd == null) { throw new IOException("socket not created"); } diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 11146bd45fe4..b1bca6efa02b 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; +import android.annotation.TestApi; import android.app.ActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -55,6 +56,7 @@ import java.util.concurrent.ConcurrentHashMap; * * @hide */ +@TestApi @SystemService(Context.NETWORK_POLICY_SERVICE) public class NetworkPolicyManager { @@ -125,6 +127,7 @@ public class NetworkPolicyManager { public static final int RULE_REJECT_ALL = 1 << 6; /** * Reject traffic on all networks for restricted networking mode. + * @hide */ public static final int RULE_REJECT_RESTRICTED_MODE = 1 << 10; @@ -351,6 +354,7 @@ public class NetworkPolicyManager { } /** @hide */ + @TestApi @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setRestrictBackground(boolean restrictBackground) { try { @@ -361,6 +365,7 @@ public class NetworkPolicyManager { } /** @hide */ + @TestApi @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean getRestrictBackground() { try { @@ -506,6 +511,8 @@ public class NetworkPolicyManager { /** * Get multipath preference for the given network. + * + * @hide */ public int getMultipathPreference(Network network) { try { @@ -624,7 +631,9 @@ public class NetworkPolicyManager { } /** @hide */ - public static String resolveNetworkId(WifiConfiguration config) { + @TestApi + @NonNull + public static String resolveNetworkId(@NonNull WifiConfiguration config) { return WifiInfo.sanitizeSsid(config.isPasspoint() ? config.providerFriendlyName : config.SSID); } diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java index e466d2e626be..813fde1c15f2 100644 --- a/core/java/android/net/NetworkState.java +++ b/core/java/android/net/NetworkState.java @@ -41,7 +41,6 @@ public class NetworkState implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public final Network network; public final String subscriberId; - public final String networkId; public final int legacyNetworkType; private NetworkState() { @@ -50,35 +49,33 @@ public class NetworkState implements Parcelable { networkCapabilities = null; network = null; subscriberId = null; - networkId = null; legacyNetworkType = 0; } public NetworkState(int legacyNetworkType, @NonNull LinkProperties linkProperties, @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - @Nullable String subscriberId, @Nullable String networkId) { + @Nullable String subscriberId) { this(legacyNetworkType, new NetworkInfo(legacyNetworkType, 0, null, null), linkProperties, - networkCapabilities, network, subscriberId, networkId); + networkCapabilities, network, subscriberId); } // Constructor that used internally in ConnectivityService mainline module. public NetworkState(@NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties, @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - String subscriberId, String networkId) { + @Nullable String subscriberId) { this(networkInfo.getType(), networkInfo, linkProperties, - networkCapabilities, network, subscriberId, networkId); + networkCapabilities, network, subscriberId); } public NetworkState(int legacyNetworkType, @NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties, @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - String subscriberId, String networkId) { + @Nullable String subscriberId) { this.networkInfo = networkInfo; this.linkProperties = linkProperties; this.networkCapabilities = networkCapabilities; this.network = network; this.subscriberId = subscriberId; - this.networkId = networkId; this.legacyNetworkType = legacyNetworkType; // This object is an atomic view of a network, so the various components @@ -99,7 +96,6 @@ public class NetworkState implements Parcelable { networkCapabilities = in.readParcelable(null); network = in.readParcelable(null); subscriberId = in.readString(); - networkId = in.readString(); legacyNetworkType = in.readInt(); } @@ -115,7 +111,6 @@ public class NetworkState implements Parcelable { out.writeParcelable(networkCapabilities, flags); out.writeParcelable(network, flags); out.writeString(subscriberId); - out.writeString(networkId); out.writeInt(legacyNetworkType); } diff --git a/core/java/android/net/NetworkWatchlistManager.java b/core/java/android/net/NetworkWatchlistManager.java index 49047d3a0c87..8f6510ed3ea5 100644 --- a/core/java/android/net/NetworkWatchlistManager.java +++ b/core/java/android/net/NetworkWatchlistManager.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; @@ -29,6 +31,7 @@ import com.android.internal.util.Preconditions; * Class that manage network watchlist in system. * @hide */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @SystemService(Context.NETWORK_WATCHLIST_SERVICE) public class NetworkWatchlistManager { @@ -90,6 +93,7 @@ public class NetworkWatchlistManager { /** * Get Network Watchlist config file hash. */ + @Nullable public byte[] getWatchlistConfigHash() { try { return mNetworkWatchlistManager.getWatchlistConfigHash(); diff --git a/core/java/android/net/OemNetworkPreferences.java b/core/java/android/net/OemNetworkPreferences.java index 5e56164cc82c..b4034556f66e 100644 --- a/core/java/android/net/OemNetworkPreferences.java +++ b/core/java/android/net/OemNetworkPreferences.java @@ -18,6 +18,7 @@ package android.net; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcelable; @@ -29,11 +30,12 @@ import java.util.Map; import java.util.Objects; /** @hide */ +@SystemApi public final class OemNetworkPreferences implements Parcelable { /** - * Use default behavior requesting networks. Equivalent to not setting any preference at all. + * Default in case this value is not set. Using it will result in an error. */ - public static final int OEM_NETWORK_PREFERENCE_DEFAULT = 0; + public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; /** * If an unmetered network is available, use it. @@ -45,17 +47,17 @@ public final class OemNetworkPreferences implements Parcelable { /** * If an unmetered network is available, use it. * Otherwise, if a network with the OEM_PAID capability is available, use it. - * Otherwise, the app doesn't get a network. + * Otherwise, the app doesn't get a default network. */ public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; /** - * Prefer only NET_CAPABILITY_OEM_PAID networks. + * Use only NET_CAPABILITY_OEM_PAID networks. */ public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; /** - * Prefer only NET_CAPABILITY_OEM_PRIVATE networks. + * Use only NET_CAPABILITY_OEM_PRIVATE networks. */ public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; @@ -95,8 +97,6 @@ public final class OemNetworkPreferences implements Parcelable { /** * Builder used to create {@link OemNetworkPreferences} objects. Specify the preferred Network * to package name mappings. - * - * @hide */ public static final class Builder { private final Bundle mNetworkMappings; @@ -135,7 +135,7 @@ public final class OemNetworkPreferences implements Parcelable { * @return The builder to facilitate chaining. */ @NonNull - public Builder removeNetworkPreference(@NonNull final String packageName) { + public Builder clearNetworkPreference(@NonNull final String packageName) { Objects.requireNonNull(packageName); mNetworkMappings.remove(packageName); return this; @@ -160,7 +160,7 @@ public final class OemNetworkPreferences implements Parcelable { /** @hide */ @IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = { - OEM_NETWORK_PREFERENCE_DEFAULT, + OEM_NETWORK_PREFERENCE_UNINITIALIZED, OEM_NETWORK_PREFERENCE_OEM_PAID, OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK, OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY, @@ -174,12 +174,14 @@ public final class OemNetworkPreferences implements Parcelable { * * @param value int value of OemNetworkPreference * @return string version of OemNetworkPreference + * + * @hide */ @NonNull public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) { switch (value) { - case OEM_NETWORK_PREFERENCE_DEFAULT: - return "OEM_NETWORK_PREFERENCE_DEFAULT"; + case OEM_NETWORK_PREFERENCE_UNINITIALIZED: + return "OEM_NETWORK_PREFERENCE_UNINITIALIZED"; case OEM_NETWORK_PREFERENCE_OEM_PAID: return "OEM_NETWORK_PREFERENCE_OEM_PAID"; case OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: diff --git a/packages/Connectivity/framework/src/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl index f70fc8e2fefd..f70fc8e2fefd 100644 --- a/packages/Connectivity/framework/src/android/net/UidRange.aidl +++ b/core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java index 3bc0f9ca4e6a..b172ccc4e370 100644 --- a/core/java/android/net/UidRange.java +++ b/core/java/android/net/UidRange.java @@ -21,6 +21,7 @@ import static android.os.UserHandle.PER_USER_RANGE; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import android.os.UserHandle; import java.util.Collection; @@ -45,6 +46,14 @@ public final class UidRange implements Parcelable { return new UidRange(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); } + /** Creates a UidRange for the specified user. */ + public static UidRange createForUser(UserHandle user) { + final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1); + final int start = UserHandle.getUid(user, 0 /* appId */); + final int end = UserHandle.getUid(nextUser, 0) - 1; + return new UidRange(start, end); + } + /** Returns the smallest user Id which is contained in this UidRange */ public int getStartUser() { return start / PER_USER_RANGE; diff --git a/packages/Connectivity/framework/src/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index 1812509ba6d2..f472ed4381d1 100644 --- a/packages/Connectivity/framework/src/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; @@ -37,6 +38,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.GeneralSecurityException; +import java.util.List; /** * This class provides an interface for apps to manage platform VPN profiles @@ -55,18 +57,40 @@ import java.security.GeneralSecurityException; public class VpnManager { /** Type representing a lack of VPN @hide */ public static final int TYPE_VPN_NONE = -1; - /** VPN service type code @hide */ + + /** + * A VPN created by an app using the {@link VpnService} API. + * @hide + */ public static final int TYPE_VPN_SERVICE = 1; - /** Platform VPN type code @hide */ + + /** + * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}. + * @hide + */ public static final int TYPE_VPN_PLATFORM = 2; + /** + * An IPsec VPN created by the built-in LegacyVpnRunner. + * @deprecated new Android devices should use VPN_TYPE_PLATFORM instead. + * @hide + */ + @Deprecated + public static final int TYPE_VPN_LEGACY = 3; + + /** + * Channel for VPN notifications. + * @hide + */ + public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; + /** @hide */ - @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM}) + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) @Retention(RetentionPolicy.SOURCE) public @interface VpnType {} @NonNull private final Context mContext; - @NonNull private final IConnectivityManager mService; + @NonNull private final IVpnManager mService; private static Intent getIntentForConfirmation() { final Intent intent = new Intent(); @@ -85,9 +109,9 @@ public class VpnManager { * * @hide */ - public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) { + public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) { mContext = checkNotNull(ctx, "missing Context"); - mService = checkNotNull(service, "missing IConnectivityManager"); + mService = checkNotNull(service, "missing IVpnManager"); } /** @@ -179,6 +203,19 @@ public class VpnManager { } /** + * Resets all VPN settings back to factory defaults. + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void factoryReset() { + try { + mService.factoryReset(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Prepare for a VPN application. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. @@ -224,6 +261,108 @@ public class VpnManager { } /** + * Checks if a VPN app supports always-on mode. + * + * In order to support the always-on feature, an app has to + * <ul> + * <li>target {@link VERSION_CODES#N API 24} or above, and + * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} + * meta-data field. + * </ul> + * + * @param userId The identifier of the user for whom the VPN app is installed. + * @param vpnPackage The canonical package name of the VPN app. + * @return {@code true} if and only if the VPN app exists and supports always-on mode. + * @hide + */ + public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { + try { + return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Configures an always-on VPN connection through a specific application. + * This connection is automatically granted and persisted after a reboot. + * + * <p>The designated package should declare a {@link VpnService} in its + * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, + * otherwise the call will fail. + * + * @param userId The identifier of the user to set an always-on VPN for. + * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} + * to remove an existing always-on VPN configuration. + * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or + * {@code false} otherwise. + * @param lockdownAllowlist The list of packages that are allowed to access network directly + * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so + * this method must be called when a package that should be allowed is installed or + * uninstalled. + * @return {@code true} if the package is set as always-on VPN controller; + * {@code false} otherwise. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, + boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) { + try { + return mService.setAlwaysOnVpnPackage( + userId, vpnPackage, lockdownEnabled, lockdownAllowlist); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the package name of the currently set always-on VPN application. + * If there is no always-on VPN set, or the VPN is provided by the system instead + * of by an app, {@code null} will be returned. + * + * @return Package name of VPN controller responsible for always-on VPN, + * or {@code null} if none is set. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public String getAlwaysOnVpnPackageForUser(int userId) { + try { + return mService.getAlwaysOnVpnPackage(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return whether always-on VPN is in lockdown mode. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean isVpnLockdownEnabled(int userId) { + try { + return mService.isVpnLockdownEnabled(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return the list of packages that are allowed to access network when always-on VPN is in + * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public List<String> getVpnLockdownAllowlist(int userId) { + try { + return mService.getVpnLockdownAllowlist(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Return the legacy VPN information for the specified user ID. * @hide */ diff --git a/packages/Connectivity/framework/src/android/net/VpnService.java b/core/java/android/net/VpnService.java index 8e90a119fe21..f90fbaf1e0fb 100644 --- a/packages/Connectivity/framework/src/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -170,12 +170,11 @@ public class VpnService extends Service { "android.net.VpnService.SUPPORTS_ALWAYS_ON"; /** - * Use IConnectivityManager since those methods are hidden and not - * available in ConnectivityManager. + * Use IVpnManager since those methods are hidden and not available in VpnManager. */ - private static IConnectivityManager getService() { - return IConnectivityManager.Stub.asInterface( - ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + private static IVpnManager getService() { + return IVpnManager.Stub.asInterface( + ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE)); } /** @@ -226,15 +225,15 @@ public class VpnService extends Service { @SystemApi @RequiresPermission(android.Manifest.permission.CONTROL_VPN) public static void prepareAndAuthorize(Context context) { - IConnectivityManager cm = getService(); + IVpnManager vm = getService(); String packageName = context.getPackageName(); try { // Only prepare if we're not already prepared. int userId = context.getUserId(); - if (!cm.prepareVpn(packageName, null, userId)) { - cm.prepareVpn(null, packageName, userId); + if (!vm.prepareVpn(packageName, null, userId)) { + vm.prepareVpn(null, packageName, userId); } - cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); + vm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); } catch (RemoteException e) { // ignore } @@ -597,7 +596,8 @@ public class VpnService extends Service { } } } - mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null)); + mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null, + RouteInfo.RTN_UNICAST)); mConfig.updateAllowedFamilies(address); return this; } diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl index 4f293eeb3c3b..6a3cb42ed75d 100644 --- a/core/java/android/net/vcn/IVcnManagementService.aidl +++ b/core/java/android/net/vcn/IVcnManagementService.aidl @@ -18,6 +18,7 @@ package android.net.vcn; import android.net.LinkProperties; import android.net.NetworkCapabilities; +import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; import android.net.vcn.VcnUnderlyingNetworkPolicy; @@ -33,4 +34,7 @@ interface IVcnManagementService { void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(in NetworkCapabilities nc, in LinkProperties lp); + + void registerVcnStatusCallback(in ParcelUuid subscriptionGroup, in IVcnStatusCallback callback, in String opPkgName); + void unregisterVcnStatusCallback(in IVcnStatusCallback callback); } diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl new file mode 100644 index 000000000000..555e9b5883e8 --- /dev/null +++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl @@ -0,0 +1,27 @@ +/* + * Copyright 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +/** @hide */ +interface IVcnStatusCallback { + void onEnteredSafeMode(); + void onGatewayConnectionError( + in int[] gatewayNetworkCapabilities, + int errorCode, + in String exceptionClass, + in String exceptionMessage); +}
\ No newline at end of file diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java index 5eb4ba6a2f8e..52cc2182b094 100644 --- a/core/java/android/net/vcn/VcnConfig.java +++ b/core/java/android/net/vcn/VcnConfig.java @@ -20,6 +20,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.net.NetworkRequest; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; @@ -41,7 +42,6 @@ import java.util.Set; * brought up on demand based on active {@link NetworkRequest}(s). * * @see VcnManager for more information on the Virtual Carrier Network feature - * @hide */ public final class VcnConfig implements Parcelable { @NonNull private static final String TAG = VcnConfig.class.getSimpleName(); @@ -56,7 +56,8 @@ public final class VcnConfig implements Parcelable { @NonNull String packageName, @NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs) { mPackageName = packageName; - mGatewayConnectionConfigs = Collections.unmodifiableSet(gatewayConnectionConfigs); + mGatewayConnectionConfigs = + Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs)); validate(); } @@ -96,11 +97,7 @@ public final class VcnConfig implements Parcelable { return mPackageName; } - /** - * Retrieves the set of configured tunnels. - * - * @hide - */ + /** Retrieves the set of configured GatewayConnection(s). */ @NonNull public Set<VcnGatewayConnectionConfig> getGatewayConnectionConfigs() { return Collections.unmodifiableSet(mGatewayConnectionConfigs); @@ -168,11 +165,7 @@ public final class VcnConfig implements Parcelable { } }; - /** - * This class is used to incrementally build {@link VcnConfig} objects. - * - * @hide - */ + /** This class is used to incrementally build {@link VcnConfig} objects. */ public static final class Builder { @NonNull private final String mPackageName; @@ -190,7 +183,6 @@ public final class VcnConfig implements Parcelable { * * @param gatewayConnectionConfig the configuration for an individual gateway connection * @return this {@link Builder} instance, for chaining - * @hide */ @NonNull public Builder addGatewayConnectionConfig( @@ -205,7 +197,6 @@ public final class VcnConfig implements Parcelable { * Builds and validates the VcnConfig. * * @return an immutable VcnConfig instance - * @hide */ @NonNull public VcnConfig build() { diff --git a/core/java/android/net/vcn/VcnControlPlaneConfig.java b/core/java/android/net/vcn/VcnControlPlaneConfig.java new file mode 100644 index 000000000000..92f6c4440377 --- /dev/null +++ b/core/java/android/net/vcn/VcnControlPlaneConfig.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net.vcn; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.PersistableBundle; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * This class represents a control plane configuration for a Virtual Carrier Network connection. + * + * <p>Each {@link VcnGatewayConnectionConfig} must have a {@link VcnControlPlaneConfig}, containing + * all connection, authentication and authorization parameters required to establish a Gateway + * Connection with a remote endpoint. + * + * <p>A {@link VcnControlPlaneConfig} object can be shared by multiple {@link + * VcnGatewayConnectionConfig}(s) if they will used for connecting with the same remote endpoint. + * + * @see VcnManager + * @see VcnGatewayConnectionConfig + */ +public abstract class VcnControlPlaneConfig { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({CONFIG_TYPE_IKE}) + public @interface ConfigType {} + + /** @hide */ + public static final int CONFIG_TYPE_IKE = 1; + + private static final String CONFIG_TYPE_KEY = "mConfigType"; + @ConfigType private final int mConfigType; + + /** + * Package private constructor. + * + * @hide + */ + VcnControlPlaneConfig(int configType) { + mConfigType = configType; + } + + /** + * Constructs a VcnControlPlaneConfig object by deserializing a PersistableBundle. + * + * @param in the {@link PersistableBundle} containing an {@link VcnControlPlaneConfig} object + * @hide + */ + public static VcnControlPlaneConfig fromPersistableBundle(@NonNull PersistableBundle in) { + Objects.requireNonNull(in, "PersistableBundle was null"); + + int configType = in.getInt(CONFIG_TYPE_KEY); + switch (configType) { + case CONFIG_TYPE_IKE: + return new VcnControlPlaneIkeConfig(in); + default: + throw new IllegalStateException("Unrecognized configType: " + configType); + } + } + + /** + * Converts this VcnControlPlaneConfig to a PersistableBundle. + * + * @hide + */ + @NonNull + public PersistableBundle toPersistableBundle() { + final PersistableBundle result = new PersistableBundle(); + result.putInt(CONFIG_TYPE_KEY, mConfigType); + return result; + } + + /** @hide */ + @Override + public int hashCode() { + return Objects.hash(mConfigType); + } + + /** @hide */ + @Override + public boolean equals(Object o) { + if (!(o instanceof VcnControlPlaneConfig)) { + return false; + } + + return mConfigType == ((VcnControlPlaneConfig) o).mConfigType; + } + + /** + * Returns a deep copy of this object. + * + * @hide + */ + public abstract VcnControlPlaneConfig copy(); +} diff --git a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java new file mode 100644 index 000000000000..de086f63b14d --- /dev/null +++ b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import static android.net.vcn.VcnControlPlaneConfig.CONFIG_TYPE_IKE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.TunnelModeChildSessionParams; +import android.os.PersistableBundle; +import android.util.ArraySet; + +import java.util.Objects; + +/** + * This class is an IKEv2 control plane configuration for a Virtual Carrier Network connection. + * + * <p>This class is an extension of the {@link VcnControlPlaneConfig}, containing IKEv2-specific + * configuration, authentication and authorization parameters. + * + * @see VcnControlPlaneConfig + */ +public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { + private static final String TAG = VcnControlPlaneIkeConfig.class.getSimpleName(); + + // STOPSHIP: b/163604823 Make mIkeParams and mChildParams @NonNull when it is supported to + // construct mIkeParams and mChildParams from PersistableBundles. + + private static final String IKE_PARAMS_KEY = "mIkeParams"; + @Nullable private final IkeSessionParams mIkeParams; + + private static final String CHILD_PARAMS_KEY = "mChildParams"; + @Nullable private final TunnelModeChildSessionParams mChildParams; + + private static final ArraySet<String> BUNDLE_KEY_SET = new ArraySet<>(); + + { + BUNDLE_KEY_SET.add(IKE_PARAMS_KEY); + BUNDLE_KEY_SET.add(CHILD_PARAMS_KEY); + } + + /** + * Constructs a VcnControlPlaneIkeConfig object. + * + * @param ikeParams the IKE Session negotiation parameters + * @param childParams the tunnel mode Child Session negotiation parameters + */ + public VcnControlPlaneIkeConfig( + @NonNull IkeSessionParams ikeParams, + @NonNull TunnelModeChildSessionParams childParams) { + super(CONFIG_TYPE_IKE); + mIkeParams = ikeParams; + mChildParams = childParams; + validate(); + } + + /** + * Constructs a VcnControlPlaneIkeConfig object by deserializing a PersistableBundle. + * + * @param in the {@link PersistableBundle} containing an {@link VcnControlPlaneIkeConfig} object + * @hide + */ + public VcnControlPlaneIkeConfig(@NonNull PersistableBundle in) { + super(CONFIG_TYPE_IKE); + final PersistableBundle ikeParamsBundle = in.getPersistableBundle(IKE_PARAMS_KEY); + final PersistableBundle childParamsBundle = in.getPersistableBundle(CHILD_PARAMS_KEY); + + // STOPSHIP: b/163604823 Support constructing mIkeParams and mChildParams from + // PersistableBundles. + + mIkeParams = null; + mChildParams = null; + } + + private void validate() { + Objects.requireNonNull(mIkeParams, "mIkeParams was null"); + Objects.requireNonNull(mChildParams, "mChildParams was null"); + } + + /** + * Converts this VcnControlPlaneConfig to a PersistableBundle. + * + * @hide + */ + @Override + @NonNull + public PersistableBundle toPersistableBundle() { + final PersistableBundle result = super.toPersistableBundle(); + + // STOPSHIP: b/163604823 Support converting mIkeParams and mChildParams to + // PersistableBundles. + return result; + } + + /** Retrieves the IKE Session configuration. */ + @NonNull + public IkeSessionParams getIkeSessionParams() { + return mIkeParams; + } + + /** Retrieves the tunnel mode Child Session configuration. */ + @NonNull + public TunnelModeChildSessionParams getChildSessionParams() { + return mChildParams; + } + + /** @hide */ + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), mIkeParams, mChildParams); + } + + /** @hide */ + @Override + public boolean equals(Object o) { + if (!(o instanceof VcnControlPlaneIkeConfig)) { + return false; + } + + VcnControlPlaneIkeConfig other = (VcnControlPlaneIkeConfig) o; + + // STOPSHIP: b/163604823 Also check mIkeParams and mChildParams when it is supported to + // construct mIkeParams and mChildParams from PersistableBundles. They are not checked + // now so that VcnGatewayConnectionConfigTest and VcnConfigTest can pass. + return super.equals(o); + } + + /** @hide */ + @Override + public VcnControlPlaneConfig copy() { + return new VcnControlPlaneIkeConfig( + new IkeSessionParams.Builder(mIkeParams).build(), + new TunnelModeChildSessionParams.Builder(mChildParams).build()); + } +} diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index cead2f1caad1..9f83b21f0d0c 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -21,6 +21,8 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.net.Network; import android.net.NetworkCapabilities; import android.os.PersistableBundle; import android.util.ArraySet; @@ -55,28 +57,23 @@ import java.util.concurrent.TimeUnit; * subscription group under which this configuration is registered (see {@link * VcnManager#setVcnConfig}). * - * <p>Services that can be provided by a VCN network, or required for underlying networks are - * limited to services provided by cellular networks: + * <p>As an abstraction of a cellular network, services that can be provided by a VCN network, or + * required for underlying networks are limited to services provided by cellular networks: * * <ul> - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MMS} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_SUPL} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_DUN} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_FOTA} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_IMS} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_CBS} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_IA} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_RCS} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_XCAP} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_EIMS} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET} - * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MCX} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_SUPL} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_DUN} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_FOTA} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_IMS} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_CBS} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_IA} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_RCS} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_XCAP} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_EIMS} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_INTERNET} + * <li>{@link NetworkCapabilities#NET_CAPABILITY_MCX} * </ul> - * - * <p>The meteredness and roaming of the VCN {@link Network} will be determined by that of the - * underlying Network(s). - * - * @hide */ public final class VcnGatewayConnectionConfig { // TODO: Use MIN_MTU_V6 once it is public, @hide @@ -153,14 +150,15 @@ public final class VcnGatewayConnectionConfig { TimeUnit.MINUTES.toMillis(15) }; + private static final String CTRL_PLANE_CONFIG_KEY = "mCtrlPlaneConfig"; + @NonNull private VcnControlPlaneConfig mCtrlPlaneConfig; + private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities"; @NonNull private final SortedSet<Integer> mExposedCapabilities; private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities"; @NonNull private final SortedSet<Integer> mUnderlyingCapabilities; - // TODO: Add Ike/ChildSessionParams as a subclass - maybe VcnIkeGatewayConnectionConfig - private static final String MAX_MTU_KEY = "mMaxMtu"; private final int mMaxMtu; @@ -169,10 +167,12 @@ public final class VcnGatewayConnectionConfig { /** Builds a VcnGatewayConnectionConfig with the specified parameters. */ private VcnGatewayConnectionConfig( + @NonNull VcnControlPlaneConfig ctrlPlaneConfig, @NonNull Set<Integer> exposedCapabilities, @NonNull Set<Integer> underlyingCapabilities, @NonNull long[] retryIntervalsMs, @IntRange(from = MIN_MTU_V6) int maxMtu) { + mCtrlPlaneConfig = ctrlPlaneConfig; mExposedCapabilities = new TreeSet(exposedCapabilities); mUnderlyingCapabilities = new TreeSet(underlyingCapabilities); mRetryIntervalsMs = retryIntervalsMs; @@ -184,11 +184,16 @@ public final class VcnGatewayConnectionConfig { /** @hide */ @VisibleForTesting(visibility = Visibility.PRIVATE) public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) { + final PersistableBundle ctrlPlaneConfigBundle = + in.getPersistableBundle(CTRL_PLANE_CONFIG_KEY); + Objects.requireNonNull(ctrlPlaneConfigBundle, "ctrlPlaneConfigBundle was null"); + final PersistableBundle exposedCapsBundle = in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY); final PersistableBundle underlyingCapsBundle = in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY); + mCtrlPlaneConfig = VcnControlPlaneConfig.fromPersistableBundle(ctrlPlaneConfigBundle); mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList( exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); mUnderlyingCapabilities = new TreeSet<>(PersistableBundleUtils.toList( @@ -200,6 +205,8 @@ public final class VcnGatewayConnectionConfig { } private void validate() { + Objects.requireNonNull(mCtrlPlaneConfig, "control plane config was null"); + Preconditions.checkArgument( mExposedCapabilities != null && !mExposedCapabilities.isEmpty(), "exposedCapsBundle was null or empty"); @@ -243,14 +250,23 @@ public final class VcnGatewayConnectionConfig { } /** + * Returns control plane configuration. + * + * @hide + */ + @NonNull + public VcnControlPlaneConfig getControlPlaneConfig() { + return mCtrlPlaneConfig.copy(); + } + + /** * Returns all exposed capabilities. * * <p>The returned integer-value capabilities will not contain duplicates, and will be sorted in * ascending numerical order. * * @see Builder#addExposedCapability(int) - * @see Builder#clearExposedCapability(int) - * @hide + * @see Builder#removeExposedCapability(int) */ @NonNull public int[] getExposedCapabilities() { @@ -278,8 +294,7 @@ public final class VcnGatewayConnectionConfig { * <p>The returned integer-value capabilities will be sorted in ascending numerical order. * * @see Builder#addRequiredUnderlyingCapability(int) - * @see Builder#clearRequiredUnderlyingCapability(int) - * @hide + * @see Builder#removeRequiredUnderlyingCapability(int) */ @NonNull public int[] getRequiredUnderlyingCapabilities() { @@ -305,7 +320,6 @@ public final class VcnGatewayConnectionConfig { * Retrieves the configured retry intervals. * * @see Builder#setRetryInterval(long[]) - * @hide */ @NonNull public long[] getRetryInterval() { @@ -317,7 +331,7 @@ public final class VcnGatewayConnectionConfig { * * <p>Left to prevent the need to make major changes while changes are actively in flight. * - * @deprecated use getRequiredUnderlyingCapabilities() instead + * @deprecated use getRetryInterval() instead * @hide */ @Deprecated @@ -329,8 +343,7 @@ public final class VcnGatewayConnectionConfig { /** * Retrieves the maximum MTU allowed for this Gateway Connection. * - * @see Builder.setMaxMtu(int) - * @hide + * @see Builder#setMaxMtu(int) */ @IntRange(from = MIN_MTU_V6) public int getMaxMtu() { @@ -347,6 +360,7 @@ public final class VcnGatewayConnectionConfig { public PersistableBundle toPersistableBundle() { final PersistableBundle result = new PersistableBundle(); + final PersistableBundle ctrlPlaneConfigBundle = mCtrlPlaneConfig.toPersistableBundle(); final PersistableBundle exposedCapsBundle = PersistableBundleUtils.fromList( new ArrayList<>(mExposedCapabilities), @@ -356,6 +370,7 @@ public final class VcnGatewayConnectionConfig { new ArrayList<>(mUnderlyingCapabilities), PersistableBundleUtils.INTEGER_SERIALIZER); + result.putPersistableBundle(CTRL_PLANE_CONFIG_KEY, ctrlPlaneConfigBundle); result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle); result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle); result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); @@ -388,10 +403,9 @@ public final class VcnGatewayConnectionConfig { /** * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. - * - * @hide */ public static final class Builder { + @NonNull private final VcnControlPlaneConfig mCtrlPlaneConfig; @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet(); @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet(); @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; @@ -402,6 +416,18 @@ public final class VcnGatewayConnectionConfig { // when on Cell. /** + * Construct a Builder object. + * + * @param ctrlPlaneConfig the control plane configuration + * @see VcnControlPlaneConfig + */ + public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) { + Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null"); + + mCtrlPlaneConfig = ctrlPlaneConfig; + } + + /** * Add a capability that this VCN Gateway Connection will support. * * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway @@ -409,7 +435,6 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway * Connection - * @hide */ @NonNull public Builder addExposedCapability(@VcnSupportedCapability int exposedCapability) { @@ -427,10 +452,10 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway * Connection - * @hide */ @NonNull - public Builder clearExposedCapability(@VcnSupportedCapability int exposedCapability) { + @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap + public Builder removeExposedCapability(@VcnSupportedCapability int exposedCapability) { checkValidCapability(exposedCapability); mExposedCapabilities.remove(exposedCapability); @@ -445,7 +470,6 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks - * @hide */ @NonNull public Builder addRequiredUnderlyingCapability( @@ -468,10 +492,10 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks - * @hide */ @NonNull - public Builder clearRequiredUnderlyingCapability( + @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap + public Builder removeRequiredUnderlyingCapability( @VcnSupportedCapability int underlyingCapability) { checkValidCapability(underlyingCapability); @@ -501,7 +525,6 @@ public final class VcnGatewayConnectionConfig { * 15m]} * @return this {@link Builder} instance, for chaining * @see VcnManager for additional discussion on fail-safe mode - * @hide */ @NonNull public Builder setRetryInterval(@NonNull long[] retryIntervalsMs) { @@ -523,7 +546,6 @@ public final class VcnGatewayConnectionConfig { * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than * the IPv6 minimum MTU of 1280. Defaults to 1500. * @return this {@link Builder} instance, for chaining - * @hide */ @NonNull public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) { @@ -538,12 +560,15 @@ public final class VcnGatewayConnectionConfig { * Builds and validates the VcnGatewayConnectionConfig. * * @return an immutable VcnGatewayConnectionConfig instance - * @hide */ @NonNull public VcnGatewayConnectionConfig build() { return new VcnGatewayConnectionConfig( - mExposedCapabilities, mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu); + mCtrlPlaneConfig, + mExposedCapabilities, + mUnderlyingCapabilities, + mRetryIntervalsMs, + mMaxMtu); } } } diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index fa090f59a8b9..729e68a6a911 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -17,19 +17,27 @@ package android.net.vcn; import static java.util.Objects.requireNonNull; +import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.net.LinkProperties; import android.net.NetworkCapabilities; +import android.os.Binder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceSpecificException; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting.Visibility; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; @@ -37,12 +45,12 @@ import java.util.concurrent.Executor; /** * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks. * - * <p>A VCN creates a virtualization layer to allow MVNOs to aggregate heterogeneous physical + * <p>A VCN creates a virtualization layer to allow carriers to aggregate heterogeneous physical * networks, unifying them as a single carrier network. This enables infrastructure flexibility on - * the part of MVNOs without impacting user connectivity, abstracting the physical network + * the part of carriers without impacting user connectivity, abstracting the physical network * technologies as an implementation detail of their public network. * - * <p>Each VCN virtualizes an Carrier's network by building tunnels to a carrier's core network over + * <p>Each VCN virtualizes a carrier's network by building tunnels to a carrier's core network over * carrier-managed physical links and supports a IP mobility layer to ensure seamless transitions * between the underlying networks. Each VCN is configured based on a Subscription Group (see {@link * android.telephony.SubscriptionManager}) and aggregates all networks that are brought up based on @@ -60,16 +68,12 @@ import java.util.concurrent.Executor; * tasks. In Safe Mode, the system will allow underlying cellular networks to be used as default. * Additionally, during Safe Mode, the VCN will continue to retry the connections, and will * automatically exit Safe Mode if all active tunnels connect successfully. - * - * @hide */ @SystemService(Context.VCN_MANAGEMENT_SERVICE) public class VcnManager { @NonNull private static final String TAG = VcnManager.class.getSimpleName(); - @VisibleForTesting - public static final Map< - VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder> + private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder> REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>(); @NonNull private final Context mContext; @@ -88,7 +92,18 @@ public class VcnManager { mService = requireNonNull(service, "missing service"); } - // TODO: Make setVcnConfig(), clearVcnConfig() Public API + /** + * Get all currently registered VcnNetworkPolicyListeners for testing purposes. + * + * @hide + */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + @NonNull + public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder> + getAllPolicyListeners() { + return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS); + } + /** * Sets the VCN configuration for a given subscription group. * @@ -100,11 +115,10 @@ public class VcnManager { * * @param subscriptionGroup the subscription group that the configuration should be applied to * @param config the configuration parameters for the VCN - * @throws SecurityException if the caller does not have carrier privileges, or is not running - * as the primary user - * @throws IOException if the configuration failed to be persisted. A caller encountering this - * exception should attempt to retry (possibly after a delay). - * @hide + * @throws SecurityException if the caller does not have carrier privileges for the provided + * subscriptionGroup, or is not running as the primary user + * @throws IOException if the configuration failed to be saved and persisted to disk. This may + * occur due to temporary disk errors, or more permanent conditions such as a full disk. */ @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) @@ -121,7 +135,6 @@ public class VcnManager { } } - // TODO: Make setVcnConfig(), clearVcnConfig() Public API /** * Clears the VCN configuration for a given subscription group. * @@ -132,9 +145,8 @@ public class VcnManager { * @param subscriptionGroup the subscription group that the configuration should be applied to * @throws SecurityException if the caller does not have carrier privileges, or is not running * as the primary user - * @throws IOException if the configuration failed to be cleared. A caller encountering this - * exception should attempt to retry (possibly after a delay). - * @hide + * @throws IOException if the configuration failed to be cleared from disk. This may occur due + * to temporary disk errors, or more permanent conditions such as a full disk. */ @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) throws IOException { @@ -149,45 +161,126 @@ public class VcnManager { } } - // TODO: make VcnUnderlyingNetworkPolicyListener @SystemApi + // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using + // the new VcnNetworkPolicyListener API /** * VcnUnderlyingNetworkPolicyListener is the interface through which internal system components * can register to receive updates for VCN-underlying Network policies from the System Server. * * @hide */ - public interface VcnUnderlyingNetworkPolicyListener { + public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {} + + /** + * Add a listener for VCN-underlying network policy updates. + * + * @param executor the Executor that will be used for invoking all calls to the specified + * Listener + * @param listener the VcnUnderlyingNetworkPolicyListener to be added + * @throws SecurityException if the caller does not have permission NETWORK_FACTORY + * @throws IllegalStateException if the specified VcnUnderlyingNetworkPolicyListener is already + * registered + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public void addVcnUnderlyingNetworkPolicyListener( + @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) { + addVcnNetworkPolicyListener(executor, listener); + } + + /** + * Remove the specified VcnUnderlyingNetworkPolicyListener from VcnManager. + * + * <p>If the specified listener is not currently registered, this is a no-op. + * + * @param listener the VcnUnderlyingNetworkPolicyListener that will be removed + * @hide + */ + public void removeVcnUnderlyingNetworkPolicyListener( + @NonNull VcnUnderlyingNetworkPolicyListener listener) { + removeVcnNetworkPolicyListener(listener); + } + + /** + * Queries the underlying network policy for a network with the given parameters. + * + * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy + * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network + * Provider MUST poll for the updated Network policy based on that Network's capabilities and + * properties. + * + * @param networkCapabilities the NetworkCapabilities to be used in determining the Network + * policy for this Network. + * @param linkProperties the LinkProperties to be used in determining the Network policy for + * this Network. + * @throws SecurityException if the caller does not have permission NETWORK_FACTORY + * @return the VcnUnderlyingNetworkPolicy to be used for this Network. + * @hide + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy( + @NonNull NetworkCapabilities networkCapabilities, + @NonNull LinkProperties linkProperties) { + requireNonNull(networkCapabilities, "networkCapabilities must not be null"); + requireNonNull(linkProperties, "linkProperties must not be null"); + + try { + return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * VcnNetworkPolicyListener is the interface through which internal system components (e.g. + * Network Factories) can register to receive updates for VCN-underlying Network policies from + * the System Server. + * + * <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks + * should register a VcnNetworkPolicyListener. VcnManager will then use this listener to notify + * the registrant when VCN Network policies change. Upon receiving this signal, the listener + * must check {@link VcnManager} for the current Network policy result for each of its Networks + * via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}. + * + * @hide + */ + @SystemApi + public interface VcnNetworkPolicyListener { /** * Notifies the implementation that the VCN's underlying Network policy has changed. * - * <p>After receiving this callback, implementations MUST poll VcnManager for the updated - * VcnUnderlyingNetworkPolicy via VcnManager#getUnderlyingNetworkPolicy. + * <p>After receiving this callback, implementations should get the current {@link + * VcnNetworkPolicyResult} via {@link #applyVcnNetworkPolicy(NetworkCapabilities, + * LinkProperties)}. */ void onPolicyChanged(); } /** - * Add a listener for VCN-underlying network policy updates. + * Add a listener for VCN-underlying Network policy updates. + * + * <p>A {@link VcnNetworkPolicyListener} is eligible to begin receiving callbacks once it is + * registered. No callbacks are guaranteed upon registration. * * @param executor the Executor that will be used for invoking all calls to the specified * Listener - * @param listener the VcnUnderlyingNetworkPolicyListener to be added + * @param listener the VcnNetworkPolicyListener to be added * @throws SecurityException if the caller does not have permission NETWORK_FACTORY - * @throws IllegalArgumentException if the specified VcnUnderlyingNetworkPolicyListener is - * already registered + * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public void addVcnUnderlyingNetworkPolicyListener( - @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) { + public void addVcnNetworkPolicyListener( + @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) { requireNonNull(executor, "executor must not be null"); requireNonNull(listener, "listener must not be null"); VcnUnderlyingNetworkPolicyListenerBinder binder = new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener); if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) { - throw new IllegalArgumentException( - "Attempting to add a listener that is already in use"); + throw new IllegalStateException("listener is already registered with VcnManager"); } try { @@ -199,15 +292,15 @@ public class VcnManager { } /** - * Remove the specified VcnUnderlyingNetworkPolicyListener from VcnManager. + * Remove the specified VcnNetworkPolicyListener from VcnManager. * * <p>If the specified listener is not currently registered, this is a no-op. * - * @param listener the VcnUnderlyingNetworkPolicyListener that will be removed + * @param listener the VcnNetworkPolicyListener that will be removed * @hide */ - public void removeVcnUnderlyingNetworkPolicyListener( - @NonNull VcnUnderlyingNetworkPolicyListener listener) { + @SystemApi + public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) { requireNonNull(listener, "listener must not be null"); VcnUnderlyingNetworkPolicyListenerBinder binder = @@ -224,56 +317,257 @@ public class VcnManager { } /** - * Queries the underlying network policy for a network with the given parameters. + * Applies the network policy for a {@link android.net.Network} with the given parameters. * * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy - * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network - * Provider MUST poll for the updated Network policy based on that Network's capabilities and - * properties. + * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider + * MUST poll for the updated Network policy based on that Network's capabilities and properties. * * @param networkCapabilities the NetworkCapabilities to be used in determining the Network - * policy for this Network. - * @param linkProperties the LinkProperties to be used in determining the Network policy for - * this Network. + * policy result for this Network. + * @param linkProperties the LinkProperties to be used in determining the Network policy result + * for this Network. * @throws SecurityException if the caller does not have permission NETWORK_FACTORY - * @return the VcnUnderlyingNetworkPolicy to be used for this Network. + * @return the {@link VcnNetworkPolicyResult} to be used for this Network. * @hide */ @NonNull + @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy( + public VcnNetworkPolicyResult applyVcnNetworkPolicy( @NonNull NetworkCapabilities networkCapabilities, @NonNull LinkProperties linkProperties) { requireNonNull(networkCapabilities, "networkCapabilities must not be null"); requireNonNull(linkProperties, "linkProperties must not be null"); - try { - return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + final VcnUnderlyingNetworkPolicy policy = + getUnderlyingNetworkPolicy(networkCapabilities, linkProperties); + return new VcnNetworkPolicyResult( + policy.isTeardownRequested(), policy.getMergedNetworkCapabilities()); + } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + VCN_ERROR_CODE_INTERNAL_ERROR, + VCN_ERROR_CODE_CONFIG_ERROR, + VCN_ERROR_CODE_NETWORK_ERROR + }) + public @interface VcnErrorCode {} + + /** + * Value indicating that an internal failure occurred in this Gateway Connection. + * + * @hide + */ + public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0; + + /** + * Value indicating that an error with this Gateway Connection's configuration occurred. + * + * <p>For example, this error code will be returned after authentication failures. + * + * @hide + */ + public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1; + + /** + * Value indicating that a Network error occurred with this Gateway Connection. + * + * <p>For example, this error code will be returned if an underlying {@link android.net.Network} + * for this Gateway Connection is lost, or if an error occurs while resolving the connection + * endpoint address. + * + * @hide + */ + public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2; + + // TODO: make VcnStatusCallback @SystemApi + /** + * VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs. + * + * <p>VcnStatusCallbacks may be registered before {@link VcnConfig}s are provided for a + * subscription group. + * + * @hide + */ + public abstract static class VcnStatusCallback { + private VcnStatusCallbackBinder mCbBinder; + + /** + * Invoked when the VCN for this Callback's subscription group enters safe mode. + * + * <p>A VCN will be put into safe mode if any of the gateway connections were unable to + * establish a connection within a system-determined timeout (while underlying networks were + * available). + * + * <p>A VCN-configuring app may opt to exit safe mode by (re)setting the VCN configuration + * via {@link #setVcnConfig(ParcelUuid, VcnConfig)}. + */ + public abstract void onEnteredSafeMode(); + + /** + * Invoked when a VCN Gateway Connection corresponding to this callback's subscription + * encounters an error. + * + * @param networkCapabilities an array of underlying NetworkCapabilities for the Gateway + * Connection that encountered the error for identification purposes. These will be a + * sorted list with no duplicates, matching one of the {@link + * VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription + * group. + * @param errorCode {@link VcnErrorCode} to indicate the error that occurred + * @param detail Throwable to provide additional information about the error, or {@code + * null} if none + */ + public abstract void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable Throwable detail); + } + + /** + * Registers the given callback to receive status updates for the specified subscription. + * + * <p>Callbacks can be registered for a subscription before {@link VcnConfig}s are set for it. + * + * <p>A {@link VcnStatusCallback} may only be registered for one subscription at a time. {@link + * VcnStatusCallback}s may be reused once unregistered. + * + * <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier + * privileges for the specified subscription at the time of invocation. + * + * @param subscriptionGroup The subscription group to match for callbacks + * @param executor The {@link Executor} to be used for invoking callbacks + * @param callback The VcnStatusCallback to be registered + * @throws IllegalStateException if callback is currently registered with VcnManager + * @hide + */ + public void registerVcnStatusCallback( + @NonNull ParcelUuid subscriptionGroup, + @NonNull Executor executor, + @NonNull VcnStatusCallback callback) { + requireNonNull(subscriptionGroup, "subscriptionGroup must not be null"); + requireNonNull(executor, "executor must not be null"); + requireNonNull(callback, "callback must not be null"); + + synchronized (callback) { + if (callback.mCbBinder != null) { + throw new IllegalStateException("callback is already registered with VcnManager"); + } + callback.mCbBinder = new VcnStatusCallbackBinder(executor, callback); + + try { + mService.registerVcnStatusCallback( + subscriptionGroup, callback.mCbBinder, mContext.getOpPackageName()); + } catch (RemoteException e) { + callback.mCbBinder = null; + throw e.rethrowFromSystemServer(); + } } } /** - * Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System - * Server. + * Unregisters the given callback. + * + * <p>Once unregistered, the callback will stop receiving status updates for the subscription it + * was registered with. + * + * @param callback The callback to be unregistered + * @hide + */ + public void unregisterVcnStatusCallback(@NonNull VcnStatusCallback callback) { + requireNonNull(callback, "callback must not be null"); + + synchronized (callback) { + if (callback.mCbBinder == null) { + // no Binder attached to this callback, so it's not currently registered + return; + } + + try { + mService.unregisterVcnStatusCallback(callback.mCbBinder); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } finally { + callback.mCbBinder = null; + } + } + } + + /** + * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server. * * @hide */ private static class VcnUnderlyingNetworkPolicyListenerBinder extends IVcnUnderlyingNetworkPolicyListener.Stub { @NonNull private final Executor mExecutor; - @NonNull private final VcnUnderlyingNetworkPolicyListener mListener; + @NonNull private final VcnNetworkPolicyListener mListener; private VcnUnderlyingNetworkPolicyListenerBinder( - Executor executor, VcnUnderlyingNetworkPolicyListener listener) { + Executor executor, VcnNetworkPolicyListener listener) { mExecutor = executor; mListener = listener; } @Override public void onPolicyChanged() { - mExecutor.execute(() -> mListener.onPolicyChanged()); + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> mListener.onPolicyChanged())); + } + } + + /** + * Binder wrapper for VcnStatusCallbacks to receive signals from VcnManagementService. + * + * @hide + */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + public static class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub { + @NonNull private final Executor mExecutor; + @NonNull private final VcnStatusCallback mCallback; + + public VcnStatusCallbackBinder( + @NonNull Executor executor, @NonNull VcnStatusCallback callback) { + mExecutor = executor; + mCallback = callback; + } + + @Override + public void onEnteredSafeMode() { + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> mCallback.onEnteredSafeMode())); + } + + // TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling' + @Override + public void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable String exceptionClass, + @Nullable String exceptionMessage) { + final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage); + + Binder.withCleanCallingIdentity( + () -> + mExecutor.execute( + () -> + mCallback.onGatewayConnectionError( + networkCapabilities, errorCode, cause))); + } + + private static Throwable createThrowableByClassName( + @Nullable String className, @Nullable String message) { + if (className == null) { + return null; + } + + try { + Class<?> c = Class.forName(className); + return (Throwable) c.getConstructor(String.class).newInstance(message); + } catch (ReflectiveOperationException | ClassCastException e) { + return new RuntimeException(className + ": " + message); + } } } } diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl new file mode 100644 index 000000000000..3f13abe869da --- /dev/null +++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +/** @hide */ +parcelable VcnNetworkPolicyResult; diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.java b/core/java/android/net/vcn/VcnNetworkPolicyResult.java new file mode 100644 index 000000000000..5e938200639c --- /dev/null +++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.net.NetworkCapabilities; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * VcnNetworkPolicyResult represents the Network policy result for a Network transport applying its + * VCN policy via {@link VcnManager#applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}. + * + * <p>Bearers that are bringing up networks capable of acting as a VCN's underlying network should + * query for Network policy results upon any capability changes (e.g. changing of TRUSTED bit), and + * when prompted by VcnManagementService via {@link VcnManager.VcnNetworkPolicyListener}. + * + * @hide + */ +@SystemApi +public final class VcnNetworkPolicyResult implements Parcelable { + private final boolean mIsTearDownRequested; + private final NetworkCapabilities mNetworkCapabilities; + + /** + * Constructs a VcnNetworkPolicyResult with the specified parameters. + * + * @hide + */ + public VcnNetworkPolicyResult( + boolean isTearDownRequested, @NonNull NetworkCapabilities networkCapabilities) { + Objects.requireNonNull(networkCapabilities, "networkCapabilities must be non-null"); + + mIsTearDownRequested = isTearDownRequested; + mNetworkCapabilities = networkCapabilities; + } + + /** + * Returns whether this VCN policy result requires that the underlying Network should be torn + * down. + * + * <p>Upon querying for the current Network policy result, the bearer must check this method, + * and MUST tear down the corresponding Network if it returns true. + */ + public boolean isTeardownRequested() { + return mIsTearDownRequested; + } + + /** + * Returns the NetworkCapabilities that the bearer should be using for the corresponding + * Network. + */ + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return mNetworkCapabilities; + } + + @Override + public int hashCode() { + return Objects.hash(mIsTearDownRequested, mNetworkCapabilities); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof VcnNetworkPolicyResult)) return false; + final VcnNetworkPolicyResult that = (VcnNetworkPolicyResult) o; + + return mIsTearDownRequested == that.mIsTearDownRequested + && mNetworkCapabilities.equals(that.mNetworkCapabilities); + } + + /** {@inheritDoc} */ + @Override + public int describeContents() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeBoolean(mIsTearDownRequested); + dest.writeParcelable(mNetworkCapabilities, flags); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<VcnNetworkPolicyResult> CREATOR = + new Creator<VcnNetworkPolicyResult>() { + public VcnNetworkPolicyResult createFromParcel(Parcel in) { + return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null)); + } + + public VcnNetworkPolicyResult[] newArray(int size) { + return new VcnNetworkPolicyResult[size]; + } + }; +} diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java index dd7c86d87ff2..b47d5642419e 100644 --- a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java +++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java @@ -33,8 +33,7 @@ import java.util.Objects; * @hide */ public final class VcnUnderlyingNetworkPolicy implements Parcelable { - private final boolean mIsTearDownRequested; - private final NetworkCapabilities mMergedNetworkCapabilities; + private final VcnNetworkPolicyResult mVcnNetworkPolicyResult; /** * Constructs a VcnUnderlyingNetworkPolicy with the specified parameters. @@ -46,8 +45,13 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable { Objects.requireNonNull( mergedNetworkCapabilities, "mergedNetworkCapabilities must be nonnull"); - mIsTearDownRequested = isTearDownRequested; - mMergedNetworkCapabilities = mergedNetworkCapabilities; + mVcnNetworkPolicyResult = + new VcnNetworkPolicyResult(isTearDownRequested, mergedNetworkCapabilities); + } + + private VcnUnderlyingNetworkPolicy(@NonNull VcnNetworkPolicyResult vcnNetworkPolicyResult) { + this.mVcnNetworkPolicyResult = + Objects.requireNonNull(vcnNetworkPolicyResult, "vcnNetworkPolicyResult"); } /** @@ -55,7 +59,7 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable { * be torn down. */ public boolean isTeardownRequested() { - return mIsTearDownRequested; + return mVcnNetworkPolicyResult.isTeardownRequested(); } /** @@ -64,12 +68,12 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable { */ @NonNull public NetworkCapabilities getMergedNetworkCapabilities() { - return mMergedNetworkCapabilities; + return mVcnNetworkPolicyResult.getNetworkCapabilities(); } @Override public int hashCode() { - return Objects.hash(mIsTearDownRequested, mMergedNetworkCapabilities); + return Objects.hash(mVcnNetworkPolicyResult); } @Override @@ -78,8 +82,7 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable { if (!(o instanceof VcnUnderlyingNetworkPolicy)) return false; final VcnUnderlyingNetworkPolicy that = (VcnUnderlyingNetworkPolicy) o; - return mIsTearDownRequested == that.mIsTearDownRequested - && mMergedNetworkCapabilities.equals(that.mMergedNetworkCapabilities); + return mVcnNetworkPolicyResult.equals(that.mVcnNetworkPolicyResult); } /** {@inheritDoc} */ @@ -91,16 +94,14 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable { /** {@inheritDoc} */ @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeBoolean(mIsTearDownRequested); - dest.writeParcelable(mMergedNetworkCapabilities, flags); + dest.writeParcelable(mVcnNetworkPolicyResult, flags); } /** Implement the Parcelable interface */ public static final @NonNull Creator<VcnUnderlyingNetworkPolicy> CREATOR = new Creator<VcnUnderlyingNetworkPolicy>() { public VcnUnderlyingNetworkPolicy createFromParcel(Parcel in) { - return new VcnUnderlyingNetworkPolicy( - in.readBoolean(), in.readParcelable(null)); + return new VcnUnderlyingNetworkPolicy(in.readParcelable(null)); } public VcnUnderlyingNetworkPolicy[] newArray(int size) { diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java b/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java new file mode 100644 index 000000000000..a97563724e50 --- /dev/null +++ b/core/java/android/net/vcn/VcnUnderlyingNetworkSpecifier.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import android.annotation.NonNull; +import android.net.NetworkSpecifier; +import android.net.TelephonyNetworkSpecifier; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting.Visibility; +import com.android.internal.util.ArrayUtils; + +import java.util.Arrays; +import java.util.Objects; + +/** + * NetworkSpecifier object for VCN underlying network requests. + * + * <p>This matches any underlying network with the appropriate subIds. + * + * @hide + */ +public final class VcnUnderlyingNetworkSpecifier extends NetworkSpecifier implements Parcelable { + @NonNull private final int[] mSubIds; + + /** + * Builds a new VcnUnderlyingNetworkSpecifier with the given list of subIds + * + * @hide + */ + public VcnUnderlyingNetworkSpecifier(@NonNull int[] subIds) { + mSubIds = Objects.requireNonNull(subIds, "subIds were null"); + } + + /** + * Retrieves the list of subIds supported by this VcnUnderlyingNetworkSpecifier + * + * @hide + */ + @NonNull + @VisibleForTesting(visibility = Visibility.PRIVATE) + public int[] getSubIds() { + return mSubIds; + } + + public static final @NonNull Creator<VcnUnderlyingNetworkSpecifier> CREATOR = + new Creator<VcnUnderlyingNetworkSpecifier>() { + @Override + public VcnUnderlyingNetworkSpecifier createFromParcel(Parcel in) { + int[] subIds = in.createIntArray(); + return new VcnUnderlyingNetworkSpecifier(subIds); + } + + @Override + public VcnUnderlyingNetworkSpecifier[] newArray(int size) { + return new VcnUnderlyingNetworkSpecifier[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeIntArray(mSubIds); + } + + @Override + public int hashCode() { + return Arrays.hashCode(mSubIds); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof VcnUnderlyingNetworkSpecifier)) { + return false; + } + + VcnUnderlyingNetworkSpecifier lhs = (VcnUnderlyingNetworkSpecifier) obj; + return Arrays.equals(mSubIds, lhs.mSubIds); + } + + @Override + public String toString() { + return new StringBuilder() + .append("VcnUnderlyingNetworkSpecifier [") + .append("mSubIds = ").append(Arrays.toString(mSubIds)) + .append("]") + .toString(); + } + + /** @hide */ + @Override + public boolean canBeSatisfiedBy(NetworkSpecifier other) { + if (other instanceof TelephonyNetworkSpecifier) { + return ArrayUtils.contains( + mSubIds, ((TelephonyNetworkSpecifier) other).getSubscriptionId()); + } + // TODO(b/180140053): Allow matching against WifiNetworkAgentSpecifier + + // MatchAllNetworkSpecifier matched in NetworkCapabilities. + return equals(other); + } +} diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java index 305c686f8657..a435ac12d33c 100644 --- a/core/java/android/os/BugreportManager.java +++ b/core/java/android/os/BugreportManager.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.WorkerThread; import android.app.ActivityManager; import android.content.Context; import android.util.Log; @@ -41,7 +42,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; -/** Class that provides a privileged API to capture and consume bugreports. */ +/** + * Class that provides a privileged API to capture and consume bugreports. + * + * <p>This class may only be used by apps that currently have carrier privileges (see {@link + * android.telephony.TelephonyManager#hasCarrierPrivileges}) on an active SIM or priv-apps + * explicitly allowed by the device manufacturer. + * + * <p>Only one bugreport can be generated by the system at a time. + */ @SystemService(Context.BUGREPORT_SERVICE) public final class BugreportManager { @@ -56,7 +65,12 @@ public final class BugreportManager { mBinder = binder; } - /** An interface describing the callback for bugreport progress and status. */ + /** + * An interface describing the callback for bugreport progress and status. + * + * <p>In general, callers can expect to receive {@link #onProgress} calls as the bugreport + * progresses, followed by a terminal call to either {@link #onFinished} or {@link #onError}. + */ public abstract static class BugreportCallback { /** * Possible error codes taking a bugreport can encounter. @@ -75,15 +89,18 @@ public final class BugreportManager { }) public @interface BugreportErrorCode {} - /** The input options were invalid */ + /** + * The input options were invalid. For example, the destination file the app provided could + * not be written by the system. + */ public static final int BUGREPORT_ERROR_INVALID_INPUT = IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT; - /** A runtime error occurred */ + /** A runtime error occurred. */ public static final int BUGREPORT_ERROR_RUNTIME = IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR; - /** User denied consent to share the bugreport */ + /** User denied consent to share the bugreport. */ public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT; @@ -149,6 +166,7 @@ public final class BugreportManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.DUMP) + @WorkerThread public void startBugreport( @NonNull ParcelFileDescriptor bugreportFd, @Nullable ParcelFileDescriptor screenshotFd, @@ -222,6 +240,7 @@ public final class BugreportManager { * @param callback callback for progress and status updates. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @WorkerThread public void startConnectivityBugreport( @NonNull ParcelFileDescriptor bugreportFd, @NonNull @CallbackExecutor Executor executor, @@ -247,6 +266,7 @@ public final class BugreportManager { * @throws SecurityException if trying to cancel another app's bugreport in progress */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @WorkerThread public void cancelBugreport() { try { mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName()); diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 27dc6e0ada43..903bea3dc2ce 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -1902,7 +1902,8 @@ public final class Debug * Retrieves the PSS memory used by the process as given by the smaps. Optionally supply a long * array of up to 3 entries to also receive (up to 3 values in order): the Uss and SwapPss and * Rss (only filled in as of {@link android.os.Build.VERSION_CODES#P}) of the process, and - * another array to also retrieve the separate memtrack size. + * another array to also retrieve the separate memtrack sizes (up to 4 values in order): the + * total memtrack reported size, memtrack graphics, memtrack gl and memtrack other. * * @return The PSS memory usage, or 0 if failed to retrieve (i.e., given pid has gone). * @hide @@ -2551,6 +2552,22 @@ public final class Debug public static native long getZramFreeKb(); /** + * Return total memory size in kilobytes for exported DMA-BUFs or -1 if + * the DMA-BUF sysfs stats at /sys/kernel/dmabuf/buffers could not be read. + * + * @hide + */ + public static native long getDmabufTotalExportedKb(); + + /** + * Return total memory size in kilobytes for DMA-BUFs exported from the DMA-BUF + * heaps frameworks or -1 in the case of an error. + * + * @hide + */ + public static native long getDmabufHeapTotalExportedKb(); + + /** * Return memory size in kilobytes allocated for ION heaps or -1 if * /sys/kernel/ion/total_heaps_kb could not be read. * @@ -2559,6 +2576,14 @@ public final class Debug public static native long getIonHeapsSizeKb(); /** + * Return memory size in kilobytes allocated for DMA-BUF heap pools or -1 if + * /sys/kernel/dma_heap/total_pools_kb could not be read. + * + * @hide + */ + public static native long getDmabufHeapPoolsSizeKb(); + + /** * Return memory size in kilobytes allocated for ION pools or -1 if * /sys/kernel/ion/total_pools_kb could not be read. * @@ -2567,13 +2592,20 @@ public final class Debug public static native long getIonPoolsSizeKb(); /** - * Return ION memory mapped by processes in kB. + * Return GPU DMA buffer usage in kB or -1 on error. + * + * @hide + */ + public static native long getGpuDmaBufUsageKb(); + + /** + * Return DMA-BUF memory mapped by processes in kB. * Notes: * * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process. * * @hide */ - public static native long getIonMappedSizeKb(); + public static native long getDmabufMappedSizeKb(); /** * Return memory size in kilobytes used by GPU. diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 33deddae01b6..874add5cdbd8 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -24,7 +24,6 @@ import android.net.Network; import android.net.NetworkStats; import android.net.RouteInfo; import android.net.UidRange; -import android.os.INetworkActivityListener; /** * @hide @@ -294,25 +293,6 @@ interface INetworkManagementService @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) boolean isBandwidthControlEnabled(); - /** - * Sets idletimer for an interface. - * - * This either initializes a new idletimer or increases its - * reference-counting if an idletimer already exists for given - * {@code iface}. - * - * {@code type} is the type of the interface, such as TYPE_MOBILE. - * - * Every {@code addIdleTimer} should be paired with a - * {@link removeIdleTimer} to cleanup when the network disconnects. - */ - void addIdleTimer(String iface, int timeout, int type); - - /** - * Removes idletimer for an interface. - */ - void removeIdleTimer(String iface); - void setFirewallEnabled(boolean enabled); boolean isFirewallEnabled(); void setFirewallInterfaceRule(String iface, boolean allow); @@ -320,21 +300,6 @@ interface INetworkManagementService void setFirewallUidRules(int chain, in int[] uids, in int[] rules); void setFirewallChainEnabled(int chain, boolean enable); - /** - * Start listening for mobile activity state changes. - */ - void registerNetworkActivityListener(INetworkActivityListener listener); - - /** - * Stop listening for mobile activity state changes. - */ - void unregisterNetworkActivityListener(INetworkActivityListener listener); - - /** - * Check whether the mobile radio is currently active. - */ - boolean isNetworkActive(); - void addLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid); /** diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl index 52f0ce1f054f..4d160da22ff8 100644 --- a/core/java/android/os/ISystemConfig.aidl +++ b/core/java/android/os/ISystemConfig.aidl @@ -35,4 +35,9 @@ interface ISystemConfig { * @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries */ Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); + + /** + * @see SystemConfigManager#getSystemPermissionUids + */ + int[] getSystemPermissionUids(String permissionName); } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 6713de83d394..43184ea4b9a9 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -26,6 +26,7 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.app.KeyguardManager; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.BroadcastReceiver; @@ -631,10 +632,15 @@ public class RecoverySystem { /** * Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge * Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup - * and ready to apply the OTA. This API is expected to handle requests from multiple clients - * simultaneously, e.g. from ota and mainline. + * and ready to apply the OTA. <p> * - * <p> The behavior of multi-client Resume on Reboot works as follows + * <p> If the device doesn't setup a lock screen, i.e. by checking + * {@link KeyguardManager#isKeyguardSecure()}, this API call will fail and throw an exception. + * Callers are expected to use {@link PowerManager#reboot(String)} directly without going + * through the RoR flow. <p> + * + * <p> This API is expected to handle requests from multiple clients simultaneously, e.g. + * from ota and mainline. The behavior of multi-client Resume on Reboot works as follows * <li> Each client should call this function to prepare for Resume on Reboot before calling * {@link #rebootAndApply(Context, String, boolean)} </li> * <li> One client cannot clear the Resume on Reboot preparation of another client. </li> @@ -658,6 +664,13 @@ public class RecoverySystem { if (updateToken == null) { throw new NullPointerException("updateToken == null"); } + + KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class); + if (keyguardManager == null || !keyguardManager.isDeviceSecure()) { + throw new IOException("Failed to request LSKF because the device doesn't have a" + + " lock screen. "); + } + RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); if (!rs.requestLskf(context.getPackageName(), intentSender)) { throw new IOException("preparation for update failed"); @@ -958,7 +971,11 @@ public class RecoverySystem { Intent intent = new Intent(ACTION_EUICC_FACTORY_RESET); intent.setPackage(packageName); PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM); + context, + 0, + intent, + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, + UserHandle.SYSTEM); IntentFilter filterConsent = new IntentFilter(); filterConsent.addAction(ACTION_EUICC_FACTORY_RESET); HandlerThread euiccHandlerThread = new HandlerThread("euiccWipeFinishReceiverThread"); @@ -1052,7 +1069,11 @@ public class RecoverySystem { Intent intent = new Intent(ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS); intent.setPackage(PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK); PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM); + context, + 0, + intent, + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, + UserHandle.SYSTEM); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS); HandlerThread euiccHandlerThread = diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java index 3f0632be90d1..9bfa8adc8571 100644 --- a/core/java/android/os/SystemConfigManager.java +++ b/core/java/android/os/SystemConfigManager.java @@ -111,4 +111,22 @@ public class SystemConfigManager { return Collections.emptyMap(); } } + + /** + * Get uids which have been granted given permission in system configuration. + * + * The uids and assigning permissions are defined on data/etc/platform.xml + * + * @param permissionName The target permission. + * @return The uids have been granted given permission in system configuration. + */ + @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS) + @NonNull + public int[] getSystemPermissionUids(@NonNull String permissionName) { + try { + return mInterface.getSystemPermissionUids(permissionName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index 9c9e4995d673..c8cbc517b226 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -168,8 +168,10 @@ public final class Trace { } /** - * Set whether application tracing is allowed for this process. This is intended to be set - * once at application start-up time based on whether the application is debuggable. + * From Android S, this is no-op. + * + * Before, set whether application tracing is allowed for this process. This is intended to be + * set once at application start-up time based on whether the application is debuggable. * * @hide */ diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS index d09f351bdfd1..b32346848a69 100644 --- a/core/java/android/permission/OWNERS +++ b/core/java/android/permission/OWNERS @@ -1,6 +1,5 @@ # Bug component: 137825 -moltmann@google.com evanseverson@google.com ntmyren@google.com zhanghai@google.com diff --git a/core/java/android/permissionpresenterservice/OWNERS b/core/java/android/permissionpresenterservice/OWNERS index d09f351bdfd1..b32346848a69 100644 --- a/core/java/android/permissionpresenterservice/OWNERS +++ b/core/java/android/permissionpresenterservice/OWNERS @@ -1,6 +1,5 @@ # Bug component: 137825 -moltmann@google.com evanseverson@google.com ntmyren@google.com zhanghai@google.com diff --git a/core/java/android/print/OWNERS b/core/java/android/print/OWNERS index 72f09832becf..28a242037f6a 100644 --- a/core/java/android/print/OWNERS +++ b/core/java/android/print/OWNERS @@ -1,5 +1,4 @@ # Bug component: 47273 -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com diff --git a/core/java/android/print/pdf/OWNERS b/core/java/android/print/pdf/OWNERS index 72f09832becf..28a242037f6a 100644 --- a/core/java/android/print/pdf/OWNERS +++ b/core/java/android/print/pdf/OWNERS @@ -1,5 +1,4 @@ # Bug component: 47273 -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com diff --git a/core/java/android/printservice/OWNERS b/core/java/android/printservice/OWNERS index 72f09832becf..28a242037f6a 100644 --- a/core/java/android/printservice/OWNERS +++ b/core/java/android/printservice/OWNERS @@ -1,5 +1,4 @@ # Bug component: 47273 -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com diff --git a/core/java/android/printservice/recommendation/OWNERS b/core/java/android/printservice/recommendation/OWNERS index 72f09832becf..28a242037f6a 100644 --- a/core/java/android/printservice/recommendation/OWNERS +++ b/core/java/android/printservice/recommendation/OWNERS @@ -1,5 +1,4 @@ # Bug component: 47273 -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com diff --git a/core/java/android/provider/SimPhonebookContract.java b/core/java/android/provider/SimPhonebookContract.java index 2efc21229422..074d5f167ec3 100644 --- a/core/java/android/provider/SimPhonebookContract.java +++ b/core/java/android/provider/SimPhonebookContract.java @@ -29,11 +29,8 @@ import android.annotation.SystemApi; import android.annotation.WorkerThread; import android.content.ContentResolver; import android.content.ContentValues; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; @@ -63,7 +60,6 @@ public final class SimPhonebookContract { * * @hide */ - @SystemApi public static final String SUBSCRIPTION_ID_PATH_SEGMENT = "subid"; private SimPhonebookContract() { @@ -76,7 +72,6 @@ public final class SimPhonebookContract { * @hide */ @NonNull - @SystemApi public static String getEfUriPath(@ElementaryFiles.EfType int efType) { switch (efType) { case EF_ADN: @@ -122,12 +117,12 @@ public final class SimPhonebookContract { * The name for this record. * * <p>An {@link IllegalArgumentException} will be thrown by insert and update if this - * exceeds the maximum supported length or contains unsupported characters. - * {@link #validateName(ContentResolver, int, int, String)} )} can be used to - * check whether the name is supported. + * exceeds the maximum supported length. Use + * {@link #getEncodedNameLength(ContentResolver, String)} to check how long the name + * will be after encoding. * * @see ElementaryFiles#NAME_MAX_LENGTH - * @see #validateName(ContentResolver, int, int, String) ) + * @see #getEncodedNameLength(ContentResolver, String) */ public static final String NAME = "name"; /** @@ -149,24 +144,31 @@ public final class SimPhonebookContract { public static final String CONTENT_TYPE = "vnd.android.cursor.dir/sim-contact_v2"; /** - * The path segment that is appended to {@link #getContentUri(int, int)} which indicates - * that the following path segment contains a name to be validated. + * Value returned from {@link #getEncodedNameLength(ContentResolver, String)} when the name + * length could not be determined because the name could not be encoded. + */ + public static final int ERROR_NAME_UNSUPPORTED = -1; + + /** + * The method name used to get the encoded length of a value for {@link SimRecords#NAME} + * column. * * @hide - * @see #validateName(ContentResolver, int, int, String) + * @see #getEncodedNameLength(ContentResolver, String) + * @see ContentResolver#call(String, String, String, Bundle) */ - @SystemApi - public static final String VALIDATE_NAME_PATH_SEGMENT = "validate_name"; + public static final String GET_ENCODED_NAME_LENGTH_METHOD_NAME = "get_encoded_name_length"; /** - * The key for a cursor extra that contains the result of a validate name query. + * Extra key used for an integer value that contains the length in bytes of an encoded + * name. * * @hide - * @see #validateName(ContentResolver, int, int, String) + * @see #getEncodedNameLength(ContentResolver, String) + * @see #GET_ENCODED_NAME_LENGTH_METHOD_NAME */ - @SystemApi - public static final String EXTRA_NAME_VALIDATION_RESULT = - "android.provider.extra.NAME_VALIDATION_RESULT"; + public static final String EXTRA_ENCODED_NAME_LENGTH = + "android.provider.extra.ENCODED_NAME_LENGTH"; /** @@ -244,32 +246,34 @@ public final class SimPhonebookContract { } /** - * Validates a value that is being provided for the {@link #NAME} column. + * Returns the number of bytes required to encode the specified name when it is stored + * on the SIM. * - * <p>The return value can be used to check if the name is valid. If it is not valid then - * inserts and updates to the specified elementary file that use the provided name value - * will throw an {@link IllegalArgumentException}. + * <p>{@link ElementaryFiles#NAME_MAX_LENGTH} is specified in bytes but the encoded name + * may require more than 1 byte per character depending on the characters it contains. So + * this method can be used to check whether a name exceeds the max length. * - * <p>If the specified SIM or elementary file don't exist then - * {@link NameValidationResult#getMaxEncodedLength()} will be zero and - * {@link NameValidationResult#isValid()} will return false. + * @return the number of bytes required by the encoded name or + * {@link #ERROR_NAME_UNSUPPORTED} if the name could not be encoded. + * @throws IllegalStateException if the provider fails to return the length. + * @see SimRecords#NAME + * @see ElementaryFiles#NAME_MAX_LENGTH */ - @NonNull @WorkerThread - public static NameValidationResult validateName( - @NonNull ContentResolver resolver, int subscriptionId, - @ElementaryFiles.EfType int efType, - @NonNull String name) { - Bundle queryArgs = new Bundle(); - queryArgs.putString(SimRecords.NAME, name); - try (Cursor cursor = - resolver.query(buildContentUri(subscriptionId, efType) - .appendPath(VALIDATE_NAME_PATH_SEGMENT) - .build(), null, queryArgs, null)) { - NameValidationResult result = cursor.getExtras() - .getParcelable(EXTRA_NAME_VALIDATION_RESULT); - return result != null ? result : new NameValidationResult(name, "", 0, 0); + public static int getEncodedNameLength( + @NonNull ContentResolver resolver, @NonNull String name) { + Objects.requireNonNull(name); + Bundle result = resolver.call(AUTHORITY, GET_ENCODED_NAME_LENGTH_METHOD_NAME, name, + null); + if (result == null || !result.containsKey(EXTRA_ENCODED_NAME_LENGTH)) { + throw new IllegalStateException("Provider malfunction: no length was returned."); } + int length = result.getInt(EXTRA_ENCODED_NAME_LENGTH, ERROR_NAME_UNSUPPORTED); + if (length < 0 && length != ERROR_NAME_UNSUPPORTED) { + throw new IllegalStateException( + "Provider malfunction: invalid length was returned."); + } + return length; } private static Uri.Builder buildContentUri( @@ -281,106 +285,6 @@ public final class SimPhonebookContract { .appendPath(getEfUriPath(efType)); } - /** Contains details about the validity of a value provided for the {@link #NAME} column. */ - public static final class NameValidationResult implements Parcelable { - - @NonNull - public static final Creator<NameValidationResult> CREATOR = - new Creator<NameValidationResult>() { - - @Override - public NameValidationResult createFromParcel(@NonNull Parcel in) { - return new NameValidationResult(in); - } - - @NonNull - @Override - public NameValidationResult[] newArray(int size) { - return new NameValidationResult[size]; - } - }; - - private final String mName; - private final String mSanitizedName; - private final int mEncodedLength; - private final int mMaxEncodedLength; - - /** Creates a new instance from the provided values. */ - public NameValidationResult(@NonNull String name, @NonNull String sanitizedName, - int encodedLength, int maxEncodedLength) { - this.mName = Objects.requireNonNull(name); - this.mSanitizedName = Objects.requireNonNull(sanitizedName); - this.mEncodedLength = encodedLength; - this.mMaxEncodedLength = maxEncodedLength; - } - - private NameValidationResult(Parcel in) { - this(in.readString(), in.readString(), in.readInt(), in.readInt()); - } - - /** Returns the original name that is being validated. */ - @NonNull - public String getName() { - return mName; - } - - /** - * Returns a sanitized copy of the original name with all unsupported characters - * replaced with spaces. - */ - @NonNull - public String getSanitizedName() { - return mSanitizedName; - } - - /** - * Returns whether the original name isValid. - * - * <p>If this returns false then inserts and updates using the name will throw an - * {@link IllegalArgumentException} - */ - public boolean isValid() { - return mMaxEncodedLength > 0 && mEncodedLength <= mMaxEncodedLength - && Objects.equals( - mName, mSanitizedName); - } - - /** Returns whether the character at the specified position is supported by the SIM. */ - public boolean isSupportedCharacter(int position) { - return mName.charAt(position) == mSanitizedName.charAt(position); - } - - /** - * Returns the number of bytes required to save the name. - * - * <p>This may be more than the number of characters in the name. - */ - public int getEncodedLength() { - return mEncodedLength; - } - - /** - * Returns the maximum number of bytes that are supported for the name. - * - * @see ElementaryFiles#NAME_MAX_LENGTH - */ - public int getMaxEncodedLength() { - return mMaxEncodedLength; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(mName); - dest.writeString(mSanitizedName); - dest.writeInt(mEncodedLength); - dest.writeInt(mMaxEncodedLength); - } - } } /** Constants for metadata about the elementary files of the SIM cards in the phone. */ @@ -446,13 +350,10 @@ public final class SimPhonebookContract { */ public static final int EF_SDN = 3; /** @hide */ - @SystemApi public static final String EF_ADN_PATH_SEGMENT = "adn"; /** @hide */ - @SystemApi public static final String EF_FDN_PATH_SEGMENT = "fdn"; /** @hide */ - @SystemApi public static final String EF_SDN_PATH_SEGMENT = "sdn"; /** The MIME type of CONTENT_URI providing a directory of ADN-like elementary files. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/sim-elementary-file"; @@ -464,7 +365,6 @@ public final class SimPhonebookContract { * * @hide */ - @SystemApi public static final String ELEMENTARY_FILES_PATH_SEGMENT = "elementary_files"; /** Content URI for the ADN-like elementary files available on the device. */ @@ -480,8 +380,7 @@ public final class SimPhonebookContract { * Returns a content uri for a specific elementary file. * * <p>If a SIM with the specified subscriptionId is not present an exception will be thrown. - * If the SIM doesn't support the specified elementary file it will have a zero value for - * {@link #MAX_RECORDS}. + * If the SIM doesn't support the specified elementary file it will return an empty cursor. */ @NonNull public static Uri getItemUri(int subscriptionId, @EfType int efType) { diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index a79b197d3faa..5a89cdf1d340 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -188,6 +188,7 @@ public final class KeymasterDefs { public static final int KM_PURPOSE_VERIFY = KeyPurpose.VERIFY; public static final int KM_PURPOSE_WRAP = KeyPurpose.WRAP_KEY; public static final int KM_PURPOSE_AGREE_KEY = KeyPurpose.AGREE_KEY; + public static final int KM_PURPOSE_ATTEST_KEY = KeyPurpose.ATTEST_KEY; // Key formats. public static final int KM_KEY_FORMAT_X509 = KeyFormat.X509; diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp index ffbdb035c36c..a527d3d10fdf 100644 --- a/core/java/android/service/wallpaper/Android.bp +++ b/core/java/android/service/wallpaper/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "WallpaperSharedLib", diff --git a/core/java/android/uwb/OWNERS b/core/java/android/uwb/OWNERS index ea41c3984dfd..17936ae7bb73 100644 --- a/core/java/android/uwb/OWNERS +++ b/core/java/android/uwb/OWNERS @@ -1,5 +1,6 @@ bstack@google.com eliptus@google.com jsolnit@google.com +matbev@google.com siyuanh@google.com zachoverflow@google.com diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java index bfa8bf21ec6a..52ec5bde0dac 100644 --- a/core/java/android/uwb/RangingSession.java +++ b/core/java/android/uwb/RangingSession.java @@ -16,8 +16,10 @@ package android.uwb; +import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.Binder; import android.os.PersistableBundle; @@ -247,6 +249,7 @@ public final class RangingSession implements AutoCloseable { * * @param params configuration parameters for starting the session */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void start(@NonNull PersistableBundle params) { if (mState != State.IDLE) { throw new IllegalStateException(); @@ -271,6 +274,7 @@ public final class RangingSession implements AutoCloseable { * * @param params the parameters to reconfigure and their new values */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void reconfigure(@NonNull PersistableBundle params) { if (mState != State.ACTIVE && mState != State.IDLE) { throw new IllegalStateException(); @@ -302,6 +306,7 @@ public final class RangingSession implements AutoCloseable { * <p>On failure to stop the session, * {@link RangingSession.Callback#onStopFailed(int, PersistableBundle)} is invoked. */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void stop() { if (mState != State.ACTIVE) { throw new IllegalStateException(); @@ -333,6 +338,7 @@ public final class RangingSession implements AutoCloseable { * {@link #close()}, even if the {@link RangingSession} is already closed. */ @Override + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void close() { if (mState == State.CLOSED) { mExecutor.execute(() -> mCallback.onClosed( diff --git a/core/java/android/uwb/TEST_MAPPING b/core/java/android/uwb/TEST_MAPPING index 9e50bd64d089..08ed2c7b71d9 100644 --- a/core/java/android/uwb/TEST_MAPPING +++ b/core/java/android/uwb/TEST_MAPPING @@ -2,6 +2,9 @@ "presubmit": [ { "name": "UwbManagerTests" + }, + { + "name": "CtsUwbTestCases" } ] -}
\ No newline at end of file +} diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java index 8adfe0601b14..2dc0ba0b9b80 100644 --- a/core/java/android/uwb/UwbManager.java +++ b/core/java/android/uwb/UwbManager.java @@ -16,9 +16,11 @@ package android.uwb; +import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -154,6 +156,7 @@ public final class UwbManager { * @param executor an {@link Executor} to execute given callback * @param callback user implementation of the {@link AdapterStateCallback} */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull @CallbackExecutor Executor executor, @NonNull AdapterStateCallback callback) { mAdapterStateListener.register(executor, callback); @@ -168,6 +171,7 @@ public final class UwbManager { * * @param callback user implementation of the {@link AdapterStateCallback} */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull AdapterStateCallback callback) { mAdapterStateListener.unregister(callback); } @@ -181,6 +185,7 @@ public final class UwbManager { * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters */ @NonNull + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public PersistableBundle getSpecificationInfo() { try { return mUwbAdapter.getSpecificationInfo(); @@ -194,6 +199,7 @@ public final class UwbManager { * * @return true if ranging is supported */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public boolean isRangingSupported() { try { return mUwbAdapter.isRangingSupported(); @@ -250,6 +256,7 @@ public final class UwbManager { * @return angle of arrival type supported */ @AngleOfArrivalSupportType + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public int getAngleOfArrivalSupport() { try { switch (mUwbAdapter.getAngleOfArrivalSupport()) { @@ -281,6 +288,7 @@ public final class UwbManager { * @return {@link List} of supported channel numbers ordered by preference */ @NonNull + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public List<Integer> getSupportedChannelNumbers() { List<Integer> channels = new ArrayList<>(); try { @@ -300,6 +308,7 @@ public final class UwbManager { * @return {@link List} of supported preamble code indices */ @NonNull + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public Set<Integer> getSupportedPreambleCodeIndices() { Set<Integer> preambles = new HashSet<>(); try { @@ -320,6 +329,7 @@ public final class UwbManager { * @return the timestamp resolution in nanoseconds */ @SuppressLint("MethodNameUnits") + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos() { try { return mUwbAdapter.getTimestampResolutionNanos(); @@ -333,6 +343,7 @@ public final class UwbManager { * * @return the maximum allowed number of simultaneously open {@link RangingSession} instances. */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public int getMaxSimultaneousSessions() { try { return mUwbAdapter.getMaxSimultaneousSessions(); @@ -347,6 +358,7 @@ public final class UwbManager { * * @return the maximum number of remote devices per {@link RangingSession} */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerInitiatorSession() { try { return mUwbAdapter.getMaxRemoteDevicesPerInitiatorSession(); @@ -361,6 +373,7 @@ public final class UwbManager { * * @return the maximum number of remote devices per {@link RangingSession} */ + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerResponderSession() { try { return mUwbAdapter.getMaxRemoteDevicesPerResponderSession(); @@ -396,6 +409,7 @@ public final class UwbManager { * {@link RangingSession.Callback#onOpened(RangingSession)}. */ @NonNull + @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters, @NonNull @CallbackExecutor Executor executor, @NonNull RangingSession.Callback callbacks) { diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index c5ca88605633..8810814849b2 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1911,7 +1911,10 @@ public final class AutofillManager { if (client == null) { return; } - + if (mService == null) { + Log.w(TAG, "Autofill service is null!"); + return; + } if (mServiceClient == null) { mServiceClient = new AutofillManagerClient(this); try { diff --git a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.aidl b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.aidl new file mode 100644 index 000000000000..5d02a29edcd5 --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.compat; + +parcelable CompatibilityOverrideConfig; diff --git a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java new file mode 100644 index 000000000000..1c222a73eabc --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.compat; + + +import android.app.compat.PackageOverride; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.HashMap; +import java.util.Map; + +/** + * Parcelable containing compat config overrides for a given application. + * @hide + */ +public final class CompatibilityOverrideConfig implements Parcelable { + public final Map<Long, PackageOverride> overrides; + + public CompatibilityOverrideConfig(Map<Long, PackageOverride> overrides) { + this.overrides = overrides; + } + + private CompatibilityOverrideConfig(Parcel in) { + int keyCount = in.readInt(); + overrides = new HashMap<>(); + for (int i = 0; i < keyCount; i++) { + long key = in.readLong(); + PackageOverride override = in.readParcelable(PackageOverride.class.getClassLoader()); + overrides.put(key, override); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(overrides.size()); + for (Long key : overrides.keySet()) { + dest.writeLong(key); + dest.writeParcelable(overrides.get(key), 0); + } + } + + public static final Creator<CompatibilityOverrideConfig> CREATOR = + new Creator<CompatibilityOverrideConfig>() { + + @Override + public CompatibilityOverrideConfig createFromParcel(Parcel in) { + return new CompatibilityOverrideConfig(in); + } + + @Override + public CompatibilityOverrideConfig[] newArray(int size) { + return new CompatibilityOverrideConfig[size]; + } + }; +} diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index a5eb5f607c12..60213e4411c3 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -21,6 +21,7 @@ import com.android.internal.compat.IOverrideValidator; import java.util.Map; parcelable CompatibilityChangeConfig; +parcelable CompatibilityOverrideConfig; parcelable CompatibilityChangeInfo; /** * Platform private API for talking with the PlatformCompat service. @@ -152,6 +153,17 @@ interface IPlatformCompat { /** * Adds overrides to compatibility changes. * + * <p>Kills the app to allow the changes to take effect. + * + * @param overrides parcelable containing the compat change overrides to be applied + * @param packageName the package name of the app whose changes will be overridden + * @throws SecurityException if overriding changes is not permitted + */ + void setOverridesFromInstaller(in CompatibilityOverrideConfig overrides, in String packageName); + + /** + * Adds overrides to compatibility changes. + * * <p>Does not kill the app, to be only used in tests. * * @param overrides parcelable containing the compat change overrides to be applied diff --git a/core/java/com/android/internal/graphics/palette/OWNERS b/core/java/com/android/internal/graphics/palette/OWNERS new file mode 100644 index 000000000000..731dca9b128f --- /dev/null +++ b/core/java/com/android/internal/graphics/palette/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 484670
+dupin@google.com
+jamesoleary@google.com
\ No newline at end of file diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index a41018000d77..65beb9360241 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -590,7 +590,7 @@ public final class Zygote { static Runnable forkUsap(LocalServerSocket usapPoolSocket, int[] sessionSocketRawFDs, boolean isPriorityFork) { - FileDescriptor[] pipeFDs = null; + FileDescriptor[] pipeFDs; try { pipeFDs = Os.pipe2(O_CLOEXEC); diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 6573e4217a7f..5a576ebbc442 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -505,8 +505,8 @@ class ZygoteConnection { parsedArgs.mDisabledCompatChanges, parsedArgs.mRemainingArgs, null /* classLoader */); } else { - return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, - parsedArgs.mRemainingArgs, null /* classLoader */); + return ZygoteInit.childZygoteInit( + parsedArgs.mRemainingArgs /* classLoader */); } } } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 7fde5474ec92..ef1c50f43681 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -117,7 +117,7 @@ public class ZygoteInit { /** * Controls whether we should preload resources during zygote init. */ - public static final boolean PRELOAD_RESOURCES = true; + private static final boolean PRELOAD_RESOURCES = true; private static final int UNPRIVILEGED_UID = 9999; private static final int UNPRIVILEGED_GID = 9999; @@ -159,7 +159,7 @@ public class ZygoteInit { sPreloadComplete = true; } - public static void lazyPreload() { + static void lazyPreload() { Preconditions.checkState(!sPreloadComplete); Log.i(TAG, "Lazily preloading resources."); @@ -364,7 +364,7 @@ public class ZygoteInit { } if ("true".equals(prop)) { Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters"); - runtime.resetJitCounters(); + VMRuntime.resetJitCounters(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); } @@ -418,8 +418,6 @@ public class ZygoteInit { * larger. */ private static void preloadResources() { - final VMRuntime runtime = VMRuntime.getRuntime(); - try { mResources = Resources.getSystem(); mResources.startPreloading(); @@ -463,9 +461,7 @@ public class ZygoteInit { int N = ar.length(); for (int i = 0; i < N; i++) { int id = ar.getResourceId(i, 0); - if (false) { - Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); - } + if (id != 0) { if (mResources.getColorStateList(id, null) == null) { throw new IllegalArgumentException( @@ -483,9 +479,7 @@ public class ZygoteInit { int N = ar.length(); for (int i = 0; i < N; i++) { int id = ar.getResourceId(i, 0); - if (false) { - Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); - } + if (id != 0) { if (mResources.getDrawable(id, null) == null) { throw new IllegalArgumentException( @@ -688,13 +682,12 @@ public class ZygoteInit { final String packageName = "*"; final String outputPath = null; final int dexFlags = 0; - final String compilerFilter = systemServerFilter; final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; final String seInfo = null; final int targetSdkVersion = 0; // SystemServer targets the system's SDK version try { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, - instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, + instructionSet, dexoptNeeded, outputPath, dexFlags, systemServerFilter, uuid, classLoaderContext, seInfo, false /* downgrade */, targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null, "server-dexopt"); @@ -770,7 +763,7 @@ public class ZygoteInit { capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32); /* Hardcoded command line to start the system server */ - String args[] = { + String[] args = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023," @@ -781,7 +774,7 @@ public class ZygoteInit { "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, "com.android.server.SystemServer", }; - ZygoteArguments parsedArgs = null; + ZygoteArguments parsedArgs; int pid; @@ -870,7 +863,7 @@ public class ZygoteInit { * @param argv Command line arguments used to specify the Zygote's configuration. */ @UnsupportedAppUsage - public static void main(String argv[]) { + public static void main(String[] argv) { ZygoteServer zygoteServer = null; // Mark zygote start. This ensures that thread creation will throw @@ -1029,7 +1022,7 @@ public class ZygoteInit { * are enabled) * @param argv arg strings */ - public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, + public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); @@ -1049,11 +1042,10 @@ public class ZygoteInit { * to zygoteInit(), which skips calling into initialization routines that start the Binder * threadpool. */ - static final Runnable childZygoteInit( - int targetSdkVersion, String[] argv, ClassLoader classLoader) { + static Runnable childZygoteInit(String[] argv) { RuntimeInit.Arguments args = new RuntimeInit.Arguments(argv); - return RuntimeInit.findStaticMain(args.startClass, args.startArgs, classLoader); + return RuntimeInit.findStaticMain(args.startClass, args.startArgs, /* classLoader= */null); } - private static final native void nativeZygoteInit(); + private static native void nativeZygoteInit(); } diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java index db7cbbca450e..585ddf6ddf98 100644 --- a/core/java/com/android/internal/os/ZygoteServer.java +++ b/core/java/com/android/internal/os/ZygoteServer.java @@ -411,7 +411,7 @@ class ZygoteServer { } } - void resetUsapRefillState() { + private void resetUsapRefillState() { mUsapPoolRefillAction = UsapPoolRefillAction.NONE; mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP; } diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java index c46d7086ca80..dd40fbcdbce1 100644 --- a/core/java/com/android/server/BootReceiver.java +++ b/core/java/com/android/server/BootReceiver.java @@ -75,6 +75,7 @@ public class BootReceiver extends BroadcastReceiver { private static final int GMSCORE_LASTK_LOG_SIZE = 196608; private static final String TAG_TOMBSTONE = "SYSTEM_TOMBSTONE"; + private static final String TAG_TOMBSTONE_PROTO = "SYSTEM_TOMBSTONE_PROTO"; // The pre-froyo package and class of the system updater, which // ran in the system process. We need to remove its packages here @@ -252,14 +253,14 @@ public class BootReceiver extends BroadcastReceiver { * @param ctx Context * @param tombstone path to the tombstone */ - public static void addTombstoneToDropBox(Context ctx, File tombstone) { + public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); final String bootReason = SystemProperties.get("ro.boot.bootreason", null); HashMap<String, Long> timestamps = readTimestamps(); try { final String headers = getBootHeadersToLogAndUpdate(); addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, - TAG_TOMBSTONE); + proto ? TAG_TOMBSTONE_PROTO : TAG_TOMBSTONE); } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 79a0dfd61e9f..0d05a6b82d36 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -1,4 +1,21 @@ +package { + default_applicable_licenses: ["frameworks_base_core_jni_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_core_jni_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_shared { name: "libandroid_runtime", host_supported: true, @@ -50,11 +67,12 @@ cc_library_shared { "libhwui", "liblog", "libminikin", - "libnativehelper", "libz", "libziparchive", ], + static_libs: ["libnativehelper_lazy"], + export_include_dirs: [ ".", "include", @@ -206,6 +224,7 @@ cc_library_shared { ], shared_libs: [ + "android.hardware.memtrack-V1-ndk_platform", "libandroidicu", "libbpf_android", "libnetdbpf", @@ -266,12 +285,13 @@ cc_library_shared { "libstatspull", ], export_shared_lib_headers: [ - // AndroidRuntime.h depends on nativehelper/jni.h - "libnativehelper", - // our headers include libnativewindow's public headers "libnativewindow", ], + export_static_lib_headers: [ + // AndroidRuntime.h depends on nativehelper/jni.h + "libnativehelper_lazy", + ], header_libs: [ "bionic_libc_platform_headers", "dnsproxyd_protocol_headers", diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 28fc8ede1653..0e3db46bd0c9 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -33,6 +33,7 @@ #include <string> #include <vector> +#include <aidl/android/hardware/memtrack/DeviceInfo.h> #include <android-base/logging.h> #include <bionic/malloc.h> #include <debuggerd/client.h> @@ -43,7 +44,9 @@ #include <nativehelper/JNIPlatformHelp.h> #include <nativehelper/ScopedUtfChars.h> #include "jni.h" +#include <dmabufinfo/dmabuf_sysfs_stats.h> #include <dmabufinfo/dmabufinfo.h> +#include <dmabufinfo/dmabuf_sysfs_stats.h> #include <meminfo/procmeminfo.h> #include <meminfo/sysmeminfo.h> #include <memtrack/memtrack.h> @@ -519,14 +522,15 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, } if (outUssSwapPssRss != NULL) { - if (env->GetArrayLength(outUssSwapPssRss) >= 1) { + int outLen = env->GetArrayLength(outUssSwapPssRss); + if (outLen >= 1) { jlong* outUssSwapPssRssArray = env->GetLongArrayElements(outUssSwapPssRss, 0); if (outUssSwapPssRssArray != NULL) { outUssSwapPssRssArray[0] = uss; - if (env->GetArrayLength(outUssSwapPssRss) >= 2) { + if (outLen >= 2) { outUssSwapPssRssArray[1] = swapPss; } - if (env->GetArrayLength(outUssSwapPssRss) >= 3) { + if (outLen >= 3) { outUssSwapPssRssArray[2] = rss; } } @@ -535,10 +539,20 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, } if (outMemtrack != NULL) { - if (env->GetArrayLength(outMemtrack) >= 1) { + int outLen = env->GetArrayLength(outMemtrack); + if (outLen >= 1) { jlong* outMemtrackArray = env->GetLongArrayElements(outMemtrack, 0); if (outMemtrackArray != NULL) { outMemtrackArray[0] = memtrack; + if (outLen >= 2) { + outMemtrackArray[1] = graphics_mem.graphics; + } + if (outLen >= 3) { + outMemtrackArray[2] = graphics_mem.gl; + } + if (outLen >= 4) { + outMemtrackArray[3] = graphics_mem.other; + } } env->ReleaseLongArrayElements(outMemtrack, outMemtrackArray, 0); } @@ -802,6 +816,26 @@ static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) { return heapsSizeKb; } +static jlong android_os_Debug_getDmabufTotalExportedKb(JNIEnv* env, jobject clazz) { + jlong dmabufTotalSizeKb = -1; + uint64_t size; + + if (dmabufinfo::GetDmabufTotalExportedKb(&size)) { + dmabufTotalSizeKb = size; + } + return dmabufTotalSizeKb; +} + +static jlong android_os_Debug_getDmabufHeapTotalExportedKb(JNIEnv* env, jobject clazz) { + jlong dmabufHeapTotalSizeKb = -1; + uint64_t size; + + if (meminfo::ReadDmabufHeapTotalExportedKb(&size)) { + dmabufHeapTotalSizeKb = size; + } + return dmabufHeapTotalSizeKb; +} + static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) { jlong poolsSizeKb = -1; uint64_t size; @@ -813,8 +847,44 @@ static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) { return poolsSizeKb; } -static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) { - jlong ionPss = 0; +static jlong android_os_Debug_getDmabufHeapPoolsSizeKb(JNIEnv* env, jobject clazz) { + jlong poolsSizeKb = -1; + uint64_t size; + + if (meminfo::ReadDmabufHeapPoolsSizeKb(&size)) { + poolsSizeKb = size; + } + + return poolsSizeKb; +} + +static jlong android_os_Debug_getGpuDmaBufUsageKb(JNIEnv* env, jobject clazz) { + std::vector<aidl::android::hardware::memtrack::DeviceInfo> gpu_device_info; + if (!memtrack_gpu_device_info(&gpu_device_info)) { + return -1; + } + + dmabufinfo::DmabufSysfsStats stats; + if (!GetDmabufSysfsStats(&stats)) { + return -1; + } + + jlong sizeKb = 0; + const auto& importer_stats = stats.importer_info(); + for (const auto& dev_info : gpu_device_info) { + const auto& importer_info = importer_stats.find(dev_info.name); + if (importer_info == importer_stats.end()) { + continue; + } + + sizeKb += importer_info->second.size; + } + + return sizeKb; +} + +static jlong android_os_Debug_getDmabufMappedSizeKb(JNIEnv* env, jobject clazz) { + jlong dmabufPss = 0; std::vector<dmabufinfo::DmaBuffer> dmabufs; std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); @@ -838,10 +908,10 @@ static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) { } for (const dmabufinfo::DmaBuffer& buf : dmabufs) { - ionPss += buf.size() / 1024; + dmabufPss += buf.size() / 1024; } - return ionPss; + return dmabufPss; } static jlong android_os_Debug_getGpuTotalUsageKb(JNIEnv* env, jobject clazz) { @@ -919,10 +989,18 @@ static const JNINativeMethod gMethods[] = { (void*)android_os_Debug_getFreeZramKb }, { "getIonHeapsSizeKb", "()J", (void*)android_os_Debug_getIonHeapsSizeKb }, + { "getDmabufTotalExportedKb", "()J", + (void*)android_os_Debug_getDmabufTotalExportedKb }, + { "getGpuDmaBufUsageKb", "()J", + (void*)android_os_Debug_getGpuDmaBufUsageKb }, + { "getDmabufHeapTotalExportedKb", "()J", + (void*)android_os_Debug_getDmabufHeapTotalExportedKb }, { "getIonPoolsSizeKb", "()J", (void*)android_os_Debug_getIonPoolsSizeKb }, - { "getIonMappedSizeKb", "()J", - (void*)android_os_Debug_getIonMappedSizeKb }, + { "getDmabufMappedSizeKb", "()J", + (void*)android_os_Debug_getDmabufMappedSizeKb }, + { "getDmabufHeapPoolsSizeKb", "()J", + (void*)android_os_Debug_getDmabufHeapPoolsSizeKb }, { "getGpuTotalUsageKb", "()J", (void*)android_os_Debug_getGpuTotalUsageKb }, { "isVmapStack", "()Z", diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp index 0f7611a8ead1..f67007cda209 100644 --- a/core/jni/android_os_Trace.cpp +++ b/core/jni/android_os_Trace.cpp @@ -83,7 +83,7 @@ static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass, } static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) { - atrace_set_debuggable(allowed); + atrace_update_tags(); } static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) { diff --git a/core/proto/android/net/networkrequest.proto b/core/proto/android/net/networkrequest.proto index 6794c8cd8acb..0041f199b448 100644 --- a/core/proto/android/net/networkrequest.proto +++ b/core/proto/android/net/networkrequest.proto @@ -63,6 +63,9 @@ message NetworkRequestProto { // higher-scoring network will not go into the background immediately, // but will linger and go into the background after the linger timeout. TYPE_BACKGROUND_REQUEST = 5; + // Like TRACK_DEFAULT, but tracks the system default network, instead of + // the default network of the calling application. + TYPE_TRACK_SYSTEM_DEFAULT = 6; } // The type of the request. This is only used by the system and is always // NONE elsewhere. diff --git a/core/res/Android.bp b/core/res/Android.bp index f94a2b08e6c3..4c05cd64db49 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -14,6 +14,36 @@ // limitations under the License. // +package { + default_applicable_licenses: ["frameworks_base_core_res_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "frameworks_base_core_res_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-GPL", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "framework-res", sdk_version: "core_platform", diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index af6b97318103..d1e6111dc35f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1790,6 +1790,12 @@ <permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi @hide Allows an application to manage an automotive device's application network + preference as it relates to OEM_PAID and OEM_PRIVATE capable networks. + <p>Not for use by third-party or privileged applications. --> + <permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE" + android:protectionLevel="signature" /> + <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> <!-- ======================================= --> @@ -1916,6 +1922,12 @@ <permission android:name="android.permission.ENABLE_TEST_HARNESS_MODE" android:protectionLevel="signature" /> + <!-- @SystemApi Allows access to ultra wideband device. + <p>Not for use by third-party applications. + @hide --> + <permission android:name="android.permission.UWB_PRIVILEGED" + android:protectionLevel="signature|privileged" /> + <!-- ================================== --> <!-- Permissions for accessing accounts --> <!-- ================================== --> @@ -3058,6 +3070,11 @@ <permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to set, update and remove the credential management app. + @hide --> + <permission android:name="android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP" + android:protectionLevel="signature" /> + <!-- ========================================= --> <!-- Permissions for special development tools --> <!-- ========================================= --> @@ -3797,6 +3814,11 @@ <permission android:name="android.permission.MOVE_PACKAGE" android:protectionLevel="signature|privileged" /> + <!-- @TestApi Allows an application to keep uninstalled packages as apks. + @hide --> + <permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES" + android:protectionLevel="signature" /> + <!-- Allows an application to change whether an application component (other than its own) is enabled or not. <p>Not for use by third-party applications. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 20cb27085661..ee45249c2030 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1547,8 +1547,8 @@ take precedence over lower ones. See com.android.server.timedetector.TimeDetectorStrategy for available sources. --> <string-array name="config_autoTimeSourcesPriority"> - <item>telephony</item> <item>network</item> + <item>telephony</item> </string-array> <!-- Enables the TimeZoneRuleManager service. This is the global switch for the updateable time diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp index 237ede2006ea..f89099e5630d 100644 --- a/core/sysprop/Android.bp +++ b/core/sysprop/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + sysprop_library { name: "com.android.sysprop.localization", srcs: ["LocalizationProperties.sysprop"], diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp index b8efd198aebe..113f45dfef55 100644 --- a/core/tests/BroadcastRadioTests/Android.bp +++ b/core/tests/BroadcastRadioTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BroadcastRadioTests", privileged: true, diff --git a/core/tests/ConnectivityManagerTest/Android.bp b/core/tests/ConnectivityManagerTest/Android.bp index a33d219f53d2..beaf17615f1d 100644 --- a/core/tests/ConnectivityManagerTest/Android.bp +++ b/core/tests/ConnectivityManagerTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ConnectivityManagerTest", libs: [ diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp index e74f30ee10a4..c7a000213029 100644 --- a/core/tests/PackageInstallerSessions/Android.bp +++ b/core/tests/PackageInstallerSessions/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksCorePackageInstallerSessionsTests", diff --git a/core/tests/PlatformCompatFramework/Android.bp b/core/tests/PlatformCompatFramework/Android.bp index 33802650fa12..95e23ad396af 100644 --- a/core/tests/PlatformCompatFramework/Android.bp +++ b/core/tests/PlatformCompatFramework/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PlatformCompatFrameworkTests", // Include all test java files. diff --git a/core/tests/bandwidthtests/Android.bp b/core/tests/bandwidthtests/Android.bp index 5d881b8be68c..f1ecd45073eb 100644 --- a/core/tests/bandwidthtests/Android.bp +++ b/core/tests/bandwidthtests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BandwidthTests", // Include all test java files. diff --git a/core/tests/benchmarks/Android.bp b/core/tests/benchmarks/Android.bp index 8dd7928e6fc2..4cd546753dbf 100644 --- a/core/tests/benchmarks/Android.bp +++ b/core/tests/benchmarks/Android.bp @@ -16,6 +16,15 @@ // build framework base core benchmarks // ============================================================ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "frameworks-base-core-benchmarks", installable: true, diff --git a/core/tests/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp index 4b6f9db33afc..a2e4dff8f826 100644 --- a/core/tests/bluetoothtests/Android.bp +++ b/core/tests/bluetoothtests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BluetoothTests", // Include all test java files. diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp index e42b4b4ae2bf..f87797a90c90 100644 --- a/core/tests/bugreports/Android.bp +++ b/core/tests/bugreports/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BugreportManagerTestCases", srcs: ["src/**/*.java"], diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 1e16ee052899..510578e1e50b 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksCoreTests", diff --git a/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp b/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp index 25e4fc366124..b47c4702eafe 100644 --- a/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp +++ b/core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "BinderDeathRecipientHelperApp1", diff --git a/core/tests/coretests/BinderProxyCountingTestApp/Android.bp b/core/tests/coretests/BinderProxyCountingTestApp/Android.bp index 6279a4873c67..b1df8dbbee19 100644 --- a/core/tests/coretests/BinderProxyCountingTestApp/Android.bp +++ b/core/tests/coretests/BinderProxyCountingTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "BinderProxyCountingTestApp", diff --git a/core/tests/coretests/BinderProxyCountingTestService/Android.bp b/core/tests/coretests/BinderProxyCountingTestService/Android.bp index 22718cb86d66..52c23a15e4e3 100644 --- a/core/tests/coretests/BinderProxyCountingTestService/Android.bp +++ b/core/tests/coretests/BinderProxyCountingTestService/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "BinderProxyCountingTestService", diff --git a/core/tests/coretests/BstatsTestApp/Android.bp b/core/tests/coretests/BstatsTestApp/Android.bp index a89d72830686..c82da9e7b449 100644 --- a/core/tests/coretests/BstatsTestApp/Android.bp +++ b/core/tests/coretests/BstatsTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "BstatsTestApp", diff --git a/core/tests/coretests/DisabledTestApp/Android.bp b/core/tests/coretests/DisabledTestApp/Android.bp index 419816e42eff..3ab321827e53 100644 --- a/core/tests/coretests/DisabledTestApp/Android.bp +++ b/core/tests/coretests/DisabledTestApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "DisabledTestApp", diff --git a/core/tests/coretests/EnabledTestApp/Android.bp b/core/tests/coretests/EnabledTestApp/Android.bp index bc4f4bd2e4d7..750b578a0253 100644 --- a/core/tests/coretests/EnabledTestApp/Android.bp +++ b/core/tests/coretests/EnabledTestApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "EnabledTestApp", diff --git a/core/tests/coretests/aidl/Android.bp b/core/tests/coretests/aidl/Android.bp index 6e442db78500..2d848cca4618 100644 --- a/core/tests/coretests/aidl/Android.bp +++ b/core/tests/coretests/aidl/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test { name: "coretests-aidl", sdk_version: "current", diff --git a/core/tests/coretests/apks/Android.bp b/core/tests/coretests/apks/Android.bp index 20c87b2d2ce9..eda875acfdb1 100644 --- a/core/tests/coretests/apks/Android.bp +++ b/core/tests/coretests/apks/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_defaults { name: "FrameworksCoreTests_apks_defaults", sdk_version: "current", diff --git a/core/tests/coretests/apks/install/Android.bp b/core/tests/coretests/apks/install/Android.bp index e783fe2ec2dc..652b49130433 100644 --- a/core/tests/coretests/apks/install/Android.bp +++ b/core/tests/coretests/apks/install/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_bad_dex/Android.bp b/core/tests/coretests/apks/install_bad_dex/Android.bp index d156793cf22a..7b96c9b47553 100644 --- a/core/tests/coretests/apks/install_bad_dex/Android.bp +++ b/core/tests/coretests/apks/install_bad_dex/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_bad_dex_", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_complete_package_info/Android.bp b/core/tests/coretests/apks/install_complete_package_info/Android.bp index 123558bda076..3fee0c6e7f7c 100644 --- a/core/tests/coretests/apks/install_complete_package_info/Android.bp +++ b/core/tests/coretests/apks/install_complete_package_info/Android.bp @@ -1,7 +1,15 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_complete_package_info", defaults: ["FrameworksCoreTests_apks_defaults"], srcs: ["**/*.java"], } - diff --git a/core/tests/coretests/apks/install_decl_perm/Android.bp b/core/tests/coretests/apks/install_decl_perm/Android.bp index 868e8b51bd49..bf1f0de9672a 100644 --- a/core/tests/coretests/apks/install_decl_perm/Android.bp +++ b/core/tests/coretests/apks/install_decl_perm/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_decl_perm", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_jni_lib/Android.bp b/core/tests/coretests/apks/install_jni_lib/Android.bp index df19fa09adcf..d315e7b70cb9 100644 --- a/core/tests/coretests/apks/install_jni_lib/Android.bp +++ b/core/tests/coretests/apks/install_jni_lib/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { name: "libframeworks_coretests_jni", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp index 602b704a0a5d..20cc96ebc5c0 100644 --- a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp +++ b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_jni_lib_open_from_apk", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_loc_auto/Android.bp b/core/tests/coretests/apks/install_loc_auto/Android.bp index 6393915ba283..37daf7608a43 100644 --- a/core/tests/coretests/apks/install_loc_auto/Android.bp +++ b/core/tests/coretests/apks/install_loc_auto/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_loc_auto", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_loc_internal/Android.bp b/core/tests/coretests/apks/install_loc_internal/Android.bp index 770aaa511b9d..3e233132b58d 100644 --- a/core/tests/coretests/apks/install_loc_internal/Android.bp +++ b/core/tests/coretests/apks/install_loc_internal/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_loc_internal", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_loc_sdcard/Android.bp b/core/tests/coretests/apks/install_loc_sdcard/Android.bp index 177940102e83..708e655e07db 100644 --- a/core/tests/coretests/apks/install_loc_sdcard/Android.bp +++ b/core/tests/coretests/apks/install_loc_sdcard/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_loc_sdcard", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_loc_unspecified/Android.bp b/core/tests/coretests/apks/install_loc_unspecified/Android.bp index 21c0f82b44ff..76869e9b9ed5 100644 --- a/core/tests/coretests/apks/install_loc_unspecified/Android.bp +++ b/core/tests/coretests/apks/install_loc_unspecified/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_loc_unspecified", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_use_perm_good/Android.bp b/core/tests/coretests/apks/install_use_perm_good/Android.bp index bb41ebb2fdca..89700ddb94be 100644 --- a/core/tests/coretests/apks/install_use_perm_good/Android.bp +++ b/core/tests/coretests/apks/install_use_perm_good/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_use_perm_good", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_uses_feature/Android.bp b/core/tests/coretests/apks/install_uses_feature/Android.bp index 0ec747b0f151..913a96a1cd27 100644 --- a/core/tests/coretests/apks/install_uses_feature/Android.bp +++ b/core/tests/coretests/apks/install_uses_feature/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_uses_feature", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.bp b/core/tests/coretests/apks/install_verifier_bad/Android.bp index 1265739a3107..ed13d74789bf 100644 --- a/core/tests/coretests/apks/install_verifier_bad/Android.bp +++ b/core/tests/coretests/apks/install_verifier_bad/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_verifier_bad", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/install_verifier_good/Android.bp b/core/tests/coretests/apks/install_verifier_good/Android.bp index 4911ffbd2020..fe9a24f6bd7b 100644 --- a/core/tests/coretests/apks/install_verifier_good/Android.bp +++ b/core/tests/coretests/apks/install_verifier_good/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_install_verifier_good", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/keyset/Android.bp b/core/tests/coretests/apks/keyset/Android.bp index e252b081341a..93c3b1f60327 100644 --- a/core/tests/coretests/apks/keyset/Android.bp +++ b/core/tests/coretests/apks/keyset/Android.bp @@ -1,4 +1,13 @@ //apks signed by keyset_A +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_keyset_sa_unone", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/locales/Android.bp b/core/tests/coretests/apks/locales/Android.bp index 4a730ef53404..4fe6c7fd09b2 100644 --- a/core/tests/coretests/apks/locales/Android.bp +++ b/core/tests/coretests/apks/locales/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_locales", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/overlay_config/Android.bp b/core/tests/coretests/apks/overlay_config/Android.bp index 957355726fe8..9c971fd2f1bc 100644 --- a/core/tests/coretests/apks/overlay_config/Android.bp +++ b/core/tests/coretests/apks/overlay_config/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_overlay_config", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/version/Android.bp b/core/tests/coretests/apks/version/Android.bp index 371ccfc301cb..8b750f7b5ee4 100644 --- a/core/tests/coretests/apks/version/Android.bp +++ b/core/tests/coretests/apks/version/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_version_1", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/apks/version_nosys/Android.bp b/core/tests/coretests/apks/version_nosys/Android.bp index 575667822393..de40f49849b7 100644 --- a/core/tests/coretests/apks/version_nosys/Android.bp +++ b/core/tests/coretests/apks/version_nosys/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksCoreTests_version_1_nosys", defaults: ["FrameworksCoreTests_apks_defaults"], diff --git a/core/tests/coretests/certs/Android.bp b/core/tests/coretests/certs/Android.bp index bd5c8293f6f6..8411183c3335 100644 --- a/core/tests/coretests/certs/Android.bp +++ b/core/tests/coretests/certs/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + android_app_certificate { name: "FrameworksCoreTests_keyset_A_cert", certificate: "keyset_A", diff --git a/core/tests/coretests/src/android/provider/OWNERS b/core/tests/coretests/src/android/provider/OWNERS new file mode 100644 index 000000000000..581da714f326 --- /dev/null +++ b/core/tests/coretests/src/android/provider/OWNERS @@ -0,0 +1 @@ +include /core/java/android/provider/OWNERS diff --git a/core/tests/coretests/src/android/provider/SimPhonebookContractTest.java b/core/tests/coretests/src/android/provider/SimPhonebookContractTest.java index be3826007aa3..bc7be1b08626 100644 --- a/core/tests/coretests/src/android/provider/SimPhonebookContractTest.java +++ b/core/tests/coretests/src/android/provider/SimPhonebookContractTest.java @@ -16,14 +16,8 @@ package android.provider; -import static com.google.common.truth.Truth.assertThat; - import static org.testng.Assert.assertThrows; -import android.content.ContentValues; -import android.os.Parcel; -import android.provider.SimPhonebookContract.SimRecords.NameValidationResult; - import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; @@ -71,50 +65,5 @@ public class SimPhonebookContractTest { SimPhonebookContract.ElementaryFiles.EF_ADN, -1) ); } - - @Test - public void nameValidationResult_isValid_validNames() { - assertThat(new NameValidationResult("", "", 0, 1).isValid()).isTrue(); - assertThat(new NameValidationResult("a", "a", 1, 1).isValid()).isTrue(); - assertThat(new NameValidationResult("First Last", "First Last", 10, 10).isValid()).isTrue(); - assertThat( - new NameValidationResult("First Last", "First Last", 10, 100).isValid()).isTrue(); - } - - @Test - public void nameValidationResult_isValid_invalidNames() { - assertThat(new NameValidationResult("", "", 0, 0).isValid()).isFalse(); - assertThat(new NameValidationResult("ab", "ab", 2, 1).isValid()).isFalse(); - NameValidationResult unsupportedCharactersResult = new NameValidationResult("A_b_c", - "A b c", 5, 5); - assertThat(unsupportedCharactersResult.isValid()).isFalse(); - assertThat(unsupportedCharactersResult.isSupportedCharacter(0)).isTrue(); - assertThat(unsupportedCharactersResult.isSupportedCharacter(1)).isFalse(); - assertThat(unsupportedCharactersResult.isSupportedCharacter(2)).isTrue(); - assertThat(unsupportedCharactersResult.isSupportedCharacter(3)).isFalse(); - assertThat(unsupportedCharactersResult.isSupportedCharacter(4)).isTrue(); - } - - @Test - public void nameValidationResult_parcel() { - ContentValues values = new ContentValues(); - values.put("name", "Name"); - values.put("phone_number", "123"); - - NameValidationResult result; - Parcel parcel = Parcel.obtain(); - try { - parcel.writeParcelable(new NameValidationResult("name", "sanitized name", 1, 2), 0); - parcel.setDataPosition(0); - result = parcel.readParcelable(NameValidationResult.class.getClassLoader()); - } finally { - parcel.recycle(); - } - - assertThat(result.getName()).isEqualTo("name"); - assertThat(result.getSanitizedName()).isEqualTo("sanitized name"); - assertThat(result.getEncodedLength()).isEqualTo(1); - assertThat(result.getMaxEncodedLength()).isEqualTo(2); - } } diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS index 5031ff913e6d..80165f065995 100644 --- a/core/tests/coretests/src/android/view/OWNERS +++ b/core/tests/coretests/src/android/view/OWNERS @@ -1,7 +1,7 @@ # Input -per-file *MotionEventTest.* = michaelwr@google.com, svv@google.com -per-file *KeyEventTest.* = michaelwr@google.com, svv@google.com -per-file VelocityTest.java = michaelwr@google.com, svv@google.com +per-file *MotionEventTest.* = file:/services/core/java/com/android/server/input/OWNERS +per-file *KeyEventTest.* = file:/services/core/java/com/android/server/input/OWNERS +per-file VelocityTest.java = file:/services/core/java/com/android/server/input/OWNERS # WindowManager per-file *Display* = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java index 7917a06cb9b7..2c1bbf0d0b83 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -232,7 +232,7 @@ public final class LooperStatsTest { assertThat(entry3.handlerClassName).isEqualTo( "com.android.internal.os.LooperStatsTest$TestHandlerSecond"); assertThat(entry3.messageName).startsWith( - "com.android.internal.os.-$$Lambda$LooperStatsTest$"); + "com.android.internal.os.LooperStatsTest-$$ExternalSyntheticLambda"); assertThat(entry3.messageCount).isEqualTo(1); assertThat(entry3.recordedMessageCount).isEqualTo(1); assertThat(entry3.exceptionCount).isEqualTo(0); diff --git a/core/tests/coretests/src/com/android/internal/widget/OWNERS b/core/tests/coretests/src/com/android/internal/widget/OWNERS new file mode 100644 index 000000000000..b40fe240d80c --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/widget/OWNERS @@ -0,0 +1,3 @@ +# LockSettings related +per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS +per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS diff --git a/core/tests/featureflagtests/Android.bp b/core/tests/featureflagtests/Android.bp index 8730b7012c4a..d9f608ea34c4 100644 --- a/core/tests/featureflagtests/Android.bp +++ b/core/tests/featureflagtests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksCoreFeatureFlagTests", // We only want this apk build for tests. diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp index 4755e0ea5259..f49e05329f62 100644 --- a/core/tests/hdmitests/Android.bp +++ b/core/tests/hdmitests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "HdmiCecTests", // Include all test java files diff --git a/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp b/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp index 14424811d3be..b4efce2c822b 100644 --- a/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AutoLocTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp index 438ed2533716..0e07ddca5edc 100644 --- a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp +++ b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AutoLocVersionedTestApp_v1", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp index 2ac72a13fee3..f40870004e92 100644 --- a/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp +++ b/core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AutoLocVersionedTestApp_v2", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp index e06e82e38ef4..964401d851af 100644 --- a/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalLocAllPermsTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp index c48dcd525232..297ed57a6b34 100644 --- a/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalLocPermFLTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp b/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp index 5c1c15a4999f..cf8c7e1abcf3 100644 --- a/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalLocTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp index 13f5066c7170..909bd7f9d0da 100644 --- a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalLocVersionedTestApp_v1", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp index e02ffb307ba2..c5f91924d243 100644 --- a/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalLocVersionedTestApp_v2", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp index de098005b40e..1545f4d0e5f9 100644 --- a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalSharedPermsTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp index 435144f31edd..8690bdfc2f93 100644 --- a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalSharedPermsBTTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp index 445bac94f10d..21b7c4c1ea77 100644 --- a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalSharedPermsDiffKeyTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp index d1da3998ca4a..63bf8dca6968 100644 --- a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp +++ b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalSharedPermsFLTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp b/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp index fab9d4394fc5..f05cde430992 100644 --- a/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "InternalLocTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp index dcf168760d4d..56f10fe075ed 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "MultiDexLegacyTestServicesTests", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp b/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp index 50a2de499d37..88e3722a5ed4 100644 --- a/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/NoLocTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NoLocTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp index 4bc9edcd9f20..fd5ab265d1e2 100644 --- a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp +++ b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NoLocVersionedTestApp_v1", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp index dd2952be00dd..fa821d84ace4 100644 --- a/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp +++ b/core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NoLocVersionedTestApp_v2", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/SharedUid/32/Android.bp b/core/tests/hosttests/test-apps/SharedUid/32/Android.bp index f3e3eded5fba..6f3d4cf9c027 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/32/Android.bp @@ -19,6 +19,15 @@ // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PMTest_Java32", srcs: ["**/*.java"], diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp index 9e6c17f0247a..867d65cbe81c 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp @@ -17,6 +17,15 @@ // This makefile supplies the rules for building a library of JNI code for // use by our example of how to bundle a shared library with an APK. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { // This is the target being built. diff --git a/core/tests/hosttests/test-apps/SharedUid/64/Android.bp b/core/tests/hosttests/test-apps/SharedUid/64/Android.bp index 5d9c0b597ef1..6bb25a82b354 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/64/Android.bp @@ -19,6 +19,15 @@ // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PMTest_Java64", srcs: ["**/*.java"], diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp index 91da6e44a8be..c032ba1503d1 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp @@ -17,6 +17,15 @@ // This Android.bp supplies the rules for building a library of JNI code for // use by our example of how to bundle a shared library with an APK. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { // This is the target being built. name: "libpmtest64", diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp b/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp index c42192dcdbf2..94dd0c6758c2 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/dual/Android.bp @@ -19,6 +19,15 @@ // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PMTest_Java_dual", srcs: ["**/*.java"], diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp index 662755dd35b0..6b9d7f337fc8 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp @@ -17,6 +17,15 @@ // This Android.bp supplies the rules for building a library of JNI code for // use by our example of how to bundle a shared library with an APK. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { // This is the target being built. diff --git a/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp b/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp index baedc6e35734..6d632671e261 100644 --- a/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp +++ b/core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp @@ -19,6 +19,15 @@ // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PMTest_Java", srcs: ["**/*.java"], diff --git a/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp b/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp index 5f443bd83605..b022bdaa6016 100644 --- a/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp +++ b/core/tests/hosttests/test-apps/SimpleTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SimpleTestApp", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp index 800e0833d35d..0ac825b3dd2e 100644 --- a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp +++ b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UpdateExtToIntLocTestApp_v1_ext", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp index 299887c9fbfc..6f66a5104499 100644 --- a/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp +++ b/core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UpdateExtToIntLocTestApp_v2_int", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp index 1530422841f6..d88bce04638b 100644 --- a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp +++ b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UpdateExternalLocTestApp_v1_ext", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp index 4c7975e5f18a..d1240df8a3ce 100644 --- a/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp +++ b/core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UpdateExternalLocTestApp_v2_none", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp index c6b60c352e38..751071cd947a 100644 --- a/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp +++ b/core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VersatileTestApp_Auto", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp index db521efc5935..b9ed015b22eb 100644 --- a/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp +++ b/core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VersatileTestApp_External", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp index ca059302ff0d..7b725704651c 100644 --- a/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp +++ b/core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VersatileTestApp_Internal", srcs: ["src/**/*.java"], diff --git a/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp b/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp index 6e1aac7d6c94..5f67bce361c5 100644 --- a/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp +++ b/core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VersatileTestApp_None", srcs: ["src/**/*.java"], diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp index ae3ff8612eee..96811be37f5a 100644 --- a/core/tests/mockingcoretests/Android.bp +++ b/core/tests/mockingcoretests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksMockingCoreTests", diff --git a/core/tests/notificationtests/Android.bp b/core/tests/notificationtests/Android.bp index e744d5a2e631..1c0e39d9e022 100644 --- a/core/tests/notificationtests/Android.bp +++ b/core/tests/notificationtests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NotificationStressTests", // Include all test java files. diff --git a/core/tests/overlaytests/device/Android.bp b/core/tests/overlaytests/device/Android.bp index f86ac9ce37e1..0d3b15a41e8c 100644 --- a/core/tests/overlaytests/device/Android.bp +++ b/core/tests/overlaytests/device/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "OverlayDeviceTests", srcs: ["src/**/*.java"], diff --git a/core/tests/overlaytests/device/AndroidTest.xml b/core/tests/overlaytests/device/AndroidTest.xml index ebbdda559ed2..2d7d9b450c8c 100644 --- a/core/tests/overlaytests/device/AndroidTest.xml +++ b/core/tests/overlaytests/device/AndroidTest.xml @@ -19,17 +19,13 @@ <option name="test-suite-tag" value="apct" /> <option name="test-suite-tag" value="apct-instrumentation" /> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> <option name="cleanup" value="true" /> <option name="remount-system" value="true" /> <option name="push" value="OverlayDeviceTests.apk->/system/app/OverlayDeviceTests.apk" /> </target_preparer> - - <!-- Reboot to have the test APK scanned by PM and reboot after to remove the test APK. --> - <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer"> - <option name="pre-reboot" value="true" /> - <option name="post-reboot" value="true" /> - </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" /> <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> <option name="cleanup-apks" value="true" /> diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp index 847b4915530b..4ff59fa56a68 100644 --- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "OverlayDeviceTests_AppOverlayOne", sdk_version: "current", diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp index 7d5f82a71b44..1f5763ee60ae 100644 --- a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "OverlayDeviceTests_AppOverlayTwo", sdk_version: "current", diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp index 50dbc6f054d3..178a02009dda 100644 --- a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp +++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "OverlayDeviceTests_FrameworkOverlay", sdk_version: "current", diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp index a2fcef56b780..e4c3fbec8afc 100644 --- a/core/tests/overlaytests/host/Android.bp +++ b/core/tests/overlaytests/host/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "OverlayHostTests", srcs: ["src/**/*.java"], diff --git a/core/tests/overlaytests/remount/Android.bp b/core/tests/overlaytests/remount/Android.bp index 939334c94312..0a6b88bcbb63 100644 --- a/core/tests/overlaytests/remount/Android.bp +++ b/core/tests/overlaytests/remount/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "OverlayRemountedTest", srcs: ["src/**/*.java"], diff --git a/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp index 032a0cdcb50d..a341c9aa88f7 100644 --- a/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "OverlayRemountedTest_Overlay", sdk_version: "current", @@ -24,4 +33,4 @@ android_test_helper_app { name: "OverlayRemountedTest_Overlay_SameCert", certificate: ":rro-remounted-test-a", sdk_version: "current", -}
\ No newline at end of file +} diff --git a/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp index ffb0572c3fd0..bc88d61df77a 100644 --- a/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "OverlayRemountedTest_SharedLibrary", sdk_version: "current", diff --git a/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp index 0d29aec909d5..88a05ab8427b 100644 --- a/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "OverlayRemountedTest_SharedLibraryOverlay", sdk_version: "current", diff --git a/core/tests/overlaytests/remount/test-apps/Target/Android.bp b/core/tests/overlaytests/remount/test-apps/Target/Android.bp index e4b4eaa8d220..869a75f5225d 100644 --- a/core/tests/overlaytests/remount/test-apps/Target/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/Target/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "OverlayRemountedTest_Target", sdk_version: "test_current", diff --git a/core/tests/overlaytests/remount/test-apps/certs/Android.bp b/core/tests/overlaytests/remount/test-apps/certs/Android.bp index 06114efc1249..f5d89bcabdad 100644 --- a/core/tests/overlaytests/remount/test-apps/certs/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/certs/Android.bp @@ -13,6 +13,17 @@ // limitations under the License. // development/tools/make_key rro-remounted-test-a '/CN=rro_test_a' +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + android_app_certificate { name: "rro-remounted-test-a", certificate: "rro-remounted-test-a", diff --git a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp index e6ebd5ea76d8..3536c4088dd8 100644 --- a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + genrule { name: "com.android.overlaytest.overlaid.pem", out: ["com.android.overlaytest.overlaid.pem"], @@ -39,4 +50,5 @@ apex { key: "com.android.overlaytest.overlaid.key", apps: ["OverlayRemountedTest_Target"], installable: false, + updatable: false, } diff --git a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp index 07f27ee55d39..f04140409bea 100644 --- a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + genrule { name: "com.android.overlaytest.overlay.pem", out: ["com.android.overlaytest.overlay.pem"], @@ -39,4 +50,5 @@ apex { key: "com.android.overlaytest.overlay.key", apps: ["OverlayRemountedTest_Overlay"], installable: false, + updatable: false, } diff --git a/core/tests/packagemanagertests/Android.bp b/core/tests/packagemanagertests/Android.bp index 6f39af8bd468..5ce71c902c7c 100644 --- a/core/tests/packagemanagertests/Android.bp +++ b/core/tests/packagemanagertests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksCorePackageManagerTests", // We only want this apk build for tests. diff --git a/core/tests/privacytests/Android.bp b/core/tests/privacytests/Android.bp index 7f5699287796..bc3dd810be8c 100644 --- a/core/tests/privacytests/Android.bp +++ b/core/tests/privacytests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksPrivacyLibraryTests", srcs: ["src/**/*.java"], diff --git a/core/tests/screenshothelpertests/Android.bp b/core/tests/screenshothelpertests/Android.bp index 3d54b68b7ddc..37af99c58d42 100644 --- a/core/tests/screenshothelpertests/Android.bp +++ b/core/tests/screenshothelpertests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ScreenshotHelperTests", @@ -25,4 +34,3 @@ android_test { certificate: "platform", } - diff --git a/core/tests/systemproperties/Android.bp b/core/tests/systemproperties/Android.bp index 7ef1b9b8f74b..765ca3e5110a 100644 --- a/core/tests/systemproperties/Android.bp +++ b/core/tests/systemproperties/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksCoreSystemPropertiesTests", // Include all test java files. diff --git a/core/tests/utillib/Android.bp b/core/tests/utillib/Android.bp index 1f742c208ba2..d40d1d2bb6e2 100644 --- a/core/tests/utillib/Android.bp +++ b/core/tests/utillib/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "frameworks-core-util-lib", diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp index a9b9c41d4719..72d6a2c67739 100644 --- a/core/tests/utiltests/Android.bp +++ b/core/tests/utiltests/Android.bp @@ -2,6 +2,15 @@ // Build FrameworksUtilTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksUtilTests", diff --git a/core/tests/utiltests/jni/Android.bp b/core/tests/utiltests/jni/Android.bp index 6b75471a358a..a9c695ed09f3 100644 --- a/core/tests/utiltests/jni/Android.bp +++ b/core/tests/utiltests/jni/Android.bp @@ -11,6 +11,15 @@ // WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared {
name: "libmemoryintarraytest",
diff --git a/core/tests/uwbtests/Android.bp b/core/tests/uwbtests/Android.bp index 8ee86f470c9e..31f446f7a60d 100644 --- a/core/tests/uwbtests/Android.bp +++ b/core/tests/uwbtests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UwbManagerTests", static_libs: [ diff --git a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java deleted file mode 100644 index 7769c28202f2..000000000000 --- a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link AngleMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class AngleMeasurementTest { - private static final double EPSILON = 0.00000000001; - - @Test - public void testBuilder() { - double radians = 0.1234; - double errorRadians = 0.5678; - double confidence = 0.5; - - AngleMeasurement.Builder builder = new AngleMeasurement.Builder(); - tryBuild(builder, false); - - builder.setRadians(radians); - tryBuild(builder, false); - - builder.setErrorRadians(errorRadians); - tryBuild(builder, false); - - builder.setConfidenceLevel(confidence); - AngleMeasurement measurement = tryBuild(builder, true); - - assertEquals(measurement.getRadians(), radians, 0); - assertEquals(measurement.getErrorRadians(), errorRadians, 0); - assertEquals(measurement.getConfidenceLevel(), confidence, 0); - } - - private AngleMeasurement tryBuild(AngleMeasurement.Builder builder, boolean expectSuccess) { - AngleMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected AngleMeasurement.Builder.build() to fail, but it succeeded"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected AngleMeasurement.Builder.build() to succeed, but it failed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java deleted file mode 100644 index 9394dec7f46f..000000000000 --- a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link AngleOfArrivalMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class AngleOfArrivalMeasurementTest { - - @Test - public void testBuilder() { - AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement(); - AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement(); - - AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder(); - tryBuild(builder, false); - - builder.setAltitude(altitude); - tryBuild(builder, false); - - builder.setAzimuth(azimuth); - AngleOfArrivalMeasurement measurement = tryBuild(builder, true); - - assertEquals(azimuth, measurement.getAzimuth()); - assertEquals(altitude, measurement.getAltitude()); - } - - private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) { - return new AngleMeasurement.Builder() - .setRadians(radian) - .setErrorRadians(error) - .setConfidenceLevel(confidence) - .build(); - } - - private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder, - boolean expectSuccess) { - AngleOfArrivalMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AngleOfArrivalMeasurement fromParcel = - AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java deleted file mode 100644 index 439c884723be..000000000000 --- a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link DistanceMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class DistanceMeasurementTest { - private static final double EPSILON = 0.00000000001; - - @Test - public void testBuilder() { - double meters = 0.12; - double error = 0.54; - double confidence = 0.99; - - DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder(); - tryBuild(builder, false); - - builder.setMeters(meters); - tryBuild(builder, false); - - builder.setErrorMeters(error); - tryBuild(builder, false); - - builder.setConfidenceLevel(confidence); - DistanceMeasurement measurement = tryBuild(builder, true); - - assertEquals(meters, measurement.getMeters(), 0); - assertEquals(error, measurement.getErrorMeters(), 0); - assertEquals(confidence, measurement.getConfidenceLevel(), 0); - } - - private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder, - boolean expectSuccess) { - DistanceMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - DistanceMeasurement fromParcel = - DistanceMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java deleted file mode 100644 index edd4d08992ba..000000000000 --- a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.os.SystemClock; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link RangingMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RangingMeasurementTest { - - @Test - public void testBuilder() { - int status = RangingMeasurement.RANGING_STATUS_SUCCESS; - UwbAddress address = UwbTestUtils.getUwbAddress(false); - long time = SystemClock.elapsedRealtimeNanos(); - AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement(); - DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement(); - - RangingMeasurement.Builder builder = new RangingMeasurement.Builder(); - - builder.setStatus(status); - tryBuild(builder, false); - - builder.setElapsedRealtimeNanos(time); - tryBuild(builder, false); - - builder.setAngleOfArrivalMeasurement(angleMeasurement); - tryBuild(builder, false); - - builder.setDistanceMeasurement(distanceMeasurement); - tryBuild(builder, false); - - builder.setRemoteDeviceAddress(address); - RangingMeasurement measurement = tryBuild(builder, true); - - assertEquals(status, measurement.getStatus()); - assertEquals(address, measurement.getRemoteDeviceAddress()); - assertEquals(time, measurement.getElapsedRealtimeNanos()); - assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement()); - assertEquals(distanceMeasurement, measurement.getDistanceMeasurement()); - } - - private RangingMeasurement tryBuild(RangingMeasurement.Builder builder, - boolean expectSuccess) { - RangingMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected RangingMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java deleted file mode 100644 index 64c48ba4b6f4..000000000000 --- a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -/** - * Test of {@link RangingReport}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RangingReportTest { - - @Test - public void testBuilder() { - List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5); - - RangingReport.Builder builder = new RangingReport.Builder(); - builder.addMeasurements(measurements); - RangingReport report = tryBuild(builder, true); - verifyMeasurementsEqual(measurements, report.getMeasurements()); - - - builder = new RangingReport.Builder(); - for (RangingMeasurement measurement : measurements) { - builder.addMeasurement(measurement); - } - report = tryBuild(builder, true); - verifyMeasurementsEqual(measurements, report.getMeasurements()); - } - - private void verifyMeasurementsEqual(List<RangingMeasurement> expected, - List<RangingMeasurement> actual) { - assertEquals(expected.size(), actual.size()); - for (int i = 0; i < expected.size(); i++) { - assertEquals(expected.get(i), actual.get(i)); - } - } - - private RangingReport tryBuild(RangingReport.Builder builder, - boolean expectSuccess) { - RangingReport report = null; - try { - report = builder.build(); - if (!expectSuccess) { - fail("Expected RangingReport.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected RangingReport.Builder.build() to succeed"); - } - } - return report; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - RangingReport report = UwbTestUtils.getRangingReports(5); - report.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel); - assertEquals(report, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java deleted file mode 100644 index e5eea26f5d11..000000000000 --- a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.os.PersistableBundle; -import android.os.RemoteException; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.concurrent.Executor; - -/** - * Test of {@link RangingSession}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RangingSessionTest { - private static final Executor EXECUTOR = UwbTestUtils.getExecutor(); - private static final PersistableBundle PARAMS = new PersistableBundle(); - private static final @RangingSession.Callback.Reason int REASON = - RangingSession.Callback.REASON_GENERIC_ERROR; - - @Test - public void testOnRangingOpened_OnOpenSuccessCalled() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - verifyOpenState(session, false); - - session.onRangingOpened(); - verifyOpenState(session, true); - - // Verify that the onOpenSuccess callback was invoked - verify(callback, times(1)).onOpened(eq(session)); - verify(callback, times(0)).onClosed(anyInt(), any()); - } - - @Test - public void testOnRangingOpened_CannotOpenClosedSession() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - - session.onRangingOpened(); - verifyOpenState(session, true); - verify(callback, times(1)).onOpened(eq(session)); - verify(callback, times(0)).onClosed(anyInt(), any()); - - session.onRangingClosed(REASON, PARAMS); - verifyOpenState(session, false); - verify(callback, times(1)).onOpened(eq(session)); - verify(callback, times(1)).onClosed(anyInt(), any()); - - // Now invoke the ranging started callback and ensure the session remains closed - session.onRangingOpened(); - verifyOpenState(session, false); - verify(callback, times(1)).onOpened(eq(session)); - verify(callback, times(1)).onClosed(anyInt(), any()); - } - - @Test - public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - verifyOpenState(session, false); - - session.onRangingClosed(REASON, PARAMS); - verifyOpenState(session, false); - - // Verify that the onOpenSuccess callback was invoked - verify(callback, times(0)).onOpened(eq(session)); - verify(callback, times(1)).onClosed(anyInt(), any()); - } - - @Test - public void testOnRangingClosed_OnClosedCalled() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - session.onRangingStarted(PARAMS); - session.onRangingClosed(REASON, PARAMS); - verify(callback, times(1)).onClosed(anyInt(), any()); - - verifyOpenState(session, false); - session.onRangingClosed(REASON, PARAMS); - verify(callback, times(2)).onClosed(anyInt(), any()); - } - - @Test - public void testOnRangingResult_OnReportReceivedCalled() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - verifyOpenState(session, false); - - session.onRangingStarted(PARAMS); - verifyOpenState(session, true); - - RangingReport report = UwbTestUtils.getRangingReports(1); - session.onRangingResult(report); - verify(callback, times(1)).onReportReceived(eq(report)); - } - - @Test - public void testStart_CannotStartIfAlreadyStarted() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any()); - session.onRangingOpened(); - - session.start(PARAMS); - verify(callback, times(1)).onStarted(any()); - - // Calling start again should throw an illegal state - verifyThrowIllegalState(() -> session.start(PARAMS)); - verify(callback, times(1)).onStarted(any()); - } - - @Test - public void testStop_CannotStopIfAlreadyStopped() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any()); - doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any()); - session.onRangingOpened(); - session.start(PARAMS); - - verifyNoThrowIllegalState(session::stop); - verify(callback, times(1)).onStopped(); - - // Calling stop again should throw an illegal state - verifyThrowIllegalState(session::stop); - verify(callback, times(1)).onStopped(); - } - - @Test - public void testReconfigure_OnlyWhenOpened() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any()); - doAnswer(new ReconfigureAnswer(session)).when(adapter).reconfigureRanging(any(), any()); - - verifyThrowIllegalState(() -> session.reconfigure(PARAMS)); - verify(callback, times(0)).onReconfigured(any()); - verifyOpenState(session, false); - - session.onRangingOpened(); - verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS)); - verify(callback, times(1)).onReconfigured(any()); - verifyOpenState(session, true); - - session.onRangingStarted(PARAMS); - verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS)); - verify(callback, times(2)).onReconfigured(any()); - verifyOpenState(session, true); - - session.onRangingStopped(); - verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS)); - verify(callback, times(3)).onReconfigured(any()); - verifyOpenState(session, true); - - - session.onRangingClosed(REASON, PARAMS); - verifyThrowIllegalState(() -> session.reconfigure(PARAMS)); - verify(callback, times(3)).onReconfigured(any()); - verifyOpenState(session, false); - } - - @Test - public void testClose_NoCallbackUntilInvoked() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - session.onRangingOpened(); - - // Calling close multiple times should invoke closeRanging until the session receives - // the onClosed callback. - int totalCallsBeforeOnRangingClosed = 3; - for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) { - session.close(); - verifyOpenState(session, true); - verify(adapter, times(i)).closeRanging(handle); - verify(callback, times(0)).onClosed(anyInt(), any()); - } - - // After onClosed is invoked, then the adapter should no longer be called for each call to - // the session's close. - final int totalCallsAfterOnRangingClosed = 2; - for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) { - session.onRangingClosed(REASON, PARAMS); - verifyOpenState(session, false); - verify(adapter, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle); - verify(callback, times(i)).onClosed(anyInt(), any()); - } - } - - @Test - public void testClose_OnClosedCalled() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any()); - session.onRangingOpened(); - - session.close(); - verify(callback, times(1)).onClosed(anyInt(), any()); - } - - @Test - public void testClose_CannotInteractFurther() throws RemoteException { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any()); - session.close(); - - verifyThrowIllegalState(() -> session.start(PARAMS)); - verifyThrowIllegalState(() -> session.reconfigure(PARAMS)); - verifyThrowIllegalState(() -> session.stop()); - verifyNoThrowIllegalState(() -> session.close()); - } - - @Test - public void testOnRangingResult_OnReportReceivedCalledWhenOpen() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - - assertFalse(session.isOpen()); - session.onRangingStarted(PARAMS); - assertTrue(session.isOpen()); - - // Verify that the onReportReceived callback was invoked - RangingReport report = UwbTestUtils.getRangingReports(1); - session.onRangingResult(report); - verify(callback, times(1)).onReportReceived(report); - } - - @Test - public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() { - SessionHandle handle = new SessionHandle(123); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - IUwbAdapter adapter = mock(IUwbAdapter.class); - RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle); - - assertFalse(session.isOpen()); - - // Verify that the onReportReceived callback was invoked - RangingReport report = UwbTestUtils.getRangingReports(1); - session.onRangingResult(report); - verify(callback, times(0)).onReportReceived(report); - } - - private void verifyOpenState(RangingSession session, boolean expected) { - assertEquals(expected, session.isOpen()); - } - - private void verifyThrowIllegalState(Runnable runnable) { - try { - runnable.run(); - fail(); - } catch (IllegalStateException e) { - // Pass - } - } - - private void verifyNoThrowIllegalState(Runnable runnable) { - try { - runnable.run(); - } catch (IllegalStateException e) { - fail(); - } - } - - abstract class AdapterAnswer implements Answer { - protected RangingSession mSession; - - protected AdapterAnswer(RangingSession session) { - mSession = session; - } - } - - class StartAnswer extends AdapterAnswer { - StartAnswer(RangingSession session) { - super(session); - } - - @Override - public Object answer(InvocationOnMock invocation) { - mSession.onRangingStarted(PARAMS); - return null; - } - } - - class ReconfigureAnswer extends AdapterAnswer { - ReconfigureAnswer(RangingSession session) { - super(session); - } - - @Override - public Object answer(InvocationOnMock invocation) { - mSession.onRangingReconfigured(PARAMS); - return null; - } - } - - class StopAnswer extends AdapterAnswer { - StopAnswer(RangingSession session) { - super(session); - } - - @Override - public Object answer(InvocationOnMock invocation) { - mSession.onRangingStopped(); - return null; - } - } - - class CloseAnswer extends AdapterAnswer { - CloseAnswer(RangingSession session) { - super(session); - } - - @Override - public Object answer(InvocationOnMock invocation) { - mSession.onRangingClosed(REASON, PARAMS); - return null; - } - } -} diff --git a/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java b/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java deleted file mode 100644 index 8b42ff7f62a7..000000000000 --- a/core/tests/uwbtests/src/android/uwb/SessionHandleTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link SessionHandle}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class SessionHandleTest { - - @Test - public void testBasic() { - int handleId = 12; - SessionHandle handle = new SessionHandle(handleId); - assertEquals(handle.getId(), handleId); - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - SessionHandle handle = new SessionHandle(10); - handle.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - SessionHandle fromParcel = SessionHandle.CREATOR.createFromParcel(parcel); - assertEquals(handle, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java deleted file mode 100644 index ccc88a9a5399..000000000000 --- a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertEquals; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link UwbAddress}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class UwbAddressTest { - - @Test - public void testFromBytes_Short() { - runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH); - } - - @Test - public void testFromBytes_Extended() { - runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH); - } - - private void runFromBytes(int len) { - byte[] addressBytes = getByteArray(len); - UwbAddress address = UwbAddress.fromBytes(addressBytes); - assertEquals(address.size(), len); - assertEquals(addressBytes, address.toBytes()); - } - - private byte[] getByteArray(int len) { - byte[] res = new byte[len]; - for (int i = 0; i < len; i++) { - res[i] = (byte) i; - } - return res; - } - - @Test - public void testParcel_Short() { - runParcel(true); - } - - @Test - public void testParcel_Extended() { - runParcel(false); - } - - private void runParcel(boolean useShortAddress) { - Parcel parcel = Parcel.obtain(); - UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress); - address.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel); - assertEquals(address, fromParcel); - } -} diff --git a/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java b/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java deleted file mode 100644 index 4983bed742fd..000000000000 --- a/core/tests/uwbtests/src/android/uwb/UwbManagerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.uwb; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import android.content.Context; - -import androidx.test.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link UwbManager}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class UwbManagerTest { - - public final Context mContext = InstrumentationRegistry.getContext(); - - @Test - public void testServiceAvailable() { - UwbManager manager = mContext.getSystemService(UwbManager.class); - if (UwbTestUtils.isUwbSupported(mContext)) { - assertNotNull(manager); - } else { - assertNull(manager); - } - } -} diff --git a/core/xsd/Android.bp b/core/xsd/Android.bp index 738f33076ac9..5387f85bffb2 100644 --- a/core/xsd/Android.bp +++ b/core/xsd/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + xsd_config { name: "permission", srcs: ["permission.xsd"], diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp index ca655f18149c..5d8407f584bc 100644 --- a/core/xsd/vts/Android.bp +++ b/core/xsd/vts/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { name: "vts_permission_validate_test", srcs: [ diff --git a/data/etc/Android.bp b/data/etc/Android.bp index fb8b17c1f159..d0e247450033 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -15,6 +15,15 @@ // Sysconfig files +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + prebuilt_etc { name: "framework-sysconfig.xml", sub_dir: "sysconfig", diff --git a/data/etc/OWNERS b/data/etc/OWNERS index 65d3a012b129..549e074d297c 100644 --- a/data/etc/OWNERS +++ b/data/etc/OWNERS @@ -6,7 +6,6 @@ jeffv@google.com jsharkey@android.com jsharkey@google.com lorenzo@google.com -moltmann@google.com svetoslavganov@android.com svetoslavganov@google.com toddke@android.com diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp index 12bd0f51fa5f..67848daa4e27 100644 --- a/data/etc/car/Android.bp +++ b/data/etc/car/Android.bp @@ -16,6 +16,15 @@ // Privapp permission whitelist files +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + prebuilt_etc { name: "privapp_whitelist_android.car.cluster.loggingrenderer", sub_dir: "permissions", diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp index 3a3bea43ab86..f0d750ef30e9 100644 --- a/data/fonts/Android.bp +++ b/data/fonts/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_base_data_fonts_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_data_fonts_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + prebuilt_font { name: "DroidSansMono.ttf", src: "DroidSansMono.ttf", diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk index 7949c77ab558..6ae88007f0f5 100644 --- a/data/keyboards/Android.mk +++ b/data/keyboards/Android.mk @@ -22,6 +22,9 @@ include $(LOCAL_PATH)/common.mk include $(CLEAR_VARS) LOCAL_MODULE := validate_framework_keymaps +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE intermediates := $(call intermediates-dir-for,ETC,$(LOCAL_MODULE),,COMMON) LOCAL_BUILT_MODULE := $(intermediates)/stamp diff --git a/data/keyboards/OWNERS b/data/keyboards/OWNERS index c4f6df824a39..0ce83507160c 100644 --- a/data/keyboards/OWNERS +++ b/data/keyboards/OWNERS @@ -1,5 +1,3 @@ set noparent -michaelwr@google.com -svv@google.com -lzye@google.com +include /services/core/java/com/android/server/input/OWNERS diff --git a/drm/jni/Android.bp b/drm/jni/Android.bp index 68757d86fb89..669f10994365 100644 --- a/drm/jni/Android.bp +++ b/drm/jni/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libdrmframework_jni", diff --git a/errorprone/Android.bp b/errorprone/Android.bp index 7d0557d19393..f384ae94d36a 100644 --- a/errorprone/Android.bp +++ b/errorprone/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_plugin { name: "error_prone_android_framework", diff --git a/graphics/java/android/graphics/pdf/OWNERS b/graphics/java/android/graphics/pdf/OWNERS index f04e2008a437..057dc0d9583c 100644 --- a/graphics/java/android/graphics/pdf/OWNERS +++ b/graphics/java/android/graphics/pdf/OWNERS @@ -5,4 +5,3 @@ djsollen@google.com sumir@google.com svetoslavganov@android.com svetoslavganov@google.com -moltmann@google.com diff --git a/graphics/proto/Android.bp b/graphics/proto/Android.bp index ea79b731a365..1b192668b4a3 100644 --- a/graphics/proto/Android.bp +++ b/graphics/proto/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_static { name: "updatable-driver-protos", host_supported: true, diff --git a/keystore/Android.bp b/keystore/Android.bp new file mode 100644 index 000000000000..5db668e48431 --- /dev/null +++ b/keystore/Android.bp @@ -0,0 +1,31 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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_applicable_licenses: ["frameworks_base_keystore_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_keystore_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java new file mode 100644 index 000000000000..c81c8c54d88a --- /dev/null +++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.security.usermanager.IKeystoreUserManager; +import android.system.keystore2.ResponseCode; +import android.util.Log; + +/** + * @hide This is the client side for IKeystoreUserManager AIDL. + * It shall only be used by the LockSettingsService. + */ +public class AndroidKeyStoreMaintenance { + private static final String TAG = "AndroidKeyStoreMaintenance"; + + public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; + + private static IKeystoreUserManager getService() { + return IKeystoreUserManager.Stub.asInterface( + ServiceManager.checkService("android.security.usermanager")); + } + + /** + * Informs keystore2 about adding a user + * + * @param userId - Android user id of the user being added + * @return 0 if successful or a {@code ResponseCode} + * @hide + */ + public static int onUserAdded(@NonNull int userId) { + if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; + try { + getService().onUserAdded(userId); + return 0; + } catch (ServiceSpecificException e) { + Log.e(TAG, "onUserAdded failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } + + /** + * Informs keystore2 about removing a usergit mer + * + * @param userId - Android user id of the user being removed + * @return 0 if successful or a {@code ResponseCode} + * @hide + */ + public static int onUserRemoved(int userId) { + if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; + try { + getService().onUserRemoved(userId); + return 0; + } catch (ServiceSpecificException e) { + Log.e(TAG, "onUserRemoved failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } + + /** + * Informs keystore2 about changing user's password + * + * @param userId - Android user id of the user + * @param password - a secret derived from the synthetic password provided by the + * LockSettingService + * @return 0 if successful or a {@code ResponseCode} + * @hide + */ + public static int onUserPasswordChanged(int userId, @Nullable byte[] password) { + if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; + try { + getService().onUserPasswordChanged(userId, password); + return 0; + } catch (ServiceSpecificException e) { + Log.e(TAG, "onUserPasswordChanged failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } +} diff --git a/tools/hiddenapi/Android.bp b/keystore/java/android/security/AppUriAuthenticationPolicy.aidl index e0eb06cbea7f..5c52c86f0426 100644 --- a/tools/hiddenapi/Android.bp +++ b/keystore/java/android/security/AppUriAuthenticationPolicy.aidl @@ -14,17 +14,6 @@ * limitations under the License. */ -python_binary_host { - name: "merge_csv", - main: "merge_csv.py", - srcs: ["merge_csv.py"], - version: { - py2: { - enabled: false, - }, - py3: { - enabled: true, - embedded_launcher: true - }, - }, -} +package android.security; + +parcelable AppUriAuthenticationPolicy; diff --git a/keystore/java/android/security/AppUriAuthenticationPolicy.java b/keystore/java/android/security/AppUriAuthenticationPolicy.java new file mode 100644 index 000000000000..0244ce97c0d4 --- /dev/null +++ b/keystore/java/android/security/AppUriAuthenticationPolicy.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * The app-URI authentication policy is set by the credential management app. This policy determines + * which alias for a private key and certificate pair should be used for authentication. + * <p> + * The authentication policy should be added as a parameter when calling + * {@link KeyChain#createManageCredentialsIntent}. + * <p> + * Example: + * <pre>{@code + * AppUriAuthenticationPolicy authenticationPolicy = new AppUriAuthenticationPolicy.Builder() + * .addAppAndUriMapping("com.test.pkg", testUri, "testAlias") + * .addAppAndUriMapping("com.test2.pkg", testUri1, "testAlias2") + * .addAppAndUriMapping("com.test2.pkg", testUri2, "testAlias2") + * .build(); + * Intent requestIntent = KeyChain.createManageCredentialsIntent(authenticationPolicy); + * }</pre> + * <p> + */ +public final class AppUriAuthenticationPolicy implements Parcelable { + + private static final String KEY_AUTHENTICATION_POLICY_APP_TO_URIS = + "authentication_policy_app_to_uris"; + private static final String KEY_AUTHENTICATION_POLICY_APP = "policy_app"; + + /** + * The mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + private final Map<String, UrisToAliases> mAppToUris; + + private AppUriAuthenticationPolicy(@NonNull Map<String, UrisToAliases> appToUris) { + Objects.requireNonNull(appToUris); + this.mAppToUris = appToUris; + } + + /** + * Builder class for {@link AppUriAuthenticationPolicy} objects. + */ + public static final class Builder { + private Map<String, UrisToAliases> mPackageNameToUris; + + /** + * Initialize a new Builder to construct an {@link AppUriAuthenticationPolicy}. + */ + public Builder() { + mPackageNameToUris = new HashMap<>(); + } + + /** + * Adds mappings from an app and URI to an alias, which will be used for authentication. + * <p> + * If this method is called with a package name and URI that was previously added, the + * previous alias will be overwritten. + * + * @param appPackageName The app's package name to authenticate the user to. + * @param uri The URI to authenticate the user to. + * @param alias The alias which will be used for authentication. + * + * @return the same Builder instance. + */ + @NonNull + public Builder addAppAndUriMapping(@NonNull String appPackageName, @NonNull Uri uri, + @NonNull String alias) { + Objects.requireNonNull(appPackageName); + Objects.requireNonNull(uri); + Objects.requireNonNull(alias); + UrisToAliases urisToAliases = + mPackageNameToUris.getOrDefault(appPackageName, new UrisToAliases()); + urisToAliases.addUriToAlias(uri, alias); + mPackageNameToUris.put(appPackageName, urisToAliases); + return this; + } + + /** + * Adds mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + * + * @hide + */ + @NonNull + public Builder addAppAndUriMapping(@NonNull String appPackageName, + @NonNull UrisToAliases urisToAliases) { + Objects.requireNonNull(appPackageName); + Objects.requireNonNull(urisToAliases); + mPackageNameToUris.put(appPackageName, urisToAliases); + return this; + } + + /** + * Combines all of the attributes that have been set on the {@link Builder} + * + * @return a new {@link AppUriAuthenticationPolicy} object. + */ + @NonNull + public AppUriAuthenticationPolicy build() { + return new AppUriAuthenticationPolicy(mPackageNameToUris); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeMap(mAppToUris); + } + + @NonNull + public static final Parcelable.Creator<AppUriAuthenticationPolicy> CREATOR = + new Parcelable.Creator<AppUriAuthenticationPolicy>() { + @Override + public AppUriAuthenticationPolicy createFromParcel(Parcel in) { + Map<String, UrisToAliases> appToUris = new HashMap<>(); + in.readMap(appToUris, UrisToAliases.class.getClassLoader()); + return new AppUriAuthenticationPolicy(appToUris); + } + + @Override + public AppUriAuthenticationPolicy[] newArray(int size) { + return new AppUriAuthenticationPolicy[size]; + } + }; + + @Override + public String toString() { + return "AppUriAuthenticationPolicy{" + + "mPackageNameToUris=" + mAppToUris + + '}'; + } + + /** + * Return the authentication policy mapping, which determines which alias for a private key + * and certificate pair should be used for authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + public Map<String, Map<Uri, String>> getAppAndUriMappings() { + Map<String, Map<Uri, String>> appAndUris = new HashMap<>(); + for (Map.Entry<String, UrisToAliases> entry : mAppToUris.entrySet()) { + appAndUris.put(entry.getKey(), entry.getValue().getUrisToAliases()); + } + return appAndUris; + } + + /** + * Restore a previously saved {@link AppUriAuthenticationPolicy} from XML. + * + * @hide + */ + @Nullable + public static AppUriAuthenticationPolicy readFromXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + AppUriAuthenticationPolicy.Builder builder = new AppUriAuthenticationPolicy.Builder(); + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (!parser.getName().equals(KEY_AUTHENTICATION_POLICY_APP_TO_URIS)) { + continue; + } + String app = parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_APP); + UrisToAliases urisToAliases = UrisToAliases.readFromXml(parser); + builder.addAppAndUriMapping(app, urisToAliases); + } + return builder.build(); + } + + /** + * Save the {@link AppUriAuthenticationPolicy} to XML. + * + * @hide + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + for (Map.Entry<String, UrisToAliases> appsToUris : mAppToUris.entrySet()) { + out.startTag(null, KEY_AUTHENTICATION_POLICY_APP_TO_URIS); + out.attribute(null, KEY_AUTHENTICATION_POLICY_APP, appsToUris.getKey()); + appsToUris.getValue().writeToXml(out); + out.endTag(null, KEY_AUTHENTICATION_POLICY_APP_TO_URIS); + } + } + + /** + * Get the set of aliases found in the policy. + * + * @hide + */ + public Set<String> getAliases() { + Set<String> aliases = new HashSet<>(); + for (UrisToAliases appsToUris : mAppToUris.values()) { + aliases.addAll(appsToUris.getUrisToAliases().values()); + } + return aliases; + } + +} diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java index 21d23b1b2575..50a90820117d 100644 --- a/keystore/java/android/security/Authorization.java +++ b/keystore/java/android/security/Authorization.java @@ -33,20 +33,12 @@ import android.util.Log; */ public class Authorization { private static final String TAG = "KeystoreAuthorization"; - private static IKeystoreAuthorization sIKeystoreAuthorization; public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; - public Authorization() { - sIKeystoreAuthorization = null; - } - - private static synchronized IKeystoreAuthorization getService() { - if (sIKeystoreAuthorization == null) { - sIKeystoreAuthorization = IKeystoreAuthorization.Stub.asInterface( + private static IKeystoreAuthorization getService() { + return IKeystoreAuthorization.Stub.asInterface( ServiceManager.checkService("android.security.authorization")); - } - return sIKeystoreAuthorization; } /** @@ -55,12 +47,12 @@ public class Authorization { * @param authToken created by Android authenticators. * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}. */ - public int addAuthToken(@NonNull HardwareAuthToken authToken) { + public static int addAuthToken(@NonNull HardwareAuthToken authToken) { if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; try { getService().addAuthToken(authToken); return 0; - } catch (RemoteException e) { + } catch (RemoteException | NullPointerException e) { Log.w(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } catch (ServiceSpecificException e) { @@ -73,7 +65,7 @@ public class Authorization { * @param authToken * @return 0 if successful or a {@code ResponseCode}. */ - public int addAuthToken(@NonNull byte[] authToken) { + public static int addAuthToken(@NonNull byte[] authToken) { return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken)); } @@ -86,7 +78,7 @@ public class Authorization { * * @return 0 if successful or a {@code ResponseCode}. */ - public int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId, + public static int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId, @Nullable byte[] syntheticPassword) { if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; try { @@ -96,7 +88,7 @@ public class Authorization { getService().onLockScreenEvent(LockScreenEvent.UNLOCK, userId, syntheticPassword); } return 0; - } catch (RemoteException e) { + } catch (RemoteException | NullPointerException e) { Log.w(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } catch (ServiceSpecificException e) { diff --git a/keystore/java/android/security/CredentialManagementApp.java b/keystore/java/android/security/CredentialManagementApp.java new file mode 100644 index 000000000000..cbb23015dbe8 --- /dev/null +++ b/keystore/java/android/security/CredentialManagementApp.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.Log; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.Objects; + +/** + * The credential management app has the ability to manage the user's KeyChain credentials on + * unmanaged devices. {@link KeyChain#createManageCredentialsIntent} should be used by an app to + * request to become the credential management app. The user must approve this request before the + * app can manage the user's credentials. + * <p> + * Note: there can only be one credential management on the device. If another app requests to + * become the credential management app and the user approves, then the existing credential + * management app will no longer be able to manage credentials. + * <p> + * The requesting credential management app should include its authentication policy in the + * requesting intent. The authentication policy declares which certificates should be used for a + * given list of apps and URIs. + * + * @hide + * @see AppUriAuthenticationPolicy + */ +public class CredentialManagementApp { + + private static final String TAG = "CredentialManagementApp"; + private static final String KEY_PACKAGE_NAME = "package_name"; + + /** + * The credential management app's package name + */ + @NonNull + private final String mPackageName; + + /** + * The mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + private AppUriAuthenticationPolicy mAuthenticationPolicy; + + public CredentialManagementApp(@NonNull String packageName, + @NonNull AppUriAuthenticationPolicy authenticationPolicy) { + Objects.requireNonNull(packageName); + Objects.requireNonNull(authenticationPolicy); + mPackageName = packageName; + mAuthenticationPolicy = authenticationPolicy; + } + + /** + * Returns the package name of the credential management app. + */ + @NonNull + public String getPackageName() { + return mPackageName; + } + + /** + * Returns the authentication policy of the credential management app. + */ + @NonNull + public AppUriAuthenticationPolicy getAuthenticationPolicy() { + return mAuthenticationPolicy; + } + + /** + * Sets the authentication policy of the credential management app. + */ + public void setAuthenticationPolicy(@Nullable AppUriAuthenticationPolicy authenticationPolicy) { + Objects.requireNonNull(authenticationPolicy); + mAuthenticationPolicy = authenticationPolicy; + } + + /** + * Restore a previously saved {@link CredentialManagementApp} from XML. + */ + @Nullable + public static CredentialManagementApp readFromXml(@NonNull XmlPullParser parser) { + try { + String packageName = parser.getAttributeValue(null, KEY_PACKAGE_NAME); + AppUriAuthenticationPolicy policy = AppUriAuthenticationPolicy.readFromXml(parser); + return new CredentialManagementApp(packageName, policy); + } catch (XmlPullParserException | IOException e) { + Log.w(TAG, "Reading from xml failed", e); + } + return null; + } + + /** + * Save the {@link CredentialManagementApp} to XML. + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + out.attribute(null, KEY_PACKAGE_NAME, mPackageName); + if (mAuthenticationPolicy != null) { + mAuthenticationPolicy.writeToXml(out); + } + } +} diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index 9e1fb54bedbe..ae9f866459d6 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -49,6 +49,8 @@ public class Credentials { public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER"; + public static final String ACTION_MANAGE_CREDENTIALS = "android.security.MANAGE_CREDENTIALS"; + /** * Key prefix for CA certificates. * diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index 1ae6a631dbcb..f708298a2cbd 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -18,6 +18,8 @@ package android.security; import android.content.pm.StringParceledListSlice; import android.security.keymaster.KeymasterCertificateChain; import android.security.keystore.ParcelableKeyGenParameterSpec; +import android.security.AppUriAuthenticationPolicy; +import android.net.Uri; /** * Caller is required to ensure that {@link KeyStore#unlock @@ -47,6 +49,7 @@ interface IKeyChainService { in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid); boolean removeKeyPair(String alias); boolean containsKeyPair(String alias); + int[] getGrants(String alias); // APIs used by Settings boolean deleteCaCertificate(String alias); @@ -56,6 +59,12 @@ interface IKeyChainService { boolean containsCaAlias(String alias); byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem); List<String> getCaCertificateChainAliases(String rootAlias, boolean includeDeletedSystem); + void setCredentialManagementApp(String packageName, in AppUriAuthenticationPolicy policy); + boolean hasCredentialManagementApp(); + String getCredentialManagementAppPackageName(); + AppUriAuthenticationPolicy getCredentialManagementAppPolicy(); + String getPredefinedAliasForPackageAndUri(String packageName, in Uri uri); + void removeCredentialManagementApp(); // APIs used by KeyChainActivity void setGrant(int uid, String alias, boolean value); diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 6df62c0a0cba..63690d3c1567 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -15,6 +15,8 @@ */ package android.security; +import static android.security.Credentials.ACTION_MANAGE_CREDENTIALS; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -122,6 +124,11 @@ public final class KeyChain { private static final String CERT_INSTALLER_PACKAGE = "com.android.certinstaller"; /** + * Package name for Settings. + */ + private static final String SETTINGS_PACKAGE = "com.android.settings"; + + /** * Extra for use with {@link #ACTION_CHOOSER} * @hide Also used by KeyChainActivity implementation */ @@ -202,6 +209,20 @@ public final class KeyChain { public static final String EXTRA_PKCS12 = "PKCS12"; /** + * Extra used by {@link #createManageCredentialsIntent(AppUriAuthenticationPolicy)} to specify + * the authentication policy of the credential management app. + * + * <p>The authentication policy declares which alias for a private key and certificate pair + * should be used for authentication, given a list of apps and URIs. + * + * <p>The extra value should be a {@link AppUriAuthenticationPolicy}. + * + * @hide + */ + public static final String EXTRA_AUTHENTICATION_POLICY = + "android.security.extra.AUTHENTICATION_POLICY"; + + /** * Broadcast Action: Indicates the trusted storage has changed. Sent when * one of this happens: * @@ -386,6 +407,23 @@ public final class KeyChain { } /** + * Returns an {@code Intent} that should be used by an app to request to manage the user's + * credentials. This is limited to unmanaged devices. The authentication policy must be + * provided to be able to make this request successfully. + * + * @param policy The authentication policy determines which alias for a private key and + * certificate pair should be used for authentication. + */ + @NonNull + public static Intent createManageCredentialsIntent(@NonNull AppUriAuthenticationPolicy policy) { + Intent intent = new Intent(ACTION_MANAGE_CREDENTIALS); + intent.setComponent(ComponentName.createRelative(SETTINGS_PACKAGE, + ".security.RequestManageCredentials")); + intent.putExtra(EXTRA_AUTHENTICATION_POLICY, policy); + return intent; + } + + /** * Launches an {@code Activity} for the user to select the alias * for a private key and certificate pair for authentication. The * selected alias or null will be returned via the diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index e19d88c182ff..198df40c7d7b 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -996,7 +996,7 @@ public class KeyStore { */ public int addAuthToken(byte[] authToken) { try { - new Authorization().addAuthToken(authToken); + Authorization.addAuthToken(authToken); return mBinder.addAuthToken(authToken); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java index f7477bf92c81..476e4d7b7b18 100644 --- a/keystore/java/android/security/KeyStore2.java +++ b/keystore/java/android/security/KeyStore2.java @@ -107,7 +107,6 @@ public class KeyStore2 { try { return request.execute(service); } catch (ServiceSpecificException e) { - Log.e(TAG, "KeyStore exception", e); throw getKeyStoreException(e.errorCode); } catch (RemoteException e) { if (firstTry) { diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java index 372add9b7ecb..d188b6525579 100644 --- a/keystore/java/android/security/KeyStoreSecurityLevel.java +++ b/keystore/java/android/security/KeyStoreSecurityLevel.java @@ -190,7 +190,7 @@ public class KeyStoreSecurityLevel { keyDescriptor.blob = wrappedKey; keyDescriptor.domain = wrappedKeyDescriptor.domain; - return handleExceptions(() -> mSecurityLevel.importWrappedKey(wrappedKeyDescriptor, + return handleExceptions(() -> mSecurityLevel.importWrappedKey(keyDescriptor, wrappingKeyDescriptor, maskingKey, args.toArray(new KeyParameter[args.size()]), authenticatorSpecs)); } diff --git a/keystore/java/android/security/UrisToAliases.java b/keystore/java/android/security/UrisToAliases.java new file mode 100644 index 000000000000..65d433abe166 --- /dev/null +++ b/keystore/java/android/security/UrisToAliases.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * The mapping from URI to alias, which determines the alias to use when the user visits a URI. + * This mapping is part of the {@link AppUriAuthenticationPolicy}, which specifies which app this + * mapping should be used for. + * + * @hide + * @see AppUriAuthenticationPolicy + */ +public final class UrisToAliases implements Parcelable { + + private static final String KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS = + "authentication_policy_uri_to_alias"; + private static final String KEY_AUTHENTICATION_POLICY_URI = "policy_uri"; + private static final String KEY_AUTHENTICATION_POLICY_ALIAS = "policy_alias"; + + /** + * The mappings from URIs to aliases, which will be used for authentication. + */ + @NonNull + private final Map<Uri, String> mUrisToAliases; + + public UrisToAliases() { + this.mUrisToAliases = new HashMap<>(); + } + + private UrisToAliases(@NonNull Map<Uri, String> urisToAliases) { + this.mUrisToAliases = urisToAliases; + } + + @NonNull + public static final Creator<UrisToAliases> CREATOR = new Creator<UrisToAliases>() { + @Override + public UrisToAliases createFromParcel(Parcel in) { + Map<Uri, String> urisToAliases = new HashMap<>(); + in.readMap(urisToAliases, String.class.getClassLoader()); + return new UrisToAliases(urisToAliases); + } + + @Override + public UrisToAliases[] newArray(int size) { + return new UrisToAliases[size]; + } + }; + + /** + * Returns the mapping from URIs to aliases. + */ + @NonNull + public Map<Uri, String> getUrisToAliases() { + return Collections.unmodifiableMap(mUrisToAliases); + } + + /** + * Adds mapping from an URI to an alias. + */ + public void addUriToAlias(@NonNull Uri uri, @NonNull String alias) { + mUrisToAliases.put(uri, alias); + } + + /** + * Restore a previously saved {@link UrisToAliases} from XML. + */ + @Nullable + public static UrisToAliases readFromXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + Map<Uri, String> urisToAliases = new HashMap<>(); + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (!parser.getName().equals(KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS)) { + continue; + } + Uri uri = Uri.parse(parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_URI)); + String alias = parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_ALIAS); + urisToAliases.put(uri, alias); + } + return new UrisToAliases(urisToAliases); + } + + /** + * Save the {@link UrisToAliases} to XML. + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + for (Map.Entry<Uri, String> urisToAliases : mUrisToAliases.entrySet()) { + out.startTag(null, KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS); + out.attribute(null, KEY_AUTHENTICATION_POLICY_URI, urisToAliases.getKey().toString()); + out.attribute(null, KEY_AUTHENTICATION_POLICY_ALIAS, urisToAliases.getValue()); + out.endTag(null, KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeMap(mUrisToAliases); + } +} diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index 334b1110d651..988838b46334 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -17,6 +17,7 @@ package android.security.keystore; import android.annotation.Nullable; +import android.content.Context; import android.os.Build; import android.security.Credentials; import android.security.KeyPairGeneratorSpec; @@ -25,6 +26,8 @@ import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterCertificateChain; import android.security.keymaster.KeymasterDefs; +import android.telephony.TelephonyManager; +import android.util.ArraySet; import com.android.internal.org.bouncycastle.asn1.ASN1EncodableVector; import com.android.internal.org.bouncycastle.asn1.ASN1InputStream; @@ -477,11 +480,11 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato success = true; return keyPair; - } catch (ProviderException e) { + } catch (ProviderException | IllegalArgumentException | DeviceIdAttestationException e) { if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) { throw new SecureKeyImportUnavailableException(e); } else { - throw e; + throw new ProviderException(e); } } finally { if (!success) { @@ -491,7 +494,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair) - throws ProviderException { + throws ProviderException, DeviceIdAttestationException { byte[] challenge = mSpec.getAttestationChallenge(); if (challenge != null) { KeymasterArguments args = new KeymasterArguments(); @@ -510,6 +513,60 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato Build.MODEL.getBytes(StandardCharsets.UTF_8)); } + int[] idTypes = mSpec.getAttestationIds(); + if (idTypes != null) { + final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length); + for (int idType : idTypes) { + idTypesSet.add(idType); + } + TelephonyManager telephonyService = null; + if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI) + || idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) { + telephonyService = + (TelephonyManager) KeyStore.getApplicationContext().getSystemService( + Context.TELEPHONY_SERVICE); + if (telephonyService == null) { + throw new DeviceIdAttestationException( + "Unable to access telephony service"); + } + } + for (final Integer idType : idTypesSet) { + switch (idType) { + case AttestationUtils.ID_TYPE_SERIAL: + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL, + Build.getSerial().getBytes(StandardCharsets.UTF_8) + ); + break; + case AttestationUtils.ID_TYPE_IMEI: { + final String imei = telephonyService.getImei(0); + if (imei == null) { + throw new DeviceIdAttestationException("Unable to retrieve IMEI"); + } + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI, + imei.getBytes(StandardCharsets.UTF_8) + ); + break; + } + case AttestationUtils.ID_TYPE_MEID: { + final String meid = telephonyService.getMeid(0); + if (meid == null) { + throw new DeviceIdAttestationException("Unable to retrieve MEID"); + } + args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID, + meid.getBytes(StandardCharsets.UTF_8) + ); + break; + } + case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: { + args.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION); + break; + } + default: + throw new IllegalArgumentException("Unknown device ID type " + idType); + } + } + } + return getAttestationChain(privateKeyAlias, keyPair, args); } @@ -547,7 +604,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } } - private KeymasterArguments constructKeyGenerationArguments() { + private KeymasterArguments constructKeyGenerationArguments() + throws IllegalArgumentException, DeviceIdAttestationException { KeymasterArguments args = new KeymasterArguments(); args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits); args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); @@ -565,9 +623,9 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato mSpec.getKeyValidityForConsumptionEnd()); addAlgorithmSpecificParameters(args); - if (mSpec.isUniqueIdIncluded()) + if (mSpec.isUniqueIdIncluded()) { args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID); - + } return args; } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java index 16bf5469296f..087151711138 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java @@ -434,14 +434,16 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static java.security.KeyStore getKeyStoreForUid(int uid) throws KeyStoreException, NoSuchProviderException { - String providerName = PROVIDER_NAME; + final java.security.KeyStore.LoadStoreParameter loadParameter; if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) { - providerName = "AndroidKeyStoreLegacy"; + loadParameter = new android.security.keystore2.AndroidKeyStoreLoadStoreParameter( + KeyProperties.legacyUidToNamespace(uid)); + } else { + loadParameter = new AndroidKeyStoreLoadStoreParameter(uid); } - java.security.KeyStore result = - java.security.KeyStore.getInstance(providerName); + java.security.KeyStore result = java.security.KeyStore.getInstance(PROVIDER_NAME); try { - result.load(new AndroidKeyStoreLoadStoreParameter(uid)); + result.load(loadParameter); } catch (NoSuchAlgorithmException | CertificateException | IOException e) { throw new KeyStoreException( "Failed to load AndroidKeyStore KeyStore for UID " + uid, e); diff --git a/keystore/java/android/security/keystore/ArrayUtils.java b/keystore/java/android/security/keystore/ArrayUtils.java index c8c1de4a5e83..f22b6041800f 100644 --- a/keystore/java/android/security/keystore/ArrayUtils.java +++ b/keystore/java/android/security/keystore/ArrayUtils.java @@ -34,6 +34,14 @@ public abstract class ArrayUtils { return ((array != null) && (array.length > 0)) ? array.clone() : array; } + /** + * Clones an array if it is not null and has a length greater than 0. Otherwise, returns the + * array. + */ + public static int[] cloneIfNotEmpty(int[] array) { + return ((array != null) && (array.length > 0)) ? array.clone() : array; + } + public static byte[] cloneIfNotEmpty(byte[] array) { return ((array != null) && (array.length > 0)) ? array.clone() : array; } diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index c2a7b2ee6323..c79c12cd3343 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -236,10 +236,51 @@ import javax.security.auth.x500.X500Principal; * keyStore.load(null); * key = (SecretKey) keyStore.getKey("key2", null); * }</pre> + * + * <p><h3 id="example:ecdh">Example: EC key for ECDH key agreement</h3> + * This example illustrates how to generate an elliptic curve key pair, used to establish a shared + * secret with another party using ECDH key agreement. + * <pre> {@code + * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( + * KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); + * keyPairGenerator.initialize( + * new KeyGenParameterSpec.Builder( + * "eckeypair", + * KeyProperties.PURPOSE_AGREE_KEY) + * .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) + * .build()); + * KeyPair myKeyPair = keyPairGenerator.generateKeyPair(); + * + * // Exchange public keys with server. A new ephemeral key MUST be used for every message. + * PublicKey serverEphemeralPublicKey; // Ephemeral key received from server. + * + * // Create a shared secret based on our private key and the other party's public key. + * KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "AndroidKeyStore"); + * keyAgreement.init(myKeyPair.getPrivate()); + * keyAgreement.doPhase(serverEphemeralPublicKey, true); + * byte[] sharedSecret = keyAgreement.generateSecret(); + * + * // sharedSecret cannot safely be used as a key yet. We must run it through a key derivation + * // function with some other data: "salt" and "info". Salt is an optional random value, + * // omitted in this example. It's good practice to include both public keys and any other + * // key negotiation data in info. Here we use the public keys and a label that indicates + * // messages encrypted with this key are coming from the server. + * byte[] salt = {}; + * ByteArrayOutputStream info = new ByteArrayOutputStream(); + * info.write("ECDH secp256r1 AES-256-GCM-SIV\0".getBytes(StandardCharsets.UTF_8)); + * info.write(myKeyPair.getPublic().getEncoded()); + * info.write(serverEphemeralPublicKey.getEncoded()); + * + * // This example uses the Tink library and the HKDF key derivation function. + * AesGcmSiv key = new AesGcmSiv(Hkdf.computeHkdf( + * "HMACSHA256", sharedSecret, salt, info.toByteArray(), 32)); + * byte[] associatedData = {}; + * return key.decrypt(ciphertext, associatedData); + * } */ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs { - - private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake"); + private static final X500Principal DEFAULT_CERT_SUBJECT = + new X500Principal("CN=Android Keystore Key"); private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1"); private static final Date DEFAULT_CERT_NOT_BEFORE = new Date(0L); // Jan 1 1970 private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048 @@ -267,6 +308,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private final boolean mUserPresenceRequired; private final byte[] mAttestationChallenge; private final boolean mDevicePropertiesAttestationIncluded; + private final int[] mAttestationIds; private final boolean mUniqueIdIncluded; private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mInvalidatedByBiometricEnrollment; @@ -275,6 +317,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private final boolean mUnlockedDeviceRequired; private final boolean mCriticalToDeviceEncryption; private final int mMaxUsageCount; + private final String mAttestKeyAlias; /* * ***NOTE***: All new fields MUST also be added to the following: * ParcelableKeyGenParameterSpec class. @@ -308,6 +351,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu boolean userPresenceRequired, byte[] attestationChallenge, boolean devicePropertiesAttestationIncluded, + int[] attestationIds, boolean uniqueIdIncluded, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, @@ -315,7 +359,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu boolean userConfirmationRequired, boolean unlockedDeviceRequired, boolean criticalToDeviceEncryption, - int maxUsageCount) { + int maxUsageCount, + String attestKeyAlias) { if (TextUtils.isEmpty(keyStoreAlias)) { throw new IllegalArgumentException("keyStoreAlias must not be empty"); } @@ -361,6 +406,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUserAuthenticationType = userAuthenticationType; mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge); mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded; + mAttestationIds = attestationIds; mUniqueIdIncluded = uniqueIdIncluded; mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; @@ -369,6 +415,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUnlockedDeviceRequired = unlockedDeviceRequired; mCriticalToDeviceEncryption = criticalToDeviceEncryption; mMaxUsageCount = maxUsageCount; + mAttestKeyAlias = attestKeyAlias; } /** @@ -720,6 +767,25 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * @hide + * Allows the caller to specify device IDs to be attested to in the certificate for the + * generated key pair. These values are the enums specified in + * {@link android.security.keystore.AttestationUtils} + * + * @see android.security.keystore.AttestationUtils#ID_TYPE_SERIAL + * @see android.security.keystore.AttestationUtils#ID_TYPE_IMEI + * @see android.security.keystore.AttestationUtils#ID_TYPE_MEID + * @see android.security.keystore.AttestationUtils#USE_INDIVIDUAL_ATTESTATION + * + * @return integer array representing the requested device IDs to attest. + */ + @SystemApi + @Nullable + public int[] getAttestationIds() { + return Utils.cloneIfNotNull(mAttestationIds); + } + + /** * @hide This is a system-only API * * Returns {@code true} if the attestation certificate will contain a unique ID field. @@ -806,6 +872,18 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * Returns the alias of the attestation key that will be used to sign the attestation + * certificate of the generated key. Note that an attestation certificate will only be + * generated if an attestation challenge is set. + * + * @see Builder#setAttestKeyAlias(String) + */ + @Nullable + public String getAttestKeyAlias() { + return mAttestKeyAlias; + } + + /** * Builder of {@link KeyGenParameterSpec} instances. */ public final static class Builder { @@ -834,6 +912,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private boolean mUserPresenceRequired = false; private byte[] mAttestationChallenge = null; private boolean mDevicePropertiesAttestationIncluded = false; + private int[] mAttestationIds = null; private boolean mUniqueIdIncluded = false; private boolean mUserAuthenticationValidWhileOnBody; private boolean mInvalidatedByBiometricEnrollment = true; @@ -842,6 +921,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu private boolean mUnlockedDeviceRequired = false; private boolean mCriticalToDeviceEncryption = false; private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT; + private String mAttestKeyAlias = null; /** * Creates a new instance of the {@code Builder}. @@ -902,6 +982,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mAttestationChallenge = sourceSpec.getAttestationChallenge(); mDevicePropertiesAttestationIncluded = sourceSpec.isDevicePropertiesAttestationIncluded(); + mAttestationIds = sourceSpec.getAttestationIds(); mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded(); mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody(); mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment(); @@ -910,6 +991,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUnlockedDeviceRequired = sourceSpec.isUnlockedDeviceRequired(); mCriticalToDeviceEncryption = sourceSpec.isCriticalToDeviceEncryption(); mMaxUsageCount = sourceSpec.getMaxUsageCount(); + mAttestKeyAlias = sourceSpec.getAttestKeyAlias(); } /** @@ -1473,6 +1555,26 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * @hide + * Sets which IDs to attest in the attestation certificate for the key. The acceptable + * values in this integer array are the enums specified in + * {@link android.security.keystore.AttestationUtils} + * + * @param attestationIds the array of ID types to attest to in the certificate. + * + * @see android.security.keystore.AttestationUtils#ID_TYPE_SERIAL + * @see android.security.keystore.AttestationUtils#ID_TYPE_IMEI + * @see android.security.keystore.AttestationUtils#ID_TYPE_MEID + * @see android.security.keystore.AttestationUtils#USE_INDIVIDUAL_ATTESTATION + */ + @SystemApi + @NonNull + public Builder setAttestationIds(@NonNull int[] attestationIds) { + mAttestationIds = attestationIds; + return this; + } + + /** * @hide Only system apps can use this method. * * Sets whether to include a temporary unique ID field in the attestation certificate. @@ -1610,6 +1712,28 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** + * Sets the alias of the attestation key that will be used to sign the attestation + * certificate for the generated key pair, if an attestation challenge is set with {@link + * #setAttestationChallenge}. If an attestKeyAlias is set but no challenge, {@link + * java.security.KeyPairGenerator#initialize} will throw {@link + * java.security.InvalidAlgorithmParameterException}. + * + * <p>If the attestKeyAlias is set to null (the default), Android Keystore will select an + * appropriate system-provided attestation signing key. If not null, the alias must + * reference an Android Keystore Key that was created with {@link + * android.security.keystore.KeyProperties#PURPOSE_ATTEST_KEY}, or key generation will throw + * {@link java.security.InvalidAlgorithmParameterException}. + * + * @param attestKeyAlias the alias of the attestation key to be used to sign the + * attestation certificate. + */ + @NonNull + public Builder setAttestKeyAlias(@Nullable String attestKeyAlias) { + mAttestKeyAlias = attestKeyAlias; + return this; + } + + /** * Builds an instance of {@code KeyGenParameterSpec}. */ @NonNull @@ -1638,6 +1762,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUserPresenceRequired, mAttestationChallenge, mDevicePropertiesAttestationIncluded, + mAttestationIds, mUniqueIdIncluded, mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, @@ -1645,7 +1770,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu mUserConfirmationRequired, mUnlockedDeviceRequired, mCriticalToDeviceEncryption, - mMaxUsageCount); + mMaxUsageCount, + mAttestKeyAlias); } } } diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java index 3ebca6ad302d..7b0fa91380e1 100644 --- a/keystore/java/android/security/keystore/KeyProperties.java +++ b/keystore/java/android/security/keystore/KeyProperties.java @@ -70,6 +70,7 @@ public abstract class KeyProperties { PURPOSE_VERIFY, PURPOSE_WRAP_KEY, PURPOSE_AGREE_KEY, + PURPOSE_ATTEST_KEY, }) public @interface PurposeEnum {} @@ -100,10 +101,26 @@ public abstract class KeyProperties { /** * Purpose of key: creating a shared ECDH secret through key agreement. + * + * <p>A key having this purpose can be combined with the elliptic curve public key of another + * party to establish a shared secret over an insecure channel. It should be used as a + * parameter to {@link javax.crypto.KeyAgreement#init(java.security.Key)} (a complete example is + * available <a + * href="{@docRoot}reference/android/security/keystore/KeyGenParameterSpec#example:ecdh" + * >here</a>). + * See <a href="https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman">this + * article</a> for a more detailed explanation. */ public static final int PURPOSE_AGREE_KEY = 1 << 6; /** + * Purpose of key: Signing attestaions. This purpose is incompatible with all others, meaning + * that when generating a key with PURPOSE_ATTEST_KEY, no other purposes may be specified. In + * addition, PURPOSE_ATTEST_KEY may not be specified for imported keys. + */ + public static final int PURPOSE_ATTEST_KEY = 1 << 7; + + /** * @hide */ public static abstract class Purpose { @@ -123,6 +140,8 @@ public abstract class KeyProperties { return KeymasterDefs.KM_PURPOSE_WRAP; case PURPOSE_AGREE_KEY: return KeymasterDefs.KM_PURPOSE_AGREE_KEY; + case PURPOSE_ATTEST_KEY: + return KeymasterDefs.KM_PURPOSE_ATTEST_KEY; default: throw new IllegalArgumentException("Unknown purpose: " + purpose); } @@ -142,6 +161,8 @@ public abstract class KeyProperties { return PURPOSE_WRAP_KEY; case KeymasterDefs.KM_PURPOSE_AGREE_KEY: return PURPOSE_AGREE_KEY; + case KeymasterDefs.KM_PURPOSE_ATTEST_KEY: + return PURPOSE_ATTEST_KEY; default: throw new IllegalArgumentException("Unknown purpose: " + purpose); } diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 76ce23efd05b..673491ef523e 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -588,7 +588,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID; private boolean mCriticalToDeviceEncryption = false; private boolean mIsStrongBoxBacked = false; - private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT; + private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT; + private String mAttestKeyAlias = null; /** * Creates a new instance of the {@code Builder}. diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java index 8163472abdfb..a6e33664f2b1 100644 --- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java @@ -59,7 +59,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(mSpec.getKeystoreAlias()); out.writeInt(mSpec.getPurposes()); - out.writeInt(mSpec.getUid()); + out.writeInt(mSpec.getNamespace()); out.writeInt(mSpec.getKeySize()); // Only needs to support RSAKeyGenParameterSpec and ECGenParameterSpec. @@ -101,6 +101,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { out.writeBoolean(mSpec.isUserPresenceRequired()); out.writeByteArray(mSpec.getAttestationChallenge()); out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded()); + out.writeIntArray(mSpec.getAttestationIds()); out.writeBoolean(mSpec.isUniqueIdIncluded()); out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody()); out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment()); @@ -109,6 +110,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { out.writeBoolean(mSpec.isUnlockedDeviceRequired()); out.writeBoolean(mSpec.isCriticalToDeviceEncryption()); out.writeInt(mSpec.getMaxUsageCount()); + out.writeString(mSpec.getAttestKeyAlias()); } private static Date readDateOrNull(Parcel in) { @@ -123,7 +125,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { private ParcelableKeyGenParameterSpec(Parcel in) { final String keystoreAlias = in.readString(); final int purposes = in.readInt(); - final int uid = in.readInt(); + final int namespace = in.readInt(); final int keySize = in.readInt(); final int keySpecType = in.readInt(); @@ -160,6 +162,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { final boolean userPresenceRequired = in.readBoolean(); final byte[] attestationChallenge = in.createByteArray(); final boolean devicePropertiesAttestationIncluded = in.readBoolean(); + final int[] attestationIds = in.createIntArray(); final boolean uniqueIdIncluded = in.readBoolean(); final boolean userAuthenticationValidWhileOnBody = in.readBoolean(); final boolean invalidatedByBiometricEnrollment = in.readBoolean(); @@ -168,12 +171,13 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { final boolean unlockedDeviceRequired = in.readBoolean(); final boolean criticalToDeviceEncryption = in.readBoolean(); final int maxUsageCount = in.readInt(); + final String attestKeyAlias = in.readString(); // The KeyGenParameterSpec is intentionally not constructed using a Builder here: // The intention is for this class to break if new parameters are added to the // KeyGenParameterSpec constructor (whereas using a builder would silently drop them). mSpec = new KeyGenParameterSpec( keystoreAlias, - uid, + namespace, keySize, algorithmSpec, certificateSubject, @@ -195,6 +199,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { userPresenceRequired, attestationChallenge, devicePropertiesAttestationIncluded, + attestationIds, uniqueIdIncluded, userAuthenticationValidWhileOnBody, invalidatedByBiometricEnrollment, @@ -202,7 +207,8 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { userConfirmationRequired, unlockedDeviceRequired, criticalToDeviceEncryption, - maxUsageCount); + maxUsageCount, + attestKeyAlias); } public static final @android.annotation.NonNull Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() { diff --git a/keystore/java/android/security/keystore/Utils.java b/keystore/java/android/security/keystore/Utils.java index 5722c7b53ef4..e58b1ccb5370 100644 --- a/keystore/java/android/security/keystore/Utils.java +++ b/keystore/java/android/security/keystore/Utils.java @@ -33,4 +33,8 @@ abstract class Utils { static byte[] cloneIfNotNull(byte[] value) { return (value != null) ? value.clone() : null; } + + static int[] cloneIfNotNull(int[] value) { + return (value != null) ? value.clone() : null; + } } diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java index 8475ad9fd57b..0f777495a3fe 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java @@ -164,6 +164,9 @@ public abstract class AndroidKeyStoreHmacSpi extends MacSpi implements KeyStoreC List<KeyParameter> parameters = new ArrayList<>(); parameters.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN + )); + parameters.add(KeyStore2ParameterUtils.makeEnum( KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC )); parameters.add(KeyStore2ParameterUtils.makeEnum( diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java index 32650aeda1b1..5619585d9c3c 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java @@ -21,7 +21,6 @@ import android.security.KeyStoreSecurityLevel; import android.system.keystore2.Authorization; import android.system.keystore2.Domain; import android.system.keystore2.KeyDescriptor; -import android.util.Log; import java.security.Key; @@ -127,15 +126,6 @@ public class AndroidKeyStoreKey implements Key { return false; } - // If the key ids are equal and the class matches all the other fields cannot differ - // unless we have a bug. - if (!mAlgorithm.equals(other.mAlgorithm) - || !mAuthorizations.equals(other.mAuthorizations) - || !mDescriptor.equals(other.mDescriptor)) { - Log.e("AndroidKeyStoreKey", "Bug: key ids are identical, but key metadata" - + "differs."); - return false; - } return true; } } diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index 70e30d2de5a1..e401add9ece7 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -18,26 +18,36 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.hardware.security.keymint.KeyParameter; +import android.hardware.security.keymint.KeyPurpose; import android.hardware.security.keymint.SecurityLevel; +import android.hardware.security.keymint.Tag; import android.os.Build; import android.security.KeyPairGeneratorSpec; +import android.security.KeyStore; import android.security.KeyStore2; import android.security.KeyStoreException; import android.security.KeyStoreSecurityLevel; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; import android.security.keystore.ArrayUtils; +import android.security.keystore.AttestationUtils; +import android.security.keystore.DeviceIdAttestationException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.KeymasterUtils; import android.security.keystore.SecureKeyImportUnavailableException; import android.security.keystore.StrongBoxUnavailableException; +import android.system.keystore2.Authorization; import android.system.keystore2.Domain; import android.system.keystore2.IKeystoreSecurityLevel; import android.system.keystore2.KeyDescriptor; +import android.system.keystore2.KeyEntryResponse; import android.system.keystore2.KeyMetadata; import android.system.keystore2.ResponseCode; +import android.telephony.TelephonyManager; +import android.util.ArraySet; import android.util.Log; import libcore.util.EmptyArray; @@ -55,6 +65,7 @@ import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -63,6 +74,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.function.Predicate; /** * Provides a way to create instances of a KeyPair which will be placed in the @@ -142,11 +154,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato private KeyGenParameterSpec mSpec; private String mEntryAlias; - private int mEntryUid; + private int mEntryNamespace; private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm; private int mKeymasterAlgorithm = -1; private int mKeySizeBits; private SecureRandom mRng; + private KeyDescriptor mAttestKeyDescriptor; private int[] mKeymasterPurposes; private int[] mKeymasterBlockModes; @@ -191,83 +204,9 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato // Legacy/deprecated spec KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params; try { - KeyGenParameterSpec.Builder specBuilder; - String specKeyAlgorithm = legacySpec.getKeyType(); - if (specKeyAlgorithm != null) { - // Spec overrides the generator's default key algorithm - try { - keymasterAlgorithm = - KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( - specKeyAlgorithm); - } catch (IllegalArgumentException e) { - throw new InvalidAlgorithmParameterException( - "Invalid key type in parameters", e); - } - } - switch (keymasterAlgorithm) { - case KeymasterDefs.KM_ALGORITHM_EC: - specBuilder = new KeyGenParameterSpec.Builder( - legacySpec.getKeystoreAlias(), - KeyProperties.PURPOSE_SIGN - | KeyProperties.PURPOSE_VERIFY); - // Authorized to be used with any digest (including no digest). - // MD5 was never offered for Android Keystore for ECDSA. - specBuilder.setDigests( - KeyProperties.DIGEST_NONE, - KeyProperties.DIGEST_SHA1, - KeyProperties.DIGEST_SHA224, - KeyProperties.DIGEST_SHA256, - KeyProperties.DIGEST_SHA384, - KeyProperties.DIGEST_SHA512); - break; - case KeymasterDefs.KM_ALGORITHM_RSA: - specBuilder = new KeyGenParameterSpec.Builder( - legacySpec.getKeystoreAlias(), - KeyProperties.PURPOSE_ENCRYPT - | KeyProperties.PURPOSE_DECRYPT - | KeyProperties.PURPOSE_SIGN - | KeyProperties.PURPOSE_VERIFY); - // Authorized to be used with any digest (including no digest). - specBuilder.setDigests( - KeyProperties.DIGEST_NONE, - KeyProperties.DIGEST_MD5, - KeyProperties.DIGEST_SHA1, - KeyProperties.DIGEST_SHA224, - KeyProperties.DIGEST_SHA256, - KeyProperties.DIGEST_SHA384, - KeyProperties.DIGEST_SHA512); - // Authorized to be used with any encryption and signature padding - // schemes (including no padding). - specBuilder.setEncryptionPaddings( - KeyProperties.ENCRYPTION_PADDING_NONE, - KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, - KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); - specBuilder.setSignaturePaddings( - KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, - KeyProperties.SIGNATURE_PADDING_RSA_PSS); - // Disable randomized encryption requirement to support encryption - // padding NONE above. - specBuilder.setRandomizedEncryptionRequired(false); - break; - default: - throw new ProviderException( - "Unsupported algorithm: " + mKeymasterAlgorithm); - } - - if (legacySpec.getKeySize() != -1) { - specBuilder.setKeySize(legacySpec.getKeySize()); - } - if (legacySpec.getAlgorithmParameterSpec() != null) { - specBuilder.setAlgorithmParameterSpec( - legacySpec.getAlgorithmParameterSpec()); - } - specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); - specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); - specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); - specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); - specBuilder.setUserAuthenticationRequired(false); - - spec = specBuilder.build(); + keymasterAlgorithm = getKeymasterAlgorithmFromLegacy(keymasterAlgorithm, + legacySpec); + spec = buildKeyGenParameterSpecFromLegacy(legacySpec, keymasterAlgorithm); } catch (NullPointerException | IllegalArgumentException e) { throw new InvalidAlgorithmParameterException(e); } @@ -279,7 +218,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } mEntryAlias = spec.getKeystoreAlias(); - mEntryUid = spec.getUid(); + mEntryNamespace = spec.getNamespace(); mSpec = spec; mKeymasterAlgorithm = keymasterAlgorithm; mKeySizeBits = spec.getKeySize(); @@ -336,6 +275,10 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato mJcaKeyAlgorithm = jcaKeyAlgorithm; mRng = random; mKeyStore = KeyStore2.getInstance(); + + mAttestKeyDescriptor = buildAndCheckAttestKeyDescriptor(spec); + checkAttestKeyPurpose(spec); + success = true; } finally { if (!success) { @@ -344,9 +287,159 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } } + private void checkAttestKeyPurpose(KeyGenParameterSpec spec) + throws InvalidAlgorithmParameterException { + if ((spec.getPurposes() & KeyProperties.PURPOSE_ATTEST_KEY) != 0 + && spec.getPurposes() != KeyProperties.PURPOSE_ATTEST_KEY) { + throw new InvalidAlgorithmParameterException( + "PURPOSE_ATTEST_KEY may not be specified with any other purposes"); + } + } + + private KeyDescriptor buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec) + throws InvalidAlgorithmParameterException { + if (spec.getAttestKeyAlias() != null) { + KeyDescriptor attestKeyDescriptor = new KeyDescriptor(); + attestKeyDescriptor.domain = Domain.APP; + attestKeyDescriptor.alias = spec.getAttestKeyAlias(); + try { + KeyEntryResponse attestKey = mKeyStore.getKeyEntry(attestKeyDescriptor); + checkAttestKeyChallenge(spec); + checkAttestKeyPurpose(attestKey.metadata.authorizations); + checkAttestKeySecurityLevel(spec, attestKey); + } catch (KeyStoreException e) { + throw new InvalidAlgorithmParameterException("Invalid attestKeyAlias", e); + } + return attestKeyDescriptor; + } + return null; + } + + private void checkAttestKeyChallenge(KeyGenParameterSpec spec) + throws InvalidAlgorithmParameterException { + if (spec.getAttestationChallenge() == null) { + throw new InvalidAlgorithmParameterException( + "AttestKey specified but no attestation challenge provided"); + } + } + + private void checkAttestKeyPurpose(Authorization[] keyAuths) + throws InvalidAlgorithmParameterException { + Predicate<Authorization> isAttestKeyPurpose = x -> x.keyParameter.tag == Tag.PURPOSE + && x.keyParameter.value.getKeyPurpose() == KeyPurpose.ATTEST_KEY; + + if (Arrays.stream(keyAuths).noneMatch(isAttestKeyPurpose)) { + throw new InvalidAlgorithmParameterException( + ("Invalid attestKey, does not have PURPOSE_ATTEST_KEY")); + } + } + + private void checkAttestKeySecurityLevel(KeyGenParameterSpec spec, KeyEntryResponse key) + throws InvalidAlgorithmParameterException { + boolean attestKeyInStrongBox = key.metadata.keySecurityLevel == SecurityLevel.STRONGBOX; + if (spec.isStrongBoxBacked() != attestKeyInStrongBox) { + if (attestKeyInStrongBox) { + throw new InvalidAlgorithmParameterException( + "Invalid security level: Cannot sign non-StrongBox key with " + + "StrongBox attestKey"); + + } else { + throw new InvalidAlgorithmParameterException( + "Invalid security level: Cannot sign StrongBox key with " + + "non-StrongBox attestKey"); + } + } + } + + private int getKeymasterAlgorithmFromLegacy(int keymasterAlgorithm, + KeyPairGeneratorSpec legacySpec) throws InvalidAlgorithmParameterException { + String specKeyAlgorithm = legacySpec.getKeyType(); + if (specKeyAlgorithm != null) { + // Spec overrides the generator's default key algorithm + try { + keymasterAlgorithm = + KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( + specKeyAlgorithm); + } catch (IllegalArgumentException e) { + throw new InvalidAlgorithmParameterException( + "Invalid key type in parameters", e); + } + } + return keymasterAlgorithm; + } + + private KeyGenParameterSpec buildKeyGenParameterSpecFromLegacy(KeyPairGeneratorSpec legacySpec, + int keymasterAlgorithm) { + KeyGenParameterSpec.Builder specBuilder; + switch (keymasterAlgorithm) { + case KeymasterDefs.KM_ALGORITHM_EC: + specBuilder = new KeyGenParameterSpec.Builder( + legacySpec.getKeystoreAlias(), + KeyProperties.PURPOSE_SIGN + | KeyProperties.PURPOSE_VERIFY); + // Authorized to be used with any digest (including no digest). + // MD5 was never offered for Android Keystore for ECDSA. + specBuilder.setDigests( + KeyProperties.DIGEST_NONE, + KeyProperties.DIGEST_SHA1, + KeyProperties.DIGEST_SHA224, + KeyProperties.DIGEST_SHA256, + KeyProperties.DIGEST_SHA384, + KeyProperties.DIGEST_SHA512); + break; + case KeymasterDefs.KM_ALGORITHM_RSA: + specBuilder = new KeyGenParameterSpec.Builder( + legacySpec.getKeystoreAlias(), + KeyProperties.PURPOSE_ENCRYPT + | KeyProperties.PURPOSE_DECRYPT + | KeyProperties.PURPOSE_SIGN + | KeyProperties.PURPOSE_VERIFY); + // Authorized to be used with any digest (including no digest). + specBuilder.setDigests( + KeyProperties.DIGEST_NONE, + KeyProperties.DIGEST_MD5, + KeyProperties.DIGEST_SHA1, + KeyProperties.DIGEST_SHA224, + KeyProperties.DIGEST_SHA256, + KeyProperties.DIGEST_SHA384, + KeyProperties.DIGEST_SHA512); + // Authorized to be used with any encryption and signature padding + // schemes (including no padding). + specBuilder.setEncryptionPaddings( + KeyProperties.ENCRYPTION_PADDING_NONE, + KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, + KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); + specBuilder.setSignaturePaddings( + KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, + KeyProperties.SIGNATURE_PADDING_RSA_PSS); + // Disable randomized encryption requirement to support encryption + // padding NONE above. + specBuilder.setRandomizedEncryptionRequired(false); + break; + default: + throw new ProviderException( + "Unsupported algorithm: " + mKeymasterAlgorithm); + } + + if (legacySpec.getKeySize() != -1) { + specBuilder.setKeySize(legacySpec.getKeySize()); + } + if (legacySpec.getAlgorithmParameterSpec() != null) { + specBuilder.setAlgorithmParameterSpec( + legacySpec.getAlgorithmParameterSpec()); + } + specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); + specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); + specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); + specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); + specBuilder.setUserAuthenticationRequired(false); + + return specBuilder.build(); + } + private void resetAll() { mEntryAlias = null; - mEntryUid = KeyProperties.NAMESPACE_APPLICATION; + mEntryNamespace = KeyProperties.NAMESPACE_APPLICATION; mJcaKeyAlgorithm = null; mKeymasterAlgorithm = -1; mKeymasterPurposes = null; @@ -448,17 +541,17 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato KeyDescriptor descriptor = new KeyDescriptor(); descriptor.alias = mEntryAlias; - descriptor.domain = mEntryUid == KeyProperties.NAMESPACE_APPLICATION + descriptor.domain = mEntryNamespace == KeyProperties.NAMESPACE_APPLICATION ? Domain.APP : Domain.SELINUX; - descriptor.nspace = mEntryUid; + descriptor.nspace = mEntryNamespace; descriptor.blob = null; boolean success = false; try { KeyStoreSecurityLevel iSecurityLevel = mKeyStore.getSecurityLevel(securityLevel); - KeyMetadata metadata = iSecurityLevel.generateKey(descriptor, null, + KeyMetadata metadata = iSecurityLevel.generateKey(descriptor, mAttestKeyDescriptor, constructKeyGenerationArguments(), flags, additionalEntropy); AndroidKeyStorePublicKey publicKey = @@ -478,7 +571,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } throw p; } - } catch (UnrecoverableKeyException e) { + } catch (UnrecoverableKeyException | IllegalArgumentException + | DeviceIdAttestationException e) { throw new ProviderException( "Failed to construct key object from newly generated key pair.", e); } finally { @@ -496,7 +590,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } private void addAttestationParameters(@NonNull List<KeyParameter> params) - throws ProviderException { + throws ProviderException, IllegalArgumentException, DeviceIdAttestationException { byte[] challenge = mSpec.getAttestationChallenge(); if (challenge != null) { @@ -526,15 +620,69 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato Build.MODEL.getBytes(StandardCharsets.UTF_8) )); } - } else { - if (mSpec.isDevicePropertiesAttestationIncluded()) { - throw new ProviderException("An attestation challenge must be provided when " - + "requesting device properties attestation."); + + int[] idTypes = mSpec.getAttestationIds(); + if (idTypes == null) { + return; + } + final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length); + for (int idType : idTypes) { + idTypesSet.add(idType); + } + TelephonyManager telephonyService = null; + if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI) + || idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) { + telephonyService = + (TelephonyManager) KeyStore.getApplicationContext().getSystemService( + Context.TELEPHONY_SERVICE); + if (telephonyService == null) { + throw new DeviceIdAttestationException("Unable to access telephony service"); + } + } + for (final Integer idType : idTypesSet) { + switch (idType) { + case AttestationUtils.ID_TYPE_SERIAL: + params.add(KeyStore2ParameterUtils.makeBytes( + KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL, + Build.getSerial().getBytes(StandardCharsets.UTF_8) + )); + break; + case AttestationUtils.ID_TYPE_IMEI: { + final String imei = telephonyService.getImei(0); + if (imei == null) { + throw new DeviceIdAttestationException("Unable to retrieve IMEI"); + } + params.add(KeyStore2ParameterUtils.makeBytes( + KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI, + imei.getBytes(StandardCharsets.UTF_8) + )); + break; + } + case AttestationUtils.ID_TYPE_MEID: { + final String meid = telephonyService.getMeid(0); + if (meid == null) { + throw new DeviceIdAttestationException("Unable to retrieve MEID"); + } + params.add(KeyStore2ParameterUtils.makeBytes( + KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID, + meid.getBytes(StandardCharsets.UTF_8) + )); + break; + } + case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: { + params.add(KeyStore2ParameterUtils.makeBool( + KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION)); + break; + } + default: + throw new IllegalArgumentException("Unknown device ID type " + idType); + } } } } - private Collection<KeyParameter> constructKeyGenerationArguments() { + private Collection<KeyParameter> constructKeyGenerationArguments() + throws DeviceIdAttestationException, IllegalArgumentException { List<KeyParameter> params = new ArrayList<>(); params.add(KeyStore2ParameterUtils.makeInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits)); params.add(KeyStore2ParameterUtils.makeEnum( diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 8c8acc418a0e..39607aeb3852 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -866,7 +866,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { try { response = mKeyStore.getKeyEntry(wrappingkey); } catch (android.security.KeyStoreException e) { - throw new KeyStoreException("Failed to load wrapping key.", e); + throw new KeyStoreException("Failed to import wrapped key. Keystore error code: " + + e.getErrorCode(), e); } KeyDescriptor wrappedKey = makeKeyDescriptor(alias); diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp index e9b22c140742..2315a8568c64 100644 --- a/keystore/tests/Android.bp +++ b/keystore/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_keystore_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_keystore_license"], +} + android_test { name: "KeystoreTests", // LOCAL_MODULE := keystore diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp index 7fbbb61e469d..b6622bf0fa60 100644 --- a/libs/WindowManager/Jetpack/Android.bp +++ b/libs/WindowManager/Jetpack/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library_import { name: "window-sidecar", aars: ["window-sidecar-release.aar"], diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index b8934dc8c583..2987dabe4e30 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "WindowManager-Shell", srcs: [ diff --git a/libs/WindowManager/Shell/tests/Android.bp b/libs/WindowManager/Shell/tests/Android.bp index 78fa45ebdf94..ca37ad75467d 100644 --- a/libs/WindowManager/Shell/tests/Android.bp +++ b/libs/WindowManager/Shell/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "WindowManagerShellTests", diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index 6a7df94331f3..581af0d0628a 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -14,6 +14,23 @@ // libandroidfw is partially built for the host (used by obbtool, aapt, and others) +package { + default_applicable_licenses: ["frameworks_base_libs_androidfw_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_libs_androidfw_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "libandroidfw_defaults", cflags: [ diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING index 777aa0b429e5..766714cd7694 100644 --- a/libs/androidfw/TEST_MAPPING +++ b/libs/androidfw/TEST_MAPPING @@ -1,10 +1,6 @@ { "presubmit": [ { - "name": "libandroidfw_tests", - "host": true - }, - { "name": "CtsResourcesLoaderTests" } ] diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp index 77ef8dfb9725..b511244c4a30 100644 --- a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp +++ b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_libs_androidfw_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_libs_androidfw_license"], +} + cc_fuzz { name: "resourcefile_fuzzer", srcs: [ diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp index e713b98b867e..0388e92e1d1b 100644 --- a/libs/hostgraphics/Android.bp +++ b/libs/hostgraphics/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_host_static { name: "libhostgraphics", @@ -28,4 +37,4 @@ cc_library_host_static { enabled: true, } }, -}
\ No newline at end of file +} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index aa842ff6a7b7..6220abed05eb 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -1,3 +1,33 @@ +package { + default_applicable_licenses: ["frameworks_base_libs_hwui_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "frameworks_base_libs_hwui_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "hwui_defaults", defaults: [ @@ -313,12 +343,13 @@ cc_defaults { "libharfbuzz_ng", "liblog", "libminikin", - "libnativehelper", "libz", "libziparchive", "libjpeg", ], + static_libs: ["libnativehelper_lazy"], + target: { android: { srcs: [ // sources that depend on android only libraries diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp index d291ec001daf..697cbb9d41c0 100644 --- a/libs/incident/Android.bp +++ b/libs/incident/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "libincidentpriv_defaults", @@ -125,6 +134,3 @@ cc_test { "libgmock", ], } - - - diff --git a/libs/input/Android.bp b/libs/input/Android.bp index dca35012cbdd..55f932dffff1 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libinputservice", srcs: [ diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index 213b3adfb2a8..4eabfb238f4a 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { name: "libinputservice_test", srcs: [ diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp index d2b7d5c75d58..132d71eb6db8 100644 --- a/libs/protoutil/Android.bp +++ b/libs/protoutil/Android.bp @@ -12,6 +12,15 @@ // WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "libprotoutil_defaults", diff --git a/libs/services/Android.bp b/libs/services/Android.bp index 1e621079b532..bf2e764aae6a 100644 --- a/libs/services/Android.bp +++ b/libs/services/Android.bp @@ -14,6 +14,15 @@ // Provides C++ wrappers for system services. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libservices", srcs: [ diff --git a/libs/storage/Android.bp b/libs/storage/Android.bp index c19933e39c96..e8c6c071bc06 100644 --- a/libs/storage/Android.bp +++ b/libs/storage/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_base_libs_storage_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_libs_storage_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_static { name: "libstorage", diff --git a/libs/tracingproxy/Android.bp b/libs/tracingproxy/Android.bp index 67f407ff7599..7126bfac773d 100644 --- a/libs/tracingproxy/Android.bp +++ b/libs/tracingproxy/Android.bp @@ -14,6 +14,17 @@ // Provides C++ wrappers for system services. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libtracingproxy", diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp index e752b55f5ef7..edc847487dcb 100644 --- a/libs/usb/Android.bp +++ b/libs/usb/Android.bp @@ -14,6 +14,16 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-GPL-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.future.usb.accessory", srcs: ["src/**/*.java"], diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp index 19ed3d3ef52e..72090fb692e0 100644 --- a/libs/usb/tests/AccessoryChat/Android.bp +++ b/libs/usb/tests/AccessoryChat/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AccessoryChat", diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp index 5613745e966b..108649aa92ae 100644 --- a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp +++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary { name: "accessorychat", host_supported: true, diff --git a/libs/usb/tests/accessorytest/Android.bp b/libs/usb/tests/accessorytest/Android.bp index c6340e32e60c..69761aeb46fe 100644 --- a/libs/usb/tests/accessorytest/Android.bp +++ b/libs/usb/tests/accessorytest/Android.bp @@ -1,3 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-GPL-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "accessorytest", diff --git a/location/lib/Android.bp b/location/lib/Android.bp index cd45e8e6ffa6..5cd5a59f41ac 100644 --- a/location/lib/Android.bp +++ b/location/lib/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.location.provider", srcs: ["java/**/*.java"], diff --git a/location/tests/locationtests/Android.bp b/location/tests/locationtests/Android.bp index 1a4e2c7ba355..c18ef28ca799 100644 --- a/location/tests/locationtests/Android.bp +++ b/location/tests/locationtests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksLocationTests", // Include all test java files. diff --git a/lowpan/tests/Android.bp b/lowpan/tests/Android.bp index ad2bc27d1b39..590892926ec1 100644 --- a/lowpan/tests/Android.bp +++ b/lowpan/tests/Android.bp @@ -14,6 +14,15 @@ // Make test APK // ============================================================ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksLowpanApiTests", srcs: ["**/*.java"], diff --git a/media/Android.bp b/media/Android.bp index 0ed10472561d..6b4c3886a17d 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + aidl_interface { name: "audio_common-aidl", unstable: true, diff --git a/media/OWNERS b/media/OWNERS index e74149019b11..abfc8bfa976e 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -26,3 +26,7 @@ olly@google.com # SEO sungsoo@google.com + +# SEA/KIR/BVE +jtinker@google.com +robertshih@google.com diff --git a/media/java/Android.bp b/media/java/Android.bp index 0810699abf0a..aea63a073e95 100644 --- a/media/java/Android.bp +++ b/media/java/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "IMidiDeviceServer.aidl", srcs: ["android/media/midi/IMidiDeviceServer.aidl"], diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp index c65d25a03813..66c7bd4a1f2b 100644 --- a/media/java/android/media/tv/tunerresourcemanager/Android.bp +++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-media-tv-tunerresourcemanager-sources", srcs: [ @@ -14,4 +23,4 @@ java_library { visibility: [ "//frameworks/base", ], -}
\ No newline at end of file +} diff --git a/media/jni/Android.bp b/media/jni/Android.bp index d3466702ebf2..f65dfddef008 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_base_media_jni_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_media_jni_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_shared { name: "libmedia_jni", diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp index 40e4c54c2921..c2fc91d5cfea 100644 --- a/media/jni/audioeffect/Android.bp +++ b/media/jni/audioeffect/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_media_jni_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_media_jni_license"], +} + cc_library_shared { name: "libaudioeffect_jni", diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp index 6141308a8fdb..b3406cd89046 100644 --- a/media/jni/soundpool/Android.bp +++ b/media/jni/soundpool/Android.bp @@ -1,3 +1,22 @@ +package { + default_applicable_licenses: [ + "frameworks_base_media_jni_soundpool_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_media_jni_soundpool_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + tidy_errors = [ // https://clang.llvm.org/extra/clang-tidy/checks/list.html // For many categories, the checks are too many to specify individually. @@ -26,26 +45,30 @@ tidy_errors = [ "modernize-return-braced-init-list", "modernize-shrink-to-fit", "modernize-unary-static-assert", - "modernize-use-auto", // debatable - auto can obscure type + // "modernize-use-auto", // found in StreamManager.h, debatable - auto can obscure type "modernize-use-bool-literals", "modernize-use-default-member-init", "modernize-use-emplace", "modernize-use-equals-default", "modernize-use-equals-delete", - "modernize-use-nodiscard", + // "modernize-use-nodiscard", // found in SteamManager.h "modernize-use-noexcept", "modernize-use-nullptr", "modernize-use-override", //"modernize-use-trailing-return-type", // not necessarily more readable "modernize-use-transparent-functors", "modernize-use-uncaught-exceptions", - "modernize-use-using", + //"modernize-use-using", // found in SoundManager.h "performance-*", // Remove some pedantic stylistic requirements. "-google-readability-casting", // C++ casts not always necessary and may be verbose "-google-readability-todo", // do not require TODO(info) "-google-build-using-namespace", // Reenable and fix later. + + "-google-explicit-constructor", // found in StreamManager.h + "-misc-non-private-member-variables-in-classes", // found in SoundManager.h + "-performance-unnecessary-value-param", // found in StreamManager.h ] cc_defaults { @@ -77,8 +100,7 @@ cc_defaults { tidy_checks: tidy_errors, tidy_checks_as_errors: tidy_errors, tidy_flags: [ - "-format-style='file'", - "--header-filter='frameworks/base/media/jni/soundpool'", + "-format-style=file", ], } diff --git a/media/jni/soundpool/tests/Android.bp b/media/jni/soundpool/tests/Android.bp index 52f59ed69503..7d31c106f9c4 100644 --- a/media/jni/soundpool/tests/Android.bp +++ b/media/jni/soundpool/tests/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_media_jni_soundpool_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_base_media_jni_soundpool_license", + ], +} + cc_binary { name: "soundpool_stress", host_supported: false, diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp index 5f4b930f350e..bfb0cb854be3 100644 --- a/media/lib/remotedisplay/Android.bp +++ b/media/lib/remotedisplay/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.media.remotedisplay", srcs: ["java/**/*.java"], diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp index 3b2578754087..6504176eb6f1 100644 --- a/media/lib/signer/Android.bp +++ b/media/lib/signer/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.mediadrm.signer", srcs: ["java/**/*.java"], diff --git a/media/lib/tvremote/Android.bp b/media/lib/tvremote/Android.bp index 5f101a3141c8..5f9185aca9a2 100644 --- a/media/lib/tvremote/Android.bp +++ b/media/lib/tvremote/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.media.tv.remoteprovider", srcs: ["java/**/*.java"], diff --git a/media/lib/tvremote/tests/Android.bp b/media/lib/tvremote/tests/Android.bp index f00eed070798..f02cfc393c81 100644 --- a/media/lib/tvremote/tests/Android.bp +++ b/media/lib/tvremote/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TvRemoteTests", srcs: ["src/**/*.java"], diff --git a/media/mca/filterfw/Android.bp b/media/mca/filterfw/Android.bp index 0e0ecf331afc..ef3583f1a77f 100644 --- a/media/mca/filterfw/Android.bp +++ b/media/mca/filterfw/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libfilterfw", diff --git a/media/mca/filterfw/native/Android.bp b/media/mca/filterfw/native/Android.bp index 7a8a6a18664e..7e4a34e8d934 100644 --- a/media/mca/filterfw/native/Android.bp +++ b/media/mca/filterfw/native/Android.bp @@ -16,6 +16,15 @@ //#################### // Build module libfilterfw_static +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_static { name: "libfilterfw_native", diff --git a/media/mca/filterpacks/Android.bp b/media/mca/filterpacks/Android.bp index 34fb27dd1663..b50df6eb572c 100644 --- a/media/mca/filterpacks/Android.bp +++ b/media/mca/filterpacks/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_static { name: "libfilterpack_base", srcs: [ diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.bp b/media/mca/samples/CameraEffectsRecordingSample/Android.bp index 96e81ab9b9cc..541660c1e4a2 100644 --- a/media/mca/samples/CameraEffectsRecordingSample/Android.bp +++ b/media/mca/samples/CameraEffectsRecordingSample/Android.bp @@ -15,6 +15,15 @@ // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CameraEffectsRecordingSample", srcs: ["**/*.java"], @@ -23,4 +32,3 @@ android_test { enabled: false, }, } - diff --git a/media/mca/tests/Android.bp b/media/mca/tests/Android.bp index 6b11dd9db7ba..f02b4c0a4bfb 100644 --- a/media/mca/tests/Android.bp +++ b/media/mca/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CameraEffectsTests", libs: [ diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp index 2da45b6a78be..7acb8c744ba7 100644 --- a/media/native/midi/Android.bp +++ b/media/native/midi/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libamidi", diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp index 48fc329276bd..5ac4e7ff9d60 100644 --- a/media/packages/BluetoothMidiService/Android.bp +++ b/media/packages/BluetoothMidiService/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "BluetoothMidiLib", srcs: [ diff --git a/media/packages/BluetoothMidiService/tests/unit/Android.bp b/media/packages/BluetoothMidiService/tests/unit/Android.bp index 4d4ae9e15532..ad07993082cc 100644 --- a/media/packages/BluetoothMidiService/tests/unit/Android.bp +++ b/media/packages/BluetoothMidiService/tests/unit/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BluetoothMidiTests", srcs: ["src/**/*.java"], diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp index ed3383752695..95d1c6ccb67c 100644 --- a/media/tests/AudioPolicyTest/Android.bp +++ b/media/tests/AudioPolicyTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "audiopolicytest", srcs: ["**/*.java"], diff --git a/media/tests/CameraBrowser/Android.bp b/media/tests/CameraBrowser/Android.bp index 8e3ca1943b17..1408640a6b0d 100644 --- a/media/tests/CameraBrowser/Android.bp +++ b/media/tests/CameraBrowser/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CameraBrowser", srcs: ["**/*.java"], diff --git a/media/tests/EffectsTest/Android.bp b/media/tests/EffectsTest/Android.bp index 214e8c02f742..644e453b8956 100644 --- a/media/tests/EffectsTest/Android.bp +++ b/media/tests/EffectsTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "EffectsTest", srcs: ["**/*.java"], diff --git a/media/tests/MediaDump/Android.bp b/media/tests/MediaDump/Android.bp index 0eba8b24f6cd..f54b97a06558 100644 --- a/media/tests/MediaDump/Android.bp +++ b/media/tests/MediaDump/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "MediaDump", // Only compile source java files in this apk. diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp index ecbe2b3eb8b7..725781f5b57f 100644 --- a/media/tests/MediaFrameworkTest/Android.bp +++ b/media/tests/MediaFrameworkTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "mediaframeworktest", srcs: ["**/*.java"], diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp index 5a0a50c2ae38..b546590545e3 100644 --- a/media/tests/MediaRouter/Android.bp +++ b/media/tests/MediaRouter/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "mediaroutertest", @@ -16,4 +25,4 @@ android_test { platform_apis: true, certificate: "platform", -}
\ No newline at end of file +} diff --git a/media/tests/MtpTests/Android.bp b/media/tests/MtpTests/Android.bp index 7d2c7c693fa5..3016873e1de8 100644 --- a/media/tests/MtpTests/Android.bp +++ b/media/tests/MtpTests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "MtpTests", srcs: ["**/*.java"], diff --git a/media/tests/ScoAudioTest/Android.bp b/media/tests/ScoAudioTest/Android.bp index ad2b91716145..f8a893bf7f2c 100644 --- a/media/tests/ScoAudioTest/Android.bp +++ b/media/tests/ScoAudioTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "scoaudiotest", platform_apis: true, diff --git a/media/tests/SoundPoolTest/Android.bp b/media/tests/SoundPoolTest/Android.bp index 473f531f675b..0a50106d52c8 100644 --- a/media/tests/SoundPoolTest/Android.bp +++ b/media/tests/SoundPoolTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SoundPoolTest", srcs: ["**/*.java"], diff --git a/media/tests/TunerTest/Android.bp b/media/tests/TunerTest/Android.bp index cef879112225..2816fcc9d2f7 100644 --- a/media/tests/TunerTest/Android.bp +++ b/media/tests/TunerTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "mediatunertest", diff --git a/media/tests/audiotests/Android.bp b/media/tests/audiotests/Android.bp index 5db0ab0cde6d..c52c0336979c 100644 --- a/media/tests/audiotests/Android.bp +++ b/media/tests/audiotests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { name: "shared_mem_test", gtest: false, diff --git a/media/tests/players/Android.bp b/media/tests/players/Android.bp index 23c5f04c93a6..3b6df707badb 100644 --- a/media/tests/players/Android.bp +++ b/media/tests/players/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { name: "invoke_mock_media_player", srcs: ["invoke_mock_media_player.cpp"], diff --git a/mime/Android.bp b/mime/Android.bp index 23a8fbf5059c..a3ea65cb2efe 100644 --- a/mime/Android.bp +++ b/mime/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_defaults { name: "mimemap-defaults", srcs: [ diff --git a/native/android/Android.bp b/native/android/Android.bp index 02e1ebe05b02..d1dddbd52265 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // The headers module is in frameworks/native/Android.bp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + ndk_library { name: "libandroid", symbol_file: "libandroid.map.txt", diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index 15b473c2a6ab..3f7f445ad2c1 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libjnigraphics", diff --git a/native/webview/loader/Android.bp b/native/webview/loader/Android.bp index dfa5bdde0785..bb9b8903273e 100644 --- a/native/webview/loader/Android.bp +++ b/native/webview/loader/Android.bp @@ -17,6 +17,15 @@ // Loader library which handles address space reservation and relro sharing. // Does NOT link any native chromium code. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libwebviewchromium_loader", diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp index 1a3b36d046e1..2e94e8452fdd 100644 --- a/native/webview/plat_support/Android.bp +++ b/native/webview/plat_support/Android.bp @@ -18,6 +18,38 @@ // Native support library (libwebviewchromium_plat_support.so) - does NOT link // any native chromium code. +package { + default_applicable_licenses: [ + "frameworks_base_native_webview_plat_support_license", + ], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "frameworks_base_native_webview_plat_support_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + ], + license_text: [ + "LICENSE", + ], +} + cc_library_shared { name: "libwebviewchromium_plat_support", diff --git a/nfc-extras/Android.bp b/nfc-extras/Android.bp index cbacd48b080e..43b2830f544b 100644 --- a/nfc-extras/Android.bp +++ b/nfc-extras/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "com.android.nfc_extras", srcs: ["java/**/*.java"], diff --git a/nfc-extras/tests/Android.bp b/nfc-extras/tests/Android.bp index fc52006d14d2..4c1f2fb77e72 100644 --- a/nfc-extras/tests/Android.bp +++ b/nfc-extras/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NfcExtrasTests", diff --git a/obex/Android.bp b/obex/Android.bp index 6558eb36d001..95eac81e80be 100644 --- a/obex/Android.bp +++ b/obex/Android.bp @@ -14,6 +14,36 @@ // limitations under the License. // +package { + default_applicable_licenses: ["frameworks_base_obex_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "frameworks_base_obex_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + ], + license_text: [ + "NOTICE", + ], +} + java_sdk_library { name: "javax.obex", srcs: ["javax/**/*.java"], diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp index e0f4dedc9368..5a68fdc9ae75 100644 --- a/packages/AppPredictionLib/Android.bp +++ b/packages/AppPredictionLib/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "app_prediction", diff --git a/packages/BackupEncryption/Android.bp b/packages/BackupEncryption/Android.bp index 68e937c24a89..00f2ddb3662e 100644 --- a/packages/BackupEncryption/Android.bp +++ b/packages/BackupEncryption/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "BackupEncryption", srcs: ["src/**/*.java"], diff --git a/packages/BackupEncryption/test/robolectric-integration/Android.bp b/packages/BackupEncryption/test/robolectric-integration/Android.bp index 67365df4b28f..c842e425fd6f 100644 --- a/packages/BackupEncryption/test/robolectric-integration/Android.bp +++ b/packages/BackupEncryption/test/robolectric-integration/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_robolectric_test { name: "BackupEncryptionRoboIntegTests", srcs: [ diff --git a/packages/BackupEncryption/test/robolectric/Android.bp b/packages/BackupEncryption/test/robolectric/Android.bp index 2a36dcf0baba..7665d8f4e4c2 100644 --- a/packages/BackupEncryption/test/robolectric/Android.bp +++ b/packages/BackupEncryption/test/robolectric/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_robolectric_test { name: "BackupEncryptionRoboTests", srcs: [ diff --git a/packages/BackupEncryption/test/unittest/Android.bp b/packages/BackupEncryption/test/unittest/Android.bp index d7c510b57518..f005170884c8 100644 --- a/packages/BackupEncryption/test/unittest/Android.bp +++ b/packages/BackupEncryption/test/unittest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BackupEncryptionUnitTests", srcs: ["src/**/*.java"], @@ -19,4 +28,4 @@ android_test { test_suites: ["device-tests"], instrumentation_for: "BackupEncryption", certificate: "platform", -}
\ No newline at end of file +} diff --git a/packages/BackupRestoreConfirmation/Android.bp b/packages/BackupRestoreConfirmation/Android.bp index b0222da9405b..8152f8d134e8 100644 --- a/packages/BackupRestoreConfirmation/Android.bp +++ b/packages/BackupRestoreConfirmation/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "BackupRestoreConfirmation", srcs: ["src/**/*.java"], diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 8598f74e1441..2e1c20856519 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -13,6 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "CarSystemUI-core", diff --git a/packages/CarrierDefaultApp/Android.bp b/packages/CarrierDefaultApp/Android.bp index c1b0b2da2cb5..fc753da19394 100644 --- a/packages/CarrierDefaultApp/Android.bp +++ b/packages/CarrierDefaultApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "CarrierDefaultApp", srcs: ["src/**/*.java"], diff --git a/packages/CarrierDefaultApp/tests/unit/Android.bp b/packages/CarrierDefaultApp/tests/unit/Android.bp index 5655abb046b2..54c9016ee53a 100644 --- a/packages/CarrierDefaultApp/tests/unit/Android.bp +++ b/packages/CarrierDefaultApp/tests/unit/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CarrierDefaultAppUnitTests", certificate: "platform", diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp index 1453ec3b63cb..09505b7743a1 100644 --- a/packages/CompanionDeviceManager/Android.bp +++ b/packages/CompanionDeviceManager/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_CompanionDeviceManager_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_CompanionDeviceManager_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "CompanionDeviceManager", srcs: ["src/**/*.java"], diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp index 8db8d7699a1e..ffca97143009 100644 --- a/packages/Connectivity/framework/Android.bp +++ b/packages/Connectivity/framework/Android.bp @@ -14,16 +14,48 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + // TODO: use a java_library in the bootclasspath instead filegroup { - name: "framework-connectivity-sources", + name: "framework-connectivity-internal-sources", srcs: [ "src/**/*.java", "src/**/*.aidl", ], path: "src", visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-aidl-export-sources", + srcs: [ + "aidl-export/**/*.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +// TODO: use a java_library in the bootclasspath instead +filegroup { + name: "framework-connectivity-sources", + srcs: [ + ":framework-connectivity-internal-sources", + ":framework-connectivity-aidl-export-sources", + ], + visibility: [ "//frameworks/base", "//packages/modules/Connectivity:__subpackages__", ], -}
\ No newline at end of file +} diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.aidl b/packages/Connectivity/framework/aidl-export/android/net/CaptivePortalData.aidl index 1d57ee759136..1d57ee759136 100644 --- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/CaptivePortalData.aidl diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.aidl b/packages/Connectivity/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl index 82ba0ca113c5..82ba0ca113c5 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl diff --git a/packages/Connectivity/framework/src/android/net/DhcpInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/DhcpInfo.aidl index 29cd21fe7652..29cd21fe7652 100644 --- a/packages/Connectivity/framework/src/android/net/DhcpInfo.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/DhcpInfo.aidl diff --git a/packages/Connectivity/framework/src/android/net/IpConfiguration.aidl b/packages/Connectivity/framework/aidl-export/android/net/IpConfiguration.aidl index 7a30f0e79cad..7a30f0e79cad 100644 --- a/packages/Connectivity/framework/src/android/net/IpConfiguration.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/IpConfiguration.aidl diff --git a/packages/Connectivity/framework/src/android/net/IpPrefix.aidl b/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl index 0d70f2a1ed2c..0d70f2a1ed2c 100644 --- a/packages/Connectivity/framework/src/android/net/IpPrefix.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl diff --git a/packages/Connectivity/framework/src/android/net/KeepalivePacketData.aidl b/packages/Connectivity/framework/aidl-export/android/net/KeepalivePacketData.aidl index d456b53fd188..d456b53fd188 100644 --- a/packages/Connectivity/framework/src/android/net/KeepalivePacketData.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/KeepalivePacketData.aidl diff --git a/packages/Connectivity/framework/src/android/net/LinkAddress.aidl b/packages/Connectivity/framework/aidl-export/android/net/LinkAddress.aidl index 9c804db08d61..9c804db08d61 100644 --- a/packages/Connectivity/framework/src/android/net/LinkAddress.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/LinkAddress.aidl diff --git a/packages/Connectivity/framework/src/android/net/LinkProperties.aidl b/packages/Connectivity/framework/aidl-export/android/net/LinkProperties.aidl index a8b3c7b0392f..a8b3c7b0392f 100644 --- a/packages/Connectivity/framework/src/android/net/LinkProperties.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/LinkProperties.aidl diff --git a/packages/Connectivity/framework/src/android/net/MacAddress.aidl b/packages/Connectivity/framework/aidl-export/android/net/MacAddress.aidl index 48a18a7ac821..48a18a7ac821 100644 --- a/packages/Connectivity/framework/src/android/net/MacAddress.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/MacAddress.aidl diff --git a/packages/Connectivity/framework/src/android/net/Network.aidl b/packages/Connectivity/framework/aidl-export/android/net/Network.aidl index 05622025bf33..05622025bf33 100644 --- a/packages/Connectivity/framework/src/android/net/Network.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/Network.aidl diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkAgentConfig.aidl index cb70bdd31260..cb70bdd31260 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkAgentConfig.aidl diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkCapabilities.aidl index 01d328605de4..01d328605de4 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkCapabilities.aidl diff --git a/packages/Connectivity/framework/src/android/net/NetworkInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkInfo.aidl index f50187302966..f50187302966 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkInfo.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkInfo.aidl diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkRequest.aidl index 508defc6b497..508defc6b497 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkRequest.aidl diff --git a/packages/Connectivity/framework/src/android/net/ProxyInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/ProxyInfo.aidl index a5d0c120e747..a5d0c120e747 100644 --- a/packages/Connectivity/framework/src/android/net/ProxyInfo.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/ProxyInfo.aidl diff --git a/packages/Connectivity/framework/src/android/net/RouteInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/RouteInfo.aidl index 7af9fdaef342..7af9fdaef342 100644 --- a/packages/Connectivity/framework/src/android/net/RouteInfo.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/RouteInfo.aidl diff --git a/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.aidl b/packages/Connectivity/framework/aidl-export/android/net/StaticIpConfiguration.aidl index 8aac701fe7e1..8aac701fe7e1 100644 --- a/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/StaticIpConfiguration.aidl diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkInterface.aidl b/packages/Connectivity/framework/aidl-export/android/net/TestNetworkInterface.aidl index e1f4f9f794eb..e1f4f9f794eb 100644 --- a/packages/Connectivity/framework/src/android/net/TestNetworkInterface.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/TestNetworkInterface.aidl diff --git a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.aidl b/packages/Connectivity/framework/aidl-export/android/net/apf/ApfCapabilities.aidl index 7c4d4c2da4bc..7c4d4c2da4bc 100644 --- a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/apf/ApfCapabilities.aidl diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java index 9b56b23cc879..eafda4d2d694 100644 --- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java +++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java @@ -16,12 +16,15 @@ package android.net; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -40,10 +43,29 @@ public final class CaptivePortalData implements Parcelable { private final long mExpiryTimeMillis; private final boolean mCaptive; private final String mVenueFriendlyName; + private final int mVenueInfoUrlSource; + private final int mUserPortalUrlSource; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CAPTIVE_PORTAL_DATA_SOURCE_"}, value = { + CAPTIVE_PORTAL_DATA_SOURCE_OTHER, + CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT}) + public @interface CaptivePortalDataSource {} + + /** + * Source of information: Other (default) + */ + public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; + + /** + * Source of information: Wi-Fi Passpoint + */ + public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName) { + String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -52,11 +74,14 @@ public final class CaptivePortalData implements Parcelable { mExpiryTimeMillis = expiryTimeMillis; mCaptive = captive; mVenueFriendlyName = venueFriendlyName; + mVenueInfoUrlSource = venueInfoUrlSource; + mUserPortalUrlSource = userPortalUrlSource; } private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readString()); + p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), + p.readInt()); } @Override @@ -74,6 +99,8 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); dest.writeString(mVenueFriendlyName); + dest.writeInt(mVenueInfoUrlSource); + dest.writeInt(mUserPortalUrlSource); } /** @@ -88,6 +115,9 @@ public final class CaptivePortalData implements Parcelable { private long mExpiryTime = -1; private boolean mCaptive; private String mVenueFriendlyName; + private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; + private @CaptivePortalDataSource int mUserPortalUrlSource = + CAPTIVE_PORTAL_DATA_SOURCE_OTHER; /** * Create an empty builder. @@ -100,8 +130,8 @@ public final class CaptivePortalData implements Parcelable { public Builder(@Nullable CaptivePortalData data) { if (data == null) return; setRefreshTime(data.mRefreshTimeMillis) - .setUserPortalUrl(data.mUserPortalUrl) - .setVenueInfoUrl(data.mVenueInfoUrl) + .setUserPortalUrl(data.mUserPortalUrl, data.mUserPortalUrlSource) + .setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource) .setSessionExtendable(data.mIsSessionExtendable) .setBytesRemaining(data.mByteLimit) .setExpiryTime(data.mExpiryTimeMillis) @@ -123,7 +153,18 @@ public final class CaptivePortalData implements Parcelable { */ @NonNull public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) { + return setUserPortalUrl(userPortalUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); + } + + /** + * Set the URL to be used for users to login to the portal, if captive, and the source of + * the data, see {@link CaptivePortalDataSource} + */ + @NonNull + public Builder setUserPortalUrl(@Nullable Uri userPortalUrl, + @CaptivePortalDataSource int source) { mUserPortalUrl = userPortalUrl; + mUserPortalUrlSource = source; return this; } @@ -132,7 +173,18 @@ public final class CaptivePortalData implements Parcelable { */ @NonNull public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) { + return setVenueInfoUrl(venueInfoUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); + } + + /** + * Set the URL that can be used by users to view information about the network venue, and + * the source of the data, see {@link CaptivePortalDataSource} + */ + @NonNull + public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl, + @CaptivePortalDataSource int source) { mVenueInfoUrl = venueInfoUrl; + mVenueInfoUrlSource = source; return this; } @@ -188,7 +240,8 @@ public final class CaptivePortalData implements Parcelable { public CaptivePortalData build() { return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, - mVenueFriendlyName); + mVenueFriendlyName, mVenueInfoUrlSource, + mUserPortalUrlSource); } } @@ -249,6 +302,22 @@ public final class CaptivePortalData implements Parcelable { } /** + * Get the information source of the Venue URL + * @return The source that the Venue URL was obtained from + */ + public @CaptivePortalDataSource int getVenueInfoUrlSource() { + return mVenueInfoUrlSource; + } + + /** + * Get the information source of the user portal URL + * @return The source that the user portal URL was obtained from + */ + public @CaptivePortalDataSource int getUserPortalUrlSource() { + return mUserPortalUrlSource; + } + + /** * Get the venue friendly name */ @Nullable @@ -272,7 +341,8 @@ public final class CaptivePortalData implements Parcelable { @Override public int hashCode() { return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, - mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName); + mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName, + mVenueInfoUrlSource, mUserPortalUrlSource); } @Override @@ -286,7 +356,9 @@ public final class CaptivePortalData implements Parcelable { && mByteLimit == other.mByteLimit && mExpiryTimeMillis == other.mExpiryTimeMillis && mCaptive == other.mCaptive - && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName); + && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName) + && mVenueInfoUrlSource == other.mVenueInfoUrlSource + && mUserPortalUrlSource == other.mUserPortalUrlSource; } @Override @@ -300,6 +372,8 @@ public final class CaptivePortalData implements Parcelable { + ", expiryTime: " + mExpiryTimeMillis + ", captive: " + mCaptive + ", venueFriendlyName: " + mVenueFriendlyName + + ", venueInfoUrlSource: " + mVenueInfoUrlSource + + ", userPortalUrlSource: " + mUserPortalUrlSource + "}"; } } diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java index 9afa5d1311c5..92a792b78410 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java @@ -49,17 +49,6 @@ public final class ConnectivityFrameworkInitializer { } ); - // TODO: move outside of the connectivity JAR - SystemServiceRegistry.registerContextAwareService( - Context.VPN_MANAGEMENT_SERVICE, - VpnManager.class, - (context) -> { - final ConnectivityManager cm = context.getSystemService( - ConnectivityManager.class); - return cm.createVpnManager(); - } - ); - SystemServiceRegistry.registerContextAwareService( Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, ConnectivityDiagnosticsManager.class, diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index d04a5bee5105..6273f4bb577b 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; +import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; import android.annotation.CallbackExecutor; @@ -48,8 +49,6 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.INetworkActivityListener; -import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Messenger; @@ -455,7 +454,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI; + public static final int TETHERING_WIFI = 0; /** * USB tethering type. @@ -463,7 +462,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_USB = TetheringManager.TETHERING_USB; + public static final int TETHERING_USB = 1; /** * Bluetooth tethering type. @@ -471,7 +470,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH; + public static final int TETHERING_BLUETOOTH = 2; /** * Wifi P2p tethering type. @@ -823,6 +822,7 @@ public class ConnectivityManager { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private final IConnectivityManager mService; + /** * A kludge to facilitate static access where a Context pointer isn't available, like in the * case of the static set/getProcessDefaultNetwork methods and from the Network class. @@ -833,7 +833,6 @@ public class ConnectivityManager { private final Context mContext; - private INetworkManagementService mNMService; private INetworkPolicyManager mNPManager; private final TetheringManager mTetheringManager; @@ -1068,109 +1067,6 @@ public class ConnectivityManager { } /** - * Checks if a VPN app supports always-on mode. - * - * In order to support the always-on feature, an app has to - * <ul> - * <li>target {@link VERSION_CODES#N API 24} or above, and - * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} - * meta-data field. - * </ul> - * - * @param userId The identifier of the user for whom the VPN app is installed. - * @param vpnPackage The canonical package name of the VPN app. - * @return {@code true} if and only if the VPN app exists and supports always-on mode. - * @hide - */ - public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { - try { - return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Configures an always-on VPN connection through a specific application. - * This connection is automatically granted and persisted after a reboot. - * - * <p>The designated package should declare a {@link VpnService} in its - * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, - * otherwise the call will fail. - * - * @param userId The identifier of the user to set an always-on VPN for. - * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} - * to remove an existing always-on VPN configuration. - * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or - * {@code false} otherwise. - * @param lockdownAllowlist The list of packages that are allowed to access network directly - * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so - * this method must be called when a package that should be allowed is installed or - * uninstalled. - * @return {@code true} if the package is set as always-on VPN controller; - * {@code false} otherwise. - * @hide - */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) { - try { - return mService.setAlwaysOnVpnPackage( - userId, vpnPackage, lockdownEnabled, lockdownAllowlist); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the package name of the currently set always-on VPN application. - * If there is no always-on VPN set, or the VPN is provided by the system instead - * of by an app, {@code null} will be returned. - * - * @return Package name of VPN controller responsible for always-on VPN, - * or {@code null} if none is set. - * @hide - */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public String getAlwaysOnVpnPackageForUser(int userId) { - try { - return mService.getAlwaysOnVpnPackage(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @return whether always-on VPN is in lockdown mode. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public boolean isVpnLockdownEnabled(int userId) { - try { - return mService.isVpnLockdownEnabled(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - } - - /** - * @return the list of packages that are allowed to access network when always-on VPN is in - * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public List<String> getVpnLockdownWhitelist(int userId) { - try { - return mService.getVpnLockdownWhitelist(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Adds or removes a requirement for given UID ranges to use the VPN. * * If set to {@code true}, informs the system that the UIDs in the specified ranges must not @@ -1220,6 +1116,45 @@ public class ConnectivityManager { } /** + * Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by + * LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12 + * but is still supported for backwards compatibility. + * <p> + * This type of VPN is assumed always to use the system default network, and must always declare + * exactly one underlying network, which is the network that was the default when the VPN + * connected. + * <p> + * Calling this method with {@code true} enables legacy behaviour, specifically: + * <ul> + * <li>Any VPN that applies to userId 0 behaves specially with respect to deprecated + * {@link #CONNECTIVITY_ACTION} broadcasts. Any such broadcasts will have the state in the + * {@link #EXTRA_NETWORK_INFO} replaced by state of the VPN network. Also, any time the VPN + * connects, a {@link #CONNECTIVITY_ACTION} broadcast will be sent for the network + * underlying the VPN.</li> + * <li>Deprecated APIs that return {@link NetworkInfo} objects will have their state + * similarly replaced by the VPN network state.</li> + * <li>Information on current network interfaces passed to NetworkStatsService will not + * include any VPN interfaces.</li> + * </ul> + * + * @param enabled whether legacy lockdown VPN is enabled or disabled + * + * TODO: @SystemApi(client = MODULE_LIBRARIES) + * + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + public void setLegacyLockdownVpnEnabled(boolean enabled) { + try { + mService.setLegacyLockdownVpnEnabled(enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Returns details about the currently active default data network * for a given uid. This is for internal use only to avoid spying * other apps. @@ -2221,17 +2156,6 @@ public class ConnectivityManager { void onNetworkActive(); } - private INetworkManagementService getNetworkManagementService() { - synchronized (this) { - if (mNMService != null) { - return mNMService; - } - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); - return mNMService; - } - } - private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener> mNetworkActivityListeners = new ArrayMap<>(); @@ -2256,7 +2180,7 @@ public class ConnectivityManager { }; try { - getNetworkManagementService().registerNetworkActivityListener(rl); + mService.registerNetworkActivityListener(rl); mNetworkActivityListeners.put(l, rl); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2273,7 +2197,7 @@ public class ConnectivityManager { INetworkActivityListener rl = mNetworkActivityListeners.get(l); Preconditions.checkArgument(rl != null, "Listener was not registered."); try { - getNetworkManagementService().unregisterNetworkActivityListener(rl); + mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2289,7 +2213,7 @@ public class ConnectivityManager { */ public boolean isDefaultNetworkActive() { try { - return getNetworkManagementService().isNetworkActive(); + return mService.isDefaultNetworkActive(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2809,7 +2733,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR; + public static final int TETHER_ERROR_NO_ERROR = 0; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}. * {@hide} @@ -2885,8 +2809,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_PROVISION_FAILED = - TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; + public static final int TETHER_ERROR_PROVISION_FAILED = 11; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. * {@hide} @@ -2900,8 +2823,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = - TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; + public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; /** * Get a more detailed error code after a Tethering or Untethering @@ -3179,23 +3101,6 @@ public class ConnectivityManager { } /** - * If the LockdownVpn mechanism is enabled, updates the vpn - * with a reload of its profile. - * - * @return a boolean with {@code} indicating success - * - * <p>This method can only be called by the system UID - * {@hide} - */ - public boolean updateLockdownVpn() { - try { - return mService.updateLockdownVpn(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Set sign in error notification to visible or invisible * * @hide @@ -3721,7 +3626,8 @@ public class ConnectivityManager { printStackTrace(); checkCallbackNotNull(callback); Preconditions.checkArgument( - reqType == TRACK_DEFAULT || need != null, "null NetworkCapabilities"); + reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, + "null NetworkCapabilities"); final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -4192,8 +4098,9 @@ public class ConnectivityManager { } /** - * Registers to receive notifications about changes in the system default network. The callbacks - * will continue to be called until either the application exits or + * Registers to receive notifications about changes in the application's default network. This + * may be a physical network or a virtual network, such as a VPN that applies to the + * application. The callbacks will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the @@ -4206,7 +4113,7 @@ public class ConnectivityManager { * {@link #unregisterNetworkCallback(NetworkCallback)}. * * @param networkCallback The {@link NetworkCallback} that the system will call as the - * system default network changes. + * application's default network changes. * The callback is invoked on the default internal Handler. * @throws RuntimeException if the app already has too many callbacks registered. */ @@ -4216,8 +4123,9 @@ public class ConnectivityManager { } /** - * Registers to receive notifications about changes in the system default network. The callbacks - * will continue to be called until either the application exits or + * Registers to receive notifications about changes in the application's default network. This + * may be a physical network or a virtual network, such as a VPN that applies to the + * application. The callbacks will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the @@ -4230,26 +4138,60 @@ public class ConnectivityManager { * {@link #unregisterNetworkCallback(NetworkCallback)}. * * @param networkCallback The {@link NetworkCallback} that the system will call as the - * system default network changes. + * application's default network changes. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. * @throws RuntimeException if the app already has too many callbacks registered. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - // This works because if the NetworkCapabilities are null, - // ConnectivityService takes them from the default request. - // - // Since the capabilities are exactly the same as the default request's - // capabilities, this request is guaranteed, at all times, to be - // satisfied by the same network, if any, that satisfies the default - // request, i.e., the system default network. CallbackHandler cbHandler = new CallbackHandler(handler); sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, TRACK_DEFAULT, TYPE_NONE, cbHandler); } /** + * Registers to receive notifications about changes in the system default network. The callbacks + * will continue to be called until either the application exits or + * {@link #unregisterNetworkCallback(NetworkCallback)} is called. + * + * This method should not be used to determine networking state seen by applications, because in + * many cases, most or even all application traffic may not use the default network directly, + * and traffic from different applications may go on different networks by default. As an + * example, if a VPN is connected, traffic from all applications might be sent through the VPN + * and not onto the system default network. Applications or system components desiring to do + * determine network state as seen by applications should use other methods such as + * {@link #registerDefaultNetworkCallback(NetworkCallback, Handler)}. + * + * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param networkCallback The {@link NetworkCallback} that the system will call as the + * system default network changes. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, + @NonNull Handler handler) { + CallbackHandler cbHandler = new CallbackHandler(handler); + sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, + TRACK_SYSTEM_DEFAULT, TYPE_NONE, cbHandler); + } + + /** * Requests bandwidth update for a given {@link Network} and returns whether the update request * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying * network connection for updated bandwidth information. The caller will be notified via @@ -4586,7 +4528,7 @@ public class ConnectivityManager { // Set HTTP proxy system properties to match network. // TODO: Deprecate this static method and replace it with a non-static version. try { - Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy()); + Proxy.setHttpProxyConfiguration(getInstance().getDefaultProxy()); } catch (SecurityException e) { // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy. Log.e(TAG, "Can't set proxy properties", e); @@ -4813,11 +4755,6 @@ public class ConnectivityManager { } /** @hide */ - public VpnManager createVpnManager() { - return new VpnManager(mContext, mService); - } - - /** @hide */ public ConnectivityDiagnosticsManager createDiagnosticsManager() { return new ConnectivityDiagnosticsManager(mContext, mService); } @@ -4848,15 +4785,6 @@ public class ConnectivityManager { } } - private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference) { - try { - mService.setOemNetworkPreference(preference); - } catch (RemoteException e) { - Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); - throw e.rethrowFromSystemServer(); - } - } - @NonNull private final List<QosCallbackConnection> mQosCallbackConnections = new ArrayList<>(); @@ -5058,4 +4986,60 @@ public class ConnectivityManager { sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler)); } + + /** + * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, + * OnSetOemNetworkPreferenceListener)}. + * @hide + */ + @SystemApi + public interface OnSetOemNetworkPreferenceListener { + /** + * Called when setOemNetworkPreference() successfully completes. + */ + void onComplete(); + } + + /** + * Used by automotive devices to set the network preferences used to direct traffic at an + * application level as per the given OemNetworkPreferences. An example use-case would be an + * automotive OEM wanting to provide connectivity for applications critical to the usage of a + * vehicle via a particular network. + * + * Calling this will overwrite the existing preference. + * + * @param preference {@link OemNetworkPreferences} The application network preference to be set. + * @param executor the executor on which listener will be invoked. + * @param listener {@link OnSetOemNetworkPreferenceListener} optional listener used to + * communicate completion of setOemNetworkPreference(). This will only be + * called once upon successful completion of setOemNetworkPreference(). + * @throws IllegalArgumentException if {@code preference} contains invalid preference values. + * @throws SecurityException if missing the appropriate permissions. + * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) + public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, + @Nullable @CallbackExecutor final Executor executor, + @Nullable final OnSetOemNetworkPreferenceListener listener) { + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); + if (null != listener) { + Objects.requireNonNull(executor, "Executor must be non-null"); + } + final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null : + new IOnSetOemNetworkPreferenceListener.Stub() { + @Override + public void onComplete() { + executor.execute(listener::onComplete); + } + }; + + try { + mService.setOemNetworkPreference(preference, listenerInternal); + } catch (RemoteException e) { + Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index f909d1362550..160338d396af 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -20,6 +20,8 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; +import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.INetworkActivityListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.LinkProperties; @@ -35,16 +37,12 @@ import android.net.UidRange; import android.net.QosSocketInfo; import android.os.Bundle; import android.os.IBinder; -import android.os.INetworkActivityListener; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.ResultReceiver; import com.android.connectivity.aidl.INetworkAgent; -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; /** * Interface that answers queries about, and allows changing, the @@ -122,35 +120,8 @@ interface IConnectivityManager ProxyInfo getProxyForNetwork(in Network nework); - boolean prepareVpn(String oldPackage, String newPackage, int userId); - - void setVpnPackageAuthorization(String packageName, int userId, int vpnType); - - ParcelFileDescriptor establishVpn(in VpnConfig config); - - boolean provisionVpnProfile(in VpnProfile profile, String packageName); - - void deleteVpnProfile(String packageName); - - void startVpnProfile(String packageName); - - void stopVpnProfile(String packageName); - - VpnConfig getVpnConfig(int userId); - - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - void startLegacyVpn(in VpnProfile profile); - - LegacyVpnInfo getLegacyVpnInfo(int userId); - - boolean updateLockdownVpn(); - boolean isAlwaysOnVpnPackageSupported(int userId, String packageName); - boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown, - in List<String> lockdownWhitelist); - String getAlwaysOnVpnPackage(int userId); - boolean isVpnLockdownEnabled(int userId); - List<String> getVpnLockdownWhitelist(int userId); void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges); + void setLegacyLockdownVpnEnabled(boolean enabled); void setProvisioningNotificationVisible(boolean visible, int networkType, in String action); @@ -199,10 +170,6 @@ interface IConnectivityManager int getRestoreDefaultNetworkDelay(int networkType); - boolean addVpnAddress(String address, int prefixLength); - boolean removeVpnAddress(String address, int prefixLength); - boolean setUnderlyingNetworksForVpn(in Network[] networks); - void factoryReset(); void startNattKeepalive(in Network network, int intervalSeconds, @@ -222,8 +189,6 @@ interface IConnectivityManager byte[] getNetworkWatchlistConfigHash(); int getConnectionOwnerUid(in ConnectionInfo connectionInfo); - boolean isCallerCurrentAlwaysOnVpnApp(); - boolean isCallerCurrentAlwaysOnVpnLockdownApp(); void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, in NetworkRequest request, String callingPackageName); @@ -245,5 +210,6 @@ interface IConnectivityManager void registerQosSocketCallback(in QosSocketInfo socketInfo, in IQosCallback callback); void unregisterQosCallback(in IQosCallback callback); - void setOemNetworkPreference(in OemNetworkPreferences preference); + void setOemNetworkPreference(in OemNetworkPreferences preference, + in IOnSetOemNetworkPreferenceListener listener); } diff --git a/core/java/android/os/INetworkActivityListener.aidl b/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl index 24e6e55f1e57..79687dd3bf06 100644 --- a/core/java/android/os/INetworkActivityListener.aidl +++ b/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl @@ -13,7 +13,7 @@ ** limitations under the License. */ -package android.os; +package android.net; /** * @hide diff --git a/packages/Connectivity/framework/src/android/net/IpPrefix.java b/packages/Connectivity/framework/src/android/net/IpPrefix.java index bcb65fab8571..d2ee7d13b05f 100644 --- a/packages/Connectivity/framework/src/android/net/IpPrefix.java +++ b/packages/Connectivity/framework/src/android/net/IpPrefix.java @@ -24,6 +24,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Pair; +import com.android.net.module.util.NetUtils; + import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -59,7 +61,7 @@ public final class IpPrefix implements Parcelable { throw new IllegalArgumentException( "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); } - NetworkUtils.maskRawAddress(address, prefixLength); + NetUtils.maskRawAddress(address, prefixLength); } /** @@ -190,7 +192,7 @@ public final class IpPrefix implements Parcelable { if (addrBytes == null || addrBytes.length != this.address.length) { return false; } - NetworkUtils.maskRawAddress(addrBytes, prefixLength); + NetUtils.maskRawAddress(addrBytes, prefixLength); return Arrays.equals(this.address, addrBytes); } @@ -204,7 +206,7 @@ public final class IpPrefix implements Parcelable { public boolean containsPrefix(@NonNull IpPrefix otherPrefix) { if (otherPrefix.getPrefixLength() < prefixLength) return false; final byte[] otherAddress = otherPrefix.getRawAddress(); - NetworkUtils.maskRawAddress(otherAddress, prefixLength); + NetUtils.maskRawAddress(otherAddress, prefixLength); return Arrays.equals(otherAddress, address); } diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 55b2c3c9e11f..26d14cbfaa95 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -762,12 +762,14 @@ public final class NetworkCapabilities implements Parcelable { final int originalSignalStrength = mSignalStrength; final int originalOwnerUid = getOwnerUid(); final int[] originalAdministratorUids = getAdministratorUids(); + final TransportInfo originalTransportInfo = getTransportInfo(); clearAll(); mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) | (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; + mTransportInfo = originalTransportInfo; // Only retain the owner and administrator UIDs if they match the app registering the remote // caller that registered the network. @@ -2083,9 +2085,10 @@ public final class NetworkCapabilities implements Parcelable { /** * Check if private dns is broken. * - * @return {@code true} if {@code mPrivateDnsBroken} is set when private DNS is broken. + * @return {@code true} if private DNS is broken on this network. * @hide */ + @SystemApi public boolean isPrivateDnsBroken() { return mPrivateDnsBroken; } @@ -2328,6 +2331,17 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Completely clears the contents of this object, removing even the capabilities that are + * set by default when the object is constructed. + * @return this builder + */ + @NonNull + public Builder clearAll() { + mCaps.clearAll(); + return this; + } + + /** * Sets the owner UID. * * The default value is {@link Process#INVALID_UID}. Pass this value to reset. diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index 6540397d6200..4e3085f4704d 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -16,22 +16,6 @@ package android.net; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -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_RESTRICTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -46,8 +30,6 @@ import android.os.Process; import android.text.TextUtils; import android.util.proto.ProtoOutputStream; -import java.util.Arrays; -import java.util.List; import java.util.Objects; import java.util.Set; @@ -104,17 +86,14 @@ public class NetworkRequest implements Parcelable { * callbacks about the single, highest scoring current network * (if any) that matches the specified NetworkCapabilities, or * - * - TRACK_DEFAULT, a hybrid of the two designed such that the - * framework will issue callbacks for the single, highest scoring - * current network (if any) that matches the capabilities of the - * default Internet request (mDefaultRequest), but which cannot cause - * the framework to either create or retain the existence of any - * specific network. Note that from the point of view of the request - * matching code, TRACK_DEFAULT is identical to REQUEST: its special - * behaviour is not due to different semantics, but to the fact that - * the system will only ever create a TRACK_DEFAULT with capabilities - * that are identical to the default request's capabilities, thus - * causing it to share fate in every way with the default request. + * - TRACK_DEFAULT, which causes the framework to issue callbacks for + * the single, highest scoring current network (if any) that will + * be chosen for an app, but which cannot cause the framework to + * either create or retain the existence of any specific network. + * + * - TRACK_SYSTEM_DEFAULT, which causes the framework to send callbacks + * for the network (if any) that satisfies the default Internet + * request. * * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks * to retain the NET_CAPABILITY_FOREGROUND capability. A network with @@ -137,6 +116,7 @@ public class NetworkRequest implements Parcelable { TRACK_DEFAULT, REQUEST, BACKGROUND_REQUEST, + TRACK_SYSTEM_DEFAULT, }; /** @@ -174,30 +154,8 @@ public class NetworkRequest implements Parcelable { * needed in terms of {@link NetworkCapabilities} features */ public static class Builder { - /** - * Capabilities that are currently compatible with VCN networks. - */ - private static final List<Integer> VCN_SUPPORTED_CAPABILITIES = Arrays.asList( - NET_CAPABILITY_CAPTIVE_PORTAL, - NET_CAPABILITY_DUN, - NET_CAPABILITY_FOREGROUND, - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_NOT_CONGESTED, - NET_CAPABILITY_NOT_METERED, - NET_CAPABILITY_NOT_RESTRICTED, - NET_CAPABILITY_NOT_ROAMING, - NET_CAPABILITY_NOT_SUSPENDED, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_PARTIAL_CONNECTIVITY, - NET_CAPABILITY_TEMPORARILY_NOT_METERED, - NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_VALIDATED); - private final NetworkCapabilities mNetworkCapabilities; - // A boolean that represents the user modified NOT_VCN_MANAGED capability. - private boolean mModifiedNotVcnManaged = false; - /** * Default constructor for Builder. */ @@ -219,7 +177,6 @@ public class NetworkRequest implements Parcelable { // maybeMarkCapabilitiesRestricted() doesn't add back. final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); nc.maybeMarkCapabilitiesRestricted(); - deduceNotVcnManagedCapability(nc); return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); } @@ -236,9 +193,6 @@ public class NetworkRequest implements Parcelable { */ public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; - } return this; } @@ -250,9 +204,6 @@ public class NetworkRequest implements Parcelable { */ public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; - } return this; } @@ -310,9 +261,6 @@ public class NetworkRequest implements Parcelable { @NonNull public Builder clearCapabilities() { mNetworkCapabilities.clearAll(); - // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities - // should not be add back later. - mModifiedNotVcnManaged = true; return this; } @@ -432,25 +380,6 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setSignalStrength(signalStrength); return this; } - - /** - * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities - * and user intention, which includes: - * 1. For the requests that don't have anything besides - * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to - * allow the callers automatically utilize VCN networks if available. - * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, - * do not alter them to allow user fire request that suits their need. - * - * @hide - */ - private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { - if (mModifiedNotVcnManaged) return; - for (final int cap : nc.getCapabilities()) { - if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; - } - nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - } } // implement the Parcelable interface @@ -601,6 +530,8 @@ public class NetworkRequest implements Parcelable { return NetworkRequestProto.TYPE_REQUEST; case BACKGROUND_REQUEST: return NetworkRequestProto.TYPE_BACKGROUND_REQUEST; + case TRACK_SYSTEM_DEFAULT: + return NetworkRequestProto.TYPE_TRACK_SYSTEM_DEFAULT; default: return NetworkRequestProto.TYPE_UNKNOWN; } diff --git a/packages/Connectivity/framework/src/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java index 8be4af7b1396..9ccb04a44af4 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java +++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java @@ -29,7 +29,6 @@ import java.math.BigInteger; import java.net.Inet4Address; import java.net.InetAddress; import java.net.SocketException; -import java.net.UnknownHostException; import java.util.Locale; import java.util.TreeSet; @@ -232,46 +231,6 @@ public class NetworkUtils { } /** - * Masks a raw IP address byte array with the specified prefix length. - */ - public static void maskRawAddress(byte[] array, int prefixLength) { - if (prefixLength < 0 || prefixLength > array.length * 8) { - throw new RuntimeException("IP address with " + array.length + - " bytes has invalid prefix length " + prefixLength); - } - - int offset = prefixLength / 8; - int remainder = prefixLength % 8; - byte mask = (byte)(0xFF << (8 - remainder)); - - if (offset < array.length) array[offset] = (byte)(array[offset] & mask); - - offset++; - - for (; offset < array.length; offset++) { - array[offset] = 0; - } - } - - /** - * Get InetAddress masked with prefixLength. Will never return null. - * @param address the IP address to mask with - * @param prefixLength the prefixLength used to mask the IP - */ - public static InetAddress getNetworkPart(InetAddress address, int prefixLength) { - byte[] array = address.getAddress(); - maskRawAddress(array, prefixLength); - - InetAddress netPart = null; - try { - netPart = InetAddress.getByAddress(array); - } catch (UnknownHostException e) { - throw new RuntimeException("getNetworkPart error - " + e.toString()); - } - return netPart; - } - - /** * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) diff --git a/packages/Connectivity/framework/src/android/net/Proxy.java b/packages/Connectivity/framework/src/android/net/Proxy.java index 9cd7ab2c3e40..77c8a4f4579b 100644 --- a/packages/Connectivity/framework/src/android/net/Proxy.java +++ b/packages/Connectivity/framework/src/android/net/Proxy.java @@ -16,8 +16,10 @@ package android.net; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; @@ -185,7 +187,19 @@ public final class Proxy { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final void setHttpProxySystemProperty(ProxyInfo p) { + @Deprecated + public static void setHttpProxySystemProperty(ProxyInfo p) { + setHttpProxyConfiguration(p); + } + + /** + * Set HTTP proxy configuration for the process to match the provided ProxyInfo. + * + * If the provided ProxyInfo is null, the proxy configuration will be cleared. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static void setHttpProxyConfiguration(@Nullable ProxyInfo p) { String host = null; String port = null; String exclList = null; @@ -196,11 +210,11 @@ public final class Proxy { exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); pacFileUrl = p.getPacFileUrl(); } - setHttpProxySystemProperty(host, port, exclList, pacFileUrl); + setHttpProxyConfiguration(host, port, exclList, pacFileUrl); } /** @hide */ - public static final void setHttpProxySystemProperty(String host, String port, String exclList, + public static void setHttpProxyConfiguration(String host, String port, String exclList, Uri pacFileUrl) { if (exclList != null) exclList = exclList.replace(",", "|"); if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java index 4e894143bf91..a174a7be85d1 100644 --- a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java +++ b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java @@ -41,7 +41,6 @@ public class TestNetworkManager { /** * Prefix for tap interfaces created by this class. - * @hide */ public static final String TEST_TAP_PREFIX = "testtap"; diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java new file mode 100644 index 000000000000..0242ba08742c --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.SparseArray; + +import com.android.internal.util.MessageUtils; + +import java.util.Objects; + +/** + * Container for VPN-specific transport information. + * + * @see android.net.TransportInfo + * @see NetworkCapabilities#getTransportInfo() + * + * @hide + */ +@SystemApi(client = MODULE_LIBRARIES) +public final class VpnTransportInfo implements TransportInfo, Parcelable { + private static final SparseArray<String> sTypeToString = + MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); + + /** Type of this VPN. */ + @VpnManager.VpnType public final int type; + + public VpnTransportInfo(@VpnManager.VpnType int type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VpnTransportInfo)) return false; + + VpnTransportInfo that = (VpnTransportInfo) o; + return this.type == that.type; + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + + @Override + public String toString() { + final String typeString = sTypeToString.get(type, "VPN_TYPE_???"); + return String.format("VpnTransportInfo{%s}", typeString); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(type); + } + + public static final @NonNull Creator<VpnTransportInfo> CREATOR = + new Creator<VpnTransportInfo>() { + public VpnTransportInfo createFromParcel(Parcel in) { + return new VpnTransportInfo(in.readInt()); + } + public VpnTransportInfo[] newArray(int size) { + return new VpnTransportInfo[size]; + } + }; +} diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp index 8fc318180778..f20b89fb842c 100644 --- a/packages/Connectivity/service/Android.bp +++ b/packages/Connectivity/service/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libservice-connectivity", // TODO: build against the NDK (sdk_version: "30" for example) @@ -25,7 +34,6 @@ cc_library_shared { ], srcs: [ "jni/com_android_server_TestNetworkService.cpp", - "jni/com_android_server_connectivity_Vpn.cpp", "jni/onload.cpp", ], shared_libs: [ diff --git a/packages/Connectivity/service/jni/onload.cpp b/packages/Connectivity/service/jni/onload.cpp index 3afcb0e8f688..00128794bcd0 100644 --- a/packages/Connectivity/service/jni/onload.cpp +++ b/packages/Connectivity/service/jni/onload.cpp @@ -19,7 +19,6 @@ namespace android { -int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_TestNetworkService(JNIEnv* env); extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { @@ -29,12 +28,11 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } - if (register_android_server_connectivity_Vpn(env) < 0 - || register_android_server_TestNetworkService(env) < 0) { + if (register_android_server_TestNetworkService(env) < 0) { return JNI_ERR; } return JNI_VERSION_1_6; } -};
\ No newline at end of file +}; diff --git a/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp index 49608b3856e0..31cd76079131 100644 --- a/packages/CtsShim/Android.bp +++ b/packages/CtsShim/Android.bp @@ -17,6 +17,15 @@ //########################################################## // Variant: Privileged app +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app_import { name: "CtsShimPrivPrebuilt", diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp index 14a3376380df..0b3f9bb62a9b 100644 --- a/packages/CtsShim/build/Android.bp +++ b/packages/CtsShim/build/Android.bp @@ -17,6 +17,15 @@ //########################################################## // Variant: Privileged app upgrade +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "CtsShimPrivUpgrade", // this needs to be a privileged application diff --git a/packages/CtsShim/build/jni/Android.bp b/packages/CtsShim/build/jni/Android.bp index 4a1973cc0b46..ba586dbb2d88 100644 --- a/packages/CtsShim/build/jni/Android.bp +++ b/packages/CtsShim/build/jni/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libshim_jni", srcs: ["Shim.c"], diff --git a/packages/DynamicSystemInstallationService/Android.bp b/packages/DynamicSystemInstallationService/Android.bp index f1a18ae2a53f..04333204b0cb 100644 --- a/packages/DynamicSystemInstallationService/Android.bp +++ b/packages/DynamicSystemInstallationService/Android.bp @@ -1,3 +1,22 @@ +package { + default_applicable_licenses: [ + "frameworks_base_packages_DynamicSystemInstallationService_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_DynamicSystemInstallationService_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "DynamicSystemInstallationService", diff --git a/packages/DynamicSystemInstallationService/tests/Android.bp b/packages/DynamicSystemInstallationService/tests/Android.bp index 3bdf82966889..50b65b4067fd 100644 --- a/packages/DynamicSystemInstallationService/tests/Android.bp +++ b/packages/DynamicSystemInstallationService/tests/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_DynamicSystemInstallationService_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_base_packages_DynamicSystemInstallationService_license", + ], +} + android_test { name: "DynamicSystemInstallationServiceTests", diff --git a/packages/EasterEgg/Android.bp b/packages/EasterEgg/Android.bp index b858ab01ffd9..f8785f2b8e2c 100644 --- a/packages/EasterEgg/Android.bp +++ b/packages/EasterEgg/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { // the build system in pi-dev can't quite handle R.java in kt // so we will have a mix of java and kotlin files diff --git a/packages/EncryptedLocalTransport/Android.bp b/packages/EncryptedLocalTransport/Android.bp index dd30ad177d69..f851bc49d8af 100644 --- a/packages/EncryptedLocalTransport/Android.bp +++ b/packages/EncryptedLocalTransport/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "EncryptedLocalTransport", srcs: ["src/**/*.java"], diff --git a/packages/ExtShared/Android.bp b/packages/ExtShared/Android.bp index a9823b923256..8e51215706db 100644 --- a/packages/ExtShared/Android.bp +++ b/packages/ExtShared/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_base_packages_ExtShared_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_ExtShared_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "ExtShared", srcs: ["src/**/*.java"], diff --git a/packages/ExternalStorageProvider/Android.bp b/packages/ExternalStorageProvider/Android.bp index 973fef3e666d..8718cc56704d 100644 --- a/packages/ExternalStorageProvider/Android.bp +++ b/packages/ExternalStorageProvider/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "ExternalStorageProvider", diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp index 04cf01af073a..633f18610921 100644 --- a/packages/ExternalStorageProvider/tests/Android.bp +++ b/packages/ExternalStorageProvider/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ExternalStorageProviderTests", diff --git a/packages/FakeOemFeatures/Android.bp b/packages/FakeOemFeatures/Android.bp index b265158220da..276132fb19c0 100644 --- a/packages/FakeOemFeatures/Android.bp +++ b/packages/FakeOemFeatures/Android.bp @@ -1,3 +1,22 @@ +package { + default_applicable_licenses: [ + "frameworks_base_packages_FakeOemFeatures_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_FakeOemFeatures_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "FakeOemFeatures", srcs: ["src/**/*.java"], diff --git a/packages/FusedLocation/Android.bp b/packages/FusedLocation/Android.bp index c70ab716aa44..ee459fed28ce 100644 --- a/packages/FusedLocation/Android.bp +++ b/packages/FusedLocation/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_FusedLocation_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_FusedLocation_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "FusedLocation", srcs: ["src/**/*.java"], @@ -43,4 +62,4 @@ android_test { "truth-prebuilt", ], test_suites: ["device-tests"] -}
\ No newline at end of file +} diff --git a/packages/InputDevices/Android.bp b/packages/InputDevices/Android.bp index 7532aea23615..8aa8bb872e0c 100644 --- a/packages/InputDevices/Android.bp +++ b/packages/InputDevices/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_InputDevices_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_InputDevices_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "InputDevices", diff --git a/packages/InputDevices/OWNERS b/packages/InputDevices/OWNERS index 0313a40f7270..f0d6db88bcc5 100644 --- a/packages/InputDevices/OWNERS +++ b/packages/InputDevices/OWNERS @@ -1,2 +1 @@ -michaelwr@google.com -svv@google.com +include /services/core/java/com/android/server/input/OWNERS diff --git a/packages/LocalTransport/Android.bp b/packages/LocalTransport/Android.bp index 2c990fed1688..185ab5090738 100644 --- a/packages/LocalTransport/Android.bp +++ b/packages/LocalTransport/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "LocalTransport", srcs: ["src/**/*.java"], diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp index 75bd32ec0301..bf0520faa5a1 100644 --- a/packages/PackageInstaller/Android.bp +++ b/packages/PackageInstaller/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_PackageInstaller_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_PackageInstaller_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "PackageInstaller", diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS index 252670a6fb13..8e1774b0baa2 100644 --- a/packages/PackageInstaller/OWNERS +++ b/packages/PackageInstaller/OWNERS @@ -1,5 +1,4 @@ svetoslavganov@google.com -moltmann@google.com toddke@google.com suprabh@google.com diff --git a/packages/PrintRecommendationService/Android.bp b/packages/PrintRecommendationService/Android.bp index 6d28bdb7943b..c907e4e2fd8e 100644 --- a/packages/PrintRecommendationService/Android.bp +++ b/packages/PrintRecommendationService/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_PrintRecommendationService_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_PrintRecommendationService_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "PrintRecommendationService", srcs: ["src/**/*.java"], diff --git a/packages/PrintSpooler/Android.bp b/packages/PrintSpooler/Android.bp index c40a81791302..99769b74bd2d 100644 --- a/packages/PrintSpooler/Android.bp +++ b/packages/PrintSpooler/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_base_packages_PrintSpooler_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_PrintSpooler_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "PrintSpooler", diff --git a/packages/PrintSpooler/jni/Android.bp b/packages/PrintSpooler/jni/Android.bp index 789312e58863..44df70e89d54 100644 --- a/packages/PrintSpooler/jni/Android.bp +++ b/packages/PrintSpooler/jni/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_PrintSpooler_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_base_packages_PrintSpooler_license", + ], +} + cc_library_shared { name: "libprintspooler_jni", diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp index 0e028b04aaaf..69a1d7fa59e4 100644 --- a/packages/PrintSpooler/tests/outofprocess/Android.bp +++ b/packages/PrintSpooler/tests/outofprocess/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_PrintSpooler_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_base_packages_PrintSpooler_license", + ], +} + android_test { name: "PrintSpoolerOutOfProcessTests", diff --git a/packages/SettingsLib/ActionBarShadow/Android.bp b/packages/SettingsLib/ActionBarShadow/Android.bp index d2848564abea..800ab671cedb 100644 --- a/packages/SettingsLib/ActionBarShadow/Android.bp +++ b/packages/SettingsLib/ActionBarShadow/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibActionBarShadow", diff --git a/packages/SettingsLib/ActionButtonsPreference/Android.bp b/packages/SettingsLib/ActionButtonsPreference/Android.bp index cd3fb0cc2143..51c9c39cdf03 100644 --- a/packages/SettingsLib/ActionButtonsPreference/Android.bp +++ b/packages/SettingsLib/ActionButtonsPreference/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibActionButtonsPreference", diff --git a/packages/SettingsLib/AdaptiveIcon/Android.bp b/packages/SettingsLib/AdaptiveIcon/Android.bp index 7f4442deecd6..934aacfddfb9 100644 --- a/packages/SettingsLib/AdaptiveIcon/Android.bp +++ b/packages/SettingsLib/AdaptiveIcon/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibAdaptiveIcon", diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index 5afe2f3d2efc..b0b6387b7d3f 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLib", diff --git a/packages/SettingsLib/AppPreference/Android.bp b/packages/SettingsLib/AppPreference/Android.bp index b07176a064f9..1817a77981a9 100644 --- a/packages/SettingsLib/AppPreference/Android.bp +++ b/packages/SettingsLib/AppPreference/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibAppPreference", diff --git a/packages/SettingsLib/BarChartPreference/Android.bp b/packages/SettingsLib/BarChartPreference/Android.bp index 477e8979b03b..ae2606661697 100644 --- a/packages/SettingsLib/BarChartPreference/Android.bp +++ b/packages/SettingsLib/BarChartPreference/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibBarChartPreference", diff --git a/packages/SettingsLib/DisplayDensityUtils/Android.bp b/packages/SettingsLib/DisplayDensityUtils/Android.bp index 27d0cb5ad48c..b7bfb5fd8af5 100644 --- a/packages/SettingsLib/DisplayDensityUtils/Android.bp +++ b/packages/SettingsLib/DisplayDensityUtils/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibDisplayDensityUtils", diff --git a/packages/SettingsLib/EntityHeaderWidgets/Android.bp b/packages/SettingsLib/EntityHeaderWidgets/Android.bp index 280848a0d7c4..bd83cdce0078 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/Android.bp +++ b/packages/SettingsLib/EntityHeaderWidgets/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibEntityHeaderWidgets", diff --git a/packages/SettingsLib/HelpUtils/Android.bp b/packages/SettingsLib/HelpUtils/Android.bp index 285131d19725..5826047b9f52 100644 --- a/packages/SettingsLib/HelpUtils/Android.bp +++ b/packages/SettingsLib/HelpUtils/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibHelpUtils", diff --git a/packages/SettingsLib/LayoutPreference/Android.bp b/packages/SettingsLib/LayoutPreference/Android.bp index a1f9a768c76c..8a4e53d80a7c 100644 --- a/packages/SettingsLib/LayoutPreference/Android.bp +++ b/packages/SettingsLib/LayoutPreference/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibLayoutPreference", diff --git a/packages/SettingsLib/ProgressBar/Android.bp b/packages/SettingsLib/ProgressBar/Android.bp index eae21d8858dc..b5bc8f77045b 100644 --- a/packages/SettingsLib/ProgressBar/Android.bp +++ b/packages/SettingsLib/ProgressBar/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibProgressBar", @@ -6,4 +15,4 @@ android_library { sdk_version: "system_current", min_sdk_version: "21", -}
\ No newline at end of file +} diff --git a/packages/SettingsLib/RadioButtonPreference/Android.bp b/packages/SettingsLib/RadioButtonPreference/Android.bp index 136d6daad99a..b309c01e0b7b 100644 --- a/packages/SettingsLib/RadioButtonPreference/Android.bp +++ b/packages/SettingsLib/RadioButtonPreference/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibRadioButtonPreference", diff --git a/packages/SettingsLib/RestrictedLockUtils/Android.bp b/packages/SettingsLib/RestrictedLockUtils/Android.bp index b2f088257bb9..c0623edabefe 100644 --- a/packages/SettingsLib/RestrictedLockUtils/Android.bp +++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibRestrictedLockUtils", @@ -10,4 +19,4 @@ android_library { sdk_version: "system_current", min_sdk_version: "21", -}
\ No newline at end of file +} diff --git a/packages/SettingsLib/SchedulesProvider/Android.bp b/packages/SettingsLib/SchedulesProvider/Android.bp index ef592527ba92..c4373bb2dc1f 100644 --- a/packages/SettingsLib/SchedulesProvider/Android.bp +++ b/packages/SettingsLib/SchedulesProvider/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibSchedulesProvider", diff --git a/packages/SettingsLib/SearchProvider/Android.bp b/packages/SettingsLib/SearchProvider/Android.bp index 5254dde71553..f96011ad5d09 100644 --- a/packages/SettingsLib/SearchProvider/Android.bp +++ b/packages/SettingsLib/SearchProvider/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibSearchProvider", diff --git a/packages/SettingsLib/SearchWidget/Android.bp b/packages/SettingsLib/SearchWidget/Android.bp index 7541ca456138..b7367b4a10a7 100644 --- a/packages/SettingsLib/SearchWidget/Android.bp +++ b/packages/SettingsLib/SearchWidget/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibSearchWidget", diff --git a/packages/SettingsLib/SettingsSpinner/Android.bp b/packages/SettingsLib/SettingsSpinner/Android.bp index f18917cd2ebb..be0567cb52dd 100644 --- a/packages/SettingsLib/SettingsSpinner/Android.bp +++ b/packages/SettingsLib/SettingsSpinner/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibSettingsSpinner", diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp index 6d505bf8895d..e45c0caa0ce3 100644 --- a/packages/SettingsLib/SettingsTheme/Android.bp +++ b/packages/SettingsLib/SettingsTheme/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibSettingsTheme", diff --git a/packages/SettingsLib/Tile/Android.bp b/packages/SettingsLib/Tile/Android.bp index bf16ef317fd8..cc570ccbb506 100644 --- a/packages/SettingsLib/Tile/Android.bp +++ b/packages/SettingsLib/Tile/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibTile", diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp index c5f0ee6c939c..1cf42ff1c566 100644 --- a/packages/SettingsLib/Utils/Android.bp +++ b/packages/SettingsLib/Utils/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLibUtils", diff --git a/packages/SettingsLib/search/Android.bp b/packages/SettingsLib/search/Android.bp index d398aa5c44ac..45746d9848df 100644 --- a/packages/SettingsLib/search/Android.bp +++ b/packages/SettingsLib/search/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "SettingsLib-search", srcs: ["src/**/*.java"], diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp index 2ccff1ecaf6c..24ca1fbe2a49 100644 --- a/packages/SettingsLib/tests/integ/Android.bp +++ b/packages/SettingsLib/tests/integ/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SettingsLibTests", defaults: [ diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp index 3756c3bf7704..dc661c234116 100644 --- a/packages/SettingsLib/tests/robotests/Android.bp +++ b/packages/SettingsLib/tests/robotests/Android.bp @@ -16,6 +16,15 @@ // SettingsLib Shell app just for Robolectric test target. # //########################################################### +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SettingsLibShell", defaults: ["SettingsLibDefaults"], diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp index 9d042a4e15f6..5f8bfef2d290 100644 --- a/packages/SettingsProvider/Android.bp +++ b/packages/SettingsProvider/Android.bp @@ -1,3 +1,22 @@ +package { + default_applicable_licenses: [ + "frameworks_base_packages_SettingsProvider_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_SettingsProvider_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "SettingsProvider", resource_dirs: ["res"], diff --git a/packages/SharedStorageBackup/Android.bp b/packages/SharedStorageBackup/Android.bp index 5380832a17d4..db682ff554f6 100644 --- a/packages/SharedStorageBackup/Android.bp +++ b/packages/SharedStorageBackup/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SharedStorageBackup", srcs: ["src/**/*.java"], diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp index aaaf0448fc31..279cb84436d5 100644 --- a/packages/Shell/Android.bp +++ b/packages/Shell/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "Shell", srcs: ["src/**/*.java",":dumpstate_aidl"], diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 39be9cbff40d..c3fc019c6787 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -87,6 +87,7 @@ <!-- TODO(b/152310230): remove once APIs are confirmed to be sufficient --> <uses-permission android:name="com.android.permission.USE_INSTALLER_V2" /> <uses-permission android:name="android.permission.MOVE_PACKAGE" /> + <uses-permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES" /> <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> <uses-permission android:name="android.permission.CLEAR_APP_CACHE" /> <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" /> @@ -357,6 +358,7 @@ <uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> + <uses-permission android:name="android.permission.BIND_RESUME_ON_REBOOT_SERVICE" /> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS index 6ba1fcb058b1..6d738f8d4d43 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -6,7 +6,7 @@ nandana@google.com svetoslavganov@google.com hackbod@google.com yamasani@google.com -moltmann@google.com toddke@google.com cbrubaker@google.com omakoto@google.com +michaelwr@google.com diff --git a/packages/Shell/tests/Android.bp b/packages/Shell/tests/Android.bp index 8536c4fbb5a3..70e8c10a961d 100644 --- a/packages/Shell/tests/Android.bp +++ b/packages/Shell/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ShellTests", srcs: ["src/**/*.java"], diff --git a/packages/SimAppDialog/Android.bp b/packages/SimAppDialog/Android.bp index ff26710fa2e1..1aeebf5c5375 100644 --- a/packages/SimAppDialog/Android.bp +++ b/packages/SimAppDialog/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SimAppDialog", diff --git a/packages/SoundPicker/Android.bp b/packages/SoundPicker/Android.bp index 3be7ca92e8c6..31fc77c6ee5f 100644 --- a/packages/SoundPicker/Android.bp +++ b/packages/SoundPicker/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SoundPicker", manifest: "AndroidManifest.xml", diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp index 3831fd981c5c..dcb9b322405c 100644 --- a/packages/StatementService/Android.bp +++ b/packages/StatementService/Android.bp @@ -11,6 +11,15 @@ // WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "StatementService", srcs: ["src/**/*.java"], diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 249b1946d435..f11351640732 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -14,6 +14,23 @@ // limitations under the License. // +package { + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_SystemUI_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + java_library { name: "SystemUI-proto", diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp index df5561acbbc4..ad39eaeed84f 100644 --- a/packages/SystemUI/plugin/Android.bp +++ b/packages/SystemUI/plugin/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + java_library { name: "SystemUIPluginLib", diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp index c6c80f3780a3..3f0fdedb57da 100644 --- a/packages/SystemUI/plugin/ExamplePlugin/Android.bp +++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + android_app { name: "ExamplePlugin", diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp index 581fef721acc..34d31d9955fc 100644 --- a/packages/SystemUI/plugin_core/Android.bp +++ b/packages/SystemUI/plugin_core/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + java_library { sdk_version: "current", name: "PluginCoreLib", diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp index 68f4b746caa2..db7e7b50a477 100644 --- a/packages/SystemUI/shared/Android.bp +++ b/packages/SystemUI/shared/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + genrule { name: "statslog-SystemUI-java-gen", tools: ["stats-log-api-gen"], diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 75f4809d752f..dfa1b7e01809 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -62,6 +62,7 @@ import android.telephony.TelephonyManager; import android.util.EventLog; import android.util.Log; import android.util.Slog; +import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.view.View; import android.view.ViewGroup; @@ -294,6 +295,13 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { */ private final SparseIntArray mLastSimStates = new SparseIntArray(); + /** + * Indicates if a SIM card had the SIM PIN enabled during the initialization, before + * reaching the SIM_STATE_READY state. The flag is reset to false at SIM_STATE_READY. + * Index is the slotId - in case of multiple SIM cards. + */ + private final SparseBooleanArray mSimWasLocked = new SparseBooleanArray(); + private boolean mDeviceInteractive; private boolean mGoingToSleep; @@ -465,10 +473,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { } } - boolean simWasLocked; + boolean lastSimStateWasLocked; synchronized (KeyguardViewMediator.this) { int lastState = mLastSimStates.get(slotId); - simWasLocked = (lastState == TelephonyManager.SIM_STATE_PIN_REQUIRED + lastSimStateWasLocked = (lastState == TelephonyManager.SIM_STATE_PIN_REQUIRED || lastState == TelephonyManager.SIM_STATE_PUK_REQUIRED); mLastSimStates.append(slotId, simState); } @@ -492,17 +500,19 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { if (simState == TelephonyManager.SIM_STATE_ABSENT) { // MVNO SIMs can become transiently NOT_READY when switching networks, // so we should only lock when they are ABSENT. - if (simWasLocked) { + if (lastSimStateWasLocked) { if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to ABSENT when the " + "previous state was locked. Reset the state."); resetStateLocked(); } + mSimWasLocked.append(slotId, false); } } break; case TelephonyManager.SIM_STATE_PIN_REQUIRED: case TelephonyManager.SIM_STATE_PUK_REQUIRED: synchronized (KeyguardViewMediator.this) { + mSimWasLocked.append(slotId, true); if (!mShowing) { if (DEBUG_SIM_STATES) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't " @@ -529,9 +539,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { case TelephonyManager.SIM_STATE_READY: synchronized (KeyguardViewMediator.this) { if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing); - if (mShowing && simWasLocked) { + if (mShowing && mSimWasLocked.get(slotId, false)) { if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to READY when the " - + "previous state was locked. Reset the state."); + + "previously was locked. Reset the state."); + mSimWasLocked.append(slotId, false); resetStateLocked(); } } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java index e6f43c1ff1d2..328cb8ab062f 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java @@ -187,12 +187,12 @@ public class ScreenMediaRecorder { */ void end() { mMediaRecorder.stop(); - mMediaProjection.stop(); mMediaRecorder.release(); - mMediaRecorder = null; - mMediaProjection = null; mInputSurface.release(); mVirtualDisplay.release(); + mMediaProjection.stop(); + mMediaRecorder = null; + mMediaProjection = null; stopInternalAudioRecording(); Log.d(TAG, "end recording"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index c5a35eaf3e6c..d18902a7796b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -27,12 +27,11 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; -import android.net.IConnectivityManager; import android.net.Network; import android.net.NetworkRequest; +import android.net.VpnManager; import android.os.Handler; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.security.KeyChain; @@ -75,7 +74,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private final Context mContext; private final ConnectivityManager mConnectivityManager; - private final IConnectivityManager mConnectivityManagerService; + private final VpnManager mVpnManager; private final DevicePolicyManager mDevicePolicyManager; private final PackageManager mPackageManager; private final UserManager mUserManager; @@ -107,8 +106,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi context.getSystemService(Context.DEVICE_POLICY_SERVICE); mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - mConnectivityManagerService = IConnectivityManager.Stub.asInterface( - ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + mVpnManager = context.getSystemService(VpnManager.class); mPackageManager = context.getPackageManager(); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mBgExecutor = bgExecutor; @@ -346,25 +344,19 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private void updateState() { // Find all users with an active VPN SparseArray<VpnConfig> vpns = new SparseArray<>(); - try { - for (UserInfo user : mUserManager.getUsers()) { - VpnConfig cfg = mConnectivityManagerService.getVpnConfig(user.id); - if (cfg == null) { + for (UserInfo user : mUserManager.getUsers()) { + VpnConfig cfg = mVpnManager.getVpnConfig(user.id); + if (cfg == null) { + continue; + } else if (cfg.legacy) { + // Legacy VPNs should do nothing if the network is disconnected. Third-party + // VPN warnings need to continue as traffic can still go to the app. + LegacyVpnInfo legacyVpn = mVpnManager.getLegacyVpnInfo(user.id); + if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) { continue; - } else if (cfg.legacy) { - // Legacy VPNs should do nothing if the network is disconnected. Third-party - // VPN warnings need to continue as traffic can still go to the app. - LegacyVpnInfo legacyVpn = mConnectivityManagerService.getLegacyVpnInfo(user.id); - if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) { - continue; - } } - vpns.put(user.id, cfg); } - } catch (RemoteException rme) { - // Roll back to previous state - Log.e(TAG, "Unable to list active VPNs", rme); - return; + vpns.put(user.id, cfg); } mCurrentVpns = vpns; } diff --git a/packages/VpnDialogs/Android.bp b/packages/VpnDialogs/Android.bp index 6f2f50c0ddd4..05135b2bebf9 100644 --- a/packages/VpnDialogs/Android.bp +++ b/packages/VpnDialogs/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "VpnDialogs", certificate: "platform", diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java index 6dcad255eee4..3502baa99b6d 100644 --- a/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java +++ b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java @@ -23,7 +23,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.ConnectivityManager; +import android.net.VpnManager; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; @@ -42,7 +42,7 @@ public class AlwaysOnDisconnectedDialog extends AlertActivity private static final String TAG = "VpnDisconnected"; - private ConnectivityManager mService; + private VpnManager mService; private int mUserId; private String mVpnPackage; @@ -51,8 +51,8 @@ public class AlwaysOnDisconnectedDialog extends AlertActivity super.onCreate(savedInstanceState); mUserId = UserHandle.myUserId(); - final ConnectivityManager cm = getSystemService(ConnectivityManager.class); - mVpnPackage = cm.getAlwaysOnVpnPackageForUser(mUserId); + final VpnManager vm = getSystemService(VpnManager.class); + mVpnPackage = vm.getAlwaysOnVpnPackageForUser(mUserId); if (mVpnPackage == null) { finish(); return; diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java index aab01d03b96d..fb2367843fc1 100644 --- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java @@ -21,7 +21,6 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import android.content.DialogInterface; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; -import android.net.ConnectivityManager; import android.net.VpnManager; import android.os.Bundle; import android.os.UserHandle; @@ -45,7 +44,6 @@ public class ConfirmDialog extends AlertActivity private String mPackage; - private ConnectivityManager mCm; // TODO: switch entirely to VpnManager once VPN code moves private VpnManager mVm; public ConfirmDialog() { @@ -60,7 +58,6 @@ public class ConfirmDialog extends AlertActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPackage = getCallingPackage(); - mCm = getSystemService(ConnectivityManager.class); mVm = getSystemService(VpnManager.class); if (mVm.prepareVpn(mPackage, null, UserHandle.myUserId())) { @@ -72,7 +69,7 @@ public class ConfirmDialog extends AlertActivity finish(); return; } - final String alwaysOnVpnPackage = mCm.getAlwaysOnVpnPackageForUser(UserHandle.myUserId()); + final String alwaysOnVpnPackage = mVm.getAlwaysOnVpnPackageForUser(UserHandle.myUserId()); // Can't prepare new vpn app when another vpn is always-on if (alwaysOnVpnPackage != null && !alwaysOnVpnPackage.equals(mPackage)) { finish(); diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp index 083dac944936..eb4f14b34bab 100644 --- a/packages/WAPPushManager/Android.bp +++ b/packages/WAPPushManager/Android.bp @@ -1,5 +1,24 @@ // Copyright 2007-2008 The Android Open Source Project +package { + default_applicable_licenses: [ + "frameworks_base_packages_WAPPushManager_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_packages_WAPPushManager_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + android_app { name: "WAPPushManager", srcs: ["src/**/*.java"], diff --git a/packages/WAPPushManager/tests/Android.bp b/packages/WAPPushManager/tests/Android.bp index 25c6121324ea..0a179383fab6 100644 --- a/packages/WAPPushManager/tests/Android.bp +++ b/packages/WAPPushManager/tests/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_WAPPushManager_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_base_packages_WAPPushManager_license", + ], +} + android_test { name: "WAPPushManagerTests", libs: [ diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp index 748eb40cb8b8..03bdf9349eb6 100644 --- a/packages/WallpaperBackup/Android.bp +++ b/packages/WallpaperBackup/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "WallpaperBackup", srcs: ["src/**/*.java"], diff --git a/packages/WallpaperCropper/Android.bp b/packages/WallpaperCropper/Android.bp index ac38b271395c..6c14d0f92479 100644 --- a/packages/WallpaperCropper/Android.bp +++ b/packages/WallpaperCropper/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "WallpaperCropper", srcs: ["src/**/*.java"], diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk index 999ab0802468..94c47b938f38 100644 --- a/packages/overlays/Android.mk +++ b/packages/overlays/Android.mk @@ -16,6 +16,9 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := frameworks-base-overlays +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_REQUIRED_MODULES := \ AccentColorBlackOverlay \ AccentColorCinnamonOverlay \ @@ -83,6 +86,9 @@ include $(BUILD_PHONY_PACKAGE) include $(CLEAR_VARS) LOCAL_MODULE := frameworks-base-overlays-debug +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE include $(BUILD_PHONY_PACKAGE) include $(call first-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/overlays/tests/Android.bp b/packages/overlays/tests/Android.bp index 343367a3cd11..b117a318e848 100644 --- a/packages/overlays/tests/Android.bp +++ b/packages/overlays/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "OverlayTests", diff --git a/packages/services/PacProcessor/Android.bp b/packages/services/PacProcessor/Android.bp index 494a8187886d..6f903347f590 100644 --- a/packages/services/PacProcessor/Android.bp +++ b/packages/services/PacProcessor/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "PacProcessor", srcs: ["src/**/*.java"], diff --git a/packages/services/PacProcessor/jni/Android.bp b/packages/services/PacProcessor/jni/Android.bp index 0e7e10152f81..965143788610 100644 --- a/packages/services/PacProcessor/jni/Android.bp +++ b/packages/services/PacProcessor/jni/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libjni_pacprocessor", diff --git a/packages/services/Proxy/Android.bp b/packages/services/Proxy/Android.bp index d93c9f8d9941..4d76db725d1f 100644 --- a/packages/services/Proxy/Android.bp +++ b/packages/services/Proxy/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "ProxyHandler", srcs: ["src/**/*.java"], diff --git a/proto/Android.bp b/proto/Android.bp index 86d8ee3a662f..a5e13350ebd2 100644 --- a/proto/Android.bp +++ b/proto/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_static { name: "framework-protos", host_supported: true, diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk index 95697e6f8bac..1a113599ff55 100644 --- a/rs/jni/Android.mk +++ b/rs/jni/Android.mk @@ -29,6 +29,9 @@ LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code LOCAL_MODULE:= librs_jni +LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS:= notice +LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE LOCAL_MODULE_TAGS := optional LOCAL_REQUIRED_MODULES := libRS diff --git a/samples/demo/haptic-assessment/Android.bp b/samples/demo/haptic-assessment/Android.bp index 1c006091a755..4d54550f3762 100644 --- a/samples/demo/haptic-assessment/Android.bp +++ b/samples/demo/haptic-assessment/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "HapticAssessment", manifest: "AndroidManifest.xml", @@ -31,4 +40,4 @@ android_app { "res", ], dxflags: ["--multi-dex"], -}
\ No newline at end of file +} diff --git a/sax/tests/saxtests/Android.bp b/sax/tests/saxtests/Android.bp index 5889f769a645..cbd19c36dd73 100644 --- a/sax/tests/saxtests/Android.bp +++ b/sax/tests/saxtests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksSaxTests", // Include all test java files. diff --git a/services/Android.bp b/services/Android.bp index a13dbe612528..8369444d1615 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_defaults { name: "services_defaults", plugins: [ diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp index 21a0c7489827..a492a5f129d9 100644 --- a/services/accessibility/Android.bp +++ b/services/accessibility/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.accessibility-sources", srcs: ["java/**/*.java"], diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index fcf270b4ef35..ac2ce5c75269 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -766,6 +766,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); + + if (Binder.getCallingPid() == OWN_PROCESS_ID) { + return new ArrayList<>(getUserStateLocked(resolvedUserId).mInstalledServices); + } return getUserStateLocked(resolvedUserId).mInstalledServices; } } diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp index c12f62fc6cd1..ec98151141f9 100644 --- a/services/appprediction/Android.bp +++ b/services/appprediction/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.appprediction-sources", srcs: ["java/**/*.java"], diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp index 83a9aa493bb0..d3cb5ee1571e 100644 --- a/services/appwidget/Android.bp +++ b/services/appwidget/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.appwidget-sources", srcs: ["java/**/*.java"], diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp index 1e65e8459edf..bbb6cd865f2b 100644 --- a/services/autofill/Android.bp +++ b/services/autofill/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.autofill-sources", srcs: ["java/**/*.java"], diff --git a/services/backup/Android.bp b/services/backup/Android.bp index 56b788e34d35..89f6b5466a30 100644 --- a/services/backup/Android.bp +++ b/services/backup/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.backup-sources", srcs: ["java/**/*.java"], diff --git a/services/backup/backuplib/Android.bp b/services/backup/backuplib/Android.bp index 00f51c960636..5a28891f88c9 100644 --- a/services/backup/backuplib/Android.bp +++ b/services/backup/backuplib/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "backuplib-sources", srcs: ["java/**/*.java"], diff --git a/services/companion/Android.bp b/services/companion/Android.bp index e25104227b71..8f33a48a4a66 100644 --- a/services/companion/Android.bp +++ b/services/companion/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.companion-sources", srcs: ["java/**/*.java"], diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 66bbf66e88db..cfbfe7322e00 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -31,6 +31,8 @@ import android.annotation.CheckResult; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.PendingIntent; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.companion.Association; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; @@ -665,6 +667,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } + void onDeviceConnected(String address) { + } + + void onDeviceDisconnected(String address) { + } + private class ShellCmd extends ShellCommand { public static final String USAGE = "help\n" + "list USER_ID\n" @@ -709,4 +717,19 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } + + private class BluetoothDeviceConnectedListener + extends BluetoothAdapter.BluetoothConnectionCallback { + @Override + public void onDeviceConnected(BluetoothDevice device) { + CompanionDeviceManagerService.this.onDeviceConnected(device.getAddress()); + } + + @Override + public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) { + Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") " + + BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason)); + CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress()); + } + } } diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp index 7006430067ec..bdc706ec823f 100644 --- a/services/contentcapture/Android.bp +++ b/services/contentcapture/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.contentcapture-sources", srcs: ["java/**/*.java"], diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp index 3fe3cd252592..c1fbcbf4bdae 100644 --- a/services/contentsuggestions/Android.bp +++ b/services/contentsuggestions/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.contentsuggestions-sources", srcs: ["java/**/*.java"], diff --git a/services/core/Android.bp b/services/core/Android.bp index ba7f0805f3da..a1956476e49c 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.core-sources", srcs: ["java/**/*.java"], @@ -98,7 +107,6 @@ java_library_static { "android.hardware.power-V1-java", "android.hardware.power-V1.0-java", "android.hardware.vibrator-V1-java", - "android.net.ipsec.ike.stubs.module_lib", "app-compat-annotations", "framework-tethering.stubs.module_lib", "service-permission.stubs.system_server", @@ -207,8 +215,5 @@ filegroup { "java/com/android/server/connectivity/QosCallbackAgentConnection.java", "java/com/android/server/connectivity/QosCallbackTracker.java", "java/com/android/server/connectivity/TcpKeepaliveController.java", - "java/com/android/server/connectivity/Vpn.java", - "java/com/android/server/connectivity/VpnIkev2Utils.java", - "java/com/android/server/net/LockdownVpnTracker.java", ], } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2f883517a378..d26a7b1075a5 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -16,7 +16,6 @@ package com.android.server; -import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; @@ -45,8 +44,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; +import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -90,11 +90,13 @@ import android.net.IConnectivityDiagnosticsCallback; import android.net.IConnectivityManager; import android.net.IDnsResolver; import android.net.INetd; +import android.net.INetworkActivityListener; import android.net.INetworkManagementEventObserver; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.INetworkPolicyListener; import android.net.INetworkStatsService; +import android.net.IOnSetOemNetworkPreferenceListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.InetAddresses; @@ -132,12 +134,13 @@ import android.net.RouteInfo; import android.net.RouteInfoParcel; import android.net.SocketKeepalive; import android.net.TetheringManager; +import android.net.TransportInfo; import android.net.UidRange; import android.net.UidRangeParcel; import android.net.UnderlyingNetworkInfo; import android.net.Uri; import android.net.VpnManager; -import android.net.VpnService; +import android.net.VpnTransportInfo; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; @@ -145,13 +148,13 @@ import android.net.netlink.InetDiagMessage; import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; import android.net.util.NetdService; +import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.os.INetworkActivityListener; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; @@ -161,6 +164,7 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.SystemClock; @@ -168,10 +172,9 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.security.Credentials; -import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; import android.util.Log; @@ -185,15 +188,13 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.logging.MetricsLogger; -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; +import com.android.internal.util.BitUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.modules.utils.BasicShellCommandHandler; +import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; import com.android.net.module.util.LinkPropertiesUtils.CompareResult; import com.android.server.am.BatteryStatsService; @@ -212,9 +213,7 @@ import com.android.server.connectivity.NetworkRanker; import com.android.server.connectivity.PermissionMonitor; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; -import com.android.server.connectivity.Vpn; import com.android.server.net.BaseNetworkObserver; -import com.android.server.net.LockdownVpnTracker; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.utils.PriorityDump; @@ -307,18 +306,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private final PerUidCounter mNetworkRequestCounter; - private KeyStore mKeyStore; - - @VisibleForTesting - @GuardedBy("mVpns") - protected final SparseArray<Vpn> mVpns = new SparseArray<>(); - - // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by - // a direct call to LockdownVpnTracker.isEnabled(). - @GuardedBy("mVpns") - private boolean mLockdownEnabled; - @GuardedBy("mVpns") - private LockdownVpnTracker mLockdownTracker; + private volatile boolean mLockdownEnabled; /** * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal @@ -569,6 +557,17 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47; /** + * used internally when setting the default networks for OemNetworkPreferences. + * obj = OemNetworkPreferences + */ + private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48; + + /** + * Used to indicate the system default network becomes active. + */ + private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49; + + /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * should be shown. */ @@ -753,6 +752,27 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + // When a lockdown VPN connects, send another CONNECTED broadcast for the underlying + // network type, to preserve previous behaviour. + private void maybeSendLegacyLockdownBroadcast(@NonNull NetworkAgentInfo vpnNai) { + if (vpnNai != mService.getLegacyLockdownNai()) return; + + if (vpnNai.declaredUnderlyingNetworks == null + || vpnNai.declaredUnderlyingNetworks.length != 1) { + Log.wtf(TAG, "Legacy lockdown VPN must have exactly one underlying network: " + + Arrays.toString(vpnNai.declaredUnderlyingNetworks)); + return; + } + final NetworkAgentInfo underlyingNai = mService.getNetworkAgentInfoForNetwork( + vpnNai.declaredUnderlyingNetworks[0]); + if (underlyingNai == null) return; + + final int type = underlyingNai.networkInfo.getType(); + final DetailedState state = DetailedState.CONNECTED; + maybeLogBroadcast(underlyingNai, state, type, true /* isDefaultNetwork */); + mService.sendLegacyNetworkBroadcast(underlyingNai, state, type); + } + /** Adds the given network to the specified legacy type list. */ public void add(int type, NetworkAgentInfo nai) { if (!isTypeSupported(type)) { @@ -770,9 +790,17 @@ public class ConnectivityService extends IConnectivityManager.Stub // Send a broadcast if this is the first network of its type or if it's the default. final boolean isDefaultNetwork = mService.isDefaultNetwork(nai); + + // If a legacy lockdown VPN is active, override the NetworkInfo state in all broadcasts + // to preserve previous behaviour. + final DetailedState state = mService.getLegacyLockdownState(DetailedState.CONNECTED); if ((list.size() == 1) || isDefaultNetwork) { - maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork); - mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); + maybeLogBroadcast(nai, state, type, isDefaultNetwork); + mService.sendLegacyNetworkBroadcast(nai, state, type); + } + + if (type == TYPE_VPN && state == DetailedState.CONNECTED) { + maybeSendLegacyLockdownBroadcast(nai); } } @@ -967,13 +995,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Get a reference to the system keystore. - */ - public KeyStore getKeyStore() { - return KeyStore.getInstance(); - } - - /** * @see ProxyTracker */ public ProxyTracker makeProxyTracker(@NonNull Context context, @@ -1037,10 +1058,10 @@ public class ConnectivityService extends IConnectivityManager.Stub mMetricsLog = logger; mNetworkRanker = new NetworkRanker(); - final NetworkRequest defaultInternetRequest = createDefaultInternetRequestForTransport( - -1, NetworkRequest.Type.REQUEST); - mDefaultRequest = new NetworkRequestInfo(null, defaultInternetRequest, new Binder(), - null /* attributionTag */); + final NetworkRequest defaultInternetRequest = createDefaultRequest(); + mDefaultRequest = new NetworkRequestInfo( + defaultInternetRequest, null, new Binder(), + null /* attributionTags */); mNetworkRequests.put(defaultInternetRequest, mDefaultRequest); mDefaultNetworkRequests.add(mDefaultRequest); mNetworkRequestInfoLogs.log("REGISTER " + mDefaultRequest); @@ -1082,7 +1103,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); mNetd = netd; - mKeyStore = mDeps.getKeyStore(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mLocationPermissionChecker = new LocationPermissionChecker(mContext); @@ -1171,45 +1191,17 @@ public class ConnectivityService extends IConnectivityManager.Stub mPermissionMonitor = new PermissionMonitor(mContext, mNetd); - // Set up the listener for user state for creating user VPNs. + // Listen for user add/removes to inform PermissionMonitor. // Should run on mHandler to avoid any races. IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_USER_STARTED); - intentFilter.addAction(Intent.ACTION_USER_STOPPED); intentFilter.addAction(Intent.ACTION_USER_ADDED); intentFilter.addAction(Intent.ACTION_USER_REMOVED); - intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); - mUserAllContext.registerReceiver( - mIntentReceiver, - intentFilter, - null /* broadcastPermission */, - mHandler); - mContext.createContextAsUser(UserHandle.SYSTEM, 0 /* flags */).registerReceiver( - mUserPresentReceiver, - new IntentFilter(Intent.ACTION_USER_PRESENT), - null /* broadcastPermission */, - null /* scheduler */); - - // Listen to package add and removal events for all users. - intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); - intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilter.addDataScheme("package"); - mUserAllContext.registerReceiver( - mIntentReceiver, - intentFilter, - null /* broadcastPermission */, - mHandler); - - // Listen to lockdown VPN reset. - intentFilter = new IntentFilter(); - intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET); - mUserAllContext.registerReceiver( - mIntentReceiver, intentFilter, NETWORK_STACK, mHandler); - - mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNMS); + mUserAllContext.registerReceiver(mIntentReceiver, intentFilter, + null /* broadcastPermission */, mHandler); + + mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNMS, mNetd); mSettingsObserver = new SettingsObserver(mContext, mHandler); registerSettingsCallbacks(); @@ -1248,21 +1240,29 @@ public class ConnectivityService extends IConnectivityManager.Stub private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); netCap.removeCapability(NET_CAPABILITY_NOT_VPN); netCap.setSingleUid(uid); return netCap; } + private NetworkRequest createDefaultRequest() { + return createDefaultInternetRequestForTransport( + TYPE_NONE, NetworkRequest.Type.REQUEST); + } + private NetworkRequest createDefaultInternetRequestForTransport( int transportType, NetworkRequest.Type type) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); - if (transportType > -1) { + if (transportType > TYPE_NONE) { netCap.addTransportType(transportType); } + return createNetworkRequest(type, netCap); + } + + private NetworkRequest createNetworkRequest( + NetworkRequest.Type type, NetworkCapabilities netCap) { return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type); } @@ -1312,7 +1312,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (enable) { handleRegisterNetworkRequest(new NetworkRequestInfo( - null, networkRequest, new Binder(), null /* attributionTag */)); + networkRequest, null, new Binder(), + null /* attributionTags */)); } else { handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID, /* callOnUnavailable */ false); @@ -1385,9 +1386,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private Network[] getVpnUnderlyingNetworks(int uid) { - synchronized (mVpns) { - if (mLockdownEnabled) return null; - } + if (mLockdownEnabled) return null; final NetworkAgentInfo nai = getVpnForUid(uid); if (nai != null) return nai.declaredUnderlyingNetworks; return null; @@ -1472,11 +1471,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) { networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); } - synchronized (mVpns) { - if (mLockdownTracker != null) { - mLockdownTracker.augmentNetworkInfo(networkInfo); - } - } + networkInfo.setDetailedState( + getLegacyLockdownState(networkInfo.getDetailedState()), + "" /* reason */, null /* extraInfo */); } /** @@ -1535,14 +1532,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return nai.network; } - // Public because it's used by mLockdownTracker. - public NetworkInfo getActiveNetworkInfoUnfiltered() { - enforceAccessPermission(); - final int uid = mDeps.getCallingUid(); - NetworkState state = getUnfilteredActiveNetworkState(uid); - return state.networkInfo; - } - @Override public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { NetworkStack.checkNetworkStackPermission(mContext); @@ -2164,22 +2153,6 @@ public class ConnectivityService extends IConnectivityManager.Stub isBackgroundRestricted); } - /** - * Require that the caller is either in the same user or has appropriate permission to interact - * across users. - * - * @param userId Target user for whatever operation the current IPC is supposed to perform. - */ - private void enforceCrossUserPermission(int userId) { - if (userId == UserHandle.getCallingUserId()) { - // Not a cross-user call. - return; - } - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - "ConnectivityService"); - } - private boolean checkAnyPermissionOf(String... permissions) { for (String permission : permissions) { if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { @@ -2260,12 +2233,6 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid); } - private void enforceControlAlwaysOnVpnPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, - "ConnectivityService"); - } - private void enforceNetworkStackOrSettingsPermission() { enforceAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, @@ -2290,6 +2257,12 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } + private void enforceOemNetworkPreferencesPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, + "ConnectivityService"); + } + private boolean checkNetworkStackPermission() { return checkAnyPermissionOf( android.Manifest.permission.NETWORK_STACK, @@ -2338,13 +2311,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } private Intent makeGeneralIntent(NetworkInfo info, String bcastType) { - synchronized (mVpns) { - if (mLockdownTracker != null) { - info = new NetworkInfo(info); - mLockdownTracker.augmentNetworkInfo(info); - } - } - Intent intent = new Intent(bcastType); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info)); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); @@ -2438,10 +2404,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait - // for user to unlock device too. - updateLockdownVpn(); - // Create network requests for always-on networks. mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS)); } @@ -2451,7 +2413,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) { - // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here + mNetworkActivityTracker.registerNetworkActivityListener(l); } /** @@ -2459,7 +2421,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) { - // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here + mNetworkActivityTracker.unregisterNetworkActivityListener(l); } /** @@ -2467,8 +2429,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public boolean isDefaultNetworkActive() { - // TODO: Replace isNetworkActive() in NMS. - return false; + return mNetworkActivityTracker.isDefaultNetworkActive(); } /** @@ -2605,13 +2566,13 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!checkDumpPermission(mContext, TAG, pw)) return; if (asProto) return; - if (ArrayUtils.contains(args, DIAG_ARG)) { + if (CollectionUtils.contains(args, DIAG_ARG)) { dumpNetworkDiagnostics(pw); return; - } else if (ArrayUtils.contains(args, NETWORK_ARG)) { + } else if (CollectionUtils.contains(args, NETWORK_ARG)) { dumpNetworks(pw); return; - } else if (ArrayUtils.contains(args, REQUEST_ARG)) { + } else if (CollectionUtils.contains(args, REQUEST_ARG)) { dumpNetworkRequests(pw); return; } @@ -2632,6 +2593,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } pw.println(); + pw.print("Current per-app default networks: "); + pw.increaseIndent(); + dumpPerAppNetworkPreferences(pw); + pw.decreaseIndent(); + pw.println(); + pw.println("Current Networks:"); pw.increaseIndent(); dumpNetworks(pw); @@ -2676,7 +2643,7 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(); - if (ArrayUtils.contains(args, SHORT_ARG) == false) { + if (!CollectionUtils.contains(args, SHORT_ARG)) { pw.println(); pw.println("mNetworkRequestInfoLogs (most recent first):"); pw.increaseIndent(); @@ -2727,6 +2694,12 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.increaseIndent(); mPermissionMonitor.dump(pw); pw.decreaseIndent(); + + pw.println(); + pw.println("Legacy network activity:"); + pw.increaseIndent(); + mNetworkActivityTracker.dump(pw); + pw.decreaseIndent(); } private void dumpNetworks(IndentingPrintWriter pw) { @@ -2752,6 +2725,40 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void dumpPerAppNetworkPreferences(IndentingPrintWriter pw) { + pw.println("Per-App Network Preference:"); + pw.increaseIndent(); + if (0 == mOemNetworkPreferences.getNetworkPreferences().size()) { + pw.println("none"); + } else { + pw.println(mOemNetworkPreferences.toString()); + } + pw.decreaseIndent(); + + for (final NetworkRequestInfo defaultRequest : mDefaultNetworkRequests) { + if (mDefaultRequest == defaultRequest) { + continue; + } + + final boolean isActive = null != defaultRequest.getSatisfier(); + pw.println("Is per-app network active:"); + pw.increaseIndent(); + pw.println(isActive); + if (isActive) { + pw.println("Active network: " + defaultRequest.getSatisfier().network.netId); + } + pw.println("Tracked UIDs:"); + pw.increaseIndent(); + if (0 == defaultRequest.mRequests.size()) { + pw.println("none, this should never occur."); + } else { + pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUids()); + } + pw.decreaseIndent(); + pw.decreaseIndent(); + } + } + private void dumpNetworkRequests(IndentingPrintWriter pw) { for (NetworkRequestInfo nri : requestsSortedById()) { pw.println(nri.toString()); @@ -2885,7 +2892,15 @@ public class ConnectivityService extends IConnectivityManager.Stub Log.wtf(TAG, "Non-virtual networks cannot have underlying networks"); break; } + final List<Network> underlying = (List<Network>) arg.second; + + if (isLegacyLockdownNai(nai) + && (underlying == null || underlying.size() != 1)) { + Log.wtf(TAG, "Legacy lockdown VPN " + nai.toShortString() + + " must have exactly one underlying network: " + underlying); + } + final Network[] oldUnderlying = nai.declaredUnderlyingNetworks; nai.declaredUnderlyingNetworks = (underlying != null) ? underlying.toArray(new Network[0]) : null; @@ -3494,7 +3509,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // incorrect) behavior. mNetworkActivityTracker.updateDataActivityTracking( null /* newNetwork */, nai); - notifyLockdownVpn(nai); ensureNetworkTransitionWakelock(nai.toShortString()); } } @@ -3584,29 +3598,38 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) { + handleRegisterNetworkRequests(Collections.singleton(nri)); + } + + private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) { ensureRunningOnConnectivityServiceThread(); - mNetworkRequestInfoLogs.log("REGISTER " + nri); - for (final NetworkRequest req : nri.mRequests) { - mNetworkRequests.put(req, nri); - if (req.isListen()) { - for (final NetworkAgentInfo network : mNetworkAgentInfos) { - if (req.networkCapabilities.hasSignalStrength() - && network.satisfiesImmutableCapabilitiesOf(req)) { - updateSignalStrengthThresholds(network, "REGISTER", req); + for (final NetworkRequestInfo nri : nris) { + mNetworkRequestInfoLogs.log("REGISTER " + nri); + for (final NetworkRequest req : nri.mRequests) { + mNetworkRequests.put(req, nri); + if (req.isListen()) { + for (final NetworkAgentInfo network : mNetworkAgentInfos) { + if (req.networkCapabilities.hasSignalStrength() + && network.satisfiesImmutableCapabilitiesOf(req)) { + updateSignalStrengthThresholds(network, "REGISTER", req); + } } } } } + rematchAllNetworksAndRequests(); - // If the nri is satisfied, return as its score has already been sent if needed. - if (nri.isBeingSatisfied()) { - return; - } + for (final NetworkRequestInfo nri : nris) { + // If the nri is satisfied, return as its score has already been sent if needed. + if (nri.isBeingSatisfied()) { + return; + } - // As this request was not satisfied on rematch and thus never had any scores sent to the - // factories, send null now for each request of type REQUEST. - for (final NetworkRequest req : nri.mRequests) { - if (req.isRequest()) sendUpdatedScoreToFactories(req, null); + // As this request was not satisfied on rematch and thus never had any scores sent to + // the factories, send null now for each request of type REQUEST. + for (final NetworkRequest req : nri.mRequests) { + if (req.isRequest()) sendUpdatedScoreToFactories(req, null); + } } } @@ -3709,7 +3732,15 @@ public class ConnectivityService extends IConnectivityManager.Stub private NetworkRequestInfo getNriForAppRequest( NetworkRequest request, int callingUid, String requestedOperation) { - final NetworkRequestInfo nri = mNetworkRequests.get(request); + // Looking up the app passed param request in mRequests isn't possible since it may return + // null for a request managed by a per-app default. Therefore use getNriForAppRequest() to + // do the lookup since that will also find per-app default managed requests. + // Additionally, this lookup needs to be relatively fast (hence the lookup optimization) + // to avoid potential race conditions when validating a package->uid mapping when sending + // the callback on the very low-chance that an application shuts down prior to the callback + // being sent. + final NetworkRequestInfo nri = mNetworkRequests.get(request) != null + ? mNetworkRequests.get(request) : getNriForAppRequest(request); if (nri != null) { if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid @@ -3758,8 +3789,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nri == null) { return; } - // handleReleaseNetworkRequest() paths don't apply to multilayer requests. - ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequest"); if (VDBG || (DBG && request.isRequest())) { log("releasing " + request + " (release request)"); } @@ -3771,7 +3800,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleRemoveNetworkRequest(@NonNull final NetworkRequestInfo nri) { ensureRunningOnConnectivityServiceThread(); - nri.unlinkDeathRecipient(); for (final NetworkRequest req : nri.mRequests) { mNetworkRequests.remove(req); @@ -3779,6 +3807,7 @@ public class ConnectivityService extends IConnectivityManager.Stub removeListenRequestFromNetworks(req); } } + mDefaultNetworkRequests.remove(nri); mNetworkRequestCounter.decrementCount(nri.mUid); mNetworkRequestInfoLogs.log("RELEASE " + nri); @@ -3793,6 +3822,16 @@ public class ConnectivityService extends IConnectivityManager.Stub cancelNpiRequests(nri); } + private void handleRemoveNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) { + for (final NetworkRequestInfo nri : nris) { + if (mDefaultRequest == nri) { + // Make sure we never remove the default request. + continue; + } + handleRemoveNetworkRequest(nri); + } + } + private void cancelNpiRequests(@NonNull final NetworkRequestInfo nri) { for (final NetworkRequest req : nri.mRequests) { cancelNpiRequest(req); @@ -4417,6 +4456,19 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_SET_REQUIRE_VPN_FOR_UIDS: handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj); break; + case EVENT_SET_OEM_NETWORK_PREFERENCE: + final Pair<OemNetworkPreferences, IOnSetOemNetworkPreferenceListener> arg = + (Pair<OemNetworkPreferences, + IOnSetOemNetworkPreferenceListener>) msg.obj; + try { + handleSetOemNetworkPreference(arg.first, arg.second); + } catch (RemoteException e) { + loge("handleMessage.EVENT_SET_OEM_NETWORK_PREFERENCE failed", e); + } + break; + case EVENT_REPORT_NETWORK_ACTIVITY: + mNetworkActivityTracker.handleReportNetworkActivity(); + break; } } } @@ -4719,183 +4771,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Prepare for a VPN application. - * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, - * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. - * - * @param oldPackage Package name of the application which currently controls VPN, which will - * be replaced. If there is no such application, this should should either be - * {@code null} or {@link VpnConfig.LEGACY_VPN}. - * @param newPackage Package name of the application which should gain control of VPN, or - * {@code null} to disable. - * @param userId User for whom to prepare the new VPN. - * - * @hide - */ - @Override - public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, - int userId) { - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - throwIfLockdownEnabled(); - Vpn vpn = mVpns.get(userId); - if (vpn != null) { - return vpn.prepare(oldPackage, newPackage, VpnManager.TYPE_VPN_SERVICE); - } else { - return false; - } - } - } - - /** - * Set whether the VPN package has the ability to launch VPNs without user intervention. This - * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} - * class. If the caller is not {@code userId}, {@link - * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. - * - * @param packageName The package for which authorization state should change. - * @param userId User for whom {@code packageName} is installed. - * @param authorized {@code true} if this app should be able to start a VPN connection without - * explicit user approval, {@code false} if not. - * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN - * permissions should be granted. When unauthorizing an app, {@link - * VpnManager.TYPE_VPN_NONE} should be used. - * @hide - */ - @Override - public void setVpnPackageAuthorization( - String packageName, int userId, @VpnManager.VpnType int vpnType) { - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn != null) { - vpn.setPackageAuthorization(packageName, vpnType); - } - } - } - - /** - * Configure a TUN interface and return its file descriptor. Parameters - * are encoded and opaque to this class. This method is used by VpnBuilder - * and not available in ConnectivityManager. Permissions are checked in - * Vpn class. - * @hide - */ - @Override - public ParcelFileDescriptor establishVpn(VpnConfig config) { - int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - throwIfLockdownEnabled(); - return mVpns.get(user).establish(config); - } - } - - /** - * Stores the given VPN profile based on the provisioning package name. - * - * <p>If there is already a VPN profile stored for the provisioning package, this call will - * overwrite the profile. - * - * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed - * exclusively by the Settings app, and passed into the platform at startup time. - * - * @return {@code true} if user consent has already been granted, {@code false} otherwise. - * @hide - */ - @Override - public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) { - final int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore); - } - } - - /** - * Deletes the stored VPN profile for the provisioning package - * - * <p>If there are no profiles for the given package, this method will silently succeed. - * - * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed - * exclusively by the Settings app, and passed into the platform at startup time. - * - * @hide - */ - @Override - public void deleteVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - mVpns.get(user).deleteVpnProfile(packageName, mKeyStore); - } - } - - /** - * Starts the VPN based on the stored profile for the given package - * - * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed - * exclusively by the Settings app, and passed into the platform at startup time. - * - * @throws IllegalArgumentException if no profile was found for the given package name. - * @hide - */ - @Override - public void startVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - throwIfLockdownEnabled(); - mVpns.get(user).startVpnProfile(packageName, mKeyStore); - } - } - - /** - * Stops the Platform VPN if the provided package is running one. - * - * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed - * exclusively by the Settings app, and passed into the platform at startup time. - * - * @hide - */ - @Override - public void stopVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - mVpns.get(user).stopVpnProfile(packageName); - } - } - - /** - * Start legacy VPN, controlling native daemons as needed. Creates a - * secondary thread to perform connection work, returning quickly. - */ - @Override - public void startLegacyVpn(VpnProfile profile) { - int user = UserHandle.getUserId(mDeps.getCallingUid()); - final LinkProperties egress = getActiveLinkProperties(); - if (egress == null) { - throw new IllegalStateException("Missing active network connection"); - } - synchronized (mVpns) { - throwIfLockdownEnabled(); - mVpns.get(user).startLegacyVpn(profile, mKeyStore, null /* underlying */, egress); - } - } - - /** - * Return the information of the ongoing legacy VPN. This method is used - * by VpnSettings and not available in ConnectivityManager. Permissions - * are checked in Vpn class. - */ - @Override - public LegacyVpnInfo getLegacyVpnInfo(int userId) { - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - return mVpns.get(userId).getLegacyVpnInfo(); - } - } - - /** * Return the information of all ongoing VPNs. * * <p>This method is used to update NetworkStatsService. @@ -4904,10 +4779,8 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private UnderlyingNetworkInfo[] getAllVpnInfo() { ensureRunningOnConnectivityServiceThread(); - synchronized (mVpns) { - if (mLockdownEnabled) { - return new UnderlyingNetworkInfo[0]; - } + if (mLockdownEnabled) { + return new UnderlyingNetworkInfo[0]; } List<UnderlyingNetworkInfo> infoList = new ArrayList<>(); for (NetworkAgentInfo nai : mNetworkAgentInfos) { @@ -4937,7 +4810,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - if (ArrayUtils.isEmpty(underlyingNetworks)) return null; + if (CollectionUtils.isEmpty(underlyingNetworks)) return null; List<String> interfaces = new ArrayList<>(); for (Network network : underlyingNetworks) { @@ -4963,25 +4836,6 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.linkProperties.getInterfaceName(), interfaces); } - /** - * Returns the information of the ongoing VPN for {@code userId}. This method is used by - * VpnDialogs and not available in ConnectivityManager. - * Permissions are checked in Vpn class. - * @hide - */ - @Override - public VpnConfig getVpnConfig(int userId) { - enforceCrossUserPermission(userId); - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn != null) { - return vpn.getVpnConfig(); - } else { - return null; - } - } - } - // TODO This needs to be the default network that applies to the NAI. private Network[] underlyingNetworksOrDefault(final int ownerUid, Network[] underlyingNetworks) { @@ -5000,7 +4854,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!nai.supportsUnderlyingNetworks()) return false; final Network[] underlying = underlyingNetworksOrDefault( nai.networkCapabilities.getOwnerUid(), nai.declaredUnderlyingNetworks); - return ArrayUtils.contains(underlying, network); + return CollectionUtils.contains(underlying, network); } /** @@ -5069,195 +4923,54 @@ public class ConnectivityService extends IConnectivityManager.Stub mVpnBlockedUidRanges = newVpnBlockedUidRanges; } - private boolean isLockdownVpnEnabled() { - return mKeyStore.contains(Credentials.LOCKDOWN_VPN); - } - @Override - public boolean updateLockdownVpn() { - // Allow the system UID for the system server and for Settings. - // Also, for unit tests, allow the process that ConnectivityService is running in. - if (mDeps.getCallingUid() != Process.SYSTEM_UID - && Binder.getCallingPid() != Process.myPid()) { - logw("Lockdown VPN only available to system process or AID_SYSTEM"); - return false; - } - - synchronized (mVpns) { - // Tear down existing lockdown if profile was removed - mLockdownEnabled = isLockdownVpnEnabled(); - if (mLockdownEnabled) { - byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN); - if (profileTag == null) { - loge("Lockdown VPN configured but cannot be read from keystore"); - return false; - } - String profileName = new String(profileTag); - final VpnProfile profile = VpnProfile.decode( - profileName, mKeyStore.get(Credentials.VPN + profileName)); - if (profile == null) { - loge("Lockdown VPN configured invalid profile " + profileName); - setLockdownTracker(null); - return true; - } - int user = UserHandle.getUserId(mDeps.getCallingUid()); - Vpn vpn = mVpns.get(user); - if (vpn == null) { - logw("VPN for user " + user + " not ready yet. Skipping lockdown"); - return false; - } - setLockdownTracker( - new LockdownVpnTracker(mContext, this, mHandler, mKeyStore, vpn, profile)); - } else { - setLockdownTracker(null); - } - } - - return true; - } - - /** - * Internally set new {@link LockdownVpnTracker}, shutting down any existing - * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown. - */ - @GuardedBy("mVpns") - private void setLockdownTracker(LockdownVpnTracker tracker) { - // Shutdown any existing tracker - final LockdownVpnTracker existing = mLockdownTracker; - // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the - // necessary onBlockedStatusChanged callbacks. - mLockdownTracker = null; - if (existing != null) { - existing.shutdown(); - } - - if (tracker != null) { - mLockdownTracker = tracker; - mLockdownTracker.init(); - } - } - - /** - * Throws if there is any currently running, always-on Legacy VPN. - * - * <p>The LockdownVpnTracker and mLockdownEnabled both track whether an always-on Legacy VPN is - * running across the entire system. Tracking for app-based VPNs is done on a per-user, - * per-package basis in Vpn.java - */ - @GuardedBy("mVpns") - private void throwIfLockdownEnabled() { - if (mLockdownEnabled) { - throw new IllegalStateException("Unavailable in lockdown mode"); - } + public void setLegacyLockdownVpnEnabled(boolean enabled) { + enforceSettingsPermission(); + mHandler.post(() -> mLockdownEnabled = enabled); } - /** - * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform - * some setup and then call {@code establish()} to connect. - * - * @return {@code true} if the service was started, the service was already connected, or there - * was no always-on VPN to start. {@code false} otherwise. - */ - private boolean startAlwaysOnVpn(int userId) { - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - // Shouldn't happen as all code paths that point here should have checked the Vpn - // exists already. - Log.wtf(TAG, "User " + userId + " has no Vpn configuration"); - return false; - } - - return vpn.startAlwaysOnVpn(mKeyStore); - } + private boolean isLegacyLockdownNai(NetworkAgentInfo nai) { + return mLockdownEnabled + && getVpnType(nai) == VpnManager.TYPE_VPN_LEGACY + && nai.networkCapabilities.appliesToUid(Process.FIRST_APPLICATION_UID); } - @Override - public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) { - enforceSettingsPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - logw("User " + userId + " has no Vpn configuration"); - return false; - } - return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore); + private NetworkAgentInfo getLegacyLockdownNai() { + if (!mLockdownEnabled) { + return null; } - } - - @Override - public boolean setAlwaysOnVpnPackage( - int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - // Can't set always-on VPN if legacy VPN is already in lockdown mode. - if (isLockdownVpnEnabled()) { - return false; - } + // The legacy lockdown VPN always only applies to userId 0. + final NetworkAgentInfo nai = getVpnForUid(Process.FIRST_APPLICATION_UID); + if (nai == null || !isLegacyLockdownNai(nai)) return null; - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - logw("User " + userId + " has no Vpn configuration"); - return false; - } - if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) { - return false; - } - if (!startAlwaysOnVpn(userId)) { - vpn.setAlwaysOnPackage(null, false, null, mKeyStore); - return false; - } + // The legacy lockdown VPN must always have exactly one underlying network. + // This code may run on any thread and declaredUnderlyingNetworks may change, so store it in + // a local variable. There is no need to make a copy because its contents cannot change. + final Network[] underlying = nai.declaredUnderlyingNetworks; + if (underlying == null || underlying.length != 1) { + return null; } - return true; - } - @Override - public String getAlwaysOnVpnPackage(int userId) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - logw("User " + userId + " has no Vpn configuration"); - return null; - } - return vpn.getAlwaysOnPackage(); + // The legacy lockdown VPN always uses the default network. + // If the VPN's underlying network is no longer the current default network, it means that + // the default network has just switched, and the VPN is about to disconnect. + // Report that the VPN is not connected, so when the state of NetworkInfo objects + // overwritten by getLegacyLockdownState will be set to CONNECTING and not CONNECTED. + final NetworkAgentInfo defaultNetwork = getDefaultNetwork(); + if (defaultNetwork == null || !defaultNetwork.network.equals(underlying[0])) { + return null; } - } - @Override - public boolean isVpnLockdownEnabled(int userId) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - logw("User " + userId + " has no Vpn configuration"); - return false; - } - return vpn.getLockdown(); - } - } + return nai; + }; - @Override - public List<String> getVpnLockdownWhitelist(int userId) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - logw("User " + userId + " has no Vpn configuration"); - return null; - } - return vpn.getLockdownAllowlist(); + private DetailedState getLegacyLockdownState(DetailedState origState) { + if (origState != DetailedState.CONNECTED) { + return origState; } + return (mLockdownEnabled && getLegacyLockdownNai() == null) + ? DetailedState.CONNECTING + : DetailedState.CONNECTED; } @Override @@ -5292,111 +5005,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void onUserStarted(int userId) { - synchronized (mVpns) { - Vpn userVpn = mVpns.get(userId); - if (userVpn != null) { - loge("Starting user already has a VPN"); - return; - } - userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore); - mVpns.put(userId, userVpn); - if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { - updateLockdownVpn(); - } - } + private void onUserAdded(UserHandle user) { + mPermissionMonitor.onUserAdded(user); } - private void onUserStopped(int userId) { - synchronized (mVpns) { - Vpn userVpn = mVpns.get(userId); - if (userVpn == null) { - loge("Stopped user has no VPN"); - return; - } - userVpn.onUserStopped(); - mVpns.delete(userId); - } - } - - private void onUserAdded(int userId) { - mPermissionMonitor.onUserAdded(userId); - synchronized (mVpns) { - final int vpnsSize = mVpns.size(); - for (int i = 0; i < vpnsSize; i++) { - Vpn vpn = mVpns.valueAt(i); - vpn.onUserAdded(userId); - } - } - } - - private void onUserRemoved(int userId) { - mPermissionMonitor.onUserRemoved(userId); - synchronized (mVpns) { - final int vpnsSize = mVpns.size(); - for (int i = 0; i < vpnsSize; i++) { - Vpn vpn = mVpns.valueAt(i); - vpn.onUserRemoved(userId); - } - } - } - - private void onPackageReplaced(String packageName, int uid) { - if (TextUtils.isEmpty(packageName) || uid < 0) { - Log.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid); - return; - } - final int userId = UserHandle.getUserId(uid); - synchronized (mVpns) { - final Vpn vpn = mVpns.get(userId); - if (vpn == null) { - return; - } - // Legacy always-on VPN won't be affected since the package name is not set. - if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) { - log("Restarting always-on VPN package " + packageName + " for user " - + userId); - vpn.startAlwaysOnVpn(mKeyStore); - } - } - } - - private void onPackageRemoved(String packageName, int uid, boolean isReplacing) { - if (TextUtils.isEmpty(packageName) || uid < 0) { - Log.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid); - return; - } - - final int userId = UserHandle.getUserId(uid); - synchronized (mVpns) { - final Vpn vpn = mVpns.get(userId); - if (vpn == null) { - return; - } - // Legacy always-on VPN won't be affected since the package name is not set. - if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { - log("Removing always-on VPN package " + packageName + " for user " - + userId); - vpn.setAlwaysOnPackage(null, false, null, mKeyStore); - } - } - } - - private void onUserUnlocked(int userId) { - synchronized (mVpns) { - // User present may be sent because of an unlock, which might mean an unlocked keystore. - if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { - updateLockdownVpn(); - } else { - startAlwaysOnVpn(userId); - } - } - } - - private void onVpnLockdownReset() { - synchronized (mVpns) { - if (mLockdownTracker != null) mLockdownTracker.reset(); - } + private void onUserRemoved(UserHandle user) { + mPermissionMonitor.onUserRemoved(user); } private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @@ -5404,53 +5018,24 @@ public class ConnectivityService extends IConnectivityManager.Stub public void onReceive(Context context, Intent intent) { ensureRunningOnConnectivityServiceThread(); final String action = intent.getAction(); - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); - final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - final Uri packageData = intent.getData(); - final String packageName = - packageData != null ? packageData.getSchemeSpecificPart() : null; + final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); - if (LockdownVpnTracker.ACTION_LOCKDOWN_RESET.equals(action)) { - onVpnLockdownReset(); + // User should be filled for below intents, check the existence. + if (user == null) { + Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER"); + return; } - // UserId should be filled for below intents, check the existence. - if (userId == UserHandle.USER_NULL) return; - - if (Intent.ACTION_USER_STARTED.equals(action)) { - onUserStarted(userId); - } else if (Intent.ACTION_USER_STOPPED.equals(action)) { - onUserStopped(userId); - } else if (Intent.ACTION_USER_ADDED.equals(action)) { - onUserAdded(userId); + if (Intent.ACTION_USER_ADDED.equals(action)) { + onUserAdded(user); } else if (Intent.ACTION_USER_REMOVED.equals(action)) { - onUserRemoved(userId); - } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { - onUserUnlocked(userId); - } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) { - onPackageReplaced(packageName, uid); - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - final boolean isReplacing = intent.getBooleanExtra( - Intent.EXTRA_REPLACING, false); - onPackageRemoved(packageName, uid, isReplacing); - } else { + onUserRemoved(user); + } else { Log.wtf(TAG, "received unexpected intent: " + action); } } }; - private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - // Try creating lockdown tracker, since user present usually means - // unlocked keystore. - updateLockdownVpn(); - // Use the same context that registered receiver before to unregister it. Because use - // different context to unregister receiver will cause exception. - context.unregisterReceiver(this); - } - }; - private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>(); private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>(); @@ -5549,12 +5134,29 @@ public class ConnectivityService extends IConnectivityManager.Stub final PendingIntent mPendingIntent; boolean mPendingIntentSent; + @Nullable + final Messenger mMessenger; + @Nullable private final IBinder mBinder; final int mPid; final int mUid; - final Messenger messenger; @Nullable final String mCallingAttributionTag; + // In order to preserve the mapping of NetworkRequest-to-callback when apps register + // callbacks using a returned NetworkRequest, the original NetworkRequest needs to be + // maintained for keying off of. This is only a concern when the original nri + // mNetworkRequests changes which happens currently for apps that register callbacks to + // track the default network. In those cases, the nri is updated to have mNetworkRequests + // that match the per-app default nri that currently tracks the calling app's uid so that + // callbacks are fired at the appropriate time. When the callbacks fire, + // mNetworkRequestForCallback will be used so as to preserve the caller's mapping. When + // callbacks are updated to key off of an nri vs NetworkRequest, this stops being an issue. + // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects. + @NonNull + private final NetworkRequest mNetworkRequestForCallback; + NetworkRequest getNetworkRequestForCallback() { + return mNetworkRequestForCallback; + } /** * Get the list of UIDs this nri applies to. @@ -5568,12 +5170,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return uids; } - NetworkRequestInfo(NetworkRequest r, PendingIntent pi, + NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi, @Nullable String callingAttributionTag) { + this(Collections.singletonList(r), r, pi, callingAttributionTag); + } + + NetworkRequestInfo(@NonNull final List<NetworkRequest> r, + @NonNull final NetworkRequest requestForCallback, @Nullable final PendingIntent pi, + @Nullable String callingAttributionTag) { + ensureAllNetworkRequestsHaveType(r); mRequests = initializeRequests(r); - ensureAllNetworkRequestsHaveType(mRequests); + mNetworkRequestForCallback = requestForCallback; mPendingIntent = pi; - messenger = null; + mMessenger = null; mBinder = null; mPid = getCallingPid(); mUid = mDeps.getCallingUid(); @@ -5581,12 +5190,19 @@ public class ConnectivityService extends IConnectivityManager.Stub mCallingAttributionTag = callingAttributionTag; } - NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, - @Nullable String callingAttributionTag) { + NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final Messenger m, + @Nullable final IBinder binder, @Nullable String callingAttributionTag) { + this(Collections.singletonList(r), r, m, binder, callingAttributionTag); + } + + NetworkRequestInfo(@NonNull final List<NetworkRequest> r, + @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m, + @Nullable final IBinder binder, @Nullable String callingAttributionTag) { super(); - messenger = m; + ensureAllNetworkRequestsHaveType(r); mRequests = initializeRequests(r); - ensureAllNetworkRequestsHaveType(mRequests); + mNetworkRequestForCallback = requestForCallback; + mMessenger = m; mBinder = binder; mPid = getCallingPid(); mUid = mDeps.getCallingUid(); @@ -5601,8 +5217,26 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - NetworkRequestInfo(NetworkRequest r) { - this(r, null /* pi */, null /* callingAttributionTag */); + NetworkRequestInfo(@NonNull final NetworkRequestInfo nri, + @NonNull final List<NetworkRequest> r) { + super(); + ensureAllNetworkRequestsHaveType(r); + mRequests = initializeRequests(r); + mNetworkRequestForCallback = nri.getNetworkRequestForCallback(); + mMessenger = nri.mMessenger; + mBinder = nri.mBinder; + mPid = nri.mPid; + mUid = nri.mUid; + mPendingIntent = nri.mPendingIntent; + mCallingAttributionTag = nri.mCallingAttributionTag; + } + + NetworkRequestInfo(@NonNull final NetworkRequest r) { + this(Collections.singletonList(r)); + } + + NetworkRequestInfo(@NonNull final List<NetworkRequest> r) { + this(r, r.get(0), null /* pi */, null /* callingAttributionTag */); } // True if this NRI is being satisfied. It also accounts for if the nri has its satisifer @@ -5616,9 +5250,10 @@ public class ConnectivityService extends IConnectivityManager.Stub return mRequests.size() > 1; } - private List<NetworkRequest> initializeRequests(NetworkRequest r) { - final ArrayList<NetworkRequest> tempRequests = new ArrayList<>(); - tempRequests.add(new NetworkRequest(r)); + private List<NetworkRequest> initializeRequests(List<NetworkRequest> r) { + // Creating a defensive copy to prevent the sender from modifying the list being + // reflected in the return value of this method. + final List<NetworkRequest> tempRequests = new ArrayList<>(r); return Collections.unmodifiableList(tempRequests); } @@ -5683,8 +5318,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } - // TODO: use NetworkStackUtils.convertToIntArray after moving it - return ArrayUtils.convertToIntArray(new ArrayList<>(thresholds)); + return CollectionUtils.toIntArray(new ArrayList<>(thresholds)); } private void updateSignalStrengthThresholds( @@ -5747,6 +5381,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new SecurityException("Insufficient permissions to specify legacy type"); } } + final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities; final int callingUid = mDeps.getCallingUid(); final NetworkRequest.Type reqType; try { @@ -5757,11 +5392,16 @@ public class ConnectivityService extends IConnectivityManager.Stub switch (reqType) { case TRACK_DEFAULT: // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities} - // is unused and will be replaced by the one from the default network request. - // This allows callers to keep track of the system default network. - networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid); + // is unused and will be replaced by ones appropriate for the caller. + // This allows callers to keep track of the default network for their app. + networkCapabilities = copyDefaultNetworkCapabilitiesForUid( + defaultNc, callingUid, callingPackageName); enforceAccessPermission(); break; + case TRACK_SYSTEM_DEFAULT: + enforceSettingsPermission(); + networkCapabilities = new NetworkCapabilities(defaultNc); + break; case BACKGROUND_REQUEST: enforceNetworkStackOrSettingsPermission(); // Fall-through since other checks are the same with normal requests. @@ -5780,6 +5420,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureRequestableCapabilities(networkCapabilities); ensureSufficientPermissionsForRequest(networkCapabilities, Binder.getCallingPid(), callingUid, callingPackageName); + // Set the UID range for this request to the single UID of the requester, or to an empty // set of UIDs if the caller has the appropriate permission and UIDs have not been set. // This will overwrite any allowed UIDs in the requested capabilities. Though there @@ -5793,12 +5434,23 @@ public class ConnectivityService extends IConnectivityManager.Stub } ensureValid(networkCapabilities); - NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, + final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), reqType); - NetworkRequestInfo nri = - new NetworkRequestInfo(messenger, networkRequest, binder, callingAttributionTag); + final NetworkRequestInfo nri = getNriToRegister( + networkRequest, messenger, binder, callingAttributionTag); if (DBG) log("requestNetwork for " + nri); + // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were + // copied from the default request above. (This is necessary to ensure, for example, that + // the callback does not leak sensitive information to unprivileged apps.) Check that the + // changes don't alter request matching. + if (reqType == NetworkRequest.Type.TRACK_SYSTEM_DEFAULT && + (!networkCapabilities.equalRequestableCapabilities(defaultNc))) { + throw new IllegalStateException( + "TRACK_SYSTEM_DEFAULT capabilities don't match default request: " + + networkCapabilities + " vs. " + defaultNc); + } + mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri)); if (timeoutMs > 0) { mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST, @@ -5807,6 +5459,30 @@ public class ConnectivityService extends IConnectivityManager.Stub return networkRequest; } + /** + * Return the nri to be used when registering a network request. Specifically, this is used with + * requests registered to track the default request. If there is currently a per-app default + * tracking the app requestor, then we need to create a version of this nri that mirrors that of + * the tracking per-app default so that callbacks are sent to the app requestor appropriately. + * @param nr the network request for the nri. + * @param msgr the messenger for the nri. + * @param binder the binder for the nri. + * @param callingAttributionTag the calling attribution tag for the nri. + * @return the nri to register. + */ + private NetworkRequestInfo getNriToRegister(@NonNull final NetworkRequest nr, + @Nullable final Messenger msgr, @Nullable final IBinder binder, + @Nullable String callingAttributionTag) { + final List<NetworkRequest> requests; + if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) { + requests = copyDefaultNetworkRequestsForUid( + nr.getRequestorUid(), nr.getRequestorPackageName()); + } else { + requests = Collections.singletonList(nr); + } + return new NetworkRequestInfo(requests, nr, msgr, binder, callingAttributionTag); + } + private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities, String callingPackageName, String callingAttributionTag) { if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) { @@ -5952,7 +5628,7 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); NetworkRequestInfo nri = - new NetworkRequestInfo(messenger, networkRequest, binder, callingAttributionTag); + new NetworkRequestInfo(networkRequest, messenger, binder, callingAttributionTag); if (VDBG) log("listenForNetwork for " + nri); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); @@ -6080,19 +5756,122 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mBlockedAppUids") private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); + // Current OEM network preferences. + @NonNull + private OemNetworkPreferences mOemNetworkPreferences = + new OemNetworkPreferences.Builder().build(); + // The always-on request for an Internet-capable network that apps without a specific default // fall back to. + @VisibleForTesting @NonNull - private final NetworkRequestInfo mDefaultRequest; + final NetworkRequestInfo mDefaultRequest; // Collection of NetworkRequestInfo's used for default networks. + @VisibleForTesting @NonNull - private final ArraySet<NetworkRequestInfo> mDefaultNetworkRequests = new ArraySet<>(); + final ArraySet<NetworkRequestInfo> mDefaultNetworkRequests = new ArraySet<>(); private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) { return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri); } /** + * Return the default network request currently tracking the given uid. + * @param uid the uid to check. + * @return the NetworkRequestInfo tracking the given uid. + */ + @NonNull + private NetworkRequestInfo getDefaultRequestTrackingUid(@NonNull final int uid) { + for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { + if (nri == mDefaultRequest) { + continue; + } + // Checking the first request is sufficient as only multilayer requests will have more + // than one request and for multilayer, all requests will track the same uids. + if (nri.mRequests.get(0).networkCapabilities.appliesToUid(uid)) { + return nri; + } + } + return mDefaultRequest; + } + + /** + * Get a copy of the network requests of the default request that is currently tracking the + * given uid. + * @param requestorUid the uid to check the default for. + * @param requestorPackageName the requestor's package name. + * @return a copy of the default's NetworkRequest that is tracking the given uid. + */ + @NonNull + private List<NetworkRequest> copyDefaultNetworkRequestsForUid( + @NonNull final int requestorUid, @NonNull final String requestorPackageName) { + return copyNetworkRequestsForUid( + getDefaultRequestTrackingUid(requestorUid).mRequests, + requestorUid, requestorPackageName); + } + + /** + * Copy the given nri's NetworkRequest collection. + * @param requestsToCopy the NetworkRequest collection to be copied. + * @param requestorUid the uid to set on the copied collection. + * @param requestorPackageName the package name to set on the copied collection. + * @return the copied NetworkRequest collection. + */ + @NonNull + private List<NetworkRequest> copyNetworkRequestsForUid( + @NonNull final List<NetworkRequest> requestsToCopy, @NonNull final int requestorUid, + @NonNull final String requestorPackageName) { + final List<NetworkRequest> requests = new ArrayList<>(); + for (final NetworkRequest nr : requestsToCopy) { + requests.add(new NetworkRequest(copyDefaultNetworkCapabilitiesForUid( + nr.networkCapabilities, requestorUid, requestorPackageName), + nr.legacyType, nextNetworkRequestId(), nr.type)); + } + return requests; + } + + @NonNull + private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid( + @NonNull final NetworkCapabilities netCapToCopy, @NonNull final int requestorUid, + @NonNull final String requestorPackageName) { + final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy); + netCap.removeCapability(NET_CAPABILITY_NOT_VPN); + netCap.setSingleUid(requestorUid); + netCap.setUids(new ArraySet<>()); + restrictRequestUidsForCallerAndSetRequestorInfo( + netCap, requestorUid, requestorPackageName); + return netCap; + } + + /** + * Get the nri that is currently being tracked for callbacks by per-app defaults. + * @param nr the network request to check for equality against. + * @return the nri if one exists, null otherwise. + */ + @Nullable + private NetworkRequestInfo getNriForAppRequest(@NonNull final NetworkRequest nr) { + for (final NetworkRequestInfo nri : mNetworkRequests.values()) { + if (nri.getNetworkRequestForCallback().equals(nr)) { + return nri; + } + } + return null; + } + + /** + * Check if an nri is currently being managed by per-app default networking. + * @param nri the nri to check. + * @return true if this nri is currently being managed by per-app default networking. + */ + private boolean isPerAppTrackedNri(@NonNull final NetworkRequestInfo nri) { + // nri.mRequests.get(0) is only different from the original request filed in + // nri.getNetworkRequestForCallback() if nri.mRequests was changed by per-app default + // functionality therefore if these two don't match, it means this particular nri is + // currently being managed by a per-app default. + return nri.getNetworkRequestForCallback() != nri.mRequests.get(0); + } + + /** * Determine if an nri is a managed default request that disallows default networking. * @param nri the request to evaluate * @return true if device-default networking is disallowed @@ -6389,20 +6168,18 @@ public class ConnectivityService extends IConnectivityManager.Stub Math.max(naData.getRefreshTimeMillis(), apiData.getRefreshTimeMillis())); } - // Prioritize the user portal URL from the network agent. - if (apiData.getUserPortalUrl() != null && (naData.getUserPortalUrl() == null - || TextUtils.isEmpty(naData.getUserPortalUrl().toSafeString()))) { - captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl()); + // Prioritize the user portal URL from the network agent if the source is authenticated. + if (apiData.getUserPortalUrl() != null && naData.getUserPortalUrlSource() + != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) { + captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl(), + apiData.getUserPortalUrlSource()); } - // Prioritize the venue information URL from the network agent. - if (apiData.getVenueInfoUrl() != null && (naData.getVenueInfoUrl() == null - || TextUtils.isEmpty(naData.getVenueInfoUrl().toSafeString()))) { - captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl()); - - // Note that venue friendly name can only come from the network agent because it is not - // in use in RFC8908. However, if using the Capport venue URL, make sure that the - // friendly name is not set from the network agent. - captivePortalBuilder.setVenueFriendlyName(null); + // Prioritize the venue information URL from the network agent if the source is + // authenticated. + if (apiData.getVenueInfoUrl() != null && naData.getVenueInfoUrlSource() + != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) { + captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl(), + apiData.getVenueInfoUrlSource()); } return captivePortalBuilder.build(); } @@ -6660,7 +6437,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) { underlyingNetworks = underlyingNetworksOrDefault( agentCaps.getOwnerUid(), underlyingNetworks); - int[] transportTypes = agentCaps.getTransportTypes(); + long transportTypes = BitUtils.packBits(agentCaps.getTransportTypes()); int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; // metered if any underlying is metered, or originally declared metered by the agent. @@ -6679,7 +6456,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkCapabilities underlyingCaps = underlying.networkCapabilities; hadUnderlyingNetworks = true; for (int underlyingType : underlyingCaps.getTransportTypes()) { - transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType); + transportTypes |= 1L << underlyingType; } // Merge capabilities of this underlying network. For bandwidth, assume the @@ -6710,7 +6487,7 @@ public class ConnectivityService extends IConnectivityManager.Stub suspended = false; } - newNc.setTransportTypes(transportTypes); + newNc.setTransportTypes(BitUtils.unpackBits(transportTypes)); newNc.setLinkDownstreamBandwidthKbps(downKbps); newNc.setLinkUpstreamBandwidthKbps(upKbps); newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered); @@ -7165,20 +6942,16 @@ public class ConnectivityService extends IConnectivityManager.Stub private void callCallbackForRequest(@NonNull final NetworkRequestInfo nri, @NonNull final NetworkAgentInfo networkAgent, final int notificationType, final int arg1) { - if (nri.messenger == null) { + if (nri.mMessenger == null) { // Default request has no msgr. Also prevents callbacks from being invoked for // NetworkRequestInfos registered with ConnectivityDiagnostics requests. Those callbacks // are Type.LISTEN, but should not have NetworkCallbacks invoked. return; } Bundle bundle = new Bundle(); - // In the case of multi-layer NRIs, the first request is not necessarily the one that - // is satisfied. This is vexing, but the ConnectivityManager code that receives this - // callback is only using the request as a token to identify the callback, so it doesn't - // matter too much at this point as long as the callback can be found. // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects. // TODO: check if defensive copies of data is needed. - final NetworkRequest nrForCallback = new NetworkRequest(nri.mRequests.get(0)); + final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback(); putParcelable(bundle, nrForCallback); Message msg = Message.obtain(); if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) { @@ -7234,7 +7007,7 @@ public class ConnectivityService extends IConnectivityManager.Stub String notification = ConnectivityManager.getCallbackName(notificationType); log("sending notification " + notification + " for " + nrForCallback); } - nri.messenger.send(msg); + nri.mMessenger.send(msg); } catch (RemoteException e) { // may occur naturally in the race of binder death. loge("RemoteException caught trying to send a callback msg for " + nrForCallback); @@ -7323,7 +7096,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork); } mNetworkActivityTracker.updateDataActivityTracking(newDefaultNetwork, oldDefaultNetwork); - notifyLockdownVpn(newDefaultNetwork); handleApplyDefaultProxy(null != newDefaultNetwork ? newDefaultNetwork.linkProperties.getHttpProxy() : null); updateTcpBufferSizes(null != newDefaultNetwork @@ -7781,12 +7553,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mDefaultInetConditionPublished = newDefaultNetwork.lastValidated ? 100 : 0; mLegacyTypeTracker.add( newDefaultNetwork.networkInfo.getType(), newDefaultNetwork); - // If the legacy VPN is connected, notifyLockdownVpn may end up sending a broadcast - // to reflect the NetworkInfo of this new network. This broadcast has to be sent - // after the disconnect broadcasts above, but before the broadcasts sent by the - // legacy type tracker below. - // TODO : refactor this, it's too complex - notifyLockdownVpn(newDefaultNetwork); } } @@ -7844,18 +7610,6 @@ public class ConnectivityService extends IConnectivityManager.Stub sendInetConditionBroadcast(nai.networkInfo); } - private void notifyLockdownVpn(NetworkAgentInfo nai) { - synchronized (mVpns) { - if (mLockdownTracker != null) { - if (nai != null && nai.isVPN()) { - mLockdownTracker.onVpnStateChanged(nai.networkInfo); - } else { - mLockdownTracker.onNetworkInfoChanged(); - } - } - } - } - @NonNull private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) { final NetworkInfo newInfo = new NetworkInfo(info); @@ -7894,7 +7648,6 @@ public class ConnectivityService extends IConnectivityManager.Stub oldInfo = networkAgent.networkInfo; networkAgent.networkInfo = newInfo; } - notifyLockdownVpn(networkAgent); if (DBG) { log(networkAgent.toShortString() + " EVENT_NETWORK_INFO_CHANGED, going from " @@ -8195,34 +7948,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public boolean addVpnAddress(String address, int prefixLength) { - int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - throwIfLockdownEnabled(); - return mVpns.get(user).addAddress(address, prefixLength); - } - } - - @Override - public boolean removeVpnAddress(String address, int prefixLength) { - int user = UserHandle.getUserId(mDeps.getCallingUid()); - synchronized (mVpns) { - throwIfLockdownEnabled(); - return mVpns.get(user).removeAddress(address, prefixLength); - } - } - - @Override - public boolean setUnderlyingNetworksForVpn(Network[] networks) { - int user = UserHandle.getUserId(mDeps.getCallingUid()); - final boolean success; - synchronized (mVpns) { - success = mVpns.get(user).setUnderlyingNetworks(networks); - } - return success; - } - - @Override public String getCaptivePortalServerUrl() { enforceNetworkStackOrSettingsPermission(); String settingUrl = mContext.getResources().getString( @@ -8301,8 +8026,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - final int userId = UserHandle.getCallingUserId(); - final long token = Binder.clearCallingIdentity(); try { final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext); @@ -8314,44 +8037,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // Turn airplane mode off setAirplaneMode(false); - if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { - // Remove always-on package - synchronized (mVpns) { - final String alwaysOnPackage = getAlwaysOnVpnPackage(userId); - if (alwaysOnPackage != null) { - setAlwaysOnVpnPackage(userId, null, false, null); - setVpnPackageAuthorization(alwaysOnPackage, userId, VpnManager.TYPE_VPN_NONE); - } - - // Turn Always-on VPN off - if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { - final long ident = Binder.clearCallingIdentity(); - try { - mKeyStore.delete(Credentials.LOCKDOWN_VPN); - mLockdownEnabled = false; - setLockdownTracker(null); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - // Turn VPN off - VpnConfig vpnConfig = getVpnConfig(userId); - if (vpnConfig != null) { - if (vpnConfig.legacy) { - prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); - } else { - // Prevent this app (packagename = vpnConfig.user) from initiating - // VPN connections in the future without user intervention. - setVpnPackageAuthorization( - vpnConfig.user, userId, VpnManager.TYPE_VPN_NONE); - - prepareVpn(null, VpnConfig.LEGACY_VPN, userId); - } - } - } - } - // restore private DNS settings to default mode (opportunistic) if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) { Settings.Global.putString(mContext.getContentResolver(), @@ -8443,41 +8128,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - @GuardedBy("mVpns") - private Vpn getVpnIfOwner() { - return getVpnIfOwner(mDeps.getCallingUid()); - } - - // TODO: stop calling into Vpn.java and get this information from data in this class. - @GuardedBy("mVpns") - private Vpn getVpnIfOwner(int uid) { - final int user = UserHandle.getUserId(uid); - - final Vpn vpn = mVpns.get(user); - if (vpn == null) { - return null; - } else { - final UnderlyingNetworkInfo info = vpn.getUnderlyingNetworkInfo(); - return (info == null || info.ownerUid != uid) ? null : vpn; - } - } - - /** - * Caller either needs to be an active VPN, or hold the NETWORK_STACK permission - * for testing. - */ - private Vpn enforceActiveVpnOrNetworkStackPermission() { - if (checkNetworkStackPermission()) { - return null; - } - synchronized (mVpns) { - Vpn vpn = getVpnIfOwner(); - if (vpn != null) { - return vpn; - } - } - throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK " - + "permission"); + private @VpnManager.VpnType int getVpnType(@Nullable NetworkAgentInfo vpn) { + if (vpn == null) return VpnManager.TYPE_VPN_NONE; + final TransportInfo ti = vpn.networkCapabilities.getTransportInfo(); + if (!(ti instanceof VpnTransportInfo)) return VpnManager.TYPE_VPN_NONE; + return ((VpnTransportInfo) ti).type; } /** @@ -8487,14 +8142,6 @@ public class ConnectivityService extends IConnectivityManager.Stub * connection is not found. */ public int getConnectionOwnerUid(ConnectionInfo connectionInfo) { - final Vpn vpn = enforceActiveVpnOrNetworkStackPermission(); - - // Only VpnService based VPNs should be able to get this information. - if (vpn != null && vpn.getActiveAppVpnType() != VpnManager.TYPE_VPN_SERVICE) { - throw new SecurityException( - "getConnectionOwnerUid() not allowed for non-VpnService VPNs"); - } - if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) { throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol); } @@ -8502,28 +8149,19 @@ public class ConnectivityService extends IConnectivityManager.Stub final int uid = mDeps.getConnectionOwnerUid(connectionInfo.protocol, connectionInfo.local, connectionInfo.remote); - /* Filter out Uids not associated with the VPN. */ - if (vpn != null && !vpn.appliesToUid(uid)) { - return INVALID_UID; - } + if (uid == INVALID_UID) return uid; // Not found. - return uid; - } + // Connection owner UIDs are visible only to the network stack and to the VpnService-based + // VPN, if any, that applies to the UID that owns the connection. + if (checkNetworkStackPermission()) return uid; - @Override - public boolean isCallerCurrentAlwaysOnVpnApp() { - synchronized (mVpns) { - Vpn vpn = getVpnIfOwner(); - return vpn != null && vpn.getAlwaysOn(); + final NetworkAgentInfo vpn = getVpnForUid(uid); + if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE + || vpn.networkCapabilities.getOwnerUid() != Binder.getCallingUid()) { + return INVALID_UID; } - } - @Override - public boolean isCallerCurrentAlwaysOnVpnLockdownApp() { - synchronized (mVpns) { - Vpn vpn = getVpnIfOwner(); - return vpn != null && vpn.getLockdown(); - } + return uid; } /** @@ -8914,14 +8552,14 @@ public class ConnectivityService extends IConnectivityManager.Stub for (NetworkAgentInfo virtual : mNetworkAgentInfos) { if (virtual.supportsUnderlyingNetworks() && virtual.networkCapabilities.getOwnerUid() == callbackUid - && ArrayUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) { + && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) { return true; } } // Administrator UIDs also contains the Owner UID final int[] administratorUids = nai.networkCapabilities.getAdministratorUids(); - return ArrayUtils.contains(administratorUids, callbackUid); + return CollectionUtils.contains(administratorUids, callbackUid); } @Override @@ -9017,13 +8655,35 @@ public class ConnectivityService extends IConnectivityManager.Stub * changes. */ private static final class LegacyNetworkActivityTracker { + private static final int NO_UID = -1; private final Context mContext; + private final INetd mNetd; private final INetworkManagementService mNMS; + private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = + new RemoteCallbackList<>(); + // Indicate the current system default network activity is active or not. + @GuardedBy("mActiveIdleTimers") + private boolean mNetworkActive; + @GuardedBy("mActiveIdleTimers") + private final ArrayMap<String, IdleTimerParams> mActiveIdleTimers = new ArrayMap(); + private final Handler mHandler; + + private class IdleTimerParams { + public final int timeout; + public final int transportType; - LegacyNetworkActivityTracker(@NonNull Context context, - @NonNull INetworkManagementService nms) { + IdleTimerParams(int timeout, int transport) { + this.timeout = timeout; + this.transportType = transport; + } + } + + LegacyNetworkActivityTracker(@NonNull Context context, @NonNull Handler handler, + @NonNull INetworkManagementService nms, @NonNull INetd netd) { mContext = context; mNMS = nms; + mNetd = netd; + mHandler = handler; try { mNMS.registerObserver(mDataActivityObserver); } catch (RemoteException e) { @@ -9039,9 +8699,50 @@ public class ConnectivityService extends IConnectivityManager.Stub long tsNanos, int uid) { sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active, tsNanos); + synchronized (mActiveIdleTimers) { + mNetworkActive = active; + // If there are no idle timers, it means that system is not monitoring + // activity, so the system default network for those default network + // unspecified apps is always considered active. + // + // TODO: If the mActiveIdleTimers is empty, netd will actually not send + // any network activity change event. Whenever this event is received, + // the mActiveIdleTimers should be always not empty. The legacy behavior + // is no-op. Remove to refer to mNetworkActive only. + if (mNetworkActive || mActiveIdleTimers.isEmpty()) { + mHandler.sendMessage( + mHandler.obtainMessage(EVENT_REPORT_NETWORK_ACTIVITY)); + } + } } }; + // The network activity should only be updated from ConnectivityService handler thread + // when mActiveIdleTimers lock is held. + @GuardedBy("mActiveIdleTimers") + private void reportNetworkActive() { + final int length = mNetworkActivityListeners.beginBroadcast(); + if (DDBG) log("reportNetworkActive, notify " + length + " listeners"); + try { + for (int i = 0; i < length; i++) { + try { + mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); + } catch (RemoteException | RuntimeException e) { + loge("Fail to send network activie to listener " + e); + } + } + } finally { + mNetworkActivityListeners.finishBroadcast(); + } + } + + @GuardedBy("mActiveIdleTimers") + public void handleReportNetworkActivity() { + synchronized (mActiveIdleTimers) { + reportNetworkActive(); + } + } + // This is deprecated and only to support legacy use cases. private int transportTypeToLegacyType(int type) { switch (type) { @@ -9106,10 +8807,17 @@ public class ConnectivityService extends IConnectivityManager.Stub return; // do not track any other networks } + updateRadioPowerState(true /* isActive */, type); + if (timeout > 0 && iface != null) { try { - // TODO: Access INetd directly instead of NMS - mNMS.addIdleTimer(iface, timeout, type); + synchronized (mActiveIdleTimers) { + // Networks start up. + mNetworkActive = true; + mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); + mNetd.idletimerAddInterface(iface, timeout, Integer.toString(type)); + reportNetworkActive(); + } } catch (Exception e) { // You shall not crash! loge("Exception in setupDataActivityTracking " + e); @@ -9124,16 +8832,28 @@ public class ConnectivityService extends IConnectivityManager.Stub final String iface = networkAgent.linkProperties.getInterfaceName(); final NetworkCapabilities caps = networkAgent.networkCapabilities; - if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) - || caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) { - try { - // the call fails silently if no idle timer setup for this interface - // TODO: Access INetd directly instead of NMS - mNMS.removeIdleTimer(iface); - } catch (Exception e) { - // You shall not crash! - loge("Exception in removeDataActivityTracking " + e); + if (iface == null) return; + + final int type; + if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + type = NetworkCapabilities.TRANSPORT_CELLULAR; + } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + type = NetworkCapabilities.TRANSPORT_WIFI; + } else { + return; // do not track any other networks + } + + try { + updateRadioPowerState(false /* isActive */, type); + synchronized (mActiveIdleTimers) { + final IdleTimerParams params = mActiveIdleTimers.remove(iface); + // The call fails silently if no idle timer setup for this interface + mNetd.idletimerRemoveInterface(iface, params.timeout, + Integer.toString(params.transportType)); } + } catch (Exception e) { + // You shall not crash! + loge("Exception in removeDataActivityTracking " + e); } } @@ -9149,6 +8869,53 @@ public class ConnectivityService extends IConnectivityManager.Stub removeDataActivityTracking(oldNetwork); } } + + private void updateRadioPowerState(boolean isActive, int transportType) { + final BatteryStatsManager bs = mContext.getSystemService(BatteryStatsManager.class); + switch (transportType) { + case NetworkCapabilities.TRANSPORT_CELLULAR: + bs.reportMobileRadioPowerState(isActive, NO_UID); + break; + case NetworkCapabilities.TRANSPORT_WIFI: + bs.reportWifiRadioPowerState(isActive, NO_UID); + break; + default: + logw("Untracked transport type:" + transportType); + } + } + + public boolean isDefaultNetworkActive() { + synchronized (mActiveIdleTimers) { + // If there are no idle timers, it means that system is not monitoring activity, + // so the default network is always considered active. + // + // TODO : Distinguish between the cases where mActiveIdleTimers is empty because + // tracking is disabled (negative idle timer value configured), or no active default + // network. In the latter case, this reports active but it should report inactive. + return mNetworkActive || mActiveIdleTimers.isEmpty(); + } + } + + public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) { + mNetworkActivityListeners.register(l); + } + + public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) { + mNetworkActivityListeners.unregister(l); + } + + public void dump(IndentingPrintWriter pw) { + synchronized (mActiveIdleTimers) { + pw.print("mNetworkActive="); pw.println(mNetworkActive); + pw.println("Idle timers:"); + for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { + pw.print(" "); pw.print(ent.getKey()); pw.println(":"); + final IdleTimerParams params = ent.getValue(); + pw.print(" timeout="); pw.print(params.timeout); + pw.print(" type="); pw.println(params.transportType); + } + } + } } /** @@ -9201,9 +8968,274 @@ public class ConnectivityService extends IConnectivityManager.Stub mQosCallbackTracker.unregisterCallback(callback); } + private void enforceAutomotiveDevice() { + final boolean isAutomotiveDevice = + mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + if (!isAutomotiveDevice) { + throw new UnsupportedOperationException( + "setOemNetworkPreference() is only available on automotive devices."); + } + } + + /** + * Used by automotive devices to set the network preferences used to direct traffic at an + * application level as per the given OemNetworkPreferences. An example use-case would be an + * automotive OEM wanting to provide connectivity for applications critical to the usage of a + * vehicle via a particular network. + * + * Calling this will overwrite the existing preference. + * + * @param preference {@link OemNetworkPreferences} The application network preference to be set. + * @param listener {@link ConnectivityManager.OnSetOemNetworkPreferenceListener} Listener used + * to communicate completion of setOemNetworkPreference(); + */ @Override - public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference) { - // TODO http://b/176495594 track multiple default networks with networkPreferences - if (DBG) log("setOemNetworkPreference() called with: " + preference.toString()); + public void setOemNetworkPreference( + @NonNull final OemNetworkPreferences preference, + @Nullable final IOnSetOemNetworkPreferenceListener listener) { + + enforceAutomotiveDevice(); + enforceOemNetworkPreferencesPermission(); + + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); + validateOemNetworkPreferences(preference); + mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE, + new Pair<>(preference, listener))); + } + + private void validateOemNetworkPreferences(@NonNull OemNetworkPreferences preference) { + for (@OemNetworkPreferences.OemNetworkPreference final int pref + : preference.getNetworkPreferences().values()) { + if (OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED == pref) { + final String msg = "OEM_NETWORK_PREFERENCE_UNINITIALIZED is an invalid value."; + throw new IllegalArgumentException(msg); + } + } + } + + private void handleSetOemNetworkPreference( + @NonNull final OemNetworkPreferences preference, + @NonNull final IOnSetOemNetworkPreferenceListener listener) throws RemoteException { + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); + if (DBG) { + log("set OEM network preferences :" + preference.toString()); + } + final ArraySet<NetworkRequestInfo> nris = + new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference); + updateDefaultNetworksForOemNetworkPreference(nris); + mOemNetworkPreferences = preference; + // TODO http://b/176496396 persist data to shared preferences. + + if (null != listener) { + listener.onComplete(); + } + } + + private void updateDefaultNetworksForOemNetworkPreference( + @NonNull final Set<NetworkRequestInfo> nris) { + // Pass in a defensive copy as this collection will be updated on remove. + handleRemoveNetworkRequests(new ArraySet<>(mDefaultNetworkRequests)); + addPerAppDefaultNetworkRequests(nris); + } + + private void addPerAppDefaultNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) { + ensureRunningOnConnectivityServiceThread(); + mDefaultNetworkRequests.addAll(nris); + final ArraySet<NetworkRequestInfo> perAppCallbackRequestsToUpdate = + getPerAppCallbackRequestsToUpdate(); + handleRemoveNetworkRequests(perAppCallbackRequestsToUpdate); + final ArraySet<NetworkRequestInfo> nrisToRegister = new ArraySet<>(nris); + nrisToRegister.addAll( + createPerAppCallbackRequestsToRegister(perAppCallbackRequestsToUpdate)); + handleRegisterNetworkRequests(nrisToRegister); + } + + /** + * All current requests that are tracking the default network need to be assessed as to whether + * or not the current set of per-application default requests will be changing their default + * network. If so, those requests will need to be updated so that they will send callbacks for + * default network changes at the appropriate time. Additionally, those requests tracking the + * default that were previously updated by this flow will need to be reassessed. + * @return the nris which will need to be updated. + */ + private ArraySet<NetworkRequestInfo> getPerAppCallbackRequestsToUpdate() { + final ArraySet<NetworkRequestInfo> defaultCallbackRequests = new ArraySet<>(); + // Get the distinct nris to check since for multilayer requests, it is possible to have the + // same nri in the map's values for each of its NetworkRequest objects. + final ArraySet<NetworkRequestInfo> nris = new ArraySet<>(mNetworkRequests.values()); + for (final NetworkRequestInfo nri : nris) { + // Include this nri if it is currently being tracked. + if (isPerAppTrackedNri(nri)) { + defaultCallbackRequests.add(nri); + continue; + } + // We only track callbacks for requests tracking the default. + if (NetworkRequest.Type.TRACK_DEFAULT != nri.mRequests.get(0).type) { + continue; + } + // Include this nri if it will be tracked by the new per-app default requests. + final boolean isNriGoingToBeTracked = + getDefaultRequestTrackingUid(nri.mUid) != mDefaultRequest; + if (isNriGoingToBeTracked) { + defaultCallbackRequests.add(nri); + } + } + return defaultCallbackRequests; + } + + /** + * Create nris for those network requests that are currently tracking the default network that + * are being controlled by a per-application default. + * @param perAppCallbackRequestsForUpdate the baseline network requests to be used as the + * foundation when creating the nri. Important items include the calling uid's original + * NetworkRequest to be used when mapping callbacks as well as the caller's uid and name. These + * requests are assumed to have already been validated as needing to be updated. + * @return the Set of nris to use when registering network requests. + */ + private ArraySet<NetworkRequestInfo> createPerAppCallbackRequestsToRegister( + @NonNull final ArraySet<NetworkRequestInfo> perAppCallbackRequestsForUpdate) { + final ArraySet<NetworkRequestInfo> callbackRequestsToRegister = new ArraySet<>(); + for (final NetworkRequestInfo callbackRequest : perAppCallbackRequestsForUpdate) { + final NetworkRequestInfo trackingNri = + getDefaultRequestTrackingUid(callbackRequest.mUid); + + // If this nri is not being tracked, the change it back to an untracked nri. + if (trackingNri == mDefaultRequest) { + callbackRequestsToRegister.add(new NetworkRequestInfo( + callbackRequest, + Collections.singletonList(callbackRequest.getNetworkRequestForCallback()))); + continue; + } + + final String requestorPackageName = + callbackRequest.mRequests.get(0).getRequestorPackageName(); + callbackRequestsToRegister.add(new NetworkRequestInfo( + callbackRequest, + copyNetworkRequestsForUid( + trackingNri.mRequests, callbackRequest.mUid, requestorPackageName))); + } + return callbackRequestsToRegister; + } + + /** + * Class used to generate {@link NetworkRequestInfo} based off of {@link OemNetworkPreferences}. + */ + @VisibleForTesting + final class OemNetworkRequestFactory { + ArraySet<NetworkRequestInfo> createNrisFromOemNetworkPreferences( + @NonNull final OemNetworkPreferences preference) { + final ArraySet<NetworkRequestInfo> nris = new ArraySet<>(); + final SparseArray<Set<Integer>> uids = + createUidsFromOemNetworkPreferences(preference); + for (int i = 0; i < uids.size(); i++) { + final int key = uids.keyAt(i); + final Set<Integer> value = uids.valueAt(i); + final NetworkRequestInfo nri = createNriFromOemNetworkPreferences(key, value); + // No need to add an nri without any requests. + if (0 == nri.mRequests.size()) { + continue; + } + nris.add(nri); + } + + return nris; + } + + private SparseArray<Set<Integer>> createUidsFromOemNetworkPreferences( + @NonNull final OemNetworkPreferences preference) { + final SparseArray<Set<Integer>> uids = new SparseArray<>(); + final PackageManager pm = mContext.getPackageManager(); + for (final Map.Entry<String, Integer> entry : + preference.getNetworkPreferences().entrySet()) { + @OemNetworkPreferences.OemNetworkPreference final int pref = entry.getValue(); + try { + final int uid = pm.getApplicationInfo(entry.getKey(), 0).uid; + if (!uids.contains(pref)) { + uids.put(pref, new ArraySet<>()); + } + uids.get(pref).add(uid); + } catch (PackageManager.NameNotFoundException e) { + // Although this may seem like an error scenario, it is ok that uninstalled + // packages are sent on a network preference as the system will watch for + // package installations associated with this network preference and update + // accordingly. This is done so as to minimize race conditions on app install. + // TODO b/177092163 add app install watching. + continue; + } + } + return uids; + } + + private NetworkRequestInfo createNriFromOemNetworkPreferences( + @OemNetworkPreferences.OemNetworkPreference final int preference, + @NonNull final Set<Integer> uids) { + final List<NetworkRequest> requests = new ArrayList<>(); + // Requests will ultimately be evaluated by order of insertion therefore it matters. + switch (preference) { + case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID: + requests.add(createUnmeteredNetworkRequest()); + requests.add(createOemPaidNetworkRequest()); + requests.add(createDefaultRequest()); + break; + case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: + requests.add(createUnmeteredNetworkRequest()); + requests.add(createOemPaidNetworkRequest()); + break; + case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY: + requests.add(createOemPaidNetworkRequest()); + break; + case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY: + requests.add(createOemPrivateNetworkRequest()); + break; + default: + // This should never happen. + throw new IllegalArgumentException("createNriFromOemNetworkPreferences()" + + " called with invalid preference of " + preference); + } + + setOemNetworkRequestUids(requests, uids); + return new NetworkRequestInfo(requests); + } + + private NetworkRequest createUnmeteredNetworkRequest() { + final NetworkCapabilities netcap = createDefaultPerAppNetCap() + .addCapability(NET_CAPABILITY_NOT_METERED) + .addCapability(NET_CAPABILITY_VALIDATED); + return createNetworkRequest(NetworkRequest.Type.LISTEN, netcap); + } + + private NetworkRequest createOemPaidNetworkRequest() { + // NET_CAPABILITY_OEM_PAID is a restricted capability. + final NetworkCapabilities netcap = createDefaultPerAppNetCap() + .addCapability(NET_CAPABILITY_OEM_PAID) + .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap); + } + + private NetworkRequest createOemPrivateNetworkRequest() { + // NET_CAPABILITY_OEM_PRIVATE is a restricted capability. + final NetworkCapabilities netcap = createDefaultPerAppNetCap() + .addCapability(NET_CAPABILITY_OEM_PRIVATE) + .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap); + } + + private NetworkCapabilities createDefaultPerAppNetCap() { + final NetworkCapabilities netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); + return netCap; + } + + private void setOemNetworkRequestUids(@NonNull final List<NetworkRequest> requests, + @NonNull final Set<Integer> uids) { + final Set<UidRange> ranges = new ArraySet<>(); + for (final int uid : uids) { + ranges.add(new UidRange(uid, uid)); + } + for (final NetworkRequest req : requests) { + req.networkCapabilities.setUids(ranges); + } + } } } diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index 88ce2208adcb..e29e894a5cc0 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -28,6 +28,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.image.IDynamicSystemService; +import android.os.storage.DiskInfo; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.util.Slog; @@ -40,6 +41,7 @@ import java.io.File; */ public class DynamicSystemService extends IDynamicSystemService.Stub { private static final String TAG = "DynamicSystemService"; + private static final long MINIMUM_SD_MB = (30L << 10); private static final int GSID_ROUGH_TIMEOUT_MS = 8192; private static final String PATH_DEFAULT = "/data/gsi/"; private Context mContext; @@ -95,6 +97,13 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { if (!volume.isMountedWritable()) { continue; } + DiskInfo disk = volume.getDisk(); + long mega = disk.size >> 20; + Slog.i(TAG, volume.getPath() + ": " + mega + " MB"); + if (mega < MINIMUM_SD_MB) { + Slog.i(TAG, volume.getPath() + ": insufficient storage"); + continue; + } File sd_internal = volume.getInternalPathForUser(userId); if (sd_internal != null) { path = new File(sd_internal, dsuSlot).getPath(); diff --git a/services/core/java/com/android/server/EntropyMixer.java b/services/core/java/com/android/server/EntropyMixer.java index c56cef2d58dc..a83c981235df 100644 --- a/services/core/java/com/android/server/EntropyMixer.java +++ b/services/core/java/com/android/server/EntropyMixer.java @@ -16,12 +16,6 @@ package com.android.server; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; - import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -33,10 +27,15 @@ import android.os.Message; import android.os.SystemProperties; import android.util.Slog; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + /** * A service designed to load and periodically save "randomness" - * for the Linux kernel RNG and to mix in data from Hardware RNG (if present) - * into the Linux RNG. + * for the Linux kernel RNG. * * <p>When a Linux system starts up, the entropy pool associated with * {@code /dev/random} may be in a fairly predictable state. Applications which @@ -45,15 +44,8 @@ import android.util.Slog; * this effect, it's helpful to carry the entropy pool information across * shutdowns and startups. * - * <p>On systems with Hardware RNG (/dev/hw_random), a block of output from HW - * RNG is mixed into the Linux RNG on EntropyMixer's startup and whenever - * EntropyMixer periodically runs to save a block of output from Linux RNG on - * disk. This mixing is done in a way that does not increase the Linux RNG's - * entropy estimate is not increased. This is to avoid having to trust/verify - * the quality and authenticity of the "randomness" of the HW RNG. - * * <p>This class was modeled after the script in the - * <a href="http://www.kernel.org/doc/man-pages/online/pages/man4/random.4.html"> + * <a href="https://man7.org/linux/man-pages/man4/random.4.html"> * random(4) manual page</a>. */ public class EntropyMixer extends Binder { @@ -64,7 +56,6 @@ public class EntropyMixer extends Binder { private static final long START_NANOTIME = System.nanoTime(); private final String randomDevice; - private final String hwRandomDevice; private final String entropyFile; /** @@ -80,7 +71,6 @@ public class EntropyMixer extends Binder { Slog.e(TAG, "Will not process invalid message"); return; } - addHwRandomEntropy(); writeEntropy(); scheduleEntropyWriter(); } @@ -94,25 +84,21 @@ public class EntropyMixer extends Binder { }; public EntropyMixer(Context context) { - this(context, getSystemDir() + "/entropy.dat", "/dev/urandom", "/dev/hw_random"); + this(context, getSystemDir() + "/entropy.dat", "/dev/urandom"); } /** Test only interface, not for public use */ public EntropyMixer( Context context, String entropyFile, - String randomDevice, - String hwRandomDevice) { + String randomDevice) { if (randomDevice == null) { throw new NullPointerException("randomDevice"); } - if (hwRandomDevice == null) { throw new NullPointerException("hwRandomDevice"); } if (entropyFile == null) { throw new NullPointerException("entropyFile"); } this.randomDevice = randomDevice; - this.hwRandomDevice = hwRandomDevice; this.entropyFile = entropyFile; loadInitialEntropy(); addDeviceSpecificEntropy(); - addHwRandomEntropy(); writeEntropy(); scheduleEntropyWriter(); IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); @@ -192,23 +178,6 @@ public class EntropyMixer extends Binder { } } - /** - * Mixes in the output from HW RNG (if present) into the Linux RNG. - */ - private void addHwRandomEntropy() { - if (!new File(hwRandomDevice).exists()) { - // HW RNG not present/exposed -- ignore - return; - } - - try { - RandomBlock.fromFile(hwRandomDevice).toFile(randomDevice, false); - Slog.i(TAG, "Added HW RNG output to entropy pool"); - } catch (IOException e) { - Slog.w(TAG, "Failed to add HW RNG output to entropy pool", e); - } - } - private static String getSystemDir() { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index f648c3e146de..81d4b9da63c8 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -29,6 +29,7 @@ import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; import android.net.IIpSecService; import android.net.INetd; import android.net.InetAddresses; @@ -41,12 +42,12 @@ import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.Network; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -62,6 +63,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.net.module.util.NetdUtils; import libcore.io.IoUtils; @@ -115,9 +117,6 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; - /* NetworkManager instance */ - private final INetworkManagementService mNetworkManager; - /** * The next non-repeating global ID for tracking resources between users, this service, and * kernel data structures. Accessing this variable is not thread safe, so it is only read or @@ -797,9 +796,15 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class TunnelInterfaceRecord extends OwnedResourceRecord { + /** + * Tracks an tunnel interface, and manages cleanup paths. + * + * <p>This class is not thread-safe, and expects that that users of this class will ensure + * synchronization and thread safety by holding the IpSecService.this instance lock + */ + @VisibleForTesting + final class TunnelInterfaceRecord extends OwnedResourceRecord { private final String mInterfaceName; - private final Network mUnderlyingNetwork; // outer addresses private final String mLocalAddress; @@ -810,6 +815,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIfId; + private Network mUnderlyingNetwork; + TunnelInterfaceRecord( int resourceId, String interfaceName, @@ -870,14 +877,22 @@ public class IpSecService extends IIpSecService.Stub { releaseNetId(mOkey); } - public String getInterfaceName() { - return mInterfaceName; + @GuardedBy("IpSecService.this") + public void setUnderlyingNetwork(Network underlyingNetwork) { + // When #applyTunnelModeTransform is called, this new underlying network will be used to + // update the output mark of the input transform. + mUnderlyingNetwork = underlyingNetwork; } + @GuardedBy("IpSecService.this") public Network getUnderlyingNetwork() { return mUnderlyingNetwork; } + public String getInterfaceName() { + return mInterfaceName; + } + /** Returns the local, outer address for the tunnelInterface */ public String getLocalAddress() { return mLocalAddress; @@ -996,13 +1011,13 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context, INetworkManagementService networkManager) { - this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE); + private IpSecService(Context context) { + this(context, IpSecServiceConfiguration.GETSRVINSTANCE); } - static IpSecService create(Context context, INetworkManagementService networkManager) + static IpSecService create(Context context) throws InterruptedException { - final IpSecService service = new IpSecService(context, networkManager); + final IpSecService service = new IpSecService(context); service.connectNativeNetdService(); return service; } @@ -1016,11 +1031,9 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, INetworkManagementService networkManager, - IpSecServiceConfiguration config) { + public IpSecService(Context context, IpSecServiceConfiguration config) { this( context, - networkManager, config, (fd, uid) -> { try { @@ -1034,10 +1047,9 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, INetworkManagementService networkManager, - IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { + public IpSecService(Context context, IpSecServiceConfiguration config, + UidFdTagger uidFdTagger) { mContext = context; - mNetworkManager = Objects.requireNonNull(networkManager); mSrvConfig = config; mUidFdTagger = uidFdTagger; } @@ -1317,7 +1329,7 @@ public class IpSecService extends IIpSecService.Stub { netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); Binder.withCleanCallingIdentity(() -> { - mNetworkManager.setInterfaceUp(intfName); + NetdUtils.setInterfaceUp(netd, intfName); }); for (int selAddrFamily : ADDRESS_FAMILIES) { @@ -1429,6 +1441,34 @@ public class IpSecService extends IIpSecService.Stub { } } + /** Set TunnelInterface to use a specific underlying network. */ + @Override + public synchronized void setNetworkForTunnelInterface( + int tunnelResourceId, Network underlyingNetwork, String callingPackage) { + enforceTunnelFeatureAndPermissions(callingPackage); + Objects.requireNonNull(underlyingNetwork, "No underlying network was specified"); + + final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Get tunnelInterface record; if no such interface is found, will throw + // IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null + final TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); + + final ConnectivityManager connectivityManager = + mContext.getSystemService(ConnectivityManager.class); + final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork); + if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) { + throw new IllegalArgumentException( + "Underlying network cannot be the network being exposed by this tunnel"); + } + + // It is meaningless to check if the network exists or is valid because the network might + // disconnect at any time after it passes the check. + + tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork); + } + /** * Delete a TunnelInterface that has been been allocated by and registered with the system * server diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index d30a6405e95d..44054088d937 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -69,7 +69,6 @@ import android.os.BatteryStats; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.INetworkActivityListener; import android.os.INetworkManagementService; import android.os.Process; import android.os.RemoteCallbackList; @@ -80,7 +79,6 @@ import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; -import android.telephony.DataConnectionRealTimeInfo; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -229,32 +227,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub { @GuardedBy("mQuotaLock") private volatile boolean mDataSaverMode; - private final Object mIdleTimerLock = new Object(); - /** Set of interfaces with active idle timers. */ - private static class IdleTimerParams { - public final int timeout; - public final int type; - public int networkCount; - - IdleTimerParams(int timeout, int type) { - this.timeout = timeout; - this.type = type; - this.networkCount = 1; - } - } - private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); - private volatile boolean mFirewallEnabled; private volatile boolean mStrictEnabled; - private boolean mMobileActivityFromRadio = false; - private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; - private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; - - private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = - new RemoteCallbackList<>(); - private boolean mNetworkActive; - /** * Constructs a new NetworkManagementService instance * @@ -397,55 +372,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub { */ private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos, int uid) { - final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type); - int powerState = isActive - ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH - : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; - if (isMobile) { - if (mLastPowerStateFromRadio != powerState) { - mLastPowerStateFromRadio = powerState; - try { - // TODO: The interface changes that comes from netd are handled by BSS itself. - // There are still events caused by setting or removing idle timer, so keep - // reporting from here until setting idler timer moved to CS. - getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid); - } catch (RemoteException e) { - } - } - } - - if (ConnectivityManager.isNetworkTypeWifi(type)) { - if (mLastPowerStateFromWifi != powerState) { - mLastPowerStateFromWifi = powerState; - try { - // TODO: The interface changes that comes from netd are handled by BSS itself. - // There are still events caused by setting or removing idle timer, so keep - // reporting from here until setting idler timer moved to CS. - getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid); - } catch (RemoteException e) { - } - } - } - - final boolean active = isActive; invokeForAllObservers(o -> o.interfaceClassDataActivityChanged( - type, active, tsNanos, uid)); - - boolean report = false; - synchronized (mIdleTimerLock) { - if (mActiveIdleTimers.isEmpty()) { - // If there are no idle timers, we are not monitoring activity, so we - // are always considered active. - isActive = true; - } - if (mNetworkActive != isActive) { - mNetworkActive = isActive; - report = isActive; - } - } - if (report) { - reportNetworkActive(); - } + type, isActive, tsNanos, uid)); } @Override @@ -1122,60 +1050,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void addIdleTimer(String iface, int timeout, final int type) { - NetworkStack.checkNetworkStackPermission(mContext); - - if (DBG) Slog.d(TAG, "Adding idletimer"); - - synchronized (mIdleTimerLock) { - IdleTimerParams params = mActiveIdleTimers.get(iface); - if (params != null) { - // the interface already has idletimer, update network count - params.networkCount++; - return; - } - - try { - mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type)); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); - - // Networks start up. - if (ConnectivityManager.isNetworkTypeMobile(type)) { - mNetworkActive = false; - } - mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true, - SystemClock.elapsedRealtimeNanos(), -1)); - } - } - - @Override - public void removeIdleTimer(String iface) { - NetworkStack.checkNetworkStackPermission(mContext); - - if (DBG) Slog.d(TAG, "Removing idletimer"); - - synchronized (mIdleTimerLock) { - final IdleTimerParams params = mActiveIdleTimers.get(iface); - if (params == null || --(params.networkCount) > 0) { - return; - } - - try { - mNetdService.idletimerRemoveInterface(iface, - params.timeout, Integer.toString(params.type)); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - mActiveIdleTimers.remove(iface); - mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false, - SystemClock.elapsedRealtimeNanos(), -1)); - } - } - - @Override public void setInterfaceQuota(String iface, long quotaBytes) { NetworkStack.checkNetworkStackPermission(mContext); @@ -1813,44 +1687,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void registerNetworkActivityListener(INetworkActivityListener listener) { - mNetworkActivityListeners.register(listener); - } - - @Override - public void unregisterNetworkActivityListener(INetworkActivityListener listener) { - mNetworkActivityListeners.unregister(listener); - } - - @Override - public boolean isNetworkActive() { - synchronized (mNetworkActivityListeners) { - return mNetworkActive || mActiveIdleTimers.isEmpty(); - } - } - - private void reportNetworkActive() { - final int length = mNetworkActivityListeners.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - try { - mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); - } catch (RemoteException | RuntimeException e) { - } - } - } finally { - mNetworkActivityListeners.finishBroadcast(); - } - } - - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); - pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); - pw.print("mNetworkActive="); pw.println(mNetworkActive); - synchronized (mQuotaLock) { pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); @@ -1882,17 +1721,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { mUidFirewallRestrictedRules); } - synchronized (mIdleTimerLock) { - pw.println("Idle timers:"); - for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { - pw.print(" "); pw.print(ent.getKey()); pw.println(":"); - IdleTimerParams params = ent.getValue(); - pw.print(" timeout="); pw.print(params.timeout); - pw.print(" type="); pw.print(params.type); - pw.print(" networkCount="); pw.println(params.networkCount); - } - } - pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); pw.print("Netd service status: " ); if (mNetdService == null) { diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 4dce59f23a79..329ab9983c90 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -22,6 +22,7 @@ import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubsc import static java.util.Objects.requireNonNull; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.net.ConnectivityManager; @@ -29,8 +30,10 @@ import android.net.LinkProperties; import android.net.NetworkCapabilities; import android.net.TelephonyNetworkSpecifier; import android.net.vcn.IVcnManagementService; +import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; +import android.net.vcn.VcnManager.VcnErrorCode; import android.net.vcn.VcnUnderlyingNetworkPolicy; import android.net.wifi.WifiInfo; import android.os.Binder; @@ -54,6 +57,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; +import com.android.internal.util.LocationPermissionChecker; import com.android.server.vcn.TelephonySubscriptionTracker; import com.android.server.vcn.Vcn; import com.android.server.vcn.VcnContext; @@ -124,6 +128,7 @@ import java.util.concurrent.TimeUnit; * * @hide */ +// TODO(b/180451994): ensure all incoming + outgoing calls have a cleared calling identity public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private static final String TAG = VcnManagementService.class.getSimpleName(); @@ -147,6 +152,9 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker; @NonNull private final VcnContext mVcnContext; + /** Can only be assigned when {@link #systemReady()} is called, since it uses AppOpsManager. */ + @Nullable private LocationPermissionChecker mLocationPermissionChecker; + @GuardedBy("mLock") @NonNull private final Map<ParcelUuid, VcnConfig> mConfigs = new ArrayMap<>(); @@ -169,6 +177,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { private final Map<IBinder, PolicyListenerBinderDeath> mRegisteredPolicyListeners = new ArrayMap<>(); + @GuardedBy("mLock") + @NonNull + private final Map<IBinder, VcnStatusCallbackInfo> mRegisteredStatusCallbacks = new ArrayMap<>(); + @VisibleForTesting(visibility = Visibility.PRIVATE) VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) { mContext = requireNonNull(context, "Missing context"); @@ -293,8 +305,8 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config, @NonNull TelephonySubscriptionSnapshot snapshot, - @NonNull VcnSafemodeCallback safemodeCallback) { - return new Vcn(vcnContext, subscriptionGroup, config, snapshot, safemodeCallback); + @NonNull VcnCallback vcnCallback) { + return new Vcn(vcnContext, subscriptionGroup, config, snapshot, vcnCallback); } /** Gets the subId indicated by the given {@link WifiInfo}. */ @@ -302,6 +314,11 @@ public class VcnManagementService extends IVcnManagementService.Stub { // TODO(b/178501049): use the subId indicated by WifiInfo#getSubscriptionId return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } + + /** Creates a new LocationPermissionChecker for the provided Context. */ + public LocationPermissionChecker newLocationPermissionChecker(@NonNull Context context) { + return new LocationPermissionChecker(context); + } } /** Notifies the VcnManagementService that external dependencies can be set up. */ @@ -309,6 +326,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { mContext.getSystemService(ConnectivityManager.class) .registerNetworkProvider(mNetworkProvider); mTelephonySubscriptionTracker.register(); + mLocationPermissionChecker = mDeps.newLocationPermissionChecker(mVcnContext.getContext()); } private void enforcePrimaryUser() { @@ -440,12 +458,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { // TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active // VCN. - final VcnSafemodeCallbackImpl safemodeCallback = - new VcnSafemodeCallbackImpl(subscriptionGroup); + final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup); final Vcn newInstance = - mDeps.newVcn( - mVcnContext, subscriptionGroup, config, mLastSnapshot, safemodeCallback); + mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback); mVcns.put(subscriptionGroup, newInstance); // Now that a new VCN has started, notify all registered listeners to refresh their @@ -551,6 +567,14 @@ public class VcnManagementService extends IVcnManagementService.Stub { } } + /** Get current VcnStatusCallbacks for testing purposes. */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + public Map<IBinder, VcnStatusCallbackInfo> getAllStatusCallbacks() { + synchronized (mLock) { + return Collections.unmodifiableMap(mRegisteredStatusCallbacks); + } + } + /** Binder death recipient used to remove a registered policy listener. */ private class PolicyListenerBinderDeath implements Binder.DeathRecipient { @NonNull private final IVcnUnderlyingNetworkPolicyListener mListener; @@ -641,40 +665,167 @@ public class VcnManagementService extends IVcnManagementService.Stub { } boolean isVcnManagedNetwork = false; + boolean isRestrictedCarrierWifi = false; if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { synchronized (mLock) { ParcelUuid subGroup = mLastSnapshot.getGroupForSubId(subId); Vcn vcn = mVcns.get(subGroup); - if (vcn != null && vcn.isActive()) { - isVcnManagedNetwork = true; + if (vcn != null) { + if (vcn.isActive()) { + isVcnManagedNetwork = true; + } + + if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + // Carrier WiFi always restricted if VCN exists (even in safe mode). + isRestrictedCarrierWifi = true; + } } } } + if (isVcnManagedNetwork) { networkCapabilities.removeCapability( NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); } + if (isRestrictedCarrierWifi) { + networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + } + return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities); } - /** Callback for signalling when a Vcn has entered Safemode. */ - public interface VcnSafemodeCallback { - /** Called by a Vcn to signal that it has entered Safemode. */ - void onEnteredSafemode(); + /** Binder death recipient used to remove registered VcnStatusCallbacks. */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + class VcnStatusCallbackInfo implements Binder.DeathRecipient { + @NonNull final ParcelUuid mSubGroup; + @NonNull final IVcnStatusCallback mCallback; + @NonNull final String mPkgName; + final int mUid; + + private VcnStatusCallbackInfo( + @NonNull ParcelUuid subGroup, + @NonNull IVcnStatusCallback callback, + @NonNull String pkgName, + int uid) { + mSubGroup = subGroup; + mCallback = callback; + mPkgName = pkgName; + mUid = uid; + } + + @Override + public void binderDied() { + Log.e(TAG, "app died without unregistering VcnStatusCallback"); + unregisterVcnStatusCallback(mCallback); + } } - /** VcnSafemodeCallback is used by Vcns to notify VcnManagementService on entering Safemode. */ - private class VcnSafemodeCallbackImpl implements VcnSafemodeCallback { + /** Registers the provided callback for receiving VCN status updates. */ + @Override + public void registerVcnStatusCallback( + @NonNull ParcelUuid subGroup, + @NonNull IVcnStatusCallback callback, + @NonNull String opPkgName) { + final int callingUid = mDeps.getBinderCallingUid(); + final long identity = Binder.clearCallingIdentity(); + try { + requireNonNull(subGroup, "subGroup must not be null"); + requireNonNull(callback, "callback must not be null"); + requireNonNull(opPkgName, "opPkgName must not be null"); + + mContext.getSystemService(AppOpsManager.class).checkPackage(callingUid, opPkgName); + + final IBinder cbBinder = callback.asBinder(); + final VcnStatusCallbackInfo cbInfo = + new VcnStatusCallbackInfo( + subGroup, callback, opPkgName, mDeps.getBinderCallingUid()); + + try { + cbBinder.linkToDeath(cbInfo, 0 /* flags */); + } catch (RemoteException e) { + // Remote binder already died - don't add to mRegisteredStatusCallbacks and exit + return; + } + + synchronized (mLock) { + if (mRegisteredStatusCallbacks.containsKey(cbBinder)) { + throw new IllegalStateException( + "Attempting to register a callback that is already in use"); + } + + mRegisteredStatusCallbacks.put(cbBinder, cbInfo); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + /** Unregisters the provided callback from receiving future VCN status updates. */ + @Override + public void unregisterVcnStatusCallback(@NonNull IVcnStatusCallback callback) { + final long identity = Binder.clearCallingIdentity(); + try { + requireNonNull(callback, "callback must not be null"); + + final IBinder cbBinder = callback.asBinder(); + synchronized (mLock) { + VcnStatusCallbackInfo cbInfo = mRegisteredStatusCallbacks.remove(cbBinder); + + if (cbInfo != null) { + cbBinder.unlinkToDeath(cbInfo, 0 /* flags */); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + // TODO(b/180452282): Make name more generic and implement directly with VcnManagementService + /** Callback for Vcn signals sent up to VcnManagementService. */ + public interface VcnCallback { + /** Called by a Vcn to signal that it has entered safe mode. */ + void onEnteredSafeMode(); + + /** Called by a Vcn to signal that an error occurred. */ + void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable String exceptionClass, + @Nullable String exceptionMessage); + } + + /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */ + private class VcnCallbackImpl implements VcnCallback { @NonNull private final ParcelUuid mSubGroup; - private VcnSafemodeCallbackImpl(@NonNull final ParcelUuid subGroup) { + private VcnCallbackImpl(@NonNull final ParcelUuid subGroup) { mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup"); } + private boolean isCallbackPermissioned(@NonNull VcnStatusCallbackInfo cbInfo) { + if (!mSubGroup.equals(cbInfo.mSubGroup)) { + return false; + } + + if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup( + mSubGroup, cbInfo.mPkgName)) { + return false; + } + + if (!mLocationPermissionChecker.checkLocationPermission( + cbInfo.mPkgName, + "VcnStatusCallback" /* featureId */, + cbInfo.mUid, + null /* message */)) { + return false; + } + return true; + } + @Override - public void onEnteredSafemode() { + public void onEnteredSafeMode() { synchronized (mLock) { // Ignore if this subscription group doesn't exist anymore if (!mVcns.containsKey(mSubGroup)) { @@ -682,6 +833,40 @@ public class VcnManagementService extends IVcnManagementService.Stub { } notifyAllPolicyListenersLocked(); + + // Notify all registered StatusCallbacks for this subGroup + for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) { + if (isCallbackPermissioned(cbInfo)) { + Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode()); + } + } + } + } + + @Override + public void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable String exceptionClass, + @Nullable String exceptionMessage) { + synchronized (mLock) { + // Ignore if this subscription group doesn't exist anymore + if (!mVcns.containsKey(mSubGroup)) { + return; + } + + // Notify all registered StatusCallbacks for this subGroup + for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) { + if (isCallbackPermissioned(cbInfo)) { + Binder.withCleanCallingIdentity( + () -> + cbInfo.mCallback.onGatewayConnectionError( + networkCapabilities, + errorCode, + exceptionClass, + exceptionMessage)); + } + } } } } diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java new file mode 100644 index 000000000000..5d89bf1b1d82 --- /dev/null +++ b/services/core/java/com/android/server/VpnManagerService.java @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static android.Manifest.permission.NETWORK_STACK; + +import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.INetd; +import android.net.IVpnManager; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkStack; +import android.net.UnderlyingNetworkInfo; +import android.net.Uri; +import android.net.VpnManager; +import android.net.VpnService; +import android.net.util.NetdService; +import android.os.Binder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.INetworkManagementService; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.os.UserManager; +import android.security.Credentials; +import android.security.KeyStore; +import android.text.TextUtils; +import android.util.Log; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.LegacyVpnInfo; +import com.android.internal.net.VpnConfig; +import com.android.internal.net.VpnProfile; +import com.android.internal.util.DumpUtils; +import com.android.internal.util.IndentingPrintWriter; +import com.android.server.connectivity.Vpn; +import com.android.server.net.LockdownVpnTracker; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.List; + +/** + * Service that tracks and manages VPNs, and backs the VpnService and VpnManager APIs. + * @hide + */ +public class VpnManagerService extends IVpnManager.Stub { + private static final String TAG = VpnManagerService.class.getSimpleName(); + + @VisibleForTesting + protected final HandlerThread mHandlerThread; + private final Handler mHandler; + + private final Context mContext; + private final Context mUserAllContext; + + private final Dependencies mDeps; + + private final ConnectivityManager mCm; + private final KeyStore mKeyStore; + private final INetworkManagementService mNMS; + private final INetd mNetd; + private final UserManager mUserManager; + + @VisibleForTesting + @GuardedBy("mVpns") + protected final SparseArray<Vpn> mVpns = new SparseArray<>(); + + // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by + // a direct call to LockdownVpnTracker.isEnabled(). + @GuardedBy("mVpns") + private boolean mLockdownEnabled; + @GuardedBy("mVpns") + private LockdownVpnTracker mLockdownTracker; + + /** + * Dependencies of VpnManager, for injection in tests. + */ + @VisibleForTesting + public static class Dependencies { + /** Returns the calling UID of an IPC. */ + public int getCallingUid() { + return Binder.getCallingUid(); + } + + /** Creates a HandlerThread to be used by this class. */ + public HandlerThread makeHandlerThread() { + return new HandlerThread("VpnManagerService"); + } + + /** Returns the KeyStore instance to be used by this class. */ + public KeyStore getKeyStore() { + return KeyStore.getInstance(); + } + + public INetd getNetd() { + return NetdService.getInstance(); + } + + public INetworkManagementService getINetworkManagementService() { + return INetworkManagementService.Stub.asInterface( + ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); + } + } + + public VpnManagerService(Context context, Dependencies deps) { + mContext = context; + mDeps = deps; + mHandlerThread = mDeps.makeHandlerThread(); + mHandlerThread.start(); + mHandler = mHandlerThread.getThreadHandler(); + mKeyStore = mDeps.getKeyStore(); + mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); + mCm = mContext.getSystemService(ConnectivityManager.class); + mNMS = mDeps.getINetworkManagementService(); + mNetd = mDeps.getNetd(); + mUserManager = mContext.getSystemService(UserManager.class); + registerReceivers(); + log("VpnManagerService starting up"); + } + + /** Creates a new VpnManagerService */ + public static VpnManagerService create(Context context) { + return new VpnManagerService(context, new Dependencies()); + } + + /** Informs the service that the system is ready. */ + public void systemReady() { + // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait + // for user to unlock device too. + updateLockdownVpn(); + } + + @Override + /** Dumps service state. */ + protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, + @Nullable String[] args) { + if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; + IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); + pw.println("VPNs:"); + pw.increaseIndent(); + synchronized (mVpns) { + for (int i = 0; i < mVpns.size(); i++) { + pw.println(mVpns.keyAt(i) + ": " + mVpns.valueAt(i).getPackage()); + } + pw.decreaseIndent(); + } + } + + /** + * Prepare for a VPN application. + * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, + * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. + * + * @param oldPackage Package name of the application which currently controls VPN, which will + * be replaced. If there is no such application, this should should either be + * {@code null} or {@link VpnConfig.LEGACY_VPN}. + * @param newPackage Package name of the application which should gain control of VPN, or + * {@code null} to disable. + * @param userId User for whom to prepare the new VPN. + * + * @hide + */ + @Override + public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, + int userId) { + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + throwIfLockdownEnabled(); + Vpn vpn = mVpns.get(userId); + if (vpn != null) { + return vpn.prepare(oldPackage, newPackage, VpnManager.TYPE_VPN_SERVICE); + } else { + return false; + } + } + } + + /** + * Set whether the VPN package has the ability to launch VPNs without user intervention. This + * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} + * class. If the caller is not {@code userId}, {@link + * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. + * + * @param packageName The package for which authorization state should change. + * @param userId User for whom {@code packageName} is installed. + * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN + * permissions should be granted. When unauthorizing an app, {@link + * VpnManager.TYPE_VPN_NONE} should be used. + * @hide + */ + @Override + public void setVpnPackageAuthorization( + String packageName, int userId, @VpnManager.VpnType int vpnType) { + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn != null) { + vpn.setPackageAuthorization(packageName, vpnType); + } + } + } + + /** + * Configure a TUN interface and return its file descriptor. Parameters + * are encoded and opaque to this class. This method is used by VpnBuilder + * and not available in VpnManager. Permissions are checked in + * Vpn class. + * @hide + */ + @Override + public ParcelFileDescriptor establishVpn(VpnConfig config) { + int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + throwIfLockdownEnabled(); + return mVpns.get(user).establish(config); + } + } + + @Override + public boolean addVpnAddress(String address, int prefixLength) { + int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + throwIfLockdownEnabled(); + return mVpns.get(user).addAddress(address, prefixLength); + } + } + + @Override + public boolean removeVpnAddress(String address, int prefixLength) { + int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + throwIfLockdownEnabled(); + return mVpns.get(user).removeAddress(address, prefixLength); + } + } + + @Override + public boolean setUnderlyingNetworksForVpn(Network[] networks) { + int user = UserHandle.getUserId(mDeps.getCallingUid()); + final boolean success; + synchronized (mVpns) { + success = mVpns.get(user).setUnderlyingNetworks(networks); + } + return success; + } + + /** + * Stores the given VPN profile based on the provisioning package name. + * + * <p>If there is already a VPN profile stored for the provisioning package, this call will + * overwrite the profile. + * + * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed + * exclusively by the Settings app, and passed into the platform at startup time. + * + * @return {@code true} if user consent has already been granted, {@code false} otherwise. + * @hide + */ + @Override + public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) { + final int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore); + } + } + + /** + * Deletes the stored VPN profile for the provisioning package + * + * <p>If there are no profiles for the given package, this method will silently succeed. + * + * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed + * exclusively by the Settings app, and passed into the platform at startup time. + * + * @hide + */ + @Override + public void deleteVpnProfile(@NonNull String packageName) { + final int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + mVpns.get(user).deleteVpnProfile(packageName, mKeyStore); + } + } + + /** + * Starts the VPN based on the stored profile for the given package + * + * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed + * exclusively by the Settings app, and passed into the platform at startup time. + * + * @throws IllegalArgumentException if no profile was found for the given package name. + * @hide + */ + @Override + public void startVpnProfile(@NonNull String packageName) { + final int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + throwIfLockdownEnabled(); + mVpns.get(user).startVpnProfile(packageName, mKeyStore); + } + } + + /** + * Stops the Platform VPN if the provided package is running one. + * + * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed + * exclusively by the Settings app, and passed into the platform at startup time. + * + * @hide + */ + @Override + public void stopVpnProfile(@NonNull String packageName) { + final int user = UserHandle.getUserId(mDeps.getCallingUid()); + synchronized (mVpns) { + mVpns.get(user).stopVpnProfile(packageName); + } + } + + /** + * Start legacy VPN, controlling native daemons as needed. Creates a + * secondary thread to perform connection work, returning quickly. + */ + @Override + public void startLegacyVpn(VpnProfile profile) { + int user = UserHandle.getUserId(mDeps.getCallingUid()); + final LinkProperties egress = mCm.getActiveLinkProperties(); + if (egress == null) { + throw new IllegalStateException("Missing active network connection"); + } + synchronized (mVpns) { + throwIfLockdownEnabled(); + mVpns.get(user).startLegacyVpn(profile, mKeyStore, null /* underlying */, egress); + } + } + + /** + * Return the information of the ongoing legacy VPN. This method is used + * by VpnSettings and not available in ConnectivityManager. Permissions + * are checked in Vpn class. + */ + @Override + public LegacyVpnInfo getLegacyVpnInfo(int userId) { + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + return mVpns.get(userId).getLegacyVpnInfo(); + } + } + + /** + * Returns the information of the ongoing VPN for {@code userId}. This method is used by + * VpnDialogs and not available in ConnectivityManager. + * Permissions are checked in Vpn class. + * @hide + */ + @Override + public VpnConfig getVpnConfig(int userId) { + enforceCrossUserPermission(userId); + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn != null) { + return vpn.getVpnConfig(); + } else { + return null; + } + } + } + + private boolean isLockdownVpnEnabled() { + return mKeyStore.contains(Credentials.LOCKDOWN_VPN); + } + + @Override + public boolean updateLockdownVpn() { + // Allow the system UID for the system server and for Settings. + // Also, for unit tests, allow the process that ConnectivityService is running in. + if (mDeps.getCallingUid() != Process.SYSTEM_UID + && Binder.getCallingPid() != Process.myPid()) { + logw("Lockdown VPN only available to system process or AID_SYSTEM"); + return false; + } + + synchronized (mVpns) { + // Tear down existing lockdown if profile was removed + mLockdownEnabled = isLockdownVpnEnabled(); + if (!mLockdownEnabled) { + setLockdownTracker(null); + return true; + } + + byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN); + if (profileTag == null) { + loge("Lockdown VPN configured but cannot be read from keystore"); + return false; + } + String profileName = new String(profileTag); + final VpnProfile profile = VpnProfile.decode( + profileName, mKeyStore.get(Credentials.VPN + profileName)); + if (profile == null) { + loge("Lockdown VPN configured invalid profile " + profileName); + setLockdownTracker(null); + return true; + } + int user = UserHandle.getUserId(mDeps.getCallingUid()); + Vpn vpn = mVpns.get(user); + if (vpn == null) { + logw("VPN for user " + user + " not ready yet. Skipping lockdown"); + return false; + } + setLockdownTracker( + new LockdownVpnTracker(mContext, mHandler, mKeyStore, vpn, profile)); + } + + return true; + } + + /** + * Internally set new {@link LockdownVpnTracker}, shutting down any existing + * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown. + */ + @GuardedBy("mVpns") + private void setLockdownTracker(LockdownVpnTracker tracker) { + // Shutdown any existing tracker + final LockdownVpnTracker existing = mLockdownTracker; + // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the + // necessary onBlockedStatusChanged callbacks. + mLockdownTracker = null; + if (existing != null) { + existing.shutdown(); + } + + if (tracker != null) { + mLockdownTracker = tracker; + mLockdownTracker.init(); + } + } + + /** + * Throws if there is any currently running, always-on Legacy VPN. + * + * <p>The LockdownVpnTracker and mLockdownEnabled both track whether an always-on Legacy VPN is + * running across the entire system. Tracking for app-based VPNs is done on a per-user, + * per-package basis in Vpn.java + */ + @GuardedBy("mVpns") + private void throwIfLockdownEnabled() { + if (mLockdownEnabled) { + throw new IllegalStateException("Unavailable in lockdown mode"); + } + } + + /** + * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform + * some setup and then call {@code establish()} to connect. + * + * @return {@code true} if the service was started, the service was already connected, or there + * was no always-on VPN to start. {@code false} otherwise. + */ + private boolean startAlwaysOnVpn(int userId) { + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + // Shouldn't happen as all code paths that point here should have checked the Vpn + // exists already. + Log.wtf(TAG, "User " + userId + " has no Vpn configuration"); + return false; + } + + return vpn.startAlwaysOnVpn(mKeyStore); + } + } + + @Override + public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) { + enforceSettingsPermission(); + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + logw("User " + userId + " has no Vpn configuration"); + return false; + } + return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore); + } + } + + @Override + public boolean setAlwaysOnVpnPackage( + int userId, String packageName, boolean lockdown, List<String> lockdownAllowlist) { + enforceControlAlwaysOnVpnPermission(); + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + // Can't set always-on VPN if legacy VPN is already in lockdown mode. + if (isLockdownVpnEnabled()) { + return false; + } + + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + logw("User " + userId + " has no Vpn configuration"); + return false; + } + if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownAllowlist, mKeyStore)) { + return false; + } + if (!startAlwaysOnVpn(userId)) { + vpn.setAlwaysOnPackage(null, false, null, mKeyStore); + return false; + } + } + return true; + } + + @Override + public String getAlwaysOnVpnPackage(int userId) { + enforceControlAlwaysOnVpnPermission(); + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + logw("User " + userId + " has no Vpn configuration"); + return null; + } + return vpn.getAlwaysOnPackage(); + } + } + + @Override + public boolean isVpnLockdownEnabled(int userId) { + enforceControlAlwaysOnVpnPermission(); + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + logw("User " + userId + " has no Vpn configuration"); + return false; + } + return vpn.getLockdown(); + } + } + + @Override + public List<String> getVpnLockdownAllowlist(int userId) { + enforceControlAlwaysOnVpnPermission(); + enforceCrossUserPermission(userId); + + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn == null) { + logw("User " + userId + " has no Vpn configuration"); + return null; + } + return vpn.getLockdownAllowlist(); + } + } + + @GuardedBy("mVpns") + private Vpn getVpnIfOwner() { + return getVpnIfOwner(mDeps.getCallingUid()); + } + + // TODO: stop calling into Vpn.java and get this information from data in this class. + @GuardedBy("mVpns") + private Vpn getVpnIfOwner(int uid) { + final int user = UserHandle.getUserId(uid); + + final Vpn vpn = mVpns.get(user); + if (vpn == null) { + return null; + } else { + final UnderlyingNetworkInfo info = vpn.getUnderlyingNetworkInfo(); + return (info == null || info.ownerUid != uid) ? null : vpn; + } + } + + private void registerReceivers() { + // Set up the listener for user state for creating user VPNs. + // Should run on mHandler to avoid any races. + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_USER_STARTED); + intentFilter.addAction(Intent.ACTION_USER_STOPPED); + intentFilter.addAction(Intent.ACTION_USER_ADDED); + intentFilter.addAction(Intent.ACTION_USER_REMOVED); + intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); + + mUserAllContext.registerReceiver( + mIntentReceiver, + intentFilter, + null /* broadcastPermission */, + mHandler); + mContext.createContextAsUser(UserHandle.SYSTEM, 0 /* flags */).registerReceiver( + mUserPresentReceiver, + new IntentFilter(Intent.ACTION_USER_PRESENT), + null /* broadcastPermission */, + mHandler /* scheduler */); + + // Listen to package add and removal events for all users. + intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); + intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + intentFilter.addDataScheme("package"); + mUserAllContext.registerReceiver( + mIntentReceiver, + intentFilter, + null /* broadcastPermission */, + mHandler); + + // Listen to lockdown VPN reset. + intentFilter = new IntentFilter(); + intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET); + mUserAllContext.registerReceiver( + mIntentReceiver, intentFilter, NETWORK_STACK, mHandler); + } + + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + ensureRunningOnHandlerThread(); + final String action = intent.getAction(); + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + final Uri packageData = intent.getData(); + final String packageName = + packageData != null ? packageData.getSchemeSpecificPart() : null; + + if (LockdownVpnTracker.ACTION_LOCKDOWN_RESET.equals(action)) { + onVpnLockdownReset(); + } + + // UserId should be filled for below intents, check the existence. + if (userId == UserHandle.USER_NULL) return; + + if (Intent.ACTION_USER_STARTED.equals(action)) { + onUserStarted(userId); + } else if (Intent.ACTION_USER_STOPPED.equals(action)) { + onUserStopped(userId); + } else if (Intent.ACTION_USER_ADDED.equals(action)) { + onUserAdded(userId); + } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + onUserRemoved(userId); + } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { + onUserUnlocked(userId); + } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) { + onPackageReplaced(packageName, uid); + } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { + final boolean isReplacing = intent.getBooleanExtra( + Intent.EXTRA_REPLACING, false); + onPackageRemoved(packageName, uid, isReplacing); + } else { + Log.wtf(TAG, "received unexpected intent: " + action); + } + } + }; + + private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + ensureRunningOnHandlerThread(); + // Try creating lockdown tracker, since user present usually means + // unlocked keystore. + updateLockdownVpn(); + // Use the same context that registered receiver before to unregister it. Because use + // different context to unregister receiver will cause exception. + context.unregisterReceiver(this); + } + }; + + private void onUserStarted(int userId) { + synchronized (mVpns) { + Vpn userVpn = mVpns.get(userId); + if (userVpn != null) { + loge("Starting user already has a VPN"); + return; + } + userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore); + mVpns.put(userId, userVpn); + if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { + updateLockdownVpn(); + } + } + } + + private void onUserStopped(int userId) { + synchronized (mVpns) { + Vpn userVpn = mVpns.get(userId); + if (userVpn == null) { + loge("Stopped user has no VPN"); + return; + } + userVpn.onUserStopped(); + mVpns.delete(userId); + } + } + + @Override + public boolean isCallerCurrentAlwaysOnVpnApp() { + synchronized (mVpns) { + Vpn vpn = getVpnIfOwner(); + return vpn != null && vpn.getAlwaysOn(); + } + } + + @Override + public boolean isCallerCurrentAlwaysOnVpnLockdownApp() { + synchronized (mVpns) { + Vpn vpn = getVpnIfOwner(); + return vpn != null && vpn.getLockdown(); + } + } + + + private void onUserAdded(int userId) { + synchronized (mVpns) { + final int vpnsSize = mVpns.size(); + for (int i = 0; i < vpnsSize; i++) { + Vpn vpn = mVpns.valueAt(i); + vpn.onUserAdded(userId); + } + } + } + + private void onUserRemoved(int userId) { + synchronized (mVpns) { + final int vpnsSize = mVpns.size(); + for (int i = 0; i < vpnsSize; i++) { + Vpn vpn = mVpns.valueAt(i); + vpn.onUserRemoved(userId); + } + } + } + + private void onPackageReplaced(String packageName, int uid) { + if (TextUtils.isEmpty(packageName) || uid < 0) { + Log.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid); + return; + } + final int userId = UserHandle.getUserId(uid); + synchronized (mVpns) { + final Vpn vpn = mVpns.get(userId); + if (vpn == null) { + return; + } + // Legacy always-on VPN won't be affected since the package name is not set. + if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) { + log("Restarting always-on VPN package " + packageName + " for user " + + userId); + vpn.startAlwaysOnVpn(mKeyStore); + } + } + } + + private void onPackageRemoved(String packageName, int uid, boolean isReplacing) { + if (TextUtils.isEmpty(packageName) || uid < 0) { + Log.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid); + return; + } + + final int userId = UserHandle.getUserId(uid); + synchronized (mVpns) { + final Vpn vpn = mVpns.get(userId); + if (vpn == null) { + return; + } + // Legacy always-on VPN won't be affected since the package name is not set. + if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { + log("Removing always-on VPN package " + packageName + " for user " + + userId); + vpn.setAlwaysOnPackage(null, false, null, mKeyStore); + } + } + } + + private void onUserUnlocked(int userId) { + synchronized (mVpns) { + // User present may be sent because of an unlock, which might mean an unlocked keystore. + if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { + updateLockdownVpn(); + } else { + startAlwaysOnVpn(userId); + } + } + } + + private void onVpnLockdownReset() { + synchronized (mVpns) { + if (mLockdownTracker != null) mLockdownTracker.reset(); + } + } + + + @Override + public void factoryReset() { + enforceSettingsPermission(); + + if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET) + || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { + return; + } + + // Remove always-on package + final int userId = UserHandle.getCallingUserId(); + synchronized (mVpns) { + final String alwaysOnPackage = getAlwaysOnVpnPackage(userId); + if (alwaysOnPackage != null) { + setAlwaysOnVpnPackage(userId, null, false, null); + setVpnPackageAuthorization(alwaysOnPackage, userId, VpnManager.TYPE_VPN_NONE); + } + + // Turn Always-on VPN off + if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { + final long ident = Binder.clearCallingIdentity(); + try { + mKeyStore.delete(Credentials.LOCKDOWN_VPN); + mLockdownEnabled = false; + setLockdownTracker(null); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + // Turn VPN off + VpnConfig vpnConfig = getVpnConfig(userId); + if (vpnConfig != null) { + if (vpnConfig.legacy) { + prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); + } else { + // Prevent this app (packagename = vpnConfig.user) from initiating + // VPN connections in the future without user intervention. + setVpnPackageAuthorization( + vpnConfig.user, userId, VpnManager.TYPE_VPN_NONE); + + prepareVpn(null, VpnConfig.LEGACY_VPN, userId); + } + } + } + } + + private void ensureRunningOnHandlerThread() { + if (mHandler.getLooper().getThread() != Thread.currentThread()) { + throw new IllegalStateException( + "Not running on VpnManagerService thread: " + + Thread.currentThread().getName()); + } + } + + private void enforceControlAlwaysOnVpnPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, + "VpnManagerService"); + } + + /** + * Require that the caller is either in the same user or has appropriate permission to interact + * across users. + * + * @param userId Target user for whatever operation the current IPC is supposed to perform. + */ + private void enforceCrossUserPermission(int userId) { + if (userId == UserHandle.getCallingUserId()) { + // Not a cross-user call. + return; + } + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "VpnManagerService"); + } + + private void enforceSettingsPermission() { + enforceAnyPermissionOf(mContext, + android.Manifest.permission.NETWORK_SETTINGS, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + + private static void log(String s) { + Log.d(TAG, s); + } + + private static void logw(String s) { + Log.w(TAG, s); + } + + private static void loge(String s) { + Log.e(TAG, s); + } +} diff --git a/services/core/java/com/android/server/accounts/OWNERS b/services/core/java/com/android/server/accounts/OWNERS index ea5fd36702f9..8dcc04a27af6 100644 --- a/services/core/java/com/android/server/accounts/OWNERS +++ b/services/core/java/com/android/server/accounts/OWNERS @@ -3,7 +3,6 @@ dementyev@google.com sandrakwan@google.com hackbod@google.com svetoslavganov@google.com -moltmann@google.com fkupolov@google.com yamasani@google.com omakoto@google.com diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8f1e4e945bcb..900871dfbbb4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -364,6 +364,7 @@ import com.android.server.compat.PlatformCompat; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; +import com.android.server.os.NativeTombstoneManager; import com.android.server.pm.Installer; import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.uri.GrantUri; @@ -10410,6 +10411,9 @@ public class ActivityManagerService extends IActivityManager.Stub mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, "getHistoricalProcessExitReasons", null); + NativeTombstoneManager tombstoneService = LocalServices.getService( + NativeTombstoneManager.class); + final ArrayList<ApplicationExitInfo> results = new ArrayList<ApplicationExitInfo>(); if (!TextUtils.isEmpty(packageName)) { final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid, @@ -10417,11 +10421,13 @@ public class ActivityManagerService extends IActivityManager.Stub if (uid != Process.INVALID_UID) { mProcessList.mAppExitInfoTracker.getExitInfo( packageName, uid, pid, maxNum, results); + tombstoneService.collectTombstones(results, uid, pid, maxNum); } } else { // If no package name is given, use the caller's uid as the filter uid. mProcessList.mAppExitInfoTracker.getExitInfo( packageName, callingUid, pid, maxNum, results); + tombstoneService.collectTombstones(results, callingUid, pid, maxNum); } return new ParceledListSlice<ApplicationExitInfo>(results); @@ -13318,6 +13324,7 @@ public class ActivityManagerService extends IActivityManager.Stub long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; + long[] memtrackTmp = new long[4]; long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length]; long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length]; @@ -13330,6 +13337,8 @@ public class ActivityManagerService extends IActivityManager.Stub long totalRss = 0; long cachedPss = 0; long cachedSwapPss = 0; + long totalMemtrackGraphics = 0; + long totalMemtrackGl = 0; boolean hasSwapPss = false; Debug.MemoryInfo mi = null; @@ -13352,6 +13361,8 @@ public class ActivityManagerService extends IActivityManager.Stub final int reportType; final long startTime; final long endTime; + long memtrackGraphics = 0; + long memtrackGl = 0; if (opts.dumpDetails || (!brief && !opts.oomOnly)) { reportType = ProcessStats.ADD_PSS_EXTERNAL_SLOW; startTime = SystemClock.currentThreadTimeMillis(); @@ -13363,7 +13374,7 @@ public class ActivityManagerService extends IActivityManager.Stub } else { reportType = ProcessStats.ADD_PSS_EXTERNAL; startTime = SystemClock.currentThreadTimeMillis(); - long pss = Debug.getPss(pid, tmpLong, null); + long pss = Debug.getPss(pid, tmpLong, memtrackTmp); if (pss == 0) { continue; } @@ -13371,6 +13382,8 @@ public class ActivityManagerService extends IActivityManager.Stub endTime = SystemClock.currentThreadTimeMillis(); mi.dalvikPrivateDirty = (int) tmpLong[0]; mi.dalvikRss = (int) tmpLong[2]; + memtrackGraphics = memtrackTmp[1]; + memtrackGl = memtrackTmp[2]; } if (!opts.isCheckinRequest && opts.dumpDetails) { pw.println("\n** MEMINFO in pid " + pid + " [" + r.processName + "] **"); @@ -13435,6 +13448,8 @@ public class ActivityManagerService extends IActivityManager.Stub totalPss += myTotalPss; totalSwapPss += myTotalSwapPss; totalRss += myTotalRss; + totalMemtrackGraphics += memtrackGraphics; + totalMemtrackGl += memtrackGl; MemItem pssItem = new MemItem(r.processName + " (pid " + pid + (hasActivities ? " / activities)" : ")"), r.processName, myTotalPss, myTotalSwapPss, myTotalRss, pid, hasActivities); @@ -13500,6 +13515,8 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=0; i<N; i++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) { + long memtrackGraphics = 0; + long memtrackGl = 0; if (mi == null) { mi = new Debug.MemoryInfo(); } @@ -13508,13 +13525,15 @@ public class ActivityManagerService extends IActivityManager.Stub continue; } } else { - long pss = Debug.getPss(st.pid, tmpLong, null); + long pss = Debug.getPss(st.pid, tmpLong, memtrackTmp); if (pss == 0) { continue; } mi.nativePss = (int) pss; mi.nativePrivateDirty = (int) tmpLong[0]; mi.nativeRss = (int) tmpLong[2]; + memtrackGraphics = memtrackTmp[1]; + memtrackGl = memtrackTmp[2]; } final long myTotalPss = mi.getTotalPss(); @@ -13524,6 +13543,8 @@ public class ActivityManagerService extends IActivityManager.Stub totalSwapPss += myTotalSwapPss; totalRss += myTotalRss; nativeProcTotalPss += myTotalPss; + totalMemtrackGraphics += memtrackGraphics; + totalMemtrackGl += memtrackGl; MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", st.name, myTotalPss, mi.getSummaryTotalSwapPss(), myTotalRss, @@ -13720,13 +13741,13 @@ public class ActivityManagerService extends IActivityManager.Stub long kernelUsed = memInfo.getKernelUsedSizeKb(); final long ionHeap = Debug.getIonHeapsSizeKb(); final long ionPool = Debug.getIonPoolsSizeKb(); + final long dmabufMapped = Debug.getDmabufMappedSizeKb(); if (ionHeap >= 0 && ionPool >= 0) { - final long ionMapped = Debug.getIonMappedSizeKb(); - final long ionUnmapped = ionHeap - ionMapped; + final long ionUnmapped = ionHeap - dmabufMapped; pw.print(" ION: "); pw.print(stringifyKBSize(ionHeap + ionPool)); pw.print(" ("); - pw.print(stringifyKBSize(ionMapped)); + pw.print(stringifyKBSize(dmabufMapped)); pw.print(" mapped + "); pw.print(stringifyKBSize(ionUnmapped)); pw.print(" unmapped + "); @@ -13735,11 +13756,61 @@ public class ActivityManagerService extends IActivityManager.Stub // 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; + } else { + final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb(); + if (totalExportedDmabuf >= 0) { + final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped; + pw.print("DMA-BUF: "); + pw.print(stringifyKBSize(totalExportedDmabuf)); + pw.print(" ("); + pw.print(stringifyKBSize(dmabufMapped)); + pw.print(" mapped + "); + pw.print(stringifyKBSize(dmabufUnmapped)); + pw.println(" unmapped)"); + // Account unmapped dmabufs as part of kernel memory allocations + kernelUsed += dmabufUnmapped; + // Replace memtrack HAL reported Graphics category with mapped dmabufs + totalPss -= totalMemtrackGraphics; + totalPss += dmabufMapped; + } + + // totalDmabufHeapExported is included in totalExportedDmabuf above and hence do not + // need to be added to kernelUsed. + final long totalDmabufHeapExported = Debug.getDmabufHeapTotalExportedKb(); + if (totalDmabufHeapExported >= 0) { + pw.print("DMA-BUF Heaps: "); + pw.println(stringifyKBSize(totalDmabufHeapExported)); + } + + final long totalDmabufHeapPool = Debug.getDmabufHeapPoolsSizeKb(); + if (totalDmabufHeapPool >= 0) { + pw.print("DMA-BUF Heaps pool: "); + pw.println(stringifyKBSize(totalDmabufHeapPool)); + } } final long gpuUsage = Debug.getGpuTotalUsageKb(); if (gpuUsage >= 0) { - pw.print(" GPU: "); pw.println(stringifyKBSize(gpuUsage)); + final long gpuDmaBufUsage = Debug.getGpuDmaBufUsageKb(); + if (gpuDmaBufUsage >= 0) { + final long gpuPrivateUsage = gpuUsage - gpuDmaBufUsage; + pw.print(" GPU: "); + pw.print(stringifyKBSize(gpuUsage)); + pw.print(" ("); + pw.print(stringifyKBSize(gpuDmaBufUsage)); + pw.print(" dmabuf + "); + pw.print(stringifyKBSize(gpuPrivateUsage)); + pw.println(" private)"); + // Replace memtrack HAL reported GL category with private GPU allocations and + // account it as part of kernel memory allocations + totalPss -= totalMemtrackGl; + kernelUsed += gpuPrivateUsage; + } else { + pw.print(" GPU: "); pw.println(stringifyKBSize(gpuUsage)); + } } + + // Note: ION/DMA-BUF heap pools are reclaimable and hence, they are included as part of + // memInfo.getCachedSizeKb(). final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - kernelUsed - memInfo.getZramTotalSizeKb(); @@ -14343,7 +14414,7 @@ public class ActivityManagerService extends IActivityManager.Stub infoMap.put(mi.pid, mi); } updateCpuStatsNow(); - long[] memtrackTmp = new long[1]; + long[] memtrackTmp = new long[4]; long[] swaptrackTmp = new long[2]; final List<ProcessCpuTracker.Stats> stats; // Get a list of Stats that have vsize > 0 @@ -14371,6 +14442,8 @@ public class ActivityManagerService extends IActivityManager.Stub long totalPss = 0; long totalSwapPss = 0; long totalMemtrack = 0; + long totalMemtrackGraphics = 0; + long totalMemtrackGl = 0; for (int i=0, N=memInfos.size(); i<N; i++) { ProcessMemInfo mi = memInfos.get(i); if (mi.pss == 0) { @@ -14381,6 +14454,8 @@ public class ActivityManagerService extends IActivityManager.Stub totalPss += mi.pss; totalSwapPss += mi.swapPss; totalMemtrack += mi.memtrack; + totalMemtrackGraphics += memtrackTmp[1]; + totalMemtrackGl += memtrackTmp[2]; } Collections.sort(memInfos, new Comparator<ProcessMemInfo>() { @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) { @@ -14539,25 +14614,74 @@ public class ActivityManagerService extends IActivityManager.Stub final long ionHeap = Debug.getIonHeapsSizeKb(); final long ionPool = Debug.getIonPoolsSizeKb(); if (ionHeap >= 0 && ionPool >= 0) { - final long ionMapped = Debug.getIonMappedSizeKb(); - final long ionUnmapped = ionHeap - ionMapped; memInfoBuilder.append(" ION: "); memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool)); memInfoBuilder.append("\n"); // 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; + } else { + final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb(); + if (totalExportedDmabuf >= 0) { + final long dmabufMapped = Debug.getDmabufMappedSizeKb(); + final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped; + memInfoBuilder.append("DMA-BUF: "); + memInfoBuilder.append(stringifyKBSize(totalExportedDmabuf)); + memInfoBuilder.append("\n"); + // Account unmapped dmabufs as part of kernel memory allocations + kernelUsed += dmabufUnmapped; + // Replace memtrack HAL reported Graphics category with mapped dmabufs + totalPss -= totalMemtrackGraphics; + totalPss += dmabufMapped; + } + + // These are included in the totalExportedDmabuf above and hence do not need to be added + // to kernelUsed. + final long totalExportedDmabufHeap = Debug.getDmabufHeapTotalExportedKb(); + if (totalExportedDmabufHeap >= 0) { + memInfoBuilder.append("DMA-BUF Heap: "); + memInfoBuilder.append(stringifyKBSize(totalExportedDmabufHeap)); + memInfoBuilder.append("\n"); + } + + final long totalDmabufHeapPool = Debug.getDmabufHeapPoolsSizeKb(); + if (totalDmabufHeapPool >= 0) { + memInfoBuilder.append("DMA-BUF Heaps pool: "); + memInfoBuilder.append(stringifyKBSize(totalDmabufHeapPool)); + memInfoBuilder.append("\n"); + } } + final long gpuUsage = Debug.getGpuTotalUsageKb(); if (gpuUsage >= 0) { - memInfoBuilder.append(" GPU: "); - memInfoBuilder.append(stringifyKBSize(gpuUsage)); - memInfoBuilder.append("\n"); + final long gpuDmaBufUsage = Debug.getGpuDmaBufUsageKb(); + if (gpuDmaBufUsage >= 0) { + final long gpuPrivateUsage = gpuUsage - gpuDmaBufUsage; + memInfoBuilder.append(" GPU: "); + memInfoBuilder.append(stringifyKBSize(gpuUsage)); + memInfoBuilder.append(" ("); + memInfoBuilder.append(stringifyKBSize(gpuDmaBufUsage)); + memInfoBuilder.append(" dmabuf + "); + memInfoBuilder.append(stringifyKBSize(gpuPrivateUsage)); + memInfoBuilder.append(" private)\n"); + // Replace memtrack HAL reported GL category with private GPU allocations and + // account it as part of kernel memory allocations + totalPss -= totalMemtrackGl; + kernelUsed += gpuPrivateUsage; + } else { + memInfoBuilder.append(" GPU: "); + memInfoBuilder.append(stringifyKBSize(gpuUsage)); + memInfoBuilder.append("\n"); + } + } memInfoBuilder.append(" Used RAM: "); memInfoBuilder.append(stringifyKBSize( totalPss - cachedPss + kernelUsed)); memInfoBuilder.append("\n"); + + // Note: ION/DMA-BUF heap pools are reclaimable and hence, they are included as part of + // memInfo.getCachedSizeKb(). memInfoBuilder.append(" Lost RAM: "); memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java index 374c215fc6d0..f2c1f554afde 100644 --- a/services/core/java/com/android/server/am/AppExitInfoTracker.java +++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java @@ -63,8 +63,10 @@ import com.android.internal.app.ProcessMap; import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.IoThread; +import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemServiceManager; +import com.android.server.os.NativeTombstoneManager; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -78,6 +80,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -770,6 +773,10 @@ public final class AppExitInfoTracker { * Helper function for shell command */ void clearHistoryProcessExitInfo(String packageName, int userId) { + NativeTombstoneManager tombstoneService = LocalServices.getService( + NativeTombstoneManager.class); + Optional<Integer> appId = Optional.empty(); + if (TextUtils.isEmpty(packageName)) { synchronized (mLock) { removeByUserIdLocked(userId); @@ -777,10 +784,13 @@ public final class AppExitInfoTracker { } else { final int uid = mService.mPackageManagerInt.getPackageUid(packageName, PackageManager.MATCH_ALL, userId); + appId = Optional.of(UserHandle.getAppId(uid)); synchronized (mLock) { removePackageLocked(packageName, uid, true, userId); } } + + tombstoneService.purge(Optional.of(userId), appId); schedulePersistProcessExitInfo(true); } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a2eea1348d5c..b7ecddced0c8 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -809,7 +809,8 @@ public final class BroadcastQueue { r.resultExtras, r.ordered, r.initialSticky, r.userId); // parallel broadcasts are fire-and-forget, not bookended by a call to // finishReceiverLocked(), so we manage their activity-start token here - if (r.allowBackgroundActivityStarts && !r.ordered) { + if (filter.receiverList.app != null + && r.allowBackgroundActivityStarts && !r.ordered) { postActivityStartTokenRemoval(filter.receiverList.app, r); } } diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index d98057dc87cc..33bdac270c53 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -23,9 +23,12 @@ import static android.content.Intent.EXTRA_REPLACING; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION; +import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityThread; import android.app.IActivityManager; import android.apphibernation.IAppHibernationService; import android.content.BroadcastReceiver; @@ -45,6 +48,8 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; +import android.provider.DeviceConfig.Properties; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; @@ -93,6 +98,9 @@ public final class AppHibernationService extends SystemService { private final HibernationStateDiskStore<GlobalLevelState> mGlobalLevelHibernationDiskStore; private final Injector mInjector; + @VisibleForTesting + boolean mIsServiceEnabled; + /** * Initializes the system service. * <p> @@ -139,6 +147,13 @@ public final class AppHibernationService extends SystemService { initializeGlobalHibernationStates(states); } } + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mIsServiceEnabled = isAppHibernationEnabled(); + DeviceConfig.addOnPropertiesChangedListener( + NAMESPACE_APP_HIBERNATION, + ActivityThread.currentApplication().getMainExecutor(), + this::onDeviceConfigChanged); + } } /** @@ -149,6 +164,10 @@ public final class AppHibernationService extends SystemService { * @return true if package is hibernating for the user */ boolean isHibernatingForUser(String packageName, int userId) { + if (!checkHibernationEnabled("isHibernatingForUser")) { + return false; + } + userId = handleIncomingUser(userId, "isHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user " @@ -174,6 +193,9 @@ public final class AppHibernationService extends SystemService { * @param packageName package to check */ boolean isHibernatingGlobally(String packageName) { + if (!checkHibernationEnabled("isHibernatingGlobally")) { + return false; + } synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); if (state == null) { @@ -192,6 +214,9 @@ public final class AppHibernationService extends SystemService { * @param isHibernating new hibernation state */ void setHibernatingForUser(String packageName, int userId, boolean isHibernating) { + if (!checkHibernationEnabled("setHibernatingForUser")) { + return; + } userId = handleIncomingUser(userId, "setHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user " @@ -229,6 +254,9 @@ public final class AppHibernationService extends SystemService { * @param isHibernating new hibernation state */ void setHibernatingGlobally(String packageName, boolean isHibernating) { + if (!checkHibernationEnabled("setHibernatingGlobally")) { + return; + } synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); if (state == null) { @@ -450,6 +478,15 @@ public final class AppHibernationService extends SystemService { } } + private void onDeviceConfigChanged(Properties properties) { + for (String key : properties.getKeyset()) { + if (TextUtils.equals(KEY_APP_HIBERNATION_ENABLED, key)) { + mIsServiceEnabled = isAppHibernationEnabled(); + break; + } + } + } + /** * Private helper method to get the real user id and enforce permission checks. * @@ -467,6 +504,13 @@ public final class AppHibernationService extends SystemService { } } + private boolean checkHibernationEnabled(String methodName) { + if (!mIsServiceEnabled) { + Slog.w(TAG, String.format("Attempted to call %s on unsupported device.", methodName)); + } + return mIsServiceEnabled; + } + private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this); static final class AppHibernationServiceStub extends IAppHibernationService.Stub { @@ -542,7 +586,7 @@ public final class AppHibernationService extends SystemService { public static boolean isAppHibernationEnabled() { return DeviceConfig.getBoolean( NAMESPACE_APP_HIBERNATION, - AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED, + KEY_APP_HIBERNATION_ENABLED, false /* defaultValue */); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 4c69704df0c9..5a8396ff5886 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -8129,6 +8129,7 @@ public class AudioService extends IAudioService.Stub public void postDisplaySafeVolumeWarning(int flags) { if (mController == null) return; + flags = flags | AudioManager.FLAG_SHOW_UI; try { mController.displaySafeVolumeWarning(flags); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index e3757dfc6a59..df83df9a73fb 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -16,15 +16,24 @@ package com.android.server.compat; +import static android.app.compat.PackageOverride.VALUE_DISABLED; +import static android.app.compat.PackageOverride.VALUE_ENABLED; +import static android.app.compat.PackageOverride.VALUE_UNDEFINED; + import android.annotation.Nullable; +import android.app.compat.PackageOverride; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; +import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import com.android.internal.compat.CompatibilityChangeInfo; +import com.android.internal.compat.OverrideAllowedState; import com.android.server.compat.config.Change; import com.android.server.compat.overrides.ChangeOverrides; import com.android.server.compat.overrides.OverrideValue; +import com.android.server.compat.overrides.RawOverrideValue; import java.util.HashMap; import java.util.List; @@ -36,7 +45,7 @@ import java.util.Map; * <p>A compatibility change has a default setting, determined by the {@code enableAfterTargetSdk} * and {@code disabled} constructor parameters. If a change is {@code disabled}, this overrides any * target SDK criteria set. These settings can be overridden for a specific package using - * {@link #addPackageOverride(String, boolean)}. + * {@link #addPackageOverrideInternal(String, boolean)}. * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ @@ -63,8 +72,8 @@ public final class CompatChange extends CompatibilityChangeInfo { ChangeListener mListener = null; - private Map<String, Boolean> mPackageOverrides; - private Map<String, Boolean> mDeferredOverrides; + private Map<String, Boolean> mEvaluatedOverrides; + private Map<String, PackageOverride> mRawOverrides; public CompatChange(long changeId) { this(changeId, null, -1, -1, false, false, null, false); @@ -113,18 +122,26 @@ public final class CompatChange extends CompatibilityChangeInfo { * @param pname Package name to enable the change for. * @param enabled Whether or not to enable the change. */ - void addPackageOverride(String pname, boolean enabled) { + private void addPackageOverrideInternal(String pname, boolean enabled) { if (getLoggingOnly()) { throw new IllegalArgumentException( "Can't add overrides for a logging only change " + toString()); } - if (mPackageOverrides == null) { - mPackageOverrides = new HashMap<>(); + if (mEvaluatedOverrides == null) { + mEvaluatedOverrides = new HashMap<>(); } - mPackageOverrides.put(pname, enabled); + mEvaluatedOverrides.put(pname, enabled); notifyListener(pname); } + private void removePackageOverrideInternal(String pname) { + if (mEvaluatedOverrides != null) { + if (mEvaluatedOverrides.remove(pname) != null) { + notifyListener(pname); + } + } + } + /** * Tentatively set the state of this change for a given package name. * The override will only take effect after that package is installed, if applicable. @@ -132,17 +149,19 @@ public final class CompatChange extends CompatibilityChangeInfo { * <p>Note, this method is not thread safe so callers must ensure thread safety. * * @param packageName Package name to tentatively enable the change for. - * @param enabled Whether or not to enable the change. + * @param override The package override to be set */ - void addPackageDeferredOverride(String packageName, boolean enabled) { + void addPackageOverride(String packageName, PackageOverride override, + OverrideAllowedState allowedState, Context context) { if (getLoggingOnly()) { throw new IllegalArgumentException( "Can't add overrides for a logging only change " + toString()); } - if (mDeferredOverrides == null) { - mDeferredOverrides = new HashMap<>(); + if (mRawOverrides == null) { + mRawOverrides = new HashMap<>(); } - mDeferredOverrides.put(packageName, enabled); + mRawOverrides.put(packageName, override); + recheckOverride(packageName, allowedState, context); } /** @@ -157,24 +176,44 @@ public final class CompatChange extends CompatibilityChangeInfo { * @return {@code true} if the recheck yielded a result that requires invalidating caches * (a deferred override was consolidated or a regular override was removed). */ - boolean recheckOverride(String packageName, boolean allowed) { - // A deferred override now is allowed by the policy, so promote it to a regular override. - if (hasDeferredOverride(packageName) && allowed) { - boolean overrideValue = mDeferredOverrides.remove(packageName); - addPackageOverride(packageName, overrideValue); - return true; + boolean recheckOverride(String packageName, OverrideAllowedState allowedState, + Context context) { + boolean allowed = (allowedState.state == OverrideAllowedState.ALLOWED); + + Long version = null; + try { + ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo( + packageName, 0); + version = applicationInfo.longVersionCode; + } catch (PackageManager.NameNotFoundException e) { + // Do nothing } - // A previously set override is no longer allowed by the policy, so make it deferred. - if (hasOverride(packageName) && !allowed) { - boolean overrideValue = mPackageOverrides.remove(packageName); - addPackageDeferredOverride(packageName, overrideValue); - // Notify because the override was removed. - notifyListener(packageName); - return true; + + // If the app is not installed or no longer has raw overrides, evaluate to false + if (version == null || !hasRawOverride(packageName) || !allowed) { + removePackageOverrideInternal(packageName); + return false; } - return false; + + // Evaluate the override based on its version + int overrideValue = mRawOverrides.get(packageName).evaluate(version); + switch (overrideValue) { + case VALUE_UNDEFINED: + removePackageOverrideInternal(packageName); + break; + case VALUE_ENABLED: + addPackageOverrideInternal(packageName, true); + break; + case VALUE_DISABLED: + addPackageOverrideInternal(packageName, false); + break; + } + return true; } + boolean hasPackageOverride(String pname) { + return mRawOverrides != null && mRawOverrides.containsKey(pname); + } /** * Remove any package override for the given package name, restoring the default behaviour. * @@ -182,15 +221,13 @@ public final class CompatChange extends CompatibilityChangeInfo { * * @param pname Package name to reset to defaults for. */ - void removePackageOverride(String pname) { - if (mPackageOverrides != null) { - if (mPackageOverrides.remove(pname) != null) { - notifyListener(pname); - } - } - if (mDeferredOverrides != null) { - mDeferredOverrides.remove(pname); + boolean removePackageOverride(String pname, OverrideAllowedState allowedState, + Context context) { + if (mRawOverrides != null && (mRawOverrides.remove(pname) != null)) { + recheckOverride(pname, allowedState, context); + return true; } + return false; } /** @@ -204,8 +241,8 @@ public final class CompatChange extends CompatibilityChangeInfo { if (app == null) { return defaultValue(); } - if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) { - return mPackageOverrides.get(app.packageName); + if (mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(app.packageName)) { + return mEvaluatedOverrides.get(app.packageName); } if (getDisabled()) { return false; @@ -223,8 +260,16 @@ public final class CompatChange extends CompatibilityChangeInfo { * @return {@code true} if the change should be enabled for the package. */ boolean willBeEnabled(String packageName) { - if (hasDeferredOverride(packageName)) { - return mDeferredOverrides.get(packageName); + if (hasRawOverride(packageName)) { + int eval = mRawOverrides.get(packageName).evaluateForAllVersions(); + switch (eval) { + case VALUE_ENABLED: + return true; + case VALUE_DISABLED: + return false; + case VALUE_UNDEFINED: + return defaultValue(); + } } return defaultValue(); } @@ -243,8 +288,8 @@ public final class CompatChange extends CompatibilityChangeInfo { * @param packageName name of the package * @return true if there is such override */ - boolean hasOverride(String packageName) { - return mPackageOverrides != null && mPackageOverrides.containsKey(packageName); + private boolean hasOverride(String packageName) { + return mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(packageName); } /** @@ -252,65 +297,77 @@ public final class CompatChange extends CompatibilityChangeInfo { * @param packageName name of the package * @return true if there is such a deferred override */ - boolean hasDeferredOverride(String packageName) { - return mDeferredOverrides != null && mDeferredOverrides.containsKey(packageName); - } - - /** - * Checks whether a change has any package overrides. - * @return true if the change has at least one deferred override - */ - boolean hasAnyPackageOverride() { - return mDeferredOverrides != null && !mDeferredOverrides.isEmpty(); - } - - /** - * Checks whether a change has any deferred overrides. - * @return true if the change has at least one deferred override - */ - boolean hasAnyDeferredOverride() { - return mPackageOverrides != null && !mPackageOverrides.isEmpty(); + private boolean hasRawOverride(String packageName) { + return mRawOverrides != null && mRawOverrides.containsKey(packageName); } void loadOverrides(ChangeOverrides changeOverrides) { - if (mDeferredOverrides == null) { - mDeferredOverrides = new HashMap<>(); + if (mRawOverrides == null) { + mRawOverrides = new HashMap<>(); } - mDeferredOverrides.clear(); - for (OverrideValue override : changeOverrides.getDeferred().getOverrideValue()) { - mDeferredOverrides.put(override.getPackageName(), override.getEnabled()); + mRawOverrides.clear(); + + if (mEvaluatedOverrides == null) { + mEvaluatedOverrides = new HashMap<>(); } + mEvaluatedOverrides.clear(); - if (mPackageOverrides == null) { - mPackageOverrides = new HashMap<>(); + // Load deferred overrides for backwards compatibility + if (changeOverrides.getDeferred() != null) { + for (OverrideValue override : changeOverrides.getDeferred().getOverrideValue()) { + mRawOverrides.put(override.getPackageName(), + new PackageOverride.Builder().setEnabled( + override.getEnabled()).build()); + } + } + + // Load validated overrides. For backwards compatibility, we also add them to raw overrides. + if (changeOverrides.getValidated() != null) { + for (OverrideValue override : changeOverrides.getValidated().getOverrideValue()) { + mEvaluatedOverrides.put(override.getPackageName(), override.getEnabled()); + mRawOverrides.put(override.getPackageName(), + new PackageOverride.Builder().setEnabled( + override.getEnabled()).build()); + } } - mPackageOverrides.clear(); - for (OverrideValue override : changeOverrides.getValidated().getOverrideValue()) { - mPackageOverrides.put(override.getPackageName(), override.getEnabled()); + + // Load raw overrides + if (changeOverrides.getRaw() != null) { + for (RawOverrideValue override : changeOverrides.getRaw().getRawOverrideValue()) { + PackageOverride packageOverride = new PackageOverride.Builder() + .setMinVersionCode(override.getMinVersionCode()) + .setMaxVersionCode(override.getMaxVersionCode()) + .setEnabled(override.getEnabled()) + .build(); + mRawOverrides.put(override.getPackageName(), packageOverride); + } } } ChangeOverrides saveOverrides() { - if (!hasAnyDeferredOverride() && !hasAnyPackageOverride()) { + if (mRawOverrides == null || mRawOverrides.isEmpty()) { return null; } ChangeOverrides changeOverrides = new ChangeOverrides(); changeOverrides.setChangeId(getId()); - ChangeOverrides.Deferred deferredOverrides = new ChangeOverrides.Deferred(); - List<OverrideValue> deferredList = deferredOverrides.getOverrideValue(); - if (mDeferredOverrides != null) { - for (Map.Entry<String, Boolean> entry : mDeferredOverrides.entrySet()) { - OverrideValue override = new OverrideValue(); + ChangeOverrides.Raw rawOverrides = new ChangeOverrides.Raw(); + List<RawOverrideValue> rawList = rawOverrides.getRawOverrideValue(); + if (mRawOverrides != null) { + for (Map.Entry<String, PackageOverride> entry : mRawOverrides.entrySet()) { + RawOverrideValue override = new RawOverrideValue(); override.setPackageName(entry.getKey()); - override.setEnabled(entry.getValue()); - deferredList.add(override); + override.setMinVersionCode(entry.getValue().getMinVersionCode()); + override.setMaxVersionCode(entry.getValue().getMaxVersionCode()); + override.setEnabled(entry.getValue().getEnabled()); + rawList.add(override); } } - changeOverrides.setDeferred(deferredOverrides); + changeOverrides.setRaw(rawOverrides); + ChangeOverrides.Validated validatedOverrides = new ChangeOverrides.Validated(); List<OverrideValue> validatedList = validatedOverrides.getOverrideValue(); - if (mPackageOverrides != null) { - for (Map.Entry<String, Boolean> entry : mPackageOverrides.entrySet()) { + if (mEvaluatedOverrides != null) { + for (Map.Entry<String, Boolean> entry : mEvaluatedOverrides.entrySet()) { OverrideValue override = new OverrideValue(); override.setPackageName(entry.getKey()); override.setEnabled(entry.getValue()); @@ -337,11 +394,11 @@ public final class CompatChange extends CompatibilityChangeInfo { if (getLoggingOnly()) { sb.append("; loggingOnly"); } - if (mPackageOverrides != null && mPackageOverrides.size() > 0) { - sb.append("; packageOverrides=").append(mPackageOverrides); + if (mEvaluatedOverrides != null && mEvaluatedOverrides.size() > 0) { + sb.append("; packageOverrides=").append(mEvaluatedOverrides); } - if (mDeferredOverrides != null && mDeferredOverrides.size() > 0) { - sb.append("; deferredOverrides=").append(mDeferredOverrides); + if (mRawOverrides != null && mRawOverrides.size() > 0) { + sb.append("; rawOverrides=").append(mRawOverrides); } if (getOverridable()) { sb.append("; overridable"); diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 6b77b9d4ce39..422991e082a9 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -17,6 +17,7 @@ package com.android.server.compat; import android.app.compat.ChangeIdStateCache; +import android.app.compat.PackageOverride; import android.compat.Compatibility.ChangeConfig; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -31,6 +32,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.AndroidBuildClassifier; import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.compat.CompatibilityChangeInfo; +import com.android.internal.compat.CompatibilityOverrideConfig; import com.android.internal.compat.IOverrideValidator; import com.android.internal.compat.OverrideAllowedState; import com.android.server.compat.config.Change; @@ -70,11 +72,13 @@ final class CompatConfig { private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); private final OverrideValidatorImpl mOverrideValidator; + private Context mContext; private File mOverridesFile; @VisibleForTesting CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) { mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this); + mContext = context; } static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) { @@ -210,17 +214,33 @@ final class CompatConfig { * @throws IllegalStateException if overriding is not allowed */ boolean addOverride(long changeId, String packageName, boolean enabled) { - boolean alreadyKnown = addOverrideUnsafe(changeId, packageName, enabled); + boolean alreadyKnown = addOverrideUnsafe(changeId, packageName, + new PackageOverride.Builder().setEnabled(enabled).build()); saveOverrides(); invalidateCache(); return alreadyKnown; } /** - * Unsafe version of {@link #addOverride(long, String, boolean)}. - * It does not invalidate the cache nor save the overrides. + * Overrides the enabled state for a given change and app. + * + * <p>Note, package overrides are not persistent and will be lost on system or runtime restart. + * + * @param overrides list of overrides to default changes config. + * @param packageName app for which the overrides will be applied. */ - private boolean addOverrideUnsafe(long changeId, String packageName, boolean enabled) { + void addOverrides(CompatibilityOverrideConfig overrides, String packageName) { + synchronized (mChanges) { + for (Long changeId : overrides.overrides.keySet()) { + addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId)); + } + saveOverrides(); + invalidateCache(); + } + } + + private boolean addOverrideUnsafe(long changeId, String packageName, + PackageOverride overrides) { boolean alreadyKnown = true; OverrideAllowedState allowedState = mOverrideValidator.getOverrideAllowedState(changeId, packageName); @@ -232,17 +252,8 @@ final class CompatConfig { c = new CompatChange(changeId); addChange(c); } - switch (allowedState.state) { - case OverrideAllowedState.ALLOWED: - c.addPackageOverride(packageName, enabled); - break; - case OverrideAllowedState.DEFERRED_VERIFICATION: - c.addPackageDeferredOverride(packageName, enabled); - break; - default: - throw new IllegalStateException("Should only be able to override changes that " - + "are allowed or can be deferred."); - } + c.addPackageOverride(packageName, overrides, allowedState, mContext); + invalidateCache(); } return alreadyKnown; } @@ -311,47 +322,20 @@ final class CompatConfig { * It does not invalidate the cache nor save the overrides. */ private boolean removeOverrideUnsafe(long changeId, String packageName) { - boolean overrideExists = false; synchronized (mChanges) { CompatChange c = mChanges.get(changeId); if (c != null) { - // Always allow removing a deferred override. - if (c.hasDeferredOverride(packageName)) { - c.removePackageOverride(packageName); - overrideExists = true; - } else if (c.hasOverride(packageName)) { - // Regular overrides need to pass the policy. - overrideExists = true; - OverrideAllowedState allowedState = - mOverrideValidator.getOverrideAllowedState(changeId, packageName); + OverrideAllowedState allowedState = + mOverrideValidator.getOverrideAllowedState(changeId, packageName); + if (c.hasPackageOverride(packageName)) { allowedState.enforce(changeId, packageName); - c.removePackageOverride(packageName); + c.removePackageOverride(packageName, allowedState, mContext); + invalidateCache(); + return true; } } } - return overrideExists; - } - - /** - * Overrides the enabled state for a given change and app. - * - * <p>Note: package overrides are not persistent and will be lost on system or runtime restart. - * - * @param overrides list of overrides to default changes config - * @param packageName app for which the overrides will be applied - */ - void addOverrides(CompatibilityChangeConfig overrides, String packageName) { - synchronized (mChanges) { - for (Long changeId : overrides.enabledChanges()) { - addOverrideUnsafe(changeId, packageName, true); - } - for (Long changeId : overrides.disabledChanges()) { - addOverrideUnsafe(changeId, packageName, false); - - } - saveOverrides(); - invalidateCache(); - } + return false; } /** @@ -402,7 +386,8 @@ final class CompatConfig { int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) { long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion); for (long changeId : changes) { - addOverrideUnsafe(changeId, packageName, true); + addOverrideUnsafe(changeId, packageName, + new PackageOverride.Builder().setEnabled(true).build()); } saveOverrides(); invalidateCache(); @@ -418,7 +403,8 @@ final class CompatConfig { int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) { long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion); for (long changeId : changes) { - addOverrideUnsafe(changeId, packageName, false); + addOverrideUnsafe(changeId, packageName, + new PackageOverride.Builder().setEnabled(false).build()); } saveOverrides(); invalidateCache(); @@ -615,8 +601,7 @@ final class CompatConfig { CompatChange c = mChanges.valueAt(idx); OverrideAllowedState allowedState = mOverrideValidator.getOverrideAllowedState(c.getId(), packageName); - boolean allowedOverride = (allowedState.state == OverrideAllowedState.ALLOWED); - shouldInvalidateCache |= c.recheckOverride(packageName, allowedOverride); + shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext); } if (shouldInvalidateCache) { invalidateCache(); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 6b2a1c950e38..edfc8b8f31b0 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -25,6 +25,7 @@ import static android.os.Process.SYSTEM_UID; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.IActivityManager; +import android.app.compat.PackageOverride; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -43,6 +44,7 @@ import com.android.internal.compat.AndroidBuildClassifier; import com.android.internal.compat.ChangeReporter; import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.compat.CompatibilityChangeInfo; +import com.android.internal.compat.CompatibilityOverrideConfig; import com.android.internal.compat.IOverrideValidator; import com.android.internal.compat.IPlatformCompat; import com.android.internal.util.DumpUtils; @@ -51,6 +53,8 @@ import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** * System server internal API for gating and reporting compatibility changes. @@ -161,6 +165,22 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) { checkCompatChangeOverridePermission(); + Map<Long, PackageOverride> overridesMap = new HashMap<>(); + for (long change : overrides.enabledChanges()) { + overridesMap.put(change, new PackageOverride.Builder().setEnabled(true).build()); + } + for (long change : overrides.disabledChanges()) { + overridesMap.put(change, new PackageOverride.Builder().setEnabled(false) + .build()); + } + mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName); + killPackage(packageName); + } + + @Override + public void setOverridesFromInstaller(CompatibilityOverrideConfig overrides, + String packageName) { + checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); killPackage(packageName); } @@ -168,7 +188,15 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) { checkCompatChangeOverridePermission(); - mCompatConfig.addOverrides(overrides, packageName); + Map<Long, PackageOverride> overridesMap = new HashMap<>(); + for (long change : overrides.enabledChanges()) { + overridesMap.put(change, new PackageOverride.Builder().setEnabled(true).build()); + } + for (long change : overrides.disabledChanges()) { + overridesMap.put(change, new PackageOverride.Builder().setEnabled(false) + .build()); + } + mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName); } @Override diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java index 397af7ba2991..61b11a5851a9 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java @@ -16,7 +16,6 @@ package com.android.server.connectivity; -import static android.net.NetworkCapabilities.MAX_TRANSPORT; import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; @@ -25,15 +24,14 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; -import android.net.ConnectivityManager; import android.net.ConnectivityMetricsEvent; import android.net.metrics.ApfProgramEvent; import android.net.metrics.ApfStats; +import android.net.metrics.ConnectStats; import android.net.metrics.DefaultNetworkEvent; import android.net.metrics.DhcpClientEvent; import android.net.metrics.DhcpErrorEvent; import android.net.metrics.DnsEvent; -import android.net.metrics.ConnectStats; import android.net.metrics.IpManagerEvent; import android.net.metrics.IpReachabilityEvent; import android.net.metrics.NetworkEvent; @@ -41,12 +39,13 @@ import android.net.metrics.RaEvent; import android.net.metrics.ValidationProbeEvent; import android.net.metrics.WakeupStats; import android.os.Parcelable; -import android.util.SparseArray; import android.util.SparseIntArray; + import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -361,29 +360,22 @@ final public class IpConnectivityEventBuilder { return IpConnectivityLogClass.UNKNOWN; case 1: int t = Long.numberOfTrailingZeros(transports); - return transportToLinkLayer(t); + return TRANSPORT_LINKLAYER_MAP.get(t, IpConnectivityLogClass.UNKNOWN); default: return IpConnectivityLogClass.MULTIPLE; } } - private static int transportToLinkLayer(int transport) { - if (0 <= transport && transport < TRANSPORT_LINKLAYER_MAP.length) { - return TRANSPORT_LINKLAYER_MAP[transport]; - } - return IpConnectivityLogClass.UNKNOWN; - } - - private static final int[] TRANSPORT_LINKLAYER_MAP = new int[MAX_TRANSPORT + 1]; + private static final SparseIntArray TRANSPORT_LINKLAYER_MAP = new SparseIntArray(); static { - TRANSPORT_LINKLAYER_MAP[TRANSPORT_CELLULAR] = IpConnectivityLogClass.CELLULAR; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI] = IpConnectivityLogClass.WIFI; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_BLUETOOTH] = IpConnectivityLogClass.BLUETOOTH; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_ETHERNET] = IpConnectivityLogClass.ETHERNET; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_VPN] = IpConnectivityLogClass.UNKNOWN; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.WIFI_NAN; - TRANSPORT_LINKLAYER_MAP[TRANSPORT_LOWPAN] = IpConnectivityLogClass.LOWPAN; - }; + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_CELLULAR, IpConnectivityLogClass.CELLULAR); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_WIFI, IpConnectivityLogClass.WIFI); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_BLUETOOTH, IpConnectivityLogClass.BLUETOOTH); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_ETHERNET, IpConnectivityLogClass.ETHERNET); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_VPN, IpConnectivityLogClass.UNKNOWN); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_WIFI_AWARE, IpConnectivityLogClass.WIFI_NAN); + TRANSPORT_LINKLAYER_MAP.append(TRANSPORT_LOWPAN, IpConnectivityLogClass.LOWPAN); + } private static int ifnameToLinkLayer(String ifname) { // Do not try to catch all interface names with regexes, instead only catch patterns that diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 46c49e7fc28c..641287f0f435 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -16,6 +16,8 @@ package com.android.server.connectivity; +import static com.android.net.module.util.CollectionUtils.contains; + import android.annotation.NonNull; import android.net.ConnectivityManager; import android.net.IDnsResolver; @@ -33,7 +35,6 @@ import android.os.ServiceSpecificException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkStackConstants; import com.android.server.net.BaseNetworkObserver; @@ -117,8 +118,8 @@ public class Nat464Xlat extends BaseNetworkObserver { @VisibleForTesting protected static boolean requiresClat(NetworkAgentInfo nai) { // TODO: migrate to NetworkCapabilities.TRANSPORT_*. - final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); - final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState()); + final boolean supported = contains(NETWORK_TYPES, nai.networkInfo.getType()); + final boolean connected = contains(NETWORK_STATES, nai.networkInfo.getState()); // Only run clat on networks that have a global IPv6 address and don't have a native IPv4 // address. diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index bff1a5c99dd2..4cf527415d7e 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -717,8 +717,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { mNumBackgroundNetworkRequests += delta; break; - case TRACK_DEFAULT: case LISTEN: + case TRACK_DEFAULT: + case TRACK_SYSTEM_DEFAULT: break; case NONE: @@ -898,7 +899,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { ? networkAgentConfig.subscriberId : null; return new NetworkState(new NetworkInfo(networkInfo), new LinkProperties(linkProperties), - new NetworkCapabilities(networkCapabilities), network, subscriberId, null); + new NetworkCapabilities(networkCapabilities), network, subscriberId); } } diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 3d71b0a269c9..508739f2e1e0 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -79,7 +79,6 @@ public class NetworkNotificationManager { // server. public static final String NOTIFICATION_CHANNEL_NETWORK_STATUS = "NETWORK_STATUS"; public static final String NOTIFICATION_CHANNEL_NETWORK_ALERTS = "NETWORK_ALERTS"; - public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; // The context is for the current user (system server) private final Context mContext; @@ -161,13 +160,20 @@ public class NetworkNotificationManager { if (nai != null) { transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); - name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; + if (nai.linkProperties != null && nai.linkProperties.getCaptivePortalData() != null + && !TextUtils.isEmpty(nai.linkProperties.getCaptivePortalData() + .getVenueFriendlyName())) { + name = nai.linkProperties.getCaptivePortalData().getVenueFriendlyName(); + } else { + name = TextUtils.isEmpty(extraInfo) + ? WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid()) : extraInfo; + } // Only notify for Internet-capable networks. if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return; } else { // Legacy notifications. transportType = TRANSPORT_CELLULAR; - name = null; + name = ""; } // Clear any previous notification with lower priority, otherwise return. http://b/63676954. @@ -193,35 +199,30 @@ public class NetworkNotificationManager { final CharSequence details; int icon = getIcon(transportType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); + title = r.getString(R.string.wifi_no_internet, name); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); + title = r.getString(R.string.wifi_no_internet, name); } else { title = r.getString(R.string.other_networks_no_internet); } details = r.getString(R.string.private_dns_broken_detailed); } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.network_partial_connectivity, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); + title = r.getString(R.string.network_partial_connectivity, name); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); + title = r.getString(R.string.wifi_no_internet, name); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); - details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); + details = r.getString(R.string.network_available_sign_in_detailed, name); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 8d21f6f0f59f..9411e33434d8 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -28,6 +28,8 @@ import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; +import static com.android.net.module.util.CollectionUtils.toIntArray; + import android.annotation.NonNull; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -40,23 +42,21 @@ import android.net.UidRange; import android.os.Build; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; import android.system.OsConstants; -import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.CollectionUtils; import com.android.server.LocalServices; -import com.android.server.SystemConfig; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -80,12 +80,12 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse private final PackageManager mPackageManager; private final UserManager mUserManager; + private final SystemConfigManager mSystemConfigManager; private final INetd mNetd; private final Dependencies mDeps; - // Values are User IDs. @GuardedBy("this") - private final Set<Integer> mUsers = new HashSet<>(); + private final Set<UserHandle> mUsers = new HashSet<>(); // Keys are app uids. Values are true for SYSTEM permission and false for NETWORK permission. @GuardedBy("this") @@ -124,6 +124,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse @NonNull final Dependencies deps) { mPackageManager = context.getPackageManager(); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mSystemConfigManager = context.getSystemService(SystemConfigManager.class); mNetd = netd; mDeps = deps; } @@ -173,25 +174,20 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } - final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */); - for (UserHandle user : users) { - mUsers.add(user.getIdentifier()); - } + mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */)); - final SparseArray<ArraySet<String>> systemPermission = - SystemConfig.getInstance().getSystemPermissions(); - for (int i = 0; i < systemPermission.size(); i++) { - ArraySet<String> perms = systemPermission.valueAt(i); - int uid = systemPermission.keyAt(i); - int netdPermission = 0; - // Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission. - if (perms != null) { - netdPermission |= perms.contains(UPDATE_DEVICE_STATS) - ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0; - netdPermission |= perms.contains(INTERNET) - ? INetd.PERMISSION_INTERNET : 0; + final SparseArray<String> netdPermToSystemPerm = new SparseArray<>(); + netdPermToSystemPerm.put(INetd.PERMISSION_INTERNET, INTERNET); + netdPermToSystemPerm.put(INetd.PERMISSION_UPDATE_DEVICE_STATS, UPDATE_DEVICE_STATS); + for (int i = 0; i < netdPermToSystemPerm.size(); i++) { + final int netdPermission = netdPermToSystemPerm.keyAt(i); + final String systemPermission = netdPermToSystemPerm.valueAt(i); + final int[] hasPermissionUids = + mSystemConfigManager.getSystemPermissionUids(systemPermission); + for (int j = 0; j < hasPermissionUids.length; j++) { + final int uid = hasPermissionUids[j]; + netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } - netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); update(mUsers, mApps, true); @@ -208,7 +204,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { return false; } - final int index = ArrayUtils.indexOf(app.requestedPermissions, permission); + final int index = CollectionUtils.indexOf(app.requestedPermissions, permission); if (index < 0 || index >= app.requestedPermissionsFlags.length) return false; return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0; } @@ -250,25 +246,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return mApps.containsKey(uid); } - private int[] toIntArray(Collection<Integer> list) { - int[] array = new int[list.size()]; - int i = 0; - for (Integer item : list) { - array[i++] = item; - } - return array; - } - - private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) { + private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) { List<Integer> network = new ArrayList<>(); List<Integer> system = new ArrayList<>(); for (Entry<Integer, Boolean> app : apps.entrySet()) { List<Integer> list = app.getValue() ? system : network; - for (int user : users) { - final UserHandle handle = UserHandle.of(user); - if (handle == null) continue; + for (UserHandle user : users) { + if (user == null) continue; - list.add(UserHandle.getUid(handle, app.getKey())); + list.add(UserHandle.getUid(user, app.getKey())); } } try { @@ -291,14 +277,10 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * * @hide */ - public synchronized void onUserAdded(int user) { - if (user < 0) { - loge("Invalid user in onUserAdded: " + user); - return; - } + public synchronized void onUserAdded(@NonNull UserHandle user) { mUsers.add(user); - Set<Integer> users = new HashSet<>(); + Set<UserHandle> users = new HashSet<>(); users.add(user); update(users, mApps, true); } @@ -310,14 +292,10 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * * @hide */ - public synchronized void onUserRemoved(int user) { - if (user < 0) { - loge("Invalid user in onUserRemoved: " + user); - return; - } + public synchronized void onUserRemoved(@NonNull UserHandle user) { mUsers.remove(user); - Set<Integer> users = new HashSet<>(); + Set<UserHandle> users = new HashSet<>(); users.add(user); update(users, mApps, false); } @@ -675,23 +653,23 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse if (allPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids( INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(allPermissionAppIds)); + toIntArray(allPermissionAppIds)); } if (internetPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET, - ArrayUtils.convertToIntArray(internetPermissionAppIds)); + toIntArray(internetPermissionAppIds)); } if (updateStatsPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(updateStatsPermissionAppIds)); + toIntArray(updateStatsPermissionAppIds)); } if (noPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE, - ArrayUtils.convertToIntArray(noPermissionAppIds)); + toIntArray(noPermissionAppIds)); } if (uninstalledAppIds.size() != 0) { mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED, - ArrayUtils.convertToIntArray(uninstalledAppIds)); + toIntArray(uninstalledAppIds)); } } catch (RemoteException e) { Log.e(TAG, "Pass appId list of special permission failed." + e); diff --git a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java b/services/core/java/com/android/server/connectivity/QosCallbackTracker.java index 87b4c162a2cc..7ef315c469ae 100644 --- a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java +++ b/services/core/java/com/android/server/connectivity/QosCallbackTracker.java @@ -27,7 +27,7 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.telephony.data.EpsBearerQosSessionAttributes; -import android.util.Slog; +import android.util.Log; import com.android.internal.util.CollectionUtils; import com.android.server.ConnectivityService; @@ -260,18 +260,18 @@ public class QosCallbackTracker { } private static void log(final String msg) { - Slog.d(TAG, msg); + Log.d(TAG, msg); } private static void logw(final String msg) { - Slog.w(TAG, msg); + Log.w(TAG, msg); } private static void loge(final String msg) { - Slog.e(TAG, msg); + Log.e(TAG, msg); } private static void logwtf(final String msg) { - Slog.wtf(TAG, msg); + Log.wtf(TAG, msg); } } diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index b5f20d70db7f..c480594b8c60 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -41,7 +41,6 @@ import android.os.Handler; import android.os.MessageQueue; import android.os.Messenger; import android.system.ErrnoException; -import android.system.Int32Ref; import android.system.Os; import android.util.Log; import android.util.SparseArray; @@ -306,9 +305,8 @@ public class TcpKeepaliveController { private static boolean isReceiveQueueEmpty(FileDescriptor fd) throws ErrnoException { - Int32Ref result = new Int32Ref(-1); - Os.ioctlInt(fd, SIOCINQ, result); - if (result.value != 0) { + final int result = Os.ioctlInt(fd, SIOCINQ); + if (result != 0) { Log.e(TAG, "Read queue has data"); return false; } @@ -317,9 +315,8 @@ public class TcpKeepaliveController { private static boolean isSendQueueEmpty(FileDescriptor fd) throws ErrnoException { - Int32Ref result = new Int32Ref(-1); - Os.ioctlInt(fd, SIOCOUTQ, result); - if (result.value != 0) { + final int result = Os.ioctlInt(fd, SIOCOUTQ); + if (result != 0) { Log.e(TAG, "Write queue has data"); return false; } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index fc2c7e01efde..713ac73aa9b9 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -21,10 +21,10 @@ import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; +import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.server.connectivity.NetworkNotificationManager.NOTIFICATION_CHANNEL_VPN; import android.Manifest; import android.annotation.NonNull; @@ -74,6 +74,7 @@ import android.net.UidRangeParcel; import android.net.UnderlyingNetworkInfo; import android.net.VpnManager; import android.net.VpnService; +import android.net.VpnTransportInfo; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.ChildSessionConfiguration; import android.net.ipsec.ike.ChildSessionParams; @@ -112,6 +113,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; +import com.android.net.module.util.NetdUtils; import com.android.net.module.util.NetworkStackConstants; import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; @@ -171,6 +173,12 @@ public class Vpn { */ @VisibleForTesting static final int MAX_VPN_PROFILE_SIZE_BYTES = 1 << 17; // 128kB + /** + * Network score that VPNs will announce to ConnectivityService. + * TODO: remove when the network scoring refactor lands. + */ + private static final int VPN_DEFAULT_SCORE = 101; + // TODO: create separate trackers for each unique VPN to support // automated reconnection @@ -435,6 +443,7 @@ public class Vpn { mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE)); loadAlwaysOnPackage(keyStore); } @@ -494,6 +503,11 @@ public class Vpn { updateAlwaysOnNotification(detailedState); } + private void resetNetworkCapabilities() { + mNetworkCapabilities.setUids(null); + mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE)); + } + /** * Chooses whether to force all connections to go though VPN. * @@ -518,6 +532,11 @@ public class Vpn { } } + /** Returns the package name that is currently prepared. */ + public String getPackage() { + return mPackage; + } + /** * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected. * @@ -928,7 +947,7 @@ public class Vpn { agentDisconnect(); jniReset(mInterface); mInterface = null; - mNetworkCapabilities.setUids(null); + resetNetworkCapabilities(); } // Revoke the connection or stop the VpnRunner. @@ -999,6 +1018,8 @@ public class Vpn { case VpnManager.TYPE_VPN_SERVICE: toChange = new String[] {AppOpsManager.OPSTR_ACTIVATE_VPN}; break; + case VpnManager.TYPE_VPN_LEGACY: + return false; default: Log.wtf(TAG, "Unrecognized VPN type while granting authorization"); return false; @@ -1029,6 +1050,8 @@ public class Vpn { return isVpnServicePreConsented(context, packageName); case VpnManager.TYPE_VPN_PLATFORM: return isVpnProfilePreConsented(context, packageName); + case VpnManager.TYPE_VPN_LEGACY: + return VpnConfig.LEGACY_VPN.equals(packageName); default: return false; } @@ -1211,6 +1234,8 @@ public class Vpn { mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId, mConfig.allowedApplications, mConfig.disallowedApplications)); + mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType())); + // Only apps targeting Q and above can explicitly declare themselves as metered. // These VPNs are assumed metered unless they state otherwise. if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) { @@ -1220,8 +1245,7 @@ public class Vpn { } mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */, - mNetworkCapabilities, lp, - ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) { + mNetworkCapabilities, lp, VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) { @Override public void unwanted() { // We are user controlled, not driven by NetworkRequest. @@ -1735,7 +1759,7 @@ public class Vpn { private void cleanupVpnStateLocked() { mStatusIntent = null; - mNetworkCapabilities.setUids(null); + resetNetworkCapabilities(); mConfig = null; mInterface = null; @@ -1846,22 +1870,18 @@ public class Vpn { } /** - * Gets the currently running App-based VPN type + * Gets the currently running VPN type * - * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running an - * app-based VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always + * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running a + * VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always * Settings-based, the Platform VPNs can be initiated by both apps and Settings. */ - public synchronized int getActiveAppVpnType() { - if (VpnConfig.LEGACY_VPN.equals(mPackage)) { - return VpnManager.TYPE_VPN_NONE; - } - - if (mVpnRunner != null && mVpnRunner instanceof IkeV2VpnRunner) { - return VpnManager.TYPE_VPN_PLATFORM; - } else { - return VpnManager.TYPE_VPN_SERVICE; - } + public synchronized int getActiveVpnType() { + if (!mNetworkInfo.isConnectedOrConnecting()) return VpnManager.TYPE_VPN_NONE; + if (mVpnRunner == null) return VpnManager.TYPE_VPN_SERVICE; + return mVpnRunner instanceof IkeV2VpnRunner + ? VpnManager.TYPE_VPN_PLATFORM + : VpnManager.TYPE_VPN_LEGACY; } private void updateAlwaysOnNotification(DetailedState networkState) { @@ -2509,7 +2529,7 @@ public class Vpn { address /* unused */, address /* unused */, network); - mNms.setInterfaceUp(mTunnelIface.getInterfaceName()); + NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName()); mSession = mIkev2SessionCreator.createIkeSession( mContext, diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 5d1c4e6715f1..16d4f94277cb 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -555,7 +555,7 @@ public class HdmiControlService extends SystemService { private void bootCompleted() { // on boot, if device is interactive, set HDMI CEC state as powered on as well if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) { - onWakeUp(); + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } } diff --git a/services/core/java/com/android/server/input/OWNERS b/services/core/java/com/android/server/input/OWNERS index 0313a40f7270..82c6ee12c7ae 100644 --- a/services/core/java/com/android/server/input/OWNERS +++ b/services/core/java/com/android/server/input/OWNERS @@ -1,2 +1,3 @@ +lzye@google.com michaelwr@google.com svv@google.com diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index c005af4e9696..f1750cd16f1f 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -89,6 +89,7 @@ import android.os.storage.StorageManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; +import android.security.AndroidKeyStoreMaintenance; import android.security.Authorization; import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; @@ -225,7 +226,6 @@ public class LockSettingsService extends ILockSettings.Stub { private final SyntheticPasswordManager mSpManager; private final KeyStore mKeyStore; - private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; private ManagedProfilePasswordCache mManagedProfilePasswordCache; @@ -280,6 +280,7 @@ public class LockSettingsService extends ILockSettings.Stub { super.onBootPhase(phase); if (phase == PHASE_ACTIVITY_MANAGER_READY) { mLockSettingsService.migrateOldDataAfterSystemReady(); + mLockSettingsService.loadEscrowData(); } } @@ -802,6 +803,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { // Notify keystore that a new user was added. final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); + AndroidKeyStoreMaintenance.onUserAdded(userHandle); final KeyStore ks = KeyStore.getInstance(); final UserInfo parentInfo = mUserManager.getProfileParent(userHandle); final int parentHandle = parentInfo != null ? parentInfo.id : -1; @@ -832,11 +834,15 @@ public class LockSettingsService extends ILockSettings.Stub { mSpManager.initWeaverService(); getAuthSecretHal(); mDeviceProvisionedObserver.onSystemReady(); - mRebootEscrowManager.loadRebootEscrowDataIfAvailable(); + // TODO: maybe skip this for split system user mode. mStorage.prefetchUser(UserHandle.USER_SYSTEM); } + private void loadEscrowData() { + mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); + } + private void getAuthSecretHal() { try { mAuthSecretService = IAuthSecret.getService(/* retry */ true); @@ -1265,6 +1271,7 @@ public class LockSettingsService extends ILockSettings.Stub { } private void setKeystorePassword(byte[] password, int userHandle) { + AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password); final KeyStore ks = KeyStore.getInstance(); // TODO(b/120484642): Update keystore to accept byte[] passwords String passwordString = password == null ? null : new String(password); @@ -1273,7 +1280,7 @@ public class LockSettingsService extends ILockSettings.Stub { private void unlockKeystore(byte[] password, int userHandle) { if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle); - new Authorization().onLockScreenEvent(false, userHandle, password); + Authorization.onLockScreenEvent(false, userHandle, password); // TODO(b/120484642): Update keystore to accept byte[] passwords String passwordString = password == null ? null : new String(password); final KeyStore ks = KeyStore.getInstance(); @@ -2296,6 +2303,7 @@ public class LockSettingsService extends ILockSettings.Stub { mSpManager.removeUser(userId); mStrongAuth.removeUser(userId); + AndroidKeyStoreMaintenance.onUserRemoved(userId); final KeyStore ks = KeyStore.getInstance(); ks.onUserRemoved(userId); mManagedProfilePasswordCache.removePassword(userId); @@ -2381,10 +2389,17 @@ public class LockSettingsService extends ILockSettings.Stub { public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { enforceShell(); + final int origPid = Binder.getCallingPid(); + final int origUid = Binder.getCallingUid(); + + // The original identity is an opaque integer. final long origId = Binder.clearCallingIdentity(); + Slog.e(TAG, "Caller pid " + origPid + " Caller uid " + origUid); try { - (new LockSettingsShellCommand(new LockPatternUtils(mContext))).exec( - this, in, out, err, args, callback, resultReceiver); + final LockSettingsShellCommand command = + new LockSettingsShellCommand(new LockPatternUtils(mContext), mContext, origPid, + origUid); + command.exec(this, in, out, err, args, callback, resultReceiver); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 7b767b86f0d4..8d38bfede942 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -23,8 +23,11 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTE import android.app.ActivityManager; import android.app.admin.PasswordMetrics; +import android.content.Context; import android.os.ShellCommand; +import android.os.SystemProperties; import android.text.TextUtils; +import android.util.Slog; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils.RequestThrottledException; @@ -45,15 +48,25 @@ class LockSettingsShellCommand extends ShellCommand { private static final String COMMAND_VERIFY = "verify"; private static final String COMMAND_GET_DISABLED = "get-disabled"; private static final String COMMAND_REMOVE_CACHE = "remove-cache"; + private static final String COMMAND_SET_ROR_PROVIDER_PACKAGE = + "set-resume-on-reboot-provider-package"; private static final String COMMAND_HELP = "help"; private int mCurrentUserId; private final LockPatternUtils mLockPatternUtils; + private final Context mContext; + private final int mCallingPid; + private final int mCallingUid; + private String mOld = ""; private String mNew = ""; - LockSettingsShellCommand(LockPatternUtils lockPatternUtils) { + LockSettingsShellCommand(LockPatternUtils lockPatternUtils, Context context, int callingPid, + int callingUid) { mLockPatternUtils = lockPatternUtils; + mCallingPid = callingPid; + mCallingUid = callingUid; + mContext = context; } @Override @@ -70,6 +83,7 @@ class LockSettingsShellCommand extends ShellCommand { case COMMAND_HELP: case COMMAND_GET_DISABLED: case COMMAND_SET_DISABLED: + case COMMAND_SET_ROR_PROVIDER_PACKAGE: break; default: getErrPrintWriter().println( @@ -82,6 +96,9 @@ class LockSettingsShellCommand extends ShellCommand { case COMMAND_REMOVE_CACHE: runRemoveCache(); return 0; + case COMMAND_SET_ROR_PROVIDER_PACKAGE: + runSetResumeOnRebootProviderPackage(); + return 0; case COMMAND_HELP: onHelp(); return 0; @@ -173,6 +190,10 @@ class LockSettingsShellCommand extends ShellCommand { pw.println(" remove-cache [--user USER_ID]"); pw.println(" Removes cached unified challenge for the managed profile."); pw.println(""); + pw.println(" set-resume-on-reboot-provider-package <package_name>"); + pw.println(" Sets the package name for server based resume on reboot service " + + "provider."); + pw.println(""); } } @@ -258,6 +279,17 @@ class LockSettingsShellCommand extends ShellCommand { return true; } + private boolean runSetResumeOnRebootProviderPackage() { + final String packageName = mNew; + String name = ResumeOnRebootServiceProvider.PROP_ROR_PROVIDER_PACKAGE; + Slog.i(TAG, "Setting " + name + " to " + packageName); + + mContext.enforcePermission(android.Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE, + mCallingPid, mCallingUid, TAG); + SystemProperties.set(name, packageName); + return true; + } + private boolean runClear() { LockscreenCredential none = LockscreenCredential.createNone(); if (!isNewCredentialSufficient(none)) { diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowData.java b/services/core/java/com/android/server/locksettings/RebootEscrowData.java index 38eeb88e63b0..af0774c6c3fa 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowData.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowData.java @@ -35,6 +35,12 @@ class RebootEscrowData { */ private static final int CURRENT_VERSION = 2; + /** + * This is the legacy version of the escrow data format for R builds. The escrow data is only + * encrypted by the escrow key, without additional wrap of another key from keystore. + */ + private static final int LEGACY_SINGLE_ENCRYPTED_VERSION = 1; + private RebootEscrowData(byte spVersion, byte[] syntheticPassword, byte[] blob, RebootEscrowKey key) { mSpVersion = spVersion; @@ -64,6 +70,19 @@ class RebootEscrowData { return mKey; } + private static byte[] decryptBlobCurrentVersion(SecretKey kk, RebootEscrowKey ks, + DataInputStream dis) throws IOException { + if (kk == null) { + throw new IOException("Failed to find wrapper key in keystore, cannot decrypt the" + + " escrow data"); + } + + // Decrypt the blob with the key from keystore first, then decrypt again with the reboot + // escrow key. + byte[] ksEncryptedBlob = AesEncryptionUtil.decrypt(kk, dis); + return AesEncryptionUtil.decrypt(ks.getKey(), ksEncryptedBlob); + } + static RebootEscrowData fromEncryptedData(RebootEscrowKey ks, byte[] blob, SecretKey kk) throws IOException { Objects.requireNonNull(ks); @@ -71,17 +90,20 @@ class RebootEscrowData { DataInputStream dis = new DataInputStream(new ByteArrayInputStream(blob)); int version = dis.readInt(); - if (version != CURRENT_VERSION) { - throw new IOException("Unsupported version " + version); - } byte spVersion = dis.readByte(); - - // Decrypt the blob with the key from keystore first, then decrypt again with the reboot - // escrow key. - byte[] ksEncryptedBlob = AesEncryptionUtil.decrypt(kk, dis); - final byte[] syntheticPassword = AesEncryptionUtil.decrypt(ks.getKey(), ksEncryptedBlob); - - return new RebootEscrowData(spVersion, syntheticPassword, blob, ks); + switch (version) { + case CURRENT_VERSION: { + byte[] syntheticPassword = decryptBlobCurrentVersion(kk, ks, dis); + return new RebootEscrowData(spVersion, syntheticPassword, blob, ks); + } + case LEGACY_SINGLE_ENCRYPTED_VERSION: { + // Decrypt the blob with the escrow key directly. + byte[] syntheticPassword = AesEncryptionUtil.decrypt(ks.getKey(), dis); + return new RebootEscrowData(spVersion, syntheticPassword, blob, ks); + } + default: + throw new IOException("Unsupported version " + version); + } } static RebootEscrowData fromSyntheticPassword(RebootEscrowKey ks, byte spVersion, diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 06962d414009..30ea5556b41c 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.UserInfo; +import android.os.Handler; import android.os.SystemClock; import android.os.UserManager; import android.provider.DeviceConfig; @@ -39,6 +40,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.Objects; import javax.crypto.SecretKey; @@ -76,6 +78,13 @@ class RebootEscrowManager { private static final int BOOT_COUNT_TOLERANCE = 5; /** + * The default retry specs for loading reboot escrow data. We will attempt to retry loading + * escrow data on temporarily errors, e.g. unavailable network. + */ + private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3; + private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30; + + /** * Logs events for later debugging in bugreports. */ private final RebootEscrowEventLog mEventLog; @@ -137,6 +146,7 @@ class RebootEscrowManager { RebootEscrowProviderInterface rebootEscrowProvider; if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, "server_based_ror_enabled", false)) { + Slog.i(TAG, "Using server based resume on reboot"); rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage); } else { rebootEscrowProvider = new RebootEscrowProviderHalImpl(); @@ -148,6 +158,14 @@ class RebootEscrowManager { return null; } + void post(Handler handler, Runnable runnable) { + handler.post(runnable); + } + + void postDelayed(Handler handler, Runnable runnable, long delayMillis) { + handler.postDelayed(runnable, delayMillis); + } + public Context getContext() { return mContext; } @@ -199,7 +217,18 @@ class RebootEscrowManager { mKeyStoreManager = injector.getKeyStoreManager(); } - void loadRebootEscrowDataIfAvailable() { + private void onGetRebootEscrowKeyFailed(List<UserInfo> users) { + Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); + for (UserInfo user : users) { + mStorage.removeRebootEscrow(user.id); + } + + // Clear the old key in keystore. + mKeyStoreManager.clearKeyStoreEncryptionKey(); + onEscrowRestoreComplete(false); + } + + void loadRebootEscrowDataIfAvailable(Handler retryHandler) { List<UserInfo> users = mUserManager.getUsers(); List<UserInfo> rebootEscrowUsers = new ArrayList<>(); for (UserInfo user : users) { @@ -212,17 +241,53 @@ class RebootEscrowManager { return; } + mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry( + retryHandler, 0, users, rebootEscrowUsers)); + } + + void scheduleLoadRebootEscrowDataOrFail(Handler retryHandler, int attemptNumber, + List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { + Objects.requireNonNull(retryHandler); + + final int retryLimit = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, + "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT); + final int retryIntervalInSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, + "load_escrow_data_retry_interval_seconds", + DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS); + + if (attemptNumber < retryLimit) { + Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber); + mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry( + retryHandler, attemptNumber, users, rebootEscrowUsers), + retryIntervalInSeconds * 1000); + return; + } + + Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); + onGetRebootEscrowKeyFailed(users); + } + + void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber, + List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is // generated before reboot. Note that we will clear the escrow key even if the keystore key // is null. SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); - RebootEscrowKey escrowKey = getAndClearRebootEscrowKey(kk); - if (kk == null || escrowKey == null) { - Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); - for (UserInfo user : users) { - mStorage.removeRebootEscrow(user.id); - } - onEscrowRestoreComplete(false); + if (kk == null) { + Slog.i(TAG, "Failed to load the key for resume on reboot from key store."); + } + + RebootEscrowKey escrowKey; + try { + escrowKey = getAndClearRebootEscrowKey(kk); + } catch (IOException e) { + scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users, + rebootEscrowUsers); + return; + } + + if (escrowKey == null) { + onGetRebootEscrowKeyFailed(users); return; } @@ -249,7 +314,7 @@ class RebootEscrowManager { } } - private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) { + private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException { RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); if (rebootEscrowProvider == null) { Slog.w(TAG, diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java index 6c1040b596c8..4b00772088f2 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java @@ -33,7 +33,7 @@ import javax.crypto.SecretKey; * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL. */ class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface { - private static final String TAG = "RebootEscrowProvider"; + private static final String TAG = "RebootEscrowProviderHal"; private final Injector mInjector; diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java index 857ad5fc312a..af6faad3c76e 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java @@ -16,6 +16,8 @@ package com.android.server.locksettings; +import java.io.IOException; + import javax.crypto.SecretKey; /** @@ -33,9 +35,10 @@ public interface RebootEscrowProviderInterface { /** * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted, - * use the input key to decrypt the RebootEscrowKey. Returns null on failure. + * use the input key to decrypt the RebootEscrowKey. Returns null on failure. Throws an + * IOException if the failure is non-fatal, and a retry may succeed. */ - RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey); + RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException; /** * Clears the stored RebootEscrowKey. diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java index ba1a680ba7fb..b3b45460899d 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderServerBasedImpl.java @@ -35,7 +35,7 @@ import javax.crypto.SecretKey; * encrypt & decrypt the blob. */ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterface { - private static final String TAG = "RebootEscrowProvider"; + private static final String TAG = "RebootEscrowProviderServerBased"; // Timeout for service binding private static final long DEFAULT_SERVICE_TIMEOUT_IN_SECONDS = 10; @@ -50,6 +50,8 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa private final Injector mInjector; + private byte[] mServerBlob; + static class Injector { private ResumeOnRebootServiceConnection mServiceConnection = null; @@ -124,17 +126,25 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa } @Override - public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) { - byte[] serverBlob = mStorage.readRebootEscrowServerBlob(); + public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException { + if (mServerBlob == null) { + mServerBlob = mStorage.readRebootEscrowServerBlob(); + } // Delete the server blob in storage. mStorage.removeRebootEscrowServerBlob(); - if (serverBlob == null) { + if (mServerBlob == null) { Slog.w(TAG, "Failed to read reboot escrow server blob from storage"); return null; } + if (decryptionKey == null) { + Slog.w(TAG, "Failed to decrypt the escrow key; decryption key from keystore is" + + " null."); + return null; + } + Slog.i(TAG, "Loaded reboot escrow server blob from storage"); try { - byte[] escrowKeyBytes = unwrapServerBlob(serverBlob, decryptionKey); + byte[] escrowKeyBytes = unwrapServerBlob(mServerBlob, decryptionKey); if (escrowKeyBytes == null) { Slog.w(TAG, "Decrypted reboot escrow key bytes should not be null"); return null; @@ -145,7 +155,7 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa } return RebootEscrowKey.fromKeyBytes(escrowKeyBytes); - } catch (TimeoutException | RemoteException | IOException e) { + } catch (TimeoutException | RemoteException e) { Slog.w(TAG, "Failed to decrypt the server blob ", e); return null; } diff --git a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java index a1e18bd5a6bd..9c471b85eb76 100644 --- a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java +++ b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java @@ -31,6 +31,7 @@ import android.os.IBinder; import android.os.ParcelableException; import android.os.RemoteCallback; import android.os.RemoteException; +import android.os.SystemProperties; import android.os.UserHandle; import android.provider.DeviceConfig; import android.service.resumeonreboot.IResumeOnRebootService; @@ -55,6 +56,10 @@ public class ResumeOnRebootServiceProvider { Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE; private static final String TAG = "ResumeOnRebootServiceProvider"; + // The system property name that overrides the default service provider package name. + static final String PROP_ROR_PROVIDER_PACKAGE = + "persist.sys.resume_on_reboot_provider_package"; + private final Context mContext; private final PackageManager mPackageManager; @@ -72,12 +77,19 @@ public class ResumeOnRebootServiceProvider { private ServiceInfo resolveService() { Intent intent = new Intent(); intent.setAction(ResumeOnRebootService.SERVICE_INTERFACE); - if (PROVIDER_PACKAGE != null && !PROVIDER_PACKAGE.equals("")) { - intent.setPackage(PROVIDER_PACKAGE); + int queryFlag = PackageManager.GET_SERVICES; + String testAppName = SystemProperties.get(PROP_ROR_PROVIDER_PACKAGE, ""); + if (!testAppName.isEmpty()) { + Slog.i(TAG, "Using test app: " + testAppName); + intent.setPackage(testAppName); + } else { + queryFlag |= PackageManager.MATCH_SYSTEM_ONLY; + if (PROVIDER_PACKAGE != null && !PROVIDER_PACKAGE.equals("")) { + intent.setPackage(PROVIDER_PACKAGE); + } } - List<ResolveInfo> resolvedIntents = - mPackageManager.queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY); + List<ResolveInfo> resolvedIntents = mPackageManager.queryIntentServices(intent, queryFlag); for (ResolveInfo resolvedInfo : resolvedIntents) { if (resolvedInfo.serviceInfo != null && PROVIDER_REQUIRED_PERMISSION.equals(resolvedInfo.serviceInfo.permission)) { @@ -120,6 +132,7 @@ public class ResumeOnRebootServiceProvider { if (mServiceConnection != null) { mContext.unbindService(mServiceConnection); } + mBinder = null; } /** Bind to the service */ diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java index 6d420a95e26c..35e6489debcf 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java @@ -18,7 +18,6 @@ package com.android.server.locksettings; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; -import android.security.keystore2.AndroidKeyStoreProvider; import android.util.Slog; import java.io.ByteArrayOutputStream; @@ -141,19 +140,8 @@ public class SyntheticPasswordCrypto { } } - /** - * TODO This function redirects keystore access to the legacy keystore during a transitional - * phase during which not all calling code has been adjusted to use Keystore 2.0. - * This can be reverted to a constant of "AndroidKeyStore" when b/171305684 is complete. - * The specific bug for this component is b/171305115. - */ static String androidKeystoreProviderName() { - if (AndroidKeyStoreProvider.isInstalled()) { - return "AndroidKeyStoreLegacy"; - } else { - return "AndroidKeystore"; - } - + return "AndroidKeyStore"; } public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) { diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 6d1c68039ee5..3cc32bef0e67 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -16,10 +16,10 @@ package com.android.server.net; -import static android.net.ConnectivityManager.TYPE_NONE; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; +import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.provider.Settings.ACTION_VPN_SETTINGS; -import static com.android.server.connectivity.NetworkNotificationManager.NOTIFICATION_CHANNEL_VPN; import android.annotation.NonNull; import android.annotation.Nullable; @@ -28,43 +28,37 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.net.ConnectivityManager; import android.net.LinkAddress; import android.net.LinkProperties; +import android.net.Network; import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkInfo.State; +import android.net.NetworkRequest; import android.os.Handler; import android.security.KeyStore; import android.text.TextUtils; import android.util.Log; import com.android.internal.R; -import com.android.internal.annotations.GuardedBy; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; -import com.android.server.ConnectivityService; -import com.android.server.EventLogTags; import com.android.server.connectivity.Vpn; import java.util.List; import java.util.Objects; /** - * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be - * connected and kicks off VPN connection, managing any required {@code netd} - * firewall rules. + * State tracker for legacy lockdown VPN. Watches for physical networks to be + * connected and kicks off VPN connection. */ public class LockdownVpnTracker { private static final String TAG = "LockdownVpnTracker"; - /** Number of VPN attempts before waiting for user intervention. */ - private static final int MAX_ERROR_COUNT = 4; - public static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET"; @NonNull private final Context mContext; - @NonNull private final ConnectivityService mConnService; + @NonNull private final ConnectivityManager mCm; @NonNull private final NotificationManager mNotificationManager; @NonNull private final Handler mHandler; @NonNull private final Vpn mVpn; @@ -76,19 +70,73 @@ public class LockdownVpnTracker { @NonNull private final PendingIntent mConfigIntent; @NonNull private final PendingIntent mResetIntent; + @NonNull private final NetworkCallback mDefaultNetworkCallback = new NetworkCallback(); + @NonNull private final VpnNetworkCallback mVpnNetworkCallback = new VpnNetworkCallback(); + + private class NetworkCallback extends ConnectivityManager.NetworkCallback { + private Network mNetwork = null; + private LinkProperties mLinkProperties = null; + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties lp) { + boolean networkChanged = false; + if (!network.equals(mNetwork)) { + // The default network just changed. + mNetwork = network; + networkChanged = true; + } + mLinkProperties = lp; + // Backwards compatibility: previously, LockdownVpnTracker only responded to connects + // and disconnects, not LinkProperties changes on existing networks. + if (networkChanged) { + synchronized (mStateLock) { + handleStateChangedLocked(); + } + } + } + + @Override + public void onLost(Network network) { + // The default network has gone down. + mNetwork = null; + mLinkProperties = null; + synchronized (mStateLock) { + handleStateChangedLocked(); + } + } + + public Network getNetwork() { + return mNetwork; + } + + public LinkProperties getLinkProperties() { + return mLinkProperties; + } + } + + private class VpnNetworkCallback extends NetworkCallback { + @Override + public void onAvailable(Network network) { + synchronized (mStateLock) { + handleStateChangedLocked(); + } + } + @Override + public void onLost(Network network) { + onAvailable(network); + } + } + @Nullable private String mAcceptedEgressIface; - private int mErrorCount; - public LockdownVpnTracker(@NonNull Context context, - @NonNull ConnectivityService connService, @NonNull Handler handler, @NonNull KeyStore keyStore, @NonNull Vpn vpn, @NonNull VpnProfile profile) { mContext = Objects.requireNonNull(context); - mConnService = Objects.requireNonNull(connService); + mCm = mContext.getSystemService(ConnectivityManager.class); mHandler = Objects.requireNonNull(handler); mVpn = Objects.requireNonNull(vpn); mProfile = Objects.requireNonNull(profile); @@ -110,24 +158,20 @@ public class LockdownVpnTracker { * connection when ready, or setting firewall rules once VPN is connected. */ private void handleStateChangedLocked() { - - final NetworkInfo egressInfo = mConnService.getActiveNetworkInfoUnfiltered(); - final LinkProperties egressProp = mConnService.getActiveLinkProperties(); + final Network network = mDefaultNetworkCallback.getNetwork(); + final LinkProperties egressProp = mDefaultNetworkCallback.getLinkProperties(); final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); final VpnConfig vpnConfig = mVpn.getLegacyVpnConfig(); // Restart VPN when egress network disconnected or changed - final boolean egressDisconnected = egressInfo == null - || State.DISCONNECTED.equals(egressInfo.getState()); + final boolean egressDisconnected = (network == null); final boolean egressChanged = egressProp == null || !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName()); - final int egressType = (egressInfo == null) ? TYPE_NONE : egressInfo.getType(); final String egressIface = (egressProp == null) ? null : egressProp.getInterfaceName(); - Log.d(TAG, "handleStateChanged: egress=" + egressType - + " " + mAcceptedEgressIface + "->" + egressIface); + Log.d(TAG, "handleStateChanged: egress=" + mAcceptedEgressIface + "->" + egressIface); if (egressDisconnected || egressChanged) { mAcceptedEgressIface = null; @@ -138,46 +182,49 @@ public class LockdownVpnTracker { return; } - if (vpnInfo.getDetailedState() == DetailedState.FAILED) { - EventLogTags.writeLockdownVpnError(egressType); - } - - if (mErrorCount > MAX_ERROR_COUNT) { - showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); - - } else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) { - if (mProfile.isValidLockdownProfile()) { - Log.d(TAG, "Active network connected; starting VPN"); - EventLogTags.writeLockdownVpnConnecting(egressType); - showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected); - - mAcceptedEgressIface = egressProp.getInterfaceName(); - try { - // Use the privileged method because Lockdown VPN is initiated by the system, so - // no additional permission checks are necessary. - mVpn.startLegacyVpnPrivileged(mProfile, mKeyStore, null, egressProp); - } catch (IllegalStateException e) { - mAcceptedEgressIface = null; - Log.e(TAG, "Failed to start VPN", e); - showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); - } - } else { + // At this point, |network| is known to be non-null. + if (!vpnInfo.isConnectedOrConnecting()) { + if (!mProfile.isValidLockdownProfile()) { Log.e(TAG, "Invalid VPN profile; requires IP-based server and DNS"); showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); + return; } + Log.d(TAG, "Active network connected; starting VPN"); + showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected); + + mAcceptedEgressIface = egressIface; + try { + // Use the privileged method because Lockdown VPN is initiated by the system, so + // no additional permission checks are necessary. + // + // Pass in the underlying network here because the legacy VPN is, in fact, tightly + // coupled to a given underlying network and cannot provide mobility. This makes + // things marginally more correct in two ways: + // + // 1. When the legacy lockdown VPN connects, LegacyTypeTracker broadcasts an extra + // CONNECTED broadcast for the underlying network type. The underlying type comes + // from here. LTT *could* assume that the underlying network is the default + // network, but that might introduce a race condition if, say, the VPN starts + // connecting on cell, but when the connection succeeds and the agent is + // registered, the default network is now wifi. + // 2. If no underlying network is passed in, then CS will assume the underlying + // network is the system default. So, if the VPN is up and underlying network + // (e.g., wifi) disconnects, CS will inform apps that the VPN's capabilities have + // changed to match the new default network (e.g., cell). + mVpn.startLegacyVpnPrivileged(mProfile, mKeyStore, network, egressProp); + } catch (IllegalStateException e) { + mAcceptedEgressIface = null; + Log.e(TAG, "Failed to start VPN", e); + showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); + } } else if (vpnInfo.isConnected() && vpnConfig != null) { final String iface = vpnConfig.interfaze; final List<LinkAddress> sourceAddrs = vpnConfig.addresses; Log.d(TAG, "VPN connected using iface=" + iface + ", sourceAddr=" + sourceAddrs.toString()); - EventLogTags.writeLockdownVpnConnected(egressType); showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected); - - final NetworkInfo clone = new NetworkInfo(egressInfo); - augmentNetworkInfo(clone); - mConnService.sendConnectedBroadcast(clone); } } @@ -192,7 +239,15 @@ public class LockdownVpnTracker { mVpn.setEnableTeardown(false); mVpn.setLockdown(true); + mCm.setLegacyLockdownVpnEnabled(true); handleStateChangedLocked(); + + mCm.registerSystemDefaultNetworkCallback(mDefaultNetworkCallback, mHandler); + final NetworkRequest vpnRequest = new NetworkRequest.Builder() + .clearCapabilities() + .addTransportType(TRANSPORT_VPN) + .build(); + mCm.registerNetworkCallback(vpnRequest, mVpnNetworkCallback, mHandler); } public void shutdown() { @@ -205,20 +260,21 @@ public class LockdownVpnTracker { Log.d(TAG, "shutdownLocked()"); mAcceptedEgressIface = null; - mErrorCount = 0; mVpn.stopVpnRunnerPrivileged(); mVpn.setLockdown(false); + mCm.setLegacyLockdownVpnEnabled(false); hideNotification(); mVpn.setEnableTeardown(true); + mCm.unregisterNetworkCallback(mDefaultNetworkCallback); + mCm.unregisterNetworkCallback(mVpnNetworkCallback); } /** * Reset VPN lockdown tracker. Called by ConnectivityService when receiving * {@link #ACTION_LOCKDOWN_RESET} pending intent. */ - @GuardedBy("mConnService.mVpns") public void reset() { Log.d(TAG, "reset()"); synchronized (mStateLock) { @@ -229,28 +285,6 @@ public class LockdownVpnTracker { } } - public void onNetworkInfoChanged() { - synchronized (mStateLock) { - handleStateChangedLocked(); - } - } - - public void onVpnStateChanged(NetworkInfo info) { - if (info.getDetailedState() == DetailedState.FAILED) { - mErrorCount++; - } - synchronized (mStateLock) { - handleStateChangedLocked(); - } - } - - public void augmentNetworkInfo(NetworkInfo info) { - if (info.isConnected()) { - final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); - info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null); - } - } - private void showNotification(int titleRes, int iconRes) { final Notification.Builder builder = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_VPN) diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index a83edb75badb..9c4c5101cb6c 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -16,24 +16,38 @@ package com.android.server.os; +import static android.app.ApplicationExitInfo.REASON_CRASH_NATIVE; +import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import android.annotation.AppIdInt; +import android.annotation.CurrentTimeMillisLong; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.ActivityManager.RunningAppProcessInfo; +import android.app.ApplicationExitInfo; +import android.app.IParcelFileDescriptorRetriever; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.FileObserver; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.os.UserHandle; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoParseException; import com.android.internal.annotations.GuardedBy; import com.android.server.BootReceiver; import com.android.server.ServiceThread; +import com.android.server.os.TombstoneProtos.Cause; import com.android.server.os.TombstoneProtos.Tombstone; import libcore.io.IoUtils; @@ -42,7 +56,11 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; /** * A class to manage native tombstones. @@ -75,6 +93,9 @@ public final class NativeTombstoneManager { } void onSystemReady() { + registerForUserRemoval(); + registerForPackageRemoval(); + // Scan existing tombstones. mHandler.post(() -> { final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); @@ -94,8 +115,9 @@ public final class NativeTombstoneManager { if (filename.endsWith(".pb")) { handleProtoTombstone(path); + BootReceiver.addTombstoneToDropBox(mContext, path, true); } else { - BootReceiver.addTombstoneToDropBox(mContext, path); + BootReceiver.addTombstoneToDropBox(mContext, path, false); } } @@ -145,18 +167,164 @@ public final class NativeTombstoneManager { } } + /** + * Remove native tombstones matching a user and/or app. + * + * @param userId user id to filter by, selects all users if empty + * @param appId app id to filter by, selects all users if empty + */ + public void purge(Optional<Integer> userId, Optional<Integer> appId) { + mHandler.post(() -> { + synchronized (mLock) { + for (int i = mTombstones.size() - 1; i >= 0; --i) { + TombstoneFile tombstone = mTombstones.valueAt(i); + if (tombstone.matches(userId, appId)) { + tombstone.purge(); + mTombstones.removeAt(i); + } + } + } + }); + } + + private void purgePackage(int uid, boolean allUsers) { + final int appId = UserHandle.getAppId(uid); + Optional<Integer> userId; + if (allUsers) { + userId = Optional.empty(); + } else { + userId = Optional.of(UserHandle.getUserId(uid)); + } + purge(userId, Optional.of(appId)); + } + + private void purgeUser(int uid) { + purge(Optional.of(uid), Optional.empty()); + } + + private void registerForPackageRemoval() { + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); + filter.addDataScheme("package"); + mContext.registerReceiverForAllUsers(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final int uid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL); + if (uid == UserHandle.USER_NULL) return; + + final boolean allUsers = intent.getBooleanExtra( + Intent.EXTRA_REMOVED_FOR_ALL_USERS, false); + + purgePackage(uid, allUsers); + } + }, filter, null, mHandler); + } + + private void registerForUserRemoval() { + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_REMOVED); + mContext.registerReceiverForAllUsers(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId < 1) return; + + purgeUser(userId); + } + }, filter, null, mHandler); + } + + /** + * Collect native tombstones. + * + * @param output list to append to + * @param callingUid POSIX uid to filter by + * @param pid pid to filter by, ignored if zero + * @param maxNum maximum number of elements in output + */ + public void collectTombstones(ArrayList<ApplicationExitInfo> output, int callingUid, int pid, + int maxNum) { + CompletableFuture<Object> future = new CompletableFuture<>(); + + if (!UserHandle.isApp(callingUid)) { + return; + } + + final int userId = UserHandle.getUserId(callingUid); + final int appId = UserHandle.getAppId(callingUid); + + mHandler.post(() -> { + boolean appendedTombstones = false; + + synchronized (mLock) { + final int tombstonesSize = mTombstones.size(); + + tombstoneIter: + for (int i = 0; i < tombstonesSize; ++i) { + TombstoneFile tombstone = mTombstones.valueAt(i); + if (tombstone.matches(Optional.of(userId), Optional.of(appId))) { + if (pid != 0 && tombstone.mPid != pid) { + continue; + } + + // Try to attach to an existing REASON_CRASH_NATIVE. + final int outputSize = output.size(); + for (int j = 0; j < outputSize; ++j) { + ApplicationExitInfo exitInfo = output.get(j); + if (tombstone.matches(exitInfo)) { + exitInfo.setNativeTombstoneRetriever(tombstone.getPfdRetriever()); + continue tombstoneIter; + } + } + + if (output.size() < maxNum) { + appendedTombstones = true; + output.add(tombstone.toAppExitInfo()); + } + } + } + } + + if (appendedTombstones) { + Collections.sort(output, (lhs, rhs) -> { + // Reports should be ordered with newest reports first. + long diff = rhs.getTimestamp() - lhs.getTimestamp(); + if (diff < 0) { + return -1; + } else if (diff == 0) { + return 0; + } else { + return 1; + } + }); + } + future.complete(null); + }); + + try { + future.get(); + } catch (ExecutionException | InterruptedException ex) { + throw new RuntimeException(ex); + } + } + static class TombstoneFile { final ParcelFileDescriptor mPfd; - final @UserIdInt int mUserId; - final @AppIdInt int mAppId; + @UserIdInt int mUserId; + @AppIdInt int mAppId; + + int mPid; + int mUid; + String mProcessName; + @CurrentTimeMillisLong long mTimestampMs; + String mCrashReason; boolean mPurged = false; + final IParcelFileDescriptorRetriever mRetriever = new ParcelFileDescriptorRetriever(); - TombstoneFile(ParcelFileDescriptor pfd, @UserIdInt int userId, @AppIdInt int appId) { + TombstoneFile(ParcelFileDescriptor pfd) { mPfd = pfd; - mUserId = userId; - mAppId = appId; } public boolean matches(Optional<Integer> userId, Optional<Integer> appId) { @@ -175,24 +343,90 @@ public final class NativeTombstoneManager { return true; } + public boolean matches(ApplicationExitInfo exitInfo) { + if (exitInfo.getReason() != REASON_CRASH_NATIVE) { + return false; + } + + if (exitInfo.getPid() != mPid) { + return false; + } + + if (exitInfo.getRealUid() != mUid) { + return false; + } + + if (Math.abs(exitInfo.getTimestamp() - mTimestampMs) > 1000) { + return false; + } + + return true; + } + public void dispose() { IoUtils.closeQuietly(mPfd); } + public void purge() { + if (!mPurged) { + // There's no way to atomically unlink a specific file for which we have an fd from + // a path, which means that we can't safely delete a tombstone without coordination + // with tombstoned (which has a risk of deadlock if for example, system_server hangs + // with a flock). Do the next best thing, and just truncate the file. + // + // We don't have to worry about inflicting a SIGBUS on a process that has the + // tombstone mmaped, because we only clear if the package has been removed, which + // means no one with access to the tombstone should be left. + try { + Os.ftruncate(mPfd.getFileDescriptor(), 0); + } catch (ErrnoException ex) { + Slog.e(TAG, "Failed to truncate tombstone", ex); + } + mPurged = true; + } + } + static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) { final FileInputStream is = new FileInputStream(pfd.getFileDescriptor()); final ProtoInputStream stream = new ProtoInputStream(is); + int pid = 0; int uid = 0; + String processName = ""; + String crashReason = ""; String selinuxLabel = ""; try { while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { + case (int) Tombstone.PID: + pid = stream.readInt(Tombstone.PID); + break; + case (int) Tombstone.UID: uid = stream.readInt(Tombstone.UID); break; + case (int) Tombstone.PROCESS_NAME: + processName = stream.readString(Tombstone.PROCESS_NAME); + break; + + case (int) Tombstone.CAUSE: + long token = stream.start(Tombstone.CAUSE); + cause: + while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (stream.getFieldNumber()) { + case (int) Cause.HUMAN_READABLE: + crashReason = stream.readString(Cause.HUMAN_READABLE); + break cause; + + default: + break; + } + } + stream.end(token); + break; + case (int) Tombstone.SELINUX_LABEL: selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL); break; @@ -201,7 +435,7 @@ public final class NativeTombstoneManager { break; } } - } catch (IOException ex) { + } catch (IOException | ProtoParseException ex) { Slog.e(TAG, "Failed to parse tombstone", ex); return Optional.empty(); } @@ -211,6 +445,14 @@ public final class NativeTombstoneManager { return Optional.empty(); } + long timestampMs = 0; + try { + StructStat stat = Os.fstat(pfd.getFileDescriptor()); + timestampMs = stat.st_atim.tv_sec * 1000 + stat.st_atim.tv_nsec / 1000000; + } catch (ErrnoException ex) { + Slog.e(TAG, "Failed to get timestamp of tombstone", ex); + } + final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); @@ -219,7 +461,74 @@ public final class NativeTombstoneManager { return Optional.empty(); } - return Optional.of(new TombstoneFile(pfd, userId, appId)); + TombstoneFile result = new TombstoneFile(pfd); + + result.mUserId = userId; + result.mAppId = appId; + result.mPid = pid; + result.mUid = uid; + result.mProcessName = processName; + result.mTimestampMs = timestampMs; + result.mCrashReason = crashReason; + + return Optional.of(result); + } + + public IParcelFileDescriptorRetriever getPfdRetriever() { + return mRetriever; + } + + public ApplicationExitInfo toAppExitInfo() { + ApplicationExitInfo info = new ApplicationExitInfo(); + info.setPid(mPid); + info.setRealUid(mUid); + info.setPackageUid(mUid); + info.setDefiningUid(mUid); + info.setProcessName(mProcessName); + info.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE); + + // Signal numbers are architecture-specific! + // We choose to provide nothing here, to avoid leading users astray. + info.setStatus(0); + + // No way for us to find out. + info.setImportance(RunningAppProcessInfo.IMPORTANCE_GONE); + info.setPackageName(""); + info.setProcessStateSummary(null); + + // We could find out, but they didn't get OOM-killed... + info.setPss(0); + info.setRss(0); + + info.setTimestamp(mTimestampMs); + info.setDescription(mCrashReason); + + info.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN); + info.setNativeTombstoneRetriever(mRetriever); + + return info; + } + + + class ParcelFileDescriptorRetriever extends IParcelFileDescriptorRetriever.Stub { + ParcelFileDescriptorRetriever() {} + + public @Nullable ParcelFileDescriptor getPfd() { + if (mPurged) { + return null; + } + + // Reopen the file descriptor as read-only. + try { + final String path = "/proc/self/fd/" + mPfd.getFd(); + ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(path), + MODE_READ_ONLY); + return pfd; + } catch (FileNotFoundException ex) { + Slog.e(TAG, "failed to reopen file descriptor as read-only", ex); + return null; + } + } } } diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 48ec9b4b502d..acec93cac34d 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -241,7 +241,7 @@ public class BackgroundDexOptService extends JobService { // trade-off worth doing to save boot time work. int result = pm.performDexOptWithStatus(new DexoptOptions( pkg, - PackageManagerService.REASON_BOOT, + PackageManagerService.REASON_POST_BOOT, DexoptOptions.DEXOPT_BOOT_COMPLETE)); if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { updatedPackages.add(pkg); diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 79607351b18a..4a2fb5da5e70 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -687,7 +687,8 @@ public class PackageDexOptimizer { boolean generateCompactDex = true; switch (compilationReason) { case PackageManagerService.REASON_FIRST_BOOT: - case PackageManagerService.REASON_BOOT: + case PackageManagerService.REASON_BOOT_AFTER_OTA: + case PackageManagerService.REASON_POST_BOOT: case PackageManagerService.REASON_INSTALL: generateCompactDex = false; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a7b9622ab3c0..febbfbce9e6c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -676,17 +676,18 @@ public class PackageManagerService extends IPackageManager.Stub // Compilation reasons. public static final int REASON_UNKNOWN = -1; public static final int REASON_FIRST_BOOT = 0; - public static final int REASON_BOOT = 1; - public static final int REASON_INSTALL = 2; - public static final int REASON_INSTALL_FAST = 3; - public static final int REASON_INSTALL_BULK = 4; - public static final int REASON_INSTALL_BULK_SECONDARY = 5; - public static final int REASON_INSTALL_BULK_DOWNGRADED = 6; - public static final int REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 7; - public static final int REASON_BACKGROUND_DEXOPT = 8; - public static final int REASON_AB_OTA = 9; - public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 10; - public static final int REASON_SHARED = 11; + public static final int REASON_BOOT_AFTER_OTA = 1; + public static final int REASON_POST_BOOT = 2; + public static final int REASON_INSTALL = 3; + public static final int REASON_INSTALL_FAST = 4; + public static final int REASON_INSTALL_BULK = 5; + public static final int REASON_INSTALL_BULK_SECONDARY = 6; + public static final int REASON_INSTALL_BULK_DOWNGRADED = 7; + public static final int REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 8; + public static final int REASON_BACKGROUND_DEXOPT = 9; + public static final int REASON_AB_OTA = 10; + public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 11; + public static final int REASON_SHARED = 12; public static final int REASON_LAST = REASON_SHARED; @@ -9664,10 +9665,7 @@ public class PackageManagerService extends IPackageManager.Stub // first boot, as they do not have profile data. boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade; - // We need to re-extract after a pruned cache, as AoT-ed files will be out of date. - boolean causePrunedCache = VMRuntime.didPruneDalvikCache(); - - if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) { + if (!causeUpgrade && !causeFirstBoot) { return; } @@ -9684,7 +9682,7 @@ public class PackageManagerService extends IPackageManager.Stub final long startTime = System.nanoTime(); final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */, - causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT, + causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT_AFTER_OTA, false /* bootComplete */); final int elapsedTimeSeconds = diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java index 9cd55a6bb07e..636db111be88 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java @@ -29,7 +29,8 @@ public class PackageManagerServiceCompilerMapping { // Names for compilation reasons. public static final String REASON_STRINGS[] = { "first-boot", - "boot", + "boot-after-ota", + "post-boot", "install", "install-fast", "install-bulk", diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 6e145b5ecbe4..7de5c9467930 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -587,7 +587,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private static final int TRON_COMPILATION_REASON_ERROR = 0; private static final int TRON_COMPILATION_REASON_UNKNOWN = 1; private static final int TRON_COMPILATION_REASON_FIRST_BOOT = 2; - private static final int TRON_COMPILATION_REASON_BOOT = 3; + private static final int TRON_COMPILATION_REASON_BOOT_DEPRECATED_SINCE_S = 3; private static final int TRON_COMPILATION_REASON_INSTALL = 4; private static final int TRON_COMPILATION_REASON_BG_DEXOPT = 5; private static final int TRON_COMPILATION_REASON_AB_OTA = 6; @@ -605,6 +605,8 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM = 18; private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19; + private static final int TRON_COMPILATION_REASON_BOOT_AFTER_OTA = 20; + private static final int TRON_COMPILATION_REASON_POST_BOOT = 21; // The annotation to add as a suffix to the compilation reason when dexopt was // performed with dex metadata. @@ -618,7 +620,8 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { case "unknown" : return TRON_COMPILATION_REASON_UNKNOWN; case "error" : return TRON_COMPILATION_REASON_ERROR; case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT; - case "boot" : return TRON_COMPILATION_REASON_BOOT; + case "boot-after-ota": return TRON_COMPILATION_REASON_BOOT_AFTER_OTA; + case "post-boot" : return TRON_COMPILATION_REASON_POST_BOOT; case "install" : return TRON_COMPILATION_REASON_INSTALL; case "bg-dexopt" : return TRON_COMPILATION_REASON_BG_DEXOPT; case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA; diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index cc6d80a2aeec..6d3de968b036 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -215,7 +215,7 @@ public class DexManager { searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT; if (primaryOrSplit && !isUsedByOtherApps - && !PLATFORM_PACKAGE_NAME.equals(searchResult.mOwningPackageName)) { + && !isPlatformPackage(searchResult.mOwningPackageName)) { // If the dex file is the primary apk (or a split) and not isUsedByOtherApps // do not record it. This case does not bring any new usable information // and can be safely skipped. @@ -232,15 +232,24 @@ public class DexManager { } String classLoaderContext = mapping.getValue(); + + // Overwrite the class loader context for system server (instead of merging it). + // We expect system server jars to only change contexts in between OTAs and to + // otherwise be stable. + // Instead of implementing a complex clear-context logic post OTA, it is much + // simpler to always override the context for system server. This way, the context + // will always be up to date and we will avoid merging which could lead to the + // the context being marked as variable and thus making dexopt non-optimal. + boolean overwriteCLC = isPlatformPackage(searchResult.mOwningPackageName); + if (classLoaderContext != null && VMRuntime.isValidClassLoaderContext(classLoaderContext)) { // Record dex file usage. If the current usage is a new pattern (e.g. new // secondary, or UsedByOtherApps), record will return true and we trigger an // async write to disk to make sure we don't loose the data in case of a reboot. - if (mPackageDexUsage.record(searchResult.mOwningPackageName, dexPath, loaderUserId, loaderIsa, primaryOrSplit, - loadingAppInfo.packageName, classLoaderContext)) { + loadingAppInfo.packageName, classLoaderContext, overwriteCLC)) { mPackageDexUsage.maybeWriteAsync(); } } @@ -474,7 +483,7 @@ public class DexManager { * because they don't need to be compiled).. */ public boolean dexoptSecondaryDex(DexoptOptions options) { - if (PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) { + if (isPlatformPackage(options.getPackageName())) { // We could easily redirect to #dexoptSystemServer in this case. But there should be // no-one calling this method directly for system server. // As such we prefer to abort in this case. @@ -534,7 +543,7 @@ public class DexManager { * <p>PackageDexOptimizer.DEX_OPT_PERFORMED if all dexopt operations succeeded. */ public int dexoptSystemServer(DexoptOptions options) { - if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) { + if (!isPlatformPackage(options.getPackageName())) { Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:" + options.getPackageName()); return PackageDexOptimizer.DEX_OPT_FAILED; @@ -662,7 +671,7 @@ public class DexManager { // Special handle system server files. // We don't need an installd call because we have permissions to check if the file // exists. - if (PLATFORM_PACKAGE_NAME.equals(packageName)) { + if (isPlatformPackage(packageName)) { if (!Files.exists(Paths.get(dexPath))) { if (DEBUG) { Slog.w(TAG, "A dex file previously loaded by System Server does not exist " @@ -739,7 +748,8 @@ public class DexManager { boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName, dexPath, userId, isa, /*primaryOrSplit*/ false, loadingPackage, - PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT); + PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT, + /*overwriteCLC*/ false); update |= newUpdate; } if (update) { @@ -809,7 +819,7 @@ public class DexManager { // Note: We don't have any way to detect which code paths are actually // owned by system server. We can only assume that such paths are on // system partitions. - if (PLATFORM_PACKAGE_NAME.equals(loadingAppInfo.packageName)) { + if (isPlatformPackage(loadingAppInfo.packageName)) { if (isSystemServerDexPathSupportedForOdex(dexPath)) { // We record system server dex files as secondary dex files. // The reason is that we only record the class loader context for secondary dex @@ -842,6 +852,11 @@ public class DexManager { return new DexSearchResult(null, DEX_SEARCH_NOT_FOUND); } + /** Returns true if this is the platform package .*/ + private static boolean isPlatformPackage(String packageName) { + return PLATFORM_PACKAGE_NAME.equals(packageName); + } + private static <K,V> V putIfAbsent(Map<K,V> map, K key, V newValue) { V existingValue = map.putIfAbsent(key, newValue); return existingValue == null ? newValue : existingValue; diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java index 10760f52a02b..3d63b75c5da1 100644 --- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java +++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java @@ -111,17 +111,18 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { * @param dexPath the path of the dex files being loaded * @param ownerUserId the user id which runs the code loading the dex files * @param loaderIsa the ISA of the app loading the dex files - * @param isUsedByOtherApps whether or not this dex file was not loaded by its owning package * @param primaryOrSplit whether or not the dex file is a primary/split dex. True indicates * the file is either primary or a split. False indicates the file is secondary dex. * @param loadingPackageName the package performing the load. Recorded only if it is different * than {@param owningPackageName}. + * @param overwriteCLC if true, the class loader context will be overwritten instead of being + * merged * @return true if the dex load constitutes new information, or false if this information * has been seen before. */ /* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId, String loaderIsa, boolean primaryOrSplit, - String loadingPackageName, String classLoaderContext) { + String loadingPackageName, String classLoaderContext, boolean overwriteCLC) { if (!PackageManagerServiceUtils.checkISA(loaderIsa)) { throw new IllegalArgumentException("loaderIsa " + loaderIsa + " is unsupported"); } @@ -193,7 +194,7 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { } // Merge the information into the existing data. // Returns true if there was an update. - return existingData.merge(newData) || updateLoadingPackages; + return existingData.merge(newData, overwriteCLC) || updateLoadingPackages; } } } @@ -809,14 +810,16 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { mLoadingPackages = new HashSet<>(other.mLoadingPackages); } - private boolean merge(DexUseInfo dexUseInfo) { + private boolean merge(DexUseInfo dexUseInfo, boolean overwriteCLC) { boolean oldIsUsedByOtherApps = mIsUsedByOtherApps; mIsUsedByOtherApps = mIsUsedByOtherApps || dexUseInfo.mIsUsedByOtherApps; boolean updateIsas = mLoaderIsas.addAll(dexUseInfo.mLoaderIsas); boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages); String oldClassLoaderContext = mClassLoaderContext; - if (isUnsupportedContext(mClassLoaderContext)) { + if (overwriteCLC) { + mClassLoaderContext = dexUseInfo.mClassLoaderContext; + } else if (isUnsupportedContext(mClassLoaderContext)) { mClassLoaderContext = dexUseInfo.mClassLoaderContext; } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) { // We detected a context change. diff --git a/services/core/java/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdater.java b/services/core/java/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdater.java new file mode 100644 index 000000000000..6cdd4df824a8 --- /dev/null +++ b/services/core/java/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdater.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.pm.parsing.library; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.pm.parsing.pkg.ParsedPackage; + +/** + * Updates a package to remove dependency on android.net.ipsec.ike library. + * + * @hide + */ +@VisibleForTesting +public class AndroidNetIpSecIkeUpdater extends PackageSharedLibraryUpdater { + + private static final String LIBRARY_NAME = "android.net.ipsec.ike"; + + @Override + public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) { + removeLibrary(parsedPackage, LIBRARY_NAME); + } +} diff --git a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java index 1405a7d613f1..8a8a302734b1 100644 --- a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java +++ b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java @@ -45,6 +45,9 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { static { final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>(); + // Remove android.net.ipsec.ike library, it is added to boot classpath since Android S. + packageUpdaters.add(new AndroidNetIpSecIkeUpdater()); + // Remove com.google.android.maps library. packageUpdaters.add(new ComGoogleAndroidMapsUpdater()); diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java index a6f02e7842d3..24d49a3cfefe 100644 --- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java +++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java @@ -125,8 +125,10 @@ public class AndroidPackageUtils { public static void validatePackageDexMetadata(AndroidPackage pkg) throws PackageParserException { Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values(); + String packageName = pkg.getPackageName(); + long versionCode = pkg.toAppInfoWithoutState().longVersionCode; for (String dexMetadata : apkToDexMetadataList) { - DexMetadataHelper.validateDexMetadataFile(dexMetadata); + DexMetadataHelper.validateDexMetadataFile(dexMetadata, packageName, versionCode); } } diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS index 0e88862e01b1..e05ef482ec08 100644 --- a/services/core/java/com/android/server/pm/permission/OWNERS +++ b/services/core/java/com/android/server/pm/permission/OWNERS @@ -1,4 +1,3 @@ -moltmann@google.com zhanghai@google.com per-file DefaultPermissionGrantPolicy.java = hackbod@android.com per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com @@ -7,5 +6,4 @@ per-file DefaultPermissionGrantPolicy.java = toddke@google.com per-file DefaultPermissionGrantPolicy.java = yamasani@google.com per-file DefaultPermissionGrantPolicy.java = patb@google.com per-file DefaultPermissionGrantPolicy.java = eugenesusla@google.com -per-file DefaultPermissionGrantPolicy.java = moltmann@google.com per-file DefaultPermissionGrantPolicy.java = zhanghai@google.com diff --git a/services/core/java/com/android/server/role/OWNERS b/services/core/java/com/android/server/role/OWNERS index b94d98827d71..31e3549d9111 100644 --- a/services/core/java/com/android/server/role/OWNERS +++ b/services/core/java/com/android/server/role/OWNERS @@ -1,5 +1,4 @@ svetoslavganov@google.com -moltmann@google.com zhanghai@google.com evanseverson@google.com eugenesusla@google.com diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 75277d1c338d..afcf81fdbcfa 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -700,7 +700,7 @@ public class TrustManagerService extends SystemService { if (changed) { dispatchDeviceLocked(userId, locked); - mAuthorizationService.onLockScreenEvent(locked, userId, null); + Authorization.onLockScreenEvent(locked, userId, null); 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)}) @@ -1258,7 +1258,7 @@ public class TrustManagerService extends SystemService { mDeviceLockedForUser.put(userId, locked); } - mAuthorizationService.onLockScreenEvent(locked, userId, null); + Authorization.onLockScreenEvent(locked, userId, null); KeyStore.getInstance().onUserLockedStateChanged(userId, locked); if (locked) { diff --git a/services/core/java/com/android/server/vcn/Android.bp b/services/core/java/com/android/server/vcn/Android.bp index 5ed204fd7640..ab5da3ee45b4 100644 --- a/services/core/java/com/android/server/vcn/Android.bp +++ b/services/core/java/com/android/server/vcn/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-vcn-util-sources", srcs: ["util/**/*.java"], -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index 3726407211d5..6ad30b544257 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -19,10 +19,12 @@ package com.android.server.vcn; import static com.android.server.VcnManagementService.VDBG; import android.annotation.NonNull; +import android.annotation.Nullable; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.vcn.VcnConfig; import android.net.vcn.VcnGatewayConnectionConfig; +import android.net.vcn.VcnManager.VcnErrorCode; import android.os.Handler; import android.os.Message; import android.os.ParcelUuid; @@ -30,7 +32,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; -import com.android.server.VcnManagementService.VcnSafemodeCallback; +import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import java.util.Collections; @@ -86,18 +88,18 @@ public class Vcn extends Handler { private static final int MSG_CMD_TEARDOWN = MSG_CMD_BASE; /** - * Causes this VCN to immediately enter Safemode. + * Causes this VCN to immediately enter safe mode. * - * <p>Upon entering Safemode, the VCN will unregister its RequestListener, tear down all of its - * VcnGatewayConnections, and notify VcnManagementService that it is in Safemode. + * <p>Upon entering safe mode, the VCN will unregister its RequestListener, tear down all of its + * VcnGatewayConnections, and notify VcnManagementService that it is in safe mode. */ - private static final int MSG_CMD_ENTER_SAFEMODE = MSG_CMD_BASE + 1; + private static final int MSG_CMD_ENTER_SAFE_MODE = MSG_CMD_BASE + 1; @NonNull private final VcnContext mVcnContext; @NonNull private final ParcelUuid mSubscriptionGroup; @NonNull private final Dependencies mDeps; @NonNull private final VcnNetworkRequestListener mRequestListener; - @NonNull private final VcnSafemodeCallback mVcnSafemodeCallback; + @NonNull private final VcnCallback mVcnCallback; @NonNull private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections = @@ -125,14 +127,8 @@ public class Vcn extends Handler { @NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config, @NonNull TelephonySubscriptionSnapshot snapshot, - @NonNull VcnSafemodeCallback vcnSafemodeCallback) { - this( - vcnContext, - subscriptionGroup, - config, - snapshot, - vcnSafemodeCallback, - new Dependencies()); + @NonNull VcnCallback vcnCallback) { + this(vcnContext, subscriptionGroup, config, snapshot, vcnCallback, new Dependencies()); } @VisibleForTesting(visibility = Visibility.PRIVATE) @@ -141,13 +137,12 @@ public class Vcn extends Handler { @NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config, @NonNull TelephonySubscriptionSnapshot snapshot, - @NonNull VcnSafemodeCallback vcnSafemodeCallback, + @NonNull VcnCallback vcnCallback, @NonNull Dependencies deps) { super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper()); mVcnContext = vcnContext; mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup"); - mVcnSafemodeCallback = - Objects.requireNonNull(vcnSafemodeCallback, "Missing vcnSafemodeCallback"); + mVcnCallback = Objects.requireNonNull(vcnCallback, "Missing vcnCallback"); mDeps = Objects.requireNonNull(deps, "Missing deps"); mRequestListener = new VcnNetworkRequestListener(); @@ -216,8 +211,8 @@ public class Vcn extends Handler { case MSG_CMD_TEARDOWN: handleTeardown(); break; - case MSG_CMD_ENTER_SAFEMODE: - handleEnterSafemode(); + case MSG_CMD_ENTER_SAFE_MODE: + handleEnterSafeMode(); break; default: Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what); @@ -243,10 +238,10 @@ public class Vcn extends Handler { mIsActive.set(false); } - private void handleEnterSafemode() { + private void handleEnterSafeMode() { handleTeardown(); - mVcnSafemodeCallback.onEnteredSafemode(); + mVcnCallback.onEnteredSafeMode(); } private void handleNetworkRequested( @@ -335,14 +330,31 @@ public class Vcn extends Handler { /** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */ @VisibleForTesting(visibility = Visibility.PACKAGE) public interface VcnGatewayStatusCallback { - /** Called by a VcnGatewayConnection to indicate that it has entered Safemode. */ - void onEnteredSafemode(); + /** Called by a VcnGatewayConnection to indicate that it has entered safe mode. */ + void onEnteredSafeMode(); + + /** Callback by a VcnGatewayConnection to indicate that an error occurred. */ + void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable String exceptionClass, + @Nullable String exceptionMessage); } private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback { @Override - public void onEnteredSafemode() { - sendMessage(obtainMessage(MSG_CMD_ENTER_SAFEMODE)); + public void onEnteredSafeMode() { + sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE)); + } + + @Override + public void onGatewayConnectionError( + @NonNull int[] networkCapabilities, + @VcnErrorCode int errorCode, + @Nullable String exceptionClass, + @Nullable String exceptionMessage) { + mVcnCallback.onGatewayConnectionError( + networkCapabilities, errorCode, exceptionClass, exceptionMessage); } } diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 2503e812f9e1..06748a3aa2d1 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -22,11 +22,15 @@ 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_WIFI; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR; import static com.android.server.VcnManagementService.VDBG; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.net.InetAddresses; import android.net.IpPrefix; import android.net.IpSecManager; @@ -37,10 +41,12 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkAgent; +import android.net.NetworkAgent.ValidationStatus; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.RouteInfo; import android.net.TelephonyNetworkSpecifier; +import android.net.Uri; import android.net.annotations.PolicyDirection; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.ChildSessionConfiguration; @@ -49,7 +55,9 @@ import android.net.ipsec.ike.IkeSession; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.exceptions.AuthenticationFailedException; import android.net.ipsec.ike.exceptions.IkeException; +import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnTransportInfo; @@ -58,6 +66,9 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.Message; import android.os.ParcelUuid; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.SystemClock; import android.util.ArraySet; import android.util.Slog; @@ -65,6 +76,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.internal.util.WakeupMessage; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback; @@ -120,15 +132,37 @@ import java.util.concurrent.TimeUnit; * +----------------------------+ * </pre> * + * <p>All messages in VcnGatewayConnection <b>should</b> be enqueued using {@link + * #sendMessageAndAcquireWakeLock}. Careful consideration should be given to any uses of {@link + * #sendMessage} directly, as they are not guaranteed to be processed in a timely manner (due to the + * lack of WakeLocks). + * + * <p>Any attempt to remove messages from the Handler should be done using {@link + * #removeEqualMessages}. This is necessary to ensure that the WakeLock is correctly released when + * no messages remain in the Handler queue. + * * @hide */ public class VcnGatewayConnection extends StateMachine { private static final String TAG = VcnGatewayConnection.class.getSimpleName(); + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0"); + + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final String TEARDOWN_TIMEOUT_ALARM = TAG + "_TEARDOWN_TIMEOUT_ALARM"; + + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final String DISCONNECT_REQUEST_ALARM = TAG + "_DISCONNECT_REQUEST_ALARM"; + + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final String RETRY_TIMEOUT_ALARM = TAG + "_RETRY_TIMEOUT_ALARM"; + + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final String SAFEMODE_TIMEOUT_ALARM = TAG + "_SAFEMODE_TIMEOUT_ALARM"; + private static final int[] MERGED_CAPABILITIES = new int[] {NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_NOT_ROAMING}; - - private static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0"); private static final int ARG_NOT_PRESENT = Integer.MIN_VALUE; private static final String DISCONNECT_REASON_INTERNAL_ERROR = "Uncaught exception: "; @@ -137,11 +171,15 @@ public class VcnGatewayConnection extends StateMachine { private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel"; private static final int TOKEN_ALL = Integer.MIN_VALUE; - private static final int NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS = 30; + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS = 30; @VisibleForTesting(visibility = Visibility.PRIVATE) static final int TEARDOWN_TIMEOUT_SECONDS = 5; + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int SAFEMODE_TIMEOUT_SECONDS = 30; + private interface EventInfo {} /** @@ -384,6 +422,23 @@ public class VcnGatewayConnection extends StateMachine { // TODO(b/178426520): implement handling of this event private static final int EVENT_SUBSCRIPTIONS_CHANGED = 9; + /** + * Sent when this VcnGatewayConnection has entered safe mode. + * + * <p>A VcnGatewayConnection enters safe mode when it takes over {@link + * #SAFEMODE_TIMEOUT_SECONDS} to enter {@link ConnectedState}. + * + * <p>When a VcnGatewayConnection enters safe mode, it will fire {@link + * VcnGatewayStatusCallback#onEnteredSafeMode()} to notify its Vcn. The Vcn will then shut down + * its VcnGatewayConnectin(s). + * + * <p>Relevant in DisconnectingState, ConnectingState, ConnectedState (if the Vcn Network is not + * validated yet), and RetryTimeoutState. + * + * @param arg1 The "all" token; this signal is always honored. + */ + private static final int EVENT_SAFE_MODE_TIMEOUT_EXCEEDED = 10; + @VisibleForTesting(visibility = Visibility.PRIVATE) @NonNull final DisconnectedState mDisconnectedState = new DisconnectedState(); @@ -412,11 +467,26 @@ public class VcnGatewayConnection extends StateMachine { @NonNull private final VcnGatewayConnectionConfig mConnectionConfig; @NonNull private final VcnGatewayStatusCallback mGatewayStatusCallback; @NonNull private final Dependencies mDeps; - @NonNull private final VcnUnderlyingNetworkTrackerCallback mUnderlyingNetworkTrackerCallback; @NonNull private final IpSecManager mIpSecManager; - @NonNull private final IpSecTunnelInterface mTunnelIface; + + @Nullable private IpSecTunnelInterface mTunnelIface = null; + + /** + * WakeLock to be held when processing messages on the Handler queue. + * + * <p>Used to prevent the device from going to sleep while there are VCN-related events to + * process for this VcnGatewayConnection. + * + * <p>Obtain a WakeLock when enquing messages onto the Handler queue. Once all messages in the + * Handler queue have been processed, the WakeLock can be released and cleared. + * + * <p>This WakeLock is also used for handling delayed messages by using WakeupMessages to send + * delayed messages to the Handler. When the WakeupMessage fires, it will obtain the WakeLock + * before enquing the delayed event to the Handler. + */ + @NonNull private final VcnWakeLock mWakeLock; /** Running state of this VcnGatewayConnection. */ private boolean mIsRunning = true; @@ -480,7 +550,13 @@ public class VcnGatewayConnection extends StateMachine { * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable * otherwise. */ - private NetworkAgent mNetworkAgent; + @VisibleForTesting(visibility = Visibility.PRIVATE) + NetworkAgent mNetworkAgent; + + @Nullable private WakeupMessage mTeardownTimeoutAlarm; + @Nullable private WakeupMessage mDisconnectRequestAlarm; + @Nullable private WakeupMessage mRetryTimeoutAlarm; + @Nullable private WakeupMessage mSafeModeTimeoutAlarm; public VcnGatewayConnection( @NonNull VcnContext vcnContext, @@ -517,6 +593,9 @@ public class VcnGatewayConnection extends StateMachine { mUnderlyingNetworkTrackerCallback = new VcnUnderlyingNetworkTrackerCallback(); + mWakeLock = + mDeps.newWakeLock(mVcnContext.getContext(), PowerManager.PARTIAL_WAKE_LOCK, TAG); + mUnderlyingNetworkTracker = mDeps.newUnderlyingNetworkTracker( mVcnContext, @@ -526,20 +605,6 @@ public class VcnGatewayConnection extends StateMachine { mUnderlyingNetworkTrackerCallback); mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class); - IpSecTunnelInterface iface; - try { - iface = - mIpSecManager.createIpSecTunnelInterface( - DUMMY_ADDR, DUMMY_ADDR, new Network(-1)); - } catch (IOException | ResourceUnavailableException e) { - teardownAsynchronously(); - mTunnelIface = null; - - return; - } - - mTunnelIface = iface; - addState(mDisconnectedState); addState(mDisconnectingState); addState(mConnectingState); @@ -557,7 +622,7 @@ public class VcnGatewayConnection extends StateMachine { * <p>Once torn down, this VcnTunnel CANNOT be started again. */ public void teardownAsynchronously() { - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_DISCONNECT_REQUESTED, TOKEN_ALL, new EventDisconnectRequestedInfo(DISCONNECT_REASON_TEARDOWN)); @@ -573,6 +638,13 @@ public class VcnGatewayConnection extends StateMachine { mTunnelIface.close(); } + releaseWakeLock(); + + cancelTeardownTimeoutAlarm(); + cancelDisconnectRequestAlarm(); + cancelRetryTimeoutAlarm(); + cancelSafeModeAlarm(); + mUnderlyingNetworkTracker.teardown(); } @@ -589,79 +661,377 @@ public class VcnGatewayConnection extends StateMachine { mLastSnapshot = snapshot; mUnderlyingNetworkTracker.updateSubscriptionSnapshot(mLastSnapshot); - sendMessage(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL); + sendMessageAndAcquireWakeLock(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL); } private class VcnUnderlyingNetworkTrackerCallback implements UnderlyingNetworkTrackerCallback { @Override public void onSelectedUnderlyingNetworkChanged( @Nullable UnderlyingNetworkRecord underlying) { + // TODO(b/180132994): explore safely removing this Thread check + mVcnContext.ensureRunningOnLooperThread(); + // TODO(b/179091925): Move the delayed-message handling to BaseState // If underlying is null, all underlying networks have been lost. Disconnect VCN after a // timeout. if (underlying == null) { - sendMessageDelayed( - EVENT_DISCONNECT_REQUESTED, - TOKEN_ALL, - new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST), - TimeUnit.SECONDS.toMillis(NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS)); - } else if (getHandler() != null) { - // Cancel any existing disconnect due to loss of underlying network - // getHandler() can return null if the state machine has already quit. Since this is - // called from other classes, this condition must be verified. - - getHandler() - .removeEqualMessages( - EVENT_DISCONNECT_REQUESTED, - new EventDisconnectRequestedInfo( - DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); + setDisconnectRequestAlarm(); + } else { + // Received a new Network so any previous alarm is irrelevant - cancel + clear it, + // and cancel any queued EVENT_DISCONNECT_REQUEST messages + cancelDisconnectRequestAlarm(); } - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_UNDERLYING_NETWORK_CHANGED, TOKEN_ALL, new EventUnderlyingNetworkChangedInfo(underlying)); } } - private void sendMessage(int what, int token, EventInfo data) { + private void acquireWakeLock() { + mVcnContext.ensureRunningOnLooperThread(); + + if (mIsRunning) { + mWakeLock.acquire(); + } + } + + private void releaseWakeLock() { + mVcnContext.ensureRunningOnLooperThread(); + + mWakeLock.release(); + } + + /** + * Attempt to release mWakeLock - this can only be done if the Handler is null (meaning the + * StateMachine has been shutdown and thus has no business keeping the WakeLock) or if there are + * no more messags left to process in the Handler queue (at which point the WakeLock can be + * released until more messages must be processed). + */ + private void maybeReleaseWakeLock() { + final Handler handler = getHandler(); + if (handler == null || !handler.hasMessagesOrCallbacks()) { + releaseWakeLock(); + } + } + + @Override + public void sendMessage(int what) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(what); + } + + @Override + public void sendMessage(int what, Object obj) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(what, obj); + } + + @Override + public void sendMessage(int what, int arg1) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(what, arg1); + } + + @Override + public void sendMessage(int what, int arg1, int arg2) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(what, arg1, arg2); + } + + @Override + public void sendMessage(int what, int arg1, int arg2, Object obj) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(what, arg1, arg2, obj); + } + + @Override + public void sendMessage(Message msg) { + Slog.wtf( + TAG, + "sendMessage should not be used in VcnGatewayConnection. See" + + " sendMessageAndAcquireWakeLock()"); + super.sendMessage(msg); + } + + // TODO(b/180146061): also override and Log.wtf() other Message handling methods + // In mind are sendMessageDelayed(), sendMessageAtFrontOfQueue, removeMessages, and + // removeDeferredMessages + + /** + * WakeLock-based alternative to {@link #sendMessage}. Use to guarantee that the device will not + * go to sleep before processing the sent message. + */ + private void sendMessageAndAcquireWakeLock(int what, int token) { + acquireWakeLock(); + super.sendMessage(what, token); + } + + /** + * WakeLock-based alternative to {@link #sendMessage}. Use to guarantee that the device will not + * go to sleep before processing the sent message. + */ + private void sendMessageAndAcquireWakeLock(int what, int token, EventInfo data) { + acquireWakeLock(); super.sendMessage(what, token, ARG_NOT_PRESENT, data); } - private void sendMessage(int what, int token, int arg2, EventInfo data) { + /** + * WakeLock-based alternative to {@link #sendMessage}. Use to guarantee that the device will not + * go to sleep before processing the sent message. + */ + private void sendMessageAndAcquireWakeLock(int what, int token, int arg2, EventInfo data) { + acquireWakeLock(); super.sendMessage(what, token, arg2, data); } - private void sendMessageDelayed(int what, int token, EventInfo data, long timeout) { - super.sendMessageDelayed(what, token, ARG_NOT_PRESENT, data, timeout); + /** + * WakeLock-based alternative to {@link #sendMessage}. Use to guarantee that the device will not + * go to sleep before processing the sent message. + */ + private void sendMessageAndAcquireWakeLock(Message msg) { + acquireWakeLock(); + super.sendMessage(msg); + } + + /** + * Removes all messages matching the given parameters, and attempts to release mWakeLock if the + * Handler is empty. + * + * @param what the Message.what value to be removed + */ + private void removeEqualMessages(int what) { + removeEqualMessages(what, null /* obj */); + } + + /** + * Removes all messages matching the given parameters, and attempts to release mWakeLock if the + * Handler is empty. + * + * @param what the Message.what value to be removed + * @param obj the Message.obj to to be removed, or null if all messages matching Message.what + * should be removed + */ + private void removeEqualMessages(int what, @Nullable Object obj) { + final Handler handler = getHandler(); + if (handler != null) { + handler.removeEqualMessages(what, obj); + } + + maybeReleaseWakeLock(); + } + + private WakeupMessage createScheduledAlarm( + @NonNull String cmdName, Message delayedMessage, long delay) { + // WakeupMessage uses Handler#dispatchMessage() to immediately handle the specified Runnable + // at the scheduled time. dispatchMessage() immediately executes and there may be queued + // events that resolve the scheduled alarm pending in the queue. So, use the Runnable to + // place the alarm event at the end of the queue with sendMessageAndAcquireWakeLock (which + // guarantees the device will stay awake). + final WakeupMessage alarm = + mDeps.newWakeupMessage( + mVcnContext, + getHandler(), + cmdName, + () -> sendMessageAndAcquireWakeLock(delayedMessage)); + alarm.schedule(mDeps.getElapsedRealTime() + delay); + return alarm; + } + + private void setTeardownTimeoutAlarm() { + // Safe to assign this alarm because it is either 1) already null, or 2) already fired. In + // either case, there is nothing to cancel. + if (mTeardownTimeoutAlarm != null) { + Slog.wtf(TAG, "mTeardownTimeoutAlarm should be null before being set"); + } + + final Message delayedMessage = obtainMessage(EVENT_TEARDOWN_TIMEOUT_EXPIRED, mCurrentToken); + mTeardownTimeoutAlarm = + createScheduledAlarm( + TEARDOWN_TIMEOUT_ALARM, + delayedMessage, + TimeUnit.SECONDS.toMillis(TEARDOWN_TIMEOUT_SECONDS)); } - private void sendMessageDelayed(int what, int token, int arg2, EventInfo data, long timeout) { - super.sendMessageDelayed(what, token, arg2, data, timeout); + private void cancelTeardownTimeoutAlarm() { + if (mTeardownTimeoutAlarm != null) { + mTeardownTimeoutAlarm.cancel(); + mTeardownTimeoutAlarm = null; + } + + // Cancel any existing teardown timeouts + removeEqualMessages(EVENT_TEARDOWN_TIMEOUT_EXPIRED); + } + + private void setDisconnectRequestAlarm() { + // Only schedule a NEW alarm if none is already set. + if (mDisconnectRequestAlarm != null) { + return; + } + + final Message delayedMessage = + obtainMessage( + EVENT_DISCONNECT_REQUESTED, + TOKEN_ALL, + 0 /* arg2 */, + new EventDisconnectRequestedInfo( + DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); + mDisconnectRequestAlarm = + createScheduledAlarm( + DISCONNECT_REQUEST_ALARM, + delayedMessage, + TimeUnit.SECONDS.toMillis(NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS)); + } + + private void cancelDisconnectRequestAlarm() { + if (mDisconnectRequestAlarm != null) { + mDisconnectRequestAlarm.cancel(); + mDisconnectRequestAlarm = null; + } + + // Cancel any existing disconnect due to previous loss of underlying network + removeEqualMessages( + EVENT_DISCONNECT_REQUESTED, + new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); + } + + private void setRetryTimeoutAlarm(long delay) { + // Safe to assign this alarm because it is either 1) already null, or 2) already fired. In + // either case, there is nothing to cancel. + if (mRetryTimeoutAlarm != null) { + Slog.wtf(TAG, "mRetryTimeoutAlarm should be null before being set"); + } + + final Message delayedMessage = obtainMessage(EVENT_RETRY_TIMEOUT_EXPIRED, mCurrentToken); + mRetryTimeoutAlarm = createScheduledAlarm(RETRY_TIMEOUT_ALARM, delayedMessage, delay); + } + + private void cancelRetryTimeoutAlarm() { + if (mRetryTimeoutAlarm != null) { + mRetryTimeoutAlarm.cancel(); + mRetryTimeoutAlarm = null; + } + + removeEqualMessages(EVENT_RETRY_TIMEOUT_EXPIRED); + } + + @VisibleForTesting(visibility = Visibility.PRIVATE) + void setSafeModeAlarm() { + // Only schedule a NEW alarm if none is already set. + if (mSafeModeTimeoutAlarm != null) { + return; + } + + final Message delayedMessage = obtainMessage(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED, TOKEN_ALL); + mSafeModeTimeoutAlarm = + createScheduledAlarm( + SAFEMODE_TIMEOUT_ALARM, + delayedMessage, + TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS)); + } + + private void cancelSafeModeAlarm() { + if (mSafeModeTimeoutAlarm != null) { + mSafeModeTimeoutAlarm.cancel(); + mSafeModeTimeoutAlarm = null; + } + + removeEqualMessages(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED); + } + + private void sessionLostWithoutCallback(int token, @Nullable Exception exception) { + sendMessageAndAcquireWakeLock( + EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception)); } private void sessionLost(int token, @Nullable Exception exception) { - sendMessage(EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception)); + // Only notify mGatewayStatusCallback if the session was lost with an error. All + // authentication and DNS failures are sent through + // IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed() + if (exception != null) { + mGatewayStatusCallback.onGatewayConnectionError( + mConnectionConfig.getRequiredUnderlyingCapabilities(), + VCN_ERROR_CODE_INTERNAL_ERROR, + RuntimeException.class.getName(), + "Received " + + exception.getClass().getSimpleName() + + " with message: " + + exception.getMessage()); + } + + sessionLostWithoutCallback(token, exception); + } + + private void notifyStatusCallbackForSessionClosed(@NonNull Exception exception) { + final int errorCode; + final String exceptionClass; + final String exceptionMessage; + + if (exception instanceof AuthenticationFailedException) { + errorCode = VCN_ERROR_CODE_CONFIG_ERROR; + exceptionClass = exception.getClass().getName(); + exceptionMessage = exception.getMessage(); + } else if (exception instanceof IkeInternalException + && exception.getCause() instanceof IOException) { + errorCode = VCN_ERROR_CODE_NETWORK_ERROR; + exceptionClass = IOException.class.getName(); + exceptionMessage = exception.getCause().getMessage(); + } else { + errorCode = VCN_ERROR_CODE_INTERNAL_ERROR; + exceptionClass = RuntimeException.class.getName(); + exceptionMessage = + "Received " + + exception.getClass().getSimpleName() + + " with message: " + + exception.getMessage(); + } + + mGatewayStatusCallback.onGatewayConnectionError( + mConnectionConfig.getRequiredUnderlyingCapabilities(), + errorCode, + exceptionClass, + exceptionMessage); } private void sessionClosed(int token, @Nullable Exception exception) { + if (exception != null) { + notifyStatusCallbackForSessionClosed(exception); + } + // SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the // Disconnecting state. - sessionLost(token, exception); - sendMessage(EVENT_SESSION_CLOSED, token); + sessionLostWithoutCallback(token, exception); + sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token); } private void childTransformCreated( int token, @NonNull IpSecTransform transform, int direction) { - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_TRANSFORM_CREATED, token, new EventTransformCreatedInfo(direction, transform)); } private void childOpened(int token, @NonNull VcnChildSessionConfiguration childConfig) { - sendMessage(EVENT_SETUP_COMPLETED, token, new EventSetupCompletedInfo(childConfig)); + sendMessageAndAcquireWakeLock( + EVENT_SETUP_COMPLETED, token, new EventSetupCompletedInfo(childConfig)); } private abstract class BaseState extends State { @@ -671,7 +1041,7 @@ public class VcnGatewayConnection extends StateMachine { enterState(); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_DISCONNECT_REQUESTED, TOKEN_ALL, new EventDisconnectRequestedInfo( @@ -682,22 +1052,47 @@ public class VcnGatewayConnection extends StateMachine { protected void enterState() throws Exception {} /** + * Returns whether the given token is valid. + * + * <p>By default, States consider any and all token to be 'valid'. + * + * <p>States should override this method if they want to restrict message handling to + * specific tokens. + */ + protected boolean isValidToken(int token) { + return true; + } + + /** * Top-level processMessage with safeguards to prevent crashing the System Server on non-eng * builds. + * + * <p>Here be dragons: processMessage() is final to ensure that mWakeLock is released once + * the Handler queue is empty. Future changes (or overrides) to processMessage() to MUST + * ensure that mWakeLock is correctly released. */ @Override - public boolean processMessage(Message msg) { + public final boolean processMessage(Message msg) { + final int token = msg.arg1; + if (!isValidToken(token)) { + Slog.v(TAG, "Message called with obsolete token: " + token + "; what: " + msg.what); + return HANDLED; + } + try { processStateMsg(msg); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_DISCONNECT_REQUESTED, TOKEN_ALL, new EventDisconnectRequestedInfo( DISCONNECT_REASON_INTERNAL_ERROR + e.toString())); } + // Attempt to release the WakeLock - only possible if the Handler queue is empty + maybeReleaseWakeLock(); + return HANDLED; } @@ -709,7 +1104,7 @@ public class VcnGatewayConnection extends StateMachine { exitState(); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessage( + sendMessageAndAcquireWakeLock( EVENT_DISCONNECT_REQUESTED, TOKEN_ALL, new EventDisconnectRequestedInfo( @@ -747,6 +1142,8 @@ public class VcnGatewayConnection extends StateMachine { } protected void handleDisconnectRequested(String msg) { + // TODO(b/180526152): notify VcnStatusCallback for Network loss + Slog.v(TAG, "Tearing down. Cause: " + msg); mIsRunning = false; @@ -787,6 +1184,8 @@ public class VcnGatewayConnection extends StateMachine { if (mIkeSession != null || mNetworkAgent != null) { Slog.wtf(TAG, "Active IKE Session or NetworkAgent in DisconnectedState"); } + + cancelSafeModeAlarm(); } @Override @@ -810,27 +1209,16 @@ public class VcnGatewayConnection extends StateMachine { break; } } - } - private abstract class ActiveBaseState extends BaseState { - /** - * Handles all incoming messages, discarding messages for previous networks. - * - * <p>States that handle mobility events may need to override this method to receive - * messages for all underlying networks. - */ @Override - public boolean processMessage(Message msg) { - final int token = msg.arg1; - // Only process if a valid token is presented. - if (isValidToken(token)) { - return super.processMessage(msg); - } - - Slog.v(TAG, "Message called with obsolete token: " + token + "; what: " + msg.what); - return HANDLED; + protected void exitState() { + // Safe to blindly set up, as it is cancelled and cleared on entering this state + setSafeModeAlarm(); } + } + private abstract class ActiveBaseState extends BaseState { + @Override protected boolean isValidToken(int token) { return (token == TOKEN_ALL || token == mCurrentToken); } @@ -861,7 +1249,7 @@ public class VcnGatewayConnection extends StateMachine { protected void enterState() throws Exception { if (mIkeSession == null) { Slog.wtf(TAG, "IKE session was already closed when entering Disconnecting state."); - sendMessage(EVENT_SESSION_CLOSED, mCurrentToken); + sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, mCurrentToken); return; } @@ -873,10 +1261,9 @@ public class VcnGatewayConnection extends StateMachine { } mIkeSession.close(); - sendMessageDelayed( - EVENT_TEARDOWN_TIMEOUT_EXPIRED, - mCurrentToken, - TimeUnit.SECONDS.toMillis(TEARDOWN_TIMEOUT_SECONDS)); + + // Safe to blindly set up, as it is cancelled and cleared on exiting this state + setTeardownTimeoutAlarm(); } @Override @@ -901,6 +1288,8 @@ public class VcnGatewayConnection extends StateMachine { String reason = ((EventDisconnectRequestedInfo) msg.obj).reason; if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) { + // TODO(b/180526152): notify VcnStatusCallback for Network loss + // Will trigger EVENT_SESSION_CLOSED immediately. mIkeSession.kill(); break; @@ -918,6 +1307,10 @@ public class VcnGatewayConnection extends StateMachine { transitionTo(mDisconnectedState); } break; + case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: + mGatewayStatusCallback.onEnteredSafeMode(); + mSafeModeTimeoutAlarm = null; + break; default: logUnhandledMessage(msg); break; @@ -927,6 +1320,8 @@ public class VcnGatewayConnection extends StateMachine { @Override protected void exitState() throws Exception { mSkipRetryTimeout = false; + + cancelTeardownTimeoutAlarm(); } } @@ -998,6 +1393,10 @@ public class VcnGatewayConnection extends StateMachine { case EVENT_DISCONNECT_REQUESTED: handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); break; + case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: + mGatewayStatusCallback.onEnteredSafeMode(); + mSafeModeTimeoutAlarm = null; + break; default: logUnhandledMessage(msg); break; @@ -1041,6 +1440,14 @@ public class VcnGatewayConnection extends StateMachine { public void unwanted() { teardownAsynchronously(); } + + @Override + public void onValidationStatus( + @ValidationStatus int status, @Nullable Uri redirectUri) { + if (status == NetworkAgent.VALIDATION_STATUS_VALID) { + clearFailedAttemptCounterAndSafeModeAlarm(); + } + } }; agent.register(); @@ -1049,6 +1456,14 @@ public class VcnGatewayConnection extends StateMachine { return agent; } + protected void clearFailedAttemptCounterAndSafeModeAlarm() { + mVcnContext.ensureRunningOnLooperThread(); + + // Validated connection, clear failed attempt counter + mFailedAttempts = 0; + cancelSafeModeAlarm(); + } + protected void applyTransform( int token, @NonNull IpSecTunnelInterface tunnelIface, @@ -1056,7 +1471,7 @@ public class VcnGatewayConnection extends StateMachine { @NonNull IpSecTransform transform, int direction) { try { - // TODO: Set underlying network of tunnel interface + // TODO(b/180163196): Set underlying network of tunnel interface // Transforms do not need to be persisted; the IkeSession will keep them alive mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform); @@ -1117,8 +1532,17 @@ public class VcnGatewayConnection extends StateMachine { class ConnectedState extends ConnectedStateBase { @Override protected void enterState() throws Exception { - // Successful connection, clear failed attempt counter - mFailedAttempts = 0; + if (mTunnelIface == null) { + try { + // Requires a real Network object in order to be created; doing this any earlier + // means not having a real Network object, or picking an incorrect Network. + mTunnelIface = + mIpSecManager.createIpSecTunnelInterface( + DUMMY_ADDR, DUMMY_ADDR, mUnderlying.network); + } catch (IOException | ResourceUnavailableException e) { + teardownAsynchronously(); + } + } } @Override @@ -1155,6 +1579,10 @@ public class VcnGatewayConnection extends StateMachine { case EVENT_DISCONNECT_REQUESTED: handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); break; + case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: + mGatewayStatusCallback.onEnteredSafeMode(); + mSafeModeTimeoutAlarm = null; + break; default: logUnhandledMessage(msg); break; @@ -1174,6 +1602,7 @@ public class VcnGatewayConnection extends StateMachine { // mUnderlying assumed non-null, given check above. // If network changed, migrate. Otherwise, update any existing networkAgent. if (oldUnderlying == null || !oldUnderlying.network.equals(mUnderlying.network)) { + Slog.v(TAG, "Migrating to new network: " + mUnderlying.network); mIkeSession.setNetwork(mUnderlying.network); } else { // oldUnderlying is non-null & underlying network itself has not changed @@ -1197,8 +1626,18 @@ public class VcnGatewayConnection extends StateMachine { mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig); } else { updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig); + + // mNetworkAgent not null, so the VCN Network has already been established. Clear + // the failed attempt counter and safe mode alarm since this transition is complete. + clearFailedAttemptCounterAndSafeModeAlarm(); } } + + @Override + protected void exitState() { + // Will only set a new alarm if no safe mode alarm is currently scheduled. + setSafeModeAlarm(); + } } /** @@ -1216,8 +1655,8 @@ public class VcnGatewayConnection extends StateMachine { Slog.wtf(TAG, "Underlying network was null in retry state"); transitionTo(mDisconnectedState); } else { - sendMessageDelayed( - EVENT_RETRY_TIMEOUT_EXPIRED, mCurrentToken, getNextRetryIntervalsMs()); + // Safe to blindly set up, as it is cancelled and cleared on exiting this state + setRetryTimeoutAlarm(getNextRetryIntervalsMs()); } } @@ -1230,8 +1669,6 @@ public class VcnGatewayConnection extends StateMachine { // If new underlying is null, all networks were lost; go back to disconnected. if (mUnderlying == null) { - removeMessages(EVENT_RETRY_TIMEOUT_EXPIRED); - transitionTo(mDisconnectedState); return; } else if (oldUnderlying != null @@ -1242,19 +1679,26 @@ public class VcnGatewayConnection extends StateMachine { // Fallthrough case EVENT_RETRY_TIMEOUT_EXPIRED: - removeMessages(EVENT_RETRY_TIMEOUT_EXPIRED); - transitionTo(mConnectingState); break; case EVENT_DISCONNECT_REQUESTED: handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); break; + case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: + mGatewayStatusCallback.onEnteredSafeMode(); + mSafeModeTimeoutAlarm = null; + break; default: logUnhandledMessage(msg); break; } } + @Override + public void exitState() { + cancelRetryTimeoutAlarm(); + } + private long getNextRetryIntervalsMs() { final int retryDelayIndex = mFailedAttempts - 1; final long[] retryIntervalsMs = mConnectionConfig.getRetryIntervalsMs(); @@ -1327,8 +1771,6 @@ public class VcnGatewayConnection extends StateMachine { } } - // TODO: Make a VcnNetworkSpecifier, and match all underlying subscription IDs. - return builder.build(); } @@ -1426,6 +1868,15 @@ public class VcnGatewayConnection extends StateMachine { } @Override + public void onIpSecTransformsMigrated( + @NonNull IpSecTransform inIpSecTransform, + @NonNull IpSecTransform outIpSecTransform) { + Slog.v(TAG, "ChildTransformsMigrated; token " + mToken); + onIpSecTransformCreated(inIpSecTransform, IpSecManager.DIRECTION_IN); + onIpSecTransformCreated(outIpSecTransform, IpSecManager.DIRECTION_OUT); + } + + @Override public void onIpSecTransformDeleted(@NonNull IpSecTransform transform, int direction) { // Nothing to be done; no references to the IpSecTransform are held, and this transform // will be closed by the IKE library. @@ -1434,6 +1885,11 @@ public class VcnGatewayConnection extends StateMachine { } @VisibleForTesting(visibility = Visibility.PRIVATE) + void setTunnelInterface(IpSecTunnelInterface tunnelIface) { + mTunnelIface = tunnelIface; + } + + @VisibleForTesting(visibility = Visibility.PRIVATE) UnderlyingNetworkTrackerCallback getUnderlyingNetworkTrackerCallback() { return mUnderlyingNetworkTrackerCallback; } @@ -1522,6 +1978,26 @@ public class VcnGatewayConnection extends StateMachine { ikeSessionCallback, childSessionCallback); } + + /** Builds a new WakeLock. */ + public VcnWakeLock newWakeLock( + @NonNull Context context, int wakeLockFlag, @NonNull String wakeLockTag) { + return new VcnWakeLock(context, wakeLockFlag, wakeLockTag); + } + + /** Builds a new WakeupMessage. */ + public WakeupMessage newWakeupMessage( + @NonNull VcnContext vcnContext, + @NonNull Handler handler, + @NonNull String tag, + @NonNull Runnable runnable) { + return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable); + } + + /** Gets the elapsed real time since boot, in millis. */ + public long getElapsedRealTime() { + return SystemClock.elapsedRealtime(); + } } /** @@ -1601,4 +2077,34 @@ public class VcnGatewayConnection extends StateMachine { mImpl.setNetwork(network); } } + + /** Proxy Implementation of WakeLock, used for testing. */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + public static class VcnWakeLock { + private final WakeLock mImpl; + + public VcnWakeLock(@NonNull Context context, int flags, @NonNull String tag) { + final PowerManager powerManager = context.getSystemService(PowerManager.class); + mImpl = powerManager.newWakeLock(flags, tag); + mImpl.setReferenceCounted(false /* isReferenceCounted */); + } + + /** + * Acquire this WakeLock. + * + * <p>Synchronize this action to minimize locking around WakeLock use. + */ + public synchronized void acquire() { + mImpl.acquire(); + } + + /** + * Release this Wakelock. + * + * <p>Synchronize this action to minimize locking around WakeLock use. + */ + public synchronized void release() { + mImpl.release(); + } + } } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 87c766d961a2..ea47a2713fb1 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_static { name: "libservices.core", defaults: ["libservices.core-libs"], @@ -28,6 +37,7 @@ cc_library_static { "com_android_server_am_BatteryStatsService.cpp", "com_android_server_ConsumerIrService.cpp", "com_android_server_devicepolicy_CryptoTestHelper.cpp", + "com_android_server_connectivity_Vpn.cpp", "com_android_server_gpu_GpuService.cpp", "com_android_server_HardwarePropertiesManagerService.cpp", "com_android_server_input_InputManagerService.cpp", diff --git a/packages/Connectivity/service/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp index ea5e7183c905..ea5e7183c905 100644 --- a/packages/Connectivity/service/jni/com_android_server_connectivity_Vpn.cpp +++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index ccf685c1abd7..1e6f05322223 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -40,6 +40,7 @@ int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_vr_VrManagerService(JNIEnv* env); int register_android_server_VibratorService(JNIEnv* env); int register_android_server_location_GnssLocationProvider(JNIEnv* env); +int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*); int register_android_server_tv_TvUinputBridge(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); @@ -91,6 +92,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_VibratorService(env); register_android_server_SystemServer(env); register_android_server_location_GnssLocationProvider(env); + register_android_server_connectivity_Vpn(env); register_android_server_devicepolicy_CryptoTestHelper(env); register_android_server_ConsumerIrService(env); register_android_server_BatteryStatsService(env); diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp index 3690afc1bc41..a9b85e6130a5 100644 --- a/services/core/xsd/Android.bp +++ b/services/core/xsd/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + xsd_config { name: "default-permissions", srcs: ["default-permissions.xsd"], diff --git a/services/core/xsd/platform-compat/overrides/platform-compat-overrides.xsd b/services/core/xsd/platform-compat/overrides/platform-compat-overrides.xsd index e27e1b8ca89d..1406dbb12e02 100644 --- a/services/core/xsd/platform-compat/overrides/platform-compat-overrides.xsd +++ b/services/core/xsd/platform-compat/overrides/platform-compat-overrides.xsd @@ -27,6 +27,13 @@ <xs:attribute type="xs:boolean" name="enabled" use="required" /> </xs:complexType> + <xs:complexType name="raw-override-value"> + <xs:attribute type="xs:string" name="packageName" use="required" /> + <xs:attribute type="xs:long" name="minVersionCode" /> + <xs:attribute type="xs:long" name="maxVersionCode" /> + <xs:attribute type="xs:boolean" name="enabled" use="required" /> + </xs:complexType> + <xs:complexType name="change-overrides"> <xs:attribute type="xs:long" name="changeId" use="required"/> <xs:element name="validated"> @@ -43,6 +50,13 @@ </xs:sequence> </xs:complexType> </xs:element> + <xs:element name="raw"> + <xs:complexType> + <xs:sequence> + <xs:element name="raw-override-value" type="raw-override-value" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> </xs:complexType> <xs:element name="overrides"> diff --git a/services/core/xsd/platform-compat/overrides/schema/current.txt b/services/core/xsd/platform-compat/overrides/schema/current.txt index 08b82072747b..a5ccffcfbb2b 100644 --- a/services/core/xsd/platform-compat/overrides/schema/current.txt +++ b/services/core/xsd/platform-compat/overrides/schema/current.txt @@ -5,9 +5,11 @@ package com.android.server.compat.overrides { ctor public ChangeOverrides(); method public long getChangeId(); method public com.android.server.compat.overrides.ChangeOverrides.Deferred getDeferred(); + method public com.android.server.compat.overrides.ChangeOverrides.Raw getRaw(); method public com.android.server.compat.overrides.ChangeOverrides.Validated getValidated(); method public void setChangeId(long); method public void setDeferred(com.android.server.compat.overrides.ChangeOverrides.Deferred); + method public void setRaw(com.android.server.compat.overrides.ChangeOverrides.Raw); method public void setValidated(com.android.server.compat.overrides.ChangeOverrides.Validated); } @@ -16,6 +18,11 @@ package com.android.server.compat.overrides { method public java.util.List<com.android.server.compat.overrides.OverrideValue> getOverrideValue(); } + public static class ChangeOverrides.Raw { + ctor public ChangeOverrides.Raw(); + method public java.util.List<com.android.server.compat.overrides.RawOverrideValue> getRawOverrideValue(); + } + public static class ChangeOverrides.Validated { ctor public ChangeOverrides.Validated(); method public java.util.List<com.android.server.compat.overrides.OverrideValue> getOverrideValue(); @@ -34,6 +41,18 @@ package com.android.server.compat.overrides { method public java.util.List<com.android.server.compat.overrides.ChangeOverrides> getChangeOverrides(); } + public class RawOverrideValue { + ctor public RawOverrideValue(); + method public boolean getEnabled(); + method public long getMaxVersionCode(); + method public long getMinVersionCode(); + method public String getPackageName(); + method public void setEnabled(boolean); + method public void setMaxVersionCode(long); + method public void setMinVersionCode(long); + method public void setPackageName(String); + } + public class XmlParser { ctor public XmlParser(); method public static com.android.server.compat.overrides.Overrides read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; diff --git a/services/core/xsd/vts/Android.bp b/services/core/xsd/vts/Android.bp index a942108667a5..4d3c79eb28ae 100644 --- a/services/core/xsd/vts/Android.bp +++ b/services/core/xsd/vts/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { name: "vts_defaultPermissions_validate_test", srcs: [ diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp index df054b006cd3..0d316730c38e 100644 --- a/services/coverage/Android.bp +++ b/services/coverage/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.coverage-sources", srcs: ["java/**/*.java"], diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp index 7a80fb1b8856..2e8a0a86358f 100644 --- a/services/devicepolicy/Android.bp +++ b/services/devicepolicy/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.devicepolicy-sources", srcs: ["java/**/*.java"], diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 43537d067bce..9caef13acc8e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -197,6 +197,7 @@ import android.net.ConnectivityManager; import android.net.IIpConnectivityMetrics; import android.net.ProxyInfo; import android.net.Uri; +import android.net.VpnManager; import android.net.metrics.IpConnectivityLog; import android.net.wifi.WifiManager; import android.os.Binder; @@ -2245,6 +2246,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return mContext.getSystemService(ConnectivityManager.class); } + VpnManager getVpnManager() { + return mContext.getSystemService(VpnManager.class); + } + LocationManager getLocationManager() { return mContext.getSystemService(LocationManager.class); } @@ -7090,7 +7095,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } // If some package is uninstalled after the check above, it will be ignored by CM. - if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser( + if (!mInjector.getVpnManager().setAlwaysOnVpnPackageForUser( userId, vpnPackage, lockdown, lockdownAllowlist)) { throw new UnsupportedOperationException(); } @@ -7121,7 +7126,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = mInjector.userHandleGetCallingUserId(); return mInjector.binderWithCleanCallingIdentity( - () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId)); + () -> mInjector.getVpnManager().getAlwaysOnVpnPackageForUser(userId)); } @Override @@ -7139,7 +7144,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = mInjector.userHandleGetCallingUserId(); return mInjector.binderWithCleanCallingIdentity( - () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(userId)); + () -> mInjector.getVpnManager().isVpnLockdownEnabled(userId)); } @Override @@ -7158,7 +7163,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = mInjector.userHandleGetCallingUserId(); return mInjector.binderWithCleanCallingIdentity( - () -> mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId)); + () -> mInjector.getVpnManager().getVpnLockdownAllowlist(userId)); } private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) { diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp index 7534c7c40a3d..7e1e99fe0a23 100644 --- a/services/incremental/Android.bp +++ b/services/incremental/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "service.incremental-proto-defaults", diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java index 1801f3bca30e..a2768c637d79 100644 --- a/services/java/com/android/server/SystemConfigService.java +++ b/services/java/com/android/server/SystemConfigService.java @@ -21,6 +21,10 @@ import static java.util.stream.Collectors.toMap; import android.Manifest; import android.content.Context; import android.os.ISystemConfig; +import android.util.ArraySet; +import android.util.SparseArray; + +import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.List; @@ -64,6 +68,22 @@ public class SystemConfigService extends SystemService { return SystemConfig.getInstance() .getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); } + + @Override + public int[] getSystemPermissionUids(String permissionName) { + mContext.enforceCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, + "getSystemPermissionUids requires GET_RUNTIME_PERMISSIONS"); + final List<Integer> uids = new ArrayList<>(); + final SparseArray<ArraySet<String>> systemPermissions = + SystemConfig.getInstance().getSystemPermissions(); + for (int i = 0; i < systemPermissions.size(); i++) { + final ArraySet<String> permissions = systemPermissions.valueAt(i); + if (permissions != null && permissions.contains(permissionName)) { + uids.add(systemPermissions.keyAt(i)); + } + } + return ArrayUtils.convertToIntArray(uids); + } }; public SystemConfigService(Context context) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 62c3f43d2676..18c7e128b04e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -97,7 +97,6 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.ILockSettings; import com.android.server.am.ActivityManagerService; import com.android.server.appbinding.AppBindingService; -import com.android.server.apphibernation.AppHibernationService; import com.android.server.attention.AttentionManagerService; import com.android.server.audio.AudioService; import com.android.server.biometrics.AuthService; @@ -1104,6 +1103,7 @@ public final class SystemServer { IStorageManager storageManager = null; NetworkManagementService networkManagement = null; IpSecService ipSecService = null; + VpnManagerService vpnManager = null; VcnManagementService vcnManagement = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; @@ -1533,7 +1533,7 @@ public final class SystemServer { t.traceBegin("StartIpSecService"); try { - ipSecService = IpSecService.create(context, networkManagement); + ipSecService = IpSecService.create(context); ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService); } catch (Throwable e) { reportWtf("starting IpSec Service", e); @@ -1637,6 +1637,15 @@ public final class SystemServer { networkPolicy.bindConnectivityManager(connectivity); t.traceEnd(); + t.traceBegin("StartVpnManagerService"); + try { + vpnManager = VpnManagerService.create(context); + ServiceManager.addService(Context.VPN_MANAGEMENT_SERVICE, vpnManager); + } catch (Throwable e) { + reportWtf("starting VPN Manager Service", e); + } + t.traceEnd(); + t.traceBegin("StartVcnManagementService"); try { vcnManagement = VcnManagementService.create(context); @@ -1873,11 +1882,9 @@ public final class SystemServer { mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS); t.traceEnd(); - if (AppHibernationService.isAppHibernationEnabled()) { - t.traceBegin("StartAppHibernationService"); - mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS); - t.traceEnd(); - } + t.traceBegin("StartAppHibernationService"); + mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS); + t.traceEnd(); if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) { t.traceBegin("StartGestureLauncher"); @@ -2338,6 +2345,7 @@ public final class SystemServer { final MediaRouterService mediaRouterF = mediaRouter; final MmsServiceBroker mmsServiceF = mmsService; final IpSecService ipSecServiceF = ipSecService; + final VpnManagerService vpnManagerF = vpnManager; final VcnManagementService vcnManagementF = vcnManagement; final WindowManagerService windowManagerF = wm; final ConnectivityManager connectivityF = (ConnectivityManager) @@ -2445,6 +2453,15 @@ public final class SystemServer { reportWtf("making Connectivity Service ready", e); } t.traceEnd(); + t.traceBegin("MakeVpnManagerServiceReady"); + try { + if (vpnManagerF != null) { + vpnManagerF.systemReady(); + } + } catch (Throwable e) { + reportWtf("making VpnManagerService ready", e); + } + t.traceEnd(); t.traceBegin("MakeVcnManagementServiceReady"); try { if (vcnManagementF != null) { diff --git a/services/midi/Android.bp b/services/midi/Android.bp index 6bce5b51ecb7..cbb36a884f0d 100644 --- a/services/midi/Android.bp +++ b/services/midi/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.midi-sources", srcs: ["java/**/*.java"], diff --git a/services/net/Android.bp b/services/net/Android.bp index e0bb67a7e6d8..93aa461031de 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.net-sources", srcs: ["java/**/*.java"], diff --git a/services/people/Android.bp b/services/people/Android.bp index c863f1f5919f..b2327b5adb05 100644 --- a/services/people/Android.bp +++ b/services/people/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_static { name: "services.people", defaults: ["services_defaults"], diff --git a/services/print/Android.bp b/services/print/Android.bp index 93b5ef040926..feaeeed08866 100644 --- a/services/print/Android.bp +++ b/services/print/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.print-sources", srcs: ["java/**/*.java"], diff --git a/services/profcollect/Android.bp b/services/profcollect/Android.bp index 68fba5508b58..a636d670298f 100644 --- a/services/profcollect/Android.bp +++ b/services/profcollect/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.profcollect-javasources", srcs: ["src/**/*.java"], diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp index 28830956e7f5..9fd97f1f504c 100644 --- a/services/restrictions/Android.bp +++ b/services/restrictions/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.restrictions-sources", srcs: ["java/**/*.java"], diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp index 1ae2aec90ba3..52eae21f9e66 100644 --- a/services/robotests/Android.bp +++ b/services/robotests/Android.bp @@ -16,6 +16,15 @@ // FrameworksServicesLib app just for Robolectric test target # //################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "FrameworksServicesLib", platform_apis: true, diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp index 32587accf160..506e1561e8d7 100644 --- a/services/robotests/backup/Android.bp +++ b/services/robotests/backup/Android.bp @@ -15,6 +15,15 @@ //################################################################## // BackupFrameworksServicesLib app just for Robolectric test target # //################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "BackupFrameworksServicesLib", platform_apis: true, diff --git a/services/startop/Android.bp b/services/startop/Android.bp index 46a81aae63c5..a7ae578eb738 100644 --- a/services/startop/Android.bp +++ b/services/startop/Android.bp @@ -14,6 +14,17 @@ * limitations under the License. */ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_static { name: "services.startop", defaults: ["services_defaults"], diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp index 54968c003560..7ac44cec95cb 100644 --- a/services/systemcaptions/Android.bp +++ b/services/systemcaptions/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.systemcaptions-sources", srcs: ["java/**/*.java"], diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp index a2668a184fe0..19fdf6056453 100644 --- a/services/tests/PackageManagerComponentOverrideTests/Android.bp +++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp @@ -17,6 +17,15 @@ // NOTE: This test is separate from service tests since it relies on same vs different calling UID, // and this is more representative of a real caller. It also uses Mockito extended, and this // prevents converting the entire services test module. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PackageManagerComponentOverrideTests", srcs: [ diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp index 41dfade1a09a..cf745c2a8663 100644 --- a/services/tests/PackageManagerServiceTests/host/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "PackageManagerServiceHostTests", srcs: ["src/**/*.kt"], diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp index c9b29275a731..626b113e6e0c 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "PackageManagerDummyAppVersion1", manifest: "AndroidManifestVersion1.xml" diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp index b4e0f10f14b0..9202f6724751 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksMockingServicesTests", diff --git a/services/tests/rescueparty/Android.bp b/services/tests/rescueparty/Android.bp index 6733af4eb26a..ed7de967f069 100644 --- a/services/tests/rescueparty/Android.bp +++ b/services/tests/rescueparty/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { name: "log_rescueparty_reset_event_reported", srcs: ["log_rescueparty_reset_event_reported.cpp"], diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 0aec701a0f9a..08e2def8d10d 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -2,6 +2,15 @@ // Build FrameworksServicesTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksServicesTests", diff --git a/services/tests/servicestests/aidl/Android.bp b/services/tests/servicestests/aidl/Android.bp index d4e53dddf4a7..678053192e82 100644 --- a/services/tests/servicestests/aidl/Android.bp +++ b/services/tests/servicestests/aidl/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "servicestests-aidl", sdk_version: "current", diff --git a/services/tests/servicestests/apks/Android.bp b/services/tests/servicestests/apks/Android.bp index 3e11604005a0..6c918064dbff 100644 --- a/services/tests/servicestests/apks/Android.bp +++ b/services/tests/servicestests/apks/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_defaults { name: "FrameworksServicesTests_apks_defaults", sdk_version: "current", diff --git a/services/tests/servicestests/apks/install-split-base/Android.bp b/services/tests/servicestests/apks/install-split-base/Android.bp index 1b62aa2a8e96..39992f600b96 100644 --- a/services/tests/servicestests/apks/install-split-base/Android.bp +++ b/services/tests/servicestests/apks/install-split-base/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksServicesTests_install_split_base", defaults: ["FrameworksServicesTests_apks_defaults"], diff --git a/services/tests/servicestests/apks/install-split-feature-a/Android.bp b/services/tests/servicestests/apks/install-split-feature-a/Android.bp index 45d891720166..ca7295e48fbc 100644 --- a/services/tests/servicestests/apks/install-split-feature-a/Android.bp +++ b/services/tests/servicestests/apks/install-split-feature-a/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksServicesTests_install_split_feature_a", defaults: ["FrameworksServicesTests_apks_defaults"], diff --git a/services/tests/servicestests/apks/install_intent_filters/Android.bp b/services/tests/servicestests/apks/install_intent_filters/Android.bp index 59c8524e01c2..643824de785c 100644 --- a/services/tests/servicestests/apks/install_intent_filters/Android.bp +++ b/services/tests/servicestests/apks/install_intent_filters/Android.bp @@ -1,7 +1,15 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksServicesTests_install_intent_filters", defaults: ["FrameworksServicesTests_apks_defaults"], srcs: ["**/*.java"], } - diff --git a/services/tests/servicestests/apks/install_uses_sdk/Android.bp b/services/tests/servicestests/apks/install_uses_sdk/Android.bp index c24aa2bd8bba..feb152c49eb3 100644 --- a/services/tests/servicestests/apks/install_uses_sdk/Android.bp +++ b/services/tests/servicestests/apks/install_uses_sdk/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FrameworksServicesTests_install_uses_sdk_r0", defaults: ["FrameworksServicesTests_apks_defaults"], diff --git a/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java b/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java index 50e7a0395a2a..58d6dae1637a 100644 --- a/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java +++ b/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java @@ -34,7 +34,7 @@ public class EntropyMixerTest extends AndroidTestCase { assertEquals(0, FileUtils.readTextFile(file, 0, null).length()); // The constructor has the side effect of writing to file - new EntropyMixer(getContext(), "/dev/null", file.getCanonicalPath(), "/dev/null"); + new EntropyMixer(getContext(), "/dev/null", file.getCanonicalPath()); assertTrue(FileUtils.readTextFile(file, 0, null).length() > 0); } diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index 1328b91d03f9..07f67327b2bf 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -110,6 +110,8 @@ public final class AppHibernationServiceTest { UserInfo userInfo = addUser(USER_ID_1); mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1); + + mAppHibernationService.mIsServiceEnabled = true; } @Test diff --git a/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java index d0767ccb6f87..c165c661a625 100644 --- a/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java +++ b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java @@ -22,6 +22,7 @@ class ApplicationInfoBuilder { private boolean mIsDebuggable; private int mTargetSdk; private String mPackageName; + private long mVersionCode; private ApplicationInfoBuilder() { mTargetSdk = -1; @@ -46,6 +47,11 @@ class ApplicationInfoBuilder { return this; } + ApplicationInfoBuilder withVersionCode(Long versionCode) { + mVersionCode = versionCode; + return this; + } + ApplicationInfo build() { final ApplicationInfo applicationInfo = new ApplicationInfo(); if (mIsDebuggable) { @@ -53,6 +59,7 @@ class ApplicationInfoBuilder { } applicationInfo.packageName = mPackageName; applicationInfo.targetSdkVersion = mTargetSdk; + applicationInfo.longVersionCode = mVersionCode; return applicationInfo; } } diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index a53ff9bc7fdc..8b0e948579fb 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -18,6 +18,7 @@ package com.android.server.compat; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; @@ -25,6 +26,7 @@ import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; import android.app.compat.ChangeIdStateCache; +import android.app.compat.PackageOverride; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -33,6 +35,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import androidx.test.runner.AndroidJUnit4; import com.android.internal.compat.AndroidBuildClassifier; +import com.android.internal.compat.CompatibilityOverrideConfig; import org.junit.Before; import org.junit.Test; @@ -46,6 +49,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Collections; import java.util.UUID; @RunWith(AndroidJUnit4.class) @@ -83,6 +87,8 @@ public class CompatConfigTest { when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); ChangeIdStateCache.disable(); + when(mPackageManager.getApplicationInfo(anyString(), anyInt())) + .thenThrow(new NameNotFoundException()); } @Test @@ -163,6 +169,10 @@ public class CompatConfigTest { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addDisabledChangeWithId(1234L) .build(); + ApplicationInfo info = ApplicationInfoBuilder.create() + .withPackageName("com.some.package").build(); + when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt())) + .thenReturn(info); compatConfig.addOverride(1234L, "com.some.package", true); @@ -177,6 +187,10 @@ public class CompatConfigTest { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addEnabledChangeWithId(1234L) .build(); + ApplicationInfo info = ApplicationInfoBuilder.create() + .withPackageName("com.some.package").build(); + when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt())) + .thenReturn(info); compatConfig.addOverride(1234L, "com.some.package", false); @@ -191,6 +205,10 @@ public class CompatConfigTest { CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); compatConfig.forceNonDebuggableFinalForTest(false); + ApplicationInfo info = ApplicationInfoBuilder.create() + .withPackageName("com.some.package").build(); + when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt())) + .thenReturn(info); compatConfig.addOverride(1234L, "com.some.package", false); @@ -265,6 +283,71 @@ public class CompatConfigTest { } @Test + public void testOverrideWithAppVersion() throws Exception { + ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() + .withPackageName("com.installed.foo") + .withVersionCode(100L) + .debuggable().build(); + when(mPackageManager.getApplicationInfo(eq("com.installed.foo"), anyInt())) + .thenReturn(applicationInfo); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1234L).build(); + when(mBuildClassifier.isDebuggableBuild()).thenReturn(false); + when(mBuildClassifier.isFinalBuild()).thenReturn(true); + + // Add override that doesn't include the installed app version + CompatibilityOverrideConfig config = new CompatibilityOverrideConfig( + Collections.singletonMap(1234L, + new PackageOverride.Builder() + .setMaxVersionCode(99L) + .setEnabled(true) + .build())); + compatConfig.addOverrides(config, "com.installed.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); + + // Add override that does include the installed app version + config = new CompatibilityOverrideConfig( + Collections.singletonMap(1234L, + new PackageOverride.Builder() + .setMinVersionCode(100L) + .setMaxVersionCode(100L) + .setEnabled(true) + .build())); + compatConfig.addOverrides(config, "com.installed.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue(); + } + + @Test + public void testApplyDeferredOverridesAfterInstallingAppVersion() throws Exception { + ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() + .withPackageName("com.notinstalled.foo") + .withVersionCode(100L) + .debuggable().build(); + when(mPackageManager.getApplicationInfo(eq("com.notinstalled.foo"), anyInt())) + .thenThrow(new NameNotFoundException()); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1234L).build(); + when(mBuildClassifier.isDebuggableBuild()).thenReturn(false); + when(mBuildClassifier.isFinalBuild()).thenReturn(true); + + // Add override before the app is available. + CompatibilityOverrideConfig config = new CompatibilityOverrideConfig( + Collections.singletonMap(1234L, new PackageOverride.Builder() + .setMaxVersionCode(99L) + .setEnabled(true) + .build())); + compatConfig.addOverrides(config, "com.notinstalled.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); + + // Pretend the app is now installed. + when(mPackageManager.getApplicationInfo(eq("com.notinstalled.foo"), anyInt())) + .thenReturn(applicationInfo); + + compatConfig.recheckOverrides("com.notinstalled.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); + } + + @Test public void testApplyDeferredOverrideClearsOverrideAfterUninstall() throws Exception { ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("com.installedapp.foo") @@ -384,6 +467,8 @@ public class CompatConfigTest { ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("com.some.package") .build(); + when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt())) + .thenReturn(applicationInfo); assertThat(compatConfig.addOverride(1234L, "com.some.package", false)).isTrue(); assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); @@ -404,6 +489,8 @@ public class CompatConfigTest { .withPackageName("foo.bar") .withTargetSdk(2) .build(); + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenReturn(applicationInfo); assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse(); assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse(); @@ -425,7 +512,8 @@ public class CompatConfigTest { .withPackageName("foo.bar") .withTargetSdk(2) .build(); - + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenReturn(applicationInfo); assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1); assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue(); assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse(); @@ -533,22 +621,114 @@ public class CompatConfigTest { + " <override-value packageName=\"foo.bar\" enabled=\"true\">\n" + " </override-value>\n" + " </validated>\n" - + " <deferred>\n" - + " </deferred>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + " </change-overrides>\n" + " <change-overrides changeId=\"2\">\n" + " <validated>\n" + " </validated>\n" - + " <deferred>\n" - + " <override-value packageName=\"bar.baz\" enabled=\"false\">\n" - + " </override-value>\n" - + " </deferred>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + "</overrides>\n"); + } + + @Test + public void testSaveOverridesWithRanges() throws Exception { + File overridesFile = new File(createTempDir(), "overrides.xml"); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1L) + .addEnableSinceSdkChangeWithId(2, 2L) + .build(); + compatConfig.forceNonDebuggableFinalForTest(true); + compatConfig.initOverrides(overridesFile); + + compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L, + new PackageOverride.Builder() + .setMinVersionCode(99L) + .setMaxVersionCode(101L) + .setEnabled(true) + .build())), "foo.bar"); + + assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + + "<overrides>\n" + + " <change-overrides changeId=\"1\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"99\" maxVersionCode=\"101\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + " </change-overrides>\n" + "</overrides>\n"); } @Test - public void testLoadOverrides() throws Exception { + public void testLoadOverridesRaw() throws Exception { + File tempDir = createTempDir(); + File overridesFile = new File(tempDir, "overrides.xml"); + // Change 1 is enabled for foo.bar (validated) + // Change 2 is disabled for bar.baz (deferred) + String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>\n" + + " <change-overrides changeId=\"1\">\n" + + " <validated>\n" + + " <override-value packageName=\"foo.bar\" enabled=\"true\">\n" + + " </override-value>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + " <change-overrides changeId=\"2\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + "</overrides>\n"; + writeToFile(tempDir, "overrides.xml", xmlData); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1L) + .addEnableSinceSdkChangeWithId(2, 2L) + .build(); + compatConfig.forceNonDebuggableFinalForTest(true); + compatConfig.initOverrides(overridesFile); + ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() + .withPackageName("foo.bar") + .withVersionCode(100L) + .debuggable() + .build(); + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenReturn(applicationInfo); + when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) + .thenThrow(new NameNotFoundException()); + + assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue(); + assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse(); + + compatConfig.recheckOverrides("foo.bar"); + assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue(); + } + + @Test + public void testLoadOverridesDeferred() throws Exception { File tempDir = createTempDir(); File overridesFile = new File(tempDir, "overrides.xml"); // Change 1 is enabled for foo.bar (validated) diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index a1b2dc8bd82d..799b06734b54 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -196,6 +196,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -208,6 +211,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -219,6 +225,9 @@ public class PlatformCompatTest { public void testListenerCalledOnSetOverridesTwoListeners() throws Exception { mPlatformCompat.registerListener(1, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -244,6 +253,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -252,9 +264,12 @@ public class PlatformCompatTest { } @Test - public void testListenerCalledOnSetOverridesTwoListenersForTest() throws Exception { + public void testListenerCalledOnSetOverridesForTestTwoListeners() throws Exception { mPlatformCompat.registerListener(1, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -280,6 +295,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener2); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).build(), PACKAGE_NAME); @@ -299,6 +317,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener2); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(), PACKAGE_NAME); @@ -318,6 +339,9 @@ public class PlatformCompatTest { mPlatformCompat.registerListener(1, mListener1); mPlatformCompat.registerListener(2, mListener2); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.setOverrides( CompatibilityChangeConfigBuilder.create().enable(1L).build(), PACKAGE_NAME); @@ -336,6 +360,9 @@ public class PlatformCompatTest { public void testListenerCalledOnClearOverrideDoesntExist() throws Exception { mPlatformCompat.registerListener(1, mListener1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create().withPackageName(PACKAGE_NAME).build()); + mPlatformCompat.clearOverride(1, PACKAGE_NAME); // Listener not called when a non existing override is removed. verify(mListener1, never()).onCompatChange(PACKAGE_NAME); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java index 220569449ffb..336bbaeae2d9 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java @@ -42,6 +42,7 @@ import android.content.Context; import android.os.Binder; import android.os.Handler; import android.os.Looper; +import android.os.Process; import android.os.ResultReceiver; import android.os.ShellCallback; import android.platform.test.annotations.Presubmit; @@ -86,7 +87,8 @@ public class LockSettingsShellCommandTest { MockitoAnnotations.initMocks(this); final Context context = InstrumentationRegistry.getTargetContext(); mUserId = ActivityManager.getCurrentUser(); - mCommand = new LockSettingsShellCommand(mLockPatternUtils); + mCommand = new LockSettingsShellCommand(mLockPatternUtils, context, 0, + Process.SHELL_UID); when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(true); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java index 32445fd1a47d..2eedc3251daa 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java @@ -19,19 +19,17 @@ package com.android.server.locksettings; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; - import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.security.GeneralSecurityException; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; -import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; /** * atest FrameworksServicesTests:RebootEscrowDataTest @@ -41,22 +39,18 @@ public class RebootEscrowDataTest { private RebootEscrowKey mKey; private SecretKey mKeyStoreEncryptionKey; - private SecretKey generateNewRebootEscrowEncryptionKey() throws GeneralSecurityException { - KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); - generator.init(new KeyGenParameterSpec.Builder( - "reboot_escrow_data_test_key", - KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) - .setKeySize(256) - .setBlockModes(KeyProperties.BLOCK_MODE_GCM) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) - .build()); - return generator.generateKey(); - } + // Hex encoding of a randomly generated AES key for test. + private static final byte[] TEST_AES_KEY = new byte[] { + 0x44, 0x74, 0x61, 0x54, 0x29, 0x74, 0x37, 0x61, + 0x48, 0x19, 0x12, 0x54, 0x13, 0x13, 0x52, 0x31, + 0x70, 0x70, 0x75, 0x25, 0x27, 0x31, 0x49, 0x09, + 0x26, 0x52, 0x72, 0x63, 0x63, 0x61, 0x78, 0x23, + }; @Before public void generateKey() throws Exception { mKey = RebootEscrowKey.generate(); - mKeyStoreEncryptionKey = generateNewRebootEscrowEncryptionKey(); + mKeyStoreEncryptionKey = new SecretKeySpec(TEST_AES_KEY, "AES"); } private static byte[] getTestSp() { @@ -114,4 +108,23 @@ public class RebootEscrowDataTest { assertThat(decrypted, is(testSp)); } + @Test + public void fromEncryptedData_legacyVersion_success() throws Exception { + byte[] testSp = getTestSp(); + byte[] ksEncryptedBlob = AesEncryptionUtil.encrypt(mKey.getKey(), testSp); + + // Write a legacy blob encrypted only by k_s. + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeInt(1); + dos.writeByte(3); + dos.write(ksEncryptedBlob); + byte[] legacyBlob = bos.toByteArray(); + + RebootEscrowData actual = RebootEscrowData.fromEncryptedData(mKey, legacyBlob, null); + + assertThat(actual.getSpVersion(), is((byte) 3)); + assertThat(actual.getKey().getKeyBytes(), is(mKey.getKeyBytes())); + assertThat(actual.getSyntheticPassword(), is(testSp)); + } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index a4ba4c86a8fd..a896f1b0d60f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -43,6 +43,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.pm.UserInfo; import android.hardware.rebootescrow.IRebootEscrow; +import android.os.Handler; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserManager; @@ -155,6 +156,11 @@ public class RebootEscrowManagerTests { } @Override + void post(Handler handler, Runnable runnable) { + runnable.run(); + } + + @Override public UserManager getUserManager() { return mUserManager; } @@ -369,7 +375,7 @@ public class RebootEscrowManagerTests { @Test public void loadRebootEscrowDataIfAvailable_NothingAvailable_Success() throws Exception { - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); } @Test @@ -401,7 +407,7 @@ public class RebootEscrowManagerTests { doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); assertTrue(metricsSuccessCaptor.getValue()); verify(mKeyStoreManager).clearKeyStoreEncryptionKey(); @@ -435,7 +441,7 @@ public class RebootEscrowManagerTests { when(mServiceConnection.unwrap(any(), anyLong())) .thenAnswer(invocation -> invocation.getArgument(0)); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mServiceConnection).unwrap(any(), anyLong()); assertTrue(metricsSuccessCaptor.getValue()); verify(mKeyStoreManager).clearKeyStoreEncryptionKey(); @@ -466,7 +472,7 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(10); when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); verify(mInjected, never()).reportMetric(anyBoolean()); } @@ -493,7 +499,7 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(10); when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mInjected, never()).reportMetric(anyBoolean()); } @@ -527,7 +533,7 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(10); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mInjected).reportMetric(eq(true)); } @@ -557,7 +563,7 @@ public class RebootEscrowManagerTests { ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> new byte[32]); - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); assertFalse(metricsSuccessCaptor.getValue()); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowProviderServerBasedImplTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowProviderServerBasedImplTests.java index bc1e025dd99f..28b737b412d2 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowProviderServerBasedImplTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowProviderServerBasedImplTests.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.ContextWrapper; +import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; @@ -42,7 +43,6 @@ import org.junit.runner.RunWith; import org.mockito.stubbing.Answer; import java.io.File; -import java.io.IOException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; @@ -130,7 +130,7 @@ public class RebootEscrowProviderServerBasedImplTests { @Test public void getAndClearRebootEscrowKey_ServiceConnectionException_failure() throws Exception { when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())).thenAnswer(mFakeEncryption); - doThrow(IOException.class).when(mServiceConnection).unwrap(any(), anyLong()); + doThrow(RemoteException.class).when(mServiceConnection).unwrap(any(), anyLong()); assertTrue(mRebootEscrowProvider.hasRebootEscrowSupport()); mRebootEscrowProvider.storeRebootEscrowKey(mRebootEscrowKey, mKeyStoreEncryptionKey); diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 3ebe4efee013..7d7af03ecd3d 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -2043,7 +2043,7 @@ public class NetworkPolicyManagerServiceTest { final NetworkCapabilities networkCapabilities = new NetworkCapabilities(); networkCapabilities.addTransportType(TRANSPORT_WIFI); networkCapabilities.setSSID(TEST_SSID); - return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null, TEST_SSID); + return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null); } private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception { @@ -2067,7 +2067,7 @@ public class NetworkPolicyManagerServiceTest { new NetworkState(TYPE_MOBILE, buildLinkProperties(TEST_IFACE), buildNetworkCapabilities(TEST_SUB_ID, roaming), - new Network(TEST_NET_ID), TEST_IMSI, null) + new Network(TEST_NET_ID), TEST_IMSI) }); } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java index ff43da6370e8..ee0a16a70265 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -86,6 +86,7 @@ public class DexManagerTests { private TestData mBarUser0DelegateLastClassLoader; private TestData mSystemServerJar; + private TestData mSystemServerJarUpdatedContext; private TestData mSystemServerJarInvalid; private int mUser0; @@ -113,6 +114,8 @@ public class DexManagerTests { mSystemServerJar = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME); mSystemServerJarInvalid = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME); + mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0, + DELEGATE_LAST_CLASS_LOADER_NAME); mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null, mInstaller, mInstallLock); @@ -522,6 +525,24 @@ public class DexManagerTests { } @Test + public void testSystemServerOverwritesContext() { + // Record bar secondaries with the default PathClassLoader. + List<String> secondaries = mSystemServerJar.getSecondaryDexPaths(); + + notifyDexLoad(mSystemServerJar, secondaries, mUser0); + PackageUseInfo pui = getPackageUseInfo(mSystemServerJar); + assertSecondaryUse(mSystemServerJar, pui, secondaries, /*isUsedByOtherApps*/false, mUser0); + + // Record bar secondaries again with a different class loader. This will change the context. + notifyDexLoad(mSystemServerJarUpdatedContext, secondaries, mUser0); + + pui = getPackageUseInfo(mSystemServerJar); + // We expect that all the contexts to be updated according to the last notify. + assertSecondaryUse(mSystemServerJarUpdatedContext, pui, secondaries, + /*isUsedByOtherApps*/false, mUser0); + } + + @Test public void testNotifyUnsupportedClassLoaderDoesNotChangeExisting() { List<String> secondaries = mBarUser0.getSecondaryDexPaths(); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java index caa8ae5e0e39..59e87d45f574 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java @@ -41,6 +41,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.servicestests.R; import com.android.server.pm.parsing.TestPackageParser2; +import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.parsing.pkg.ParsedPackage; @@ -57,6 +58,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.charset.StandardCharsets; +import java.util.Collection; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -66,6 +69,9 @@ import java.util.zip.ZipOutputStream; public class DexMetadataHelperTest { private static final String APK_FILE_EXTENSION = ".apk"; private static final String DEX_METADATA_FILE_EXTENSION = ".dm"; + private static final String DEX_METADATA_PACKAGE_NAME = + "com.android.frameworks.servicestests.install_split"; + private static long DEX_METADATA_VERSION_CODE = 30; @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); @@ -78,12 +84,46 @@ public class DexMetadataHelperTest { } private File createDexMetadataFile(String apkFileName) throws IOException { + return createDexMetadataFile(apkFileName, /*validManifest=*/true); + } + + private File createDexMetadataFile(String apkFileName, boolean validManifest) throws IOException + { + return createDexMetadataFile(apkFileName,DEX_METADATA_PACKAGE_NAME, + DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, validManifest); + } + + private File createDexMetadataFile(String apkFileName, String packageName, Long versionCode, + boolean emptyManifest, boolean validManifest) throws IOException { File dmFile = new File(mTmpDir, apkFileName.replace(APK_FILE_EXTENSION, DEX_METADATA_FILE_EXTENSION)); try (FileOutputStream fos = new FileOutputStream(dmFile)) { try (ZipOutputStream zipOs = new ZipOutputStream(fos)) { zipOs.putNextEntry(new ZipEntry("primary.prof")); zipOs.closeEntry(); + + if (validManifest) { + zipOs.putNextEntry(new ZipEntry("manifest.json")); + if (!emptyManifest) { + String manifestStr = "{"; + + if (packageName != null) { + manifestStr += "\"packageName\": " + "\"" + packageName + "\""; + + if (versionCode != null) { + manifestStr += ", "; + } + } + if (versionCode != null) { + manifestStr += " \"versionCode\": " + versionCode; + } + + manifestStr += "}"; + byte[] bytes = manifestStr.getBytes(StandardCharsets.UTF_8); + zipOs.write(bytes, /*off=*/0, /*len=*/bytes.length); + } + zipOs.closeEntry(); + } } } return dmFile; @@ -98,17 +138,38 @@ public class DexMetadataHelperTest { return outFile; } + private static void validatePackageDexMetadata(AndroidPackage pkg, boolean requireManifest) + throws PackageParserException { + Collection<String> apkToDexMetadataList = + AndroidPackageUtils.getPackageDexMetadata(pkg).values(); + String packageName = pkg.getPackageName(); + long versionCode = pkg.toAppInfoWithoutState().longVersionCode; + for (String dexMetadata : apkToDexMetadataList) { + DexMetadataHelper.validateDexMetadataFile( + dexMetadata, packageName, versionCode, requireManifest); + } + } + + private static void validatePackageDexMetatadataVaryingRequireManifest(ParsedPackage pkg) + throws PackageParserException { + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + validatePackageDexMetadata(pkg, /*requireManifest=*/false); + } + @Test public void testParsePackageWithDmFileValid() throws IOException, PackageParserException { copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); createDexMetadataFile("install_split_base.apk"); - ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false); + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg); assertEquals(1, packageDexMetadata.size()); String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath()); assertNotNull(baseDexMetadata); assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath())); + + // Should throw no exceptions. + validatePackageDexMetatadataVaryingRequireManifest(pkg); } @Test @@ -118,7 +179,7 @@ public class DexMetadataHelperTest { copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a); createDexMetadataFile("install_split_base.apk"); createDexMetadataFile("install_split_feature_a.apk"); - ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false); + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg); assertEquals(2, packageDexMetadata.size()); @@ -129,6 +190,9 @@ public class DexMetadataHelperTest { String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]); assertNotNull(splitDexMetadata); assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0])); + + // Should throw no exceptions. + validatePackageDexMetatadataVaryingRequireManifest(pkg); } @Test @@ -137,7 +201,7 @@ public class DexMetadataHelperTest { copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a); createDexMetadataFile("install_split_feature_a.apk"); - ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false); + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg); assertEquals(1, packageDexMetadata.size()); @@ -145,6 +209,9 @@ public class DexMetadataHelperTest { String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]); assertNotNull(splitDexMetadata); assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0])); + + // Should throw no exceptions. + validatePackageDexMetatadataVaryingRequireManifest(pkg); } @Test @@ -153,9 +220,17 @@ public class DexMetadataHelperTest { File invalidDmFile = new File(mTmpDir, "install_split_base.dm"); Files.createFile(invalidDmFile.toPath()); try { - ParsedPackage pkg = new TestPackageParser2() - .parsePackage(mTmpDir, 0 /* flags */, false); - AndroidPackageUtils.validatePackageDexMetadata(pkg); + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: empty .dm file"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/false); + fail("Should fail validation: empty .dm file"); } catch (PackageParserException e) { assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); } @@ -171,9 +246,112 @@ public class DexMetadataHelperTest { Files.createFile(invalidDmFile.toPath()); try { - ParsedPackage pkg = new TestPackageParser2() - .parsePackage(mTmpDir, 0 /* flags */, false); - AndroidPackageUtils.validatePackageDexMetadata(pkg); + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: empty .dm file"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/false); + fail("Should fail validation: empty .dm file"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileInvalidManifest() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", /*validManifest=*/false); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: missing manifest.json in the .dm archive"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileEmptyManifest() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", /*packageName=*/"doesn't matter", + /*versionCode=*/-12345L, /*emptyManifest=*/true, /*validManifest=*/true); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: empty manifest.json in the .dm archive"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileBadPackageName() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", /*packageName=*/"bad package name", + DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, /*validManifest=*/true); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: bad package name in the .dm archive"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileBadVersionCode() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", DEX_METADATA_PACKAGE_NAME, + /*versionCode=*/12345L, /*emptyManifest=*/false, /*validManifest=*/true); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: bad version code in the .dm archive"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileMissingPackageName() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", /*packageName=*/null, + DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, /*validManifest=*/true); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: missing package name in the .dm archive"); + } catch (PackageParserException e) { + assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); + } + } + + @Test + public void testParsePackageWithDmFileMissingVersionCode() + throws IOException, PackageParserException { + copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); + createDexMetadataFile("install_split_base.apk", DEX_METADATA_PACKAGE_NAME, + /*versionCode=*/null, /*emptyManifest=*/false, /*validManifest=*/true); + + try { + ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false); + validatePackageDexMetadata(pkg, /*requireManifest=*/true); + fail("Should fail validation: missing version code in the .dm archive"); } catch (PackageParserException e) { assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); } @@ -186,7 +364,7 @@ public class DexMetadataHelperTest { try { DexMetadataHelper.validateDexPaths(mTmpDir.list()); - fail("Should fail validation"); + fail("Should fail validation: split .dm filename unmatched against .apk"); } catch (IllegalStateException e) { // expected. } @@ -202,7 +380,7 @@ public class DexMetadataHelperTest { try { DexMetadataHelper.validateDexPaths(mTmpDir.list()); - fail("Should fail validation"); + fail("Should fail validation: .dm filename has no match against .apk"); } catch (IllegalStateException e) { // expected. } @@ -214,7 +392,7 @@ public class DexMetadataHelperTest { copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); File dm = createDexMetadataFile("install_split_base.apk"); ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite( - ParseTypeImpl.forDefaultParsing().reset(), mTmpDir, 0 /* flags */); + ParseTypeImpl.forDefaultParsing().reset(), mTmpDir, /*flags=*/0); if (result.isError()) { throw new IllegalStateException(result.getErrorMessage(), result.getException()); } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java index 22020ad45666..bc84e350a329 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java @@ -96,7 +96,7 @@ public class DexoptOptionsTests { int[] reasons = new int[] { PackageManagerService.REASON_FIRST_BOOT, - PackageManagerService.REASON_BOOT, + PackageManagerService.REASON_POST_BOOT, PackageManagerService.REASON_INSTALL, PackageManagerService.REASON_BACKGROUND_DEXOPT, PackageManagerService.REASON_AB_OTA, diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS new file mode 100644 index 000000000000..66ef75d6c823 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/dex/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java index adf4551e79a8..3450710f60a0 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java @@ -451,7 +451,7 @@ public class PackageDexUsageTests { "PCL[new_context.dex]"); assertTrue(record(fooSecondary1User0NewContext)); - // Not check that the context was switch to variable. + // Now check that the context was switch to variable. TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext( PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT); @@ -461,6 +461,22 @@ public class PackageDexUsageTests { } @Test + public void testRecordClassLoaderContextOverwritten() { + // Record a secondary dex file. + assertTrue(record(mFooSecondary1User0)); + // Now update its context. + TestData fooSecondary1User0NewContext = mFooSecondary1User0.updateClassLoaderContext( + "PCL[new_context.dex]", true); + assertTrue(record(fooSecondary1User0NewContext)); + + // Now check that the context was overwritten. + TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext( + "PCL[new_context.dex]", true); + + assertPackageDexUsage(null, expectedContext); + } + + @Test public void testDexUsageClassLoaderContext() { final boolean isUsedByOtherApps = false; final int userId = 0; @@ -642,8 +658,9 @@ public class PackageDexUsageTests { private boolean record(TestData testData) { return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile, - testData.mOwnerUserId, testData.mLoaderIsa, - testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext); + testData.mOwnerUserId, testData.mLoaderIsa, + testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext, + testData.mOverwriteCLC); } private boolean record(PackageDexUsage packageDexUsage, TestData testData, Set<String> users) { @@ -651,7 +668,8 @@ public class PackageDexUsageTests { for (String user : users) { result = result && packageDexUsage.record(testData.mPackageName, testData.mDexFile, testData.mOwnerUserId, testData.mLoaderIsa, - testData.mPrimaryOrSplit, user, testData.mClassLoaderContext); + testData.mPrimaryOrSplit, user, testData.mClassLoaderContext, + testData.mOverwriteCLC); } return result; } @@ -682,15 +700,16 @@ public class PackageDexUsageTests { private final boolean mPrimaryOrSplit; private final String mUsedBy; private final String mClassLoaderContext; + private final boolean mOverwriteCLC; private TestData(String packageName, String dexFile, int ownerUserId, String loaderIsa, boolean primaryOrSplit, String usedBy) { this(packageName, dexFile, ownerUserId, loaderIsa, primaryOrSplit, - usedBy, "PCL[" + dexFile + "]"); + usedBy, "PCL[" + dexFile + "]", false); } private TestData(String packageName, String dexFile, int ownerUserId, String loaderIsa, boolean primaryOrSplit, String usedBy, - String classLoaderContext) { + String classLoaderContext, boolean overwriteCLC) { mPackageName = packageName; mDexFile = dexFile; mOwnerUserId = ownerUserId; @@ -698,16 +717,21 @@ public class PackageDexUsageTests { mPrimaryOrSplit = primaryOrSplit; mUsedBy = usedBy; mClassLoaderContext = classLoaderContext; + mOverwriteCLC = overwriteCLC; } private TestData updateClassLoaderContext(String newContext) { + return updateClassLoaderContext(newContext, mOverwriteCLC); + } + + private TestData updateClassLoaderContext(String newContext, boolean overwriteCLC) { return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, - mPrimaryOrSplit, mUsedBy, newContext); + mPrimaryOrSplit, mUsedBy, newContext, overwriteCLC); } private TestData updateUsedBy(String newUsedBy) { return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, - mPrimaryOrSplit, newUsedBy, mClassLoaderContext); + mPrimaryOrSplit, newUsedBy, mClassLoaderContext, mOverwriteCLC); } private boolean isUsedByOtherApps() { diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java new file mode 100644 index 000000000000..70d85b6e0411 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm.parsing.library; + +import android.os.Build; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.pm.parsing.pkg.PackageImpl; +import com.android.server.pm.parsing.pkg.ParsedPackage; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link AndroidNetIpSecIkeUpdater} + */ +@Presubmit +@SmallTest +@RunWith(JUnit4.class) +public class AndroidNetIpSecIkeUpdaterTest extends PackageSharedLibraryUpdaterTest { + + @Test + public void otherUsesLibraries() { + ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary("other") + .addUsesOptionalLibrary("optional") + .addUsesLibrary("android.net.ipsec.ike") + .hideAsParsed()); + AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary("other") + .addUsesOptionalLibrary("optional") + .hideAsParsed()) + .hideAsFinal(); + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary("android.net.ipsec.ike") + .hideAsParsed()); + + AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed()) + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary("android.net.ipsec.ike") + .hideAsParsed()); + + AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed()) + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + checkBackwardsCompatibility(before, after, AndroidNetIpSecIkeUpdater::new); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java index 09c8142105cc..9768f176ea85 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java @@ -165,6 +165,23 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal()); } + /** + * Ensures that the {@link PackageBackwardCompatibility} uses a + * {@link AndroidNetIpSecIkeUpdater}. + */ + @Test + public void android_net_ipsec_ike_in_usesLibraries() { + ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary("android.net.ipsec.ike") + .hideAsParsed()); + + ParsingPackage after = PackageImpl.forTesting(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT); + + checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal()); + } + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance); } diff --git a/services/tests/servicestests/test-apps/ConnTestApp/Android.bp b/services/tests/servicestests/test-apps/ConnTestApp/Android.bp index 13e664446418..0731e2ca1f41 100644 --- a/services/tests/servicestests/test-apps/ConnTestApp/Android.bp +++ b/services/tests/servicestests/test-apps/ConnTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "ConnTestApp", diff --git a/services/tests/servicestests/test-apps/ConnTestApp/OWNERS b/services/tests/servicestests/test-apps/ConnTestApp/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/test-apps/ConnTestApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/test-apps/JobTestApp/Android.bp b/services/tests/servicestests/test-apps/JobTestApp/Android.bp index b29e187576c3..6458bcd4fc8f 100644 --- a/services/tests/servicestests/test-apps/JobTestApp/Android.bp +++ b/services/tests/servicestests/test-apps/JobTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "JobTestApp", diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp index c409438e94ae..0fd3de8b14b8 100644 --- a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp +++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "PackageParserTestApp1", sdk_version: "current", diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp index 5cbd39c39434..50b89d484ee8 100644 --- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp +++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "SimpleServiceTestApp", diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp index 7257275971ab..5e77498862be 100644 --- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp +++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "SuspendTestApp", diff --git a/services/tests/shortcutmanagerutils/Android.bp b/services/tests/shortcutmanagerutils/Android.bp index c2cb688175b2..b33230e1af12 100644 --- a/services/tests/shortcutmanagerutils/Android.bp +++ b/services/tests/shortcutmanagerutils/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "ShortcutManagerTestUtils", diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp index 4a1a6ada9eeb..541fc631bca6 100644 --- a/services/tests/uiservicestests/Android.bp +++ b/services/tests/uiservicestests/Android.bp @@ -2,6 +2,15 @@ // Build FrameworksUiServicesTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksUiServicesTests", diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index e2821f40f24c..6d0953a02415 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -2,6 +2,15 @@ // Build WmTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "WmTests", diff --git a/services/usage/Android.bp b/services/usage/Android.bp index 463673f104ab..350da876fb6d 100644 --- a/services/usage/Android.bp +++ b/services/usage/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.usage-sources", srcs: ["java/**/*.java"], diff --git a/services/usb/Android.bp b/services/usb/Android.bp index 4e984093cfec..efca1a1a9040 100644 --- a/services/usb/Android.bp +++ b/services/usb/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.usb-sources", srcs: ["java/**/*.java"], diff --git a/services/usb/OWNERS b/services/usb/OWNERS index 8ee72b577f3c..60172a36128e 100644 --- a/services/usb/OWNERS +++ b/services/usb/OWNERS @@ -1,6 +1,5 @@ badhri@google.com elaurent@google.com -moltmann@google.com albertccwang@google.com jameswei@google.com howardyen@google.com
\ No newline at end of file diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp index 47129ad62e86..cfccc17e18de 100644 --- a/services/voiceinteraction/Android.bp +++ b/services/voiceinteraction/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.voiceinteraction-sources", srcs: ["java/**/*.java"], diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp index 3975fd238bb5..62d53729c3dd 100644 --- a/services/wifi/Android.bp +++ b/services/wifi/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.wifi-sources", srcs: ["java/**/*.java"], diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp index f42c755e3efd..98b9b64e1242 100644 --- a/startop/apps/test/Android.bp +++ b/startop/apps/test/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "startop_test_app", srcs: [ diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp index 993d1e1092b9..4fdf34cc1814 100644 --- a/startop/iorap/Android.bp +++ b/startop/iorap/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "services.startop.iorap-javasources", srcs: ["src/**/*.java"], diff --git a/startop/iorap/functional_tests/Android.bp b/startop/iorap/functional_tests/Android.bp index 8a5bd34af653..43c61551cdec 100644 --- a/startop/iorap/functional_tests/Android.bp +++ b/startop/iorap/functional_tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "iorap-functional-tests", srcs: ["src/**/*.java"], @@ -39,4 +48,3 @@ android_test { certificate: "platform", platform_apis: true, } - diff --git a/startop/iorap/stress/Android.bp b/startop/iorap/stress/Android.bp index f9f251bdd889..6e8725d091fb 100644 --- a/startop/iorap/stress/Android.bp +++ b/startop/iorap/stress/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary { name: "iorap.stress.memory", srcs: ["main_memory.cc"], diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp index 3e60ad448cae..ad3d001ad7d4 100644 --- a/startop/iorap/tests/Android.bp +++ b/startop/iorap/tests/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // TODO: once b/80095087 is fixed, rewrite this back to android_test +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "libiorap-java-test-lib", srcs: ["src/**/*.kt"], diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index cac7b82adc2c..90239212f665 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "viewcompiler_defaults", header_libs: [ diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp index f783aa68fe92..2048964f4af2 100644 --- a/startop/view_compiler/dex_builder_test/Android.bp +++ b/startop/view_compiler/dex_builder_test/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + genrule { name: "generate_compiled_layout1", tools: [":viewcompiler"], diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index a4ecb722bd2c..580513c12453 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -1992,7 +1992,7 @@ public abstract class ConnectionService extends Service { boolean isHandover = request.getExtras() != null && request.getExtras().getBoolean( TelecomManager.EXTRA_IS_HANDOVER_CONNECTION, false); boolean addSelfManaged = request.getExtras() != null && request.getExtras().getBoolean( - PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, false); + PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true); Log.i(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " + "isIncoming: %b, isUnknown: %b, isLegacyHandover: %b, isHandover: %b, " + " addSelfManaged: %b", callManagerAccount, callId, request, isIncoming, diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index b81c4f2c71c8..9861973bcae8 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3999,8 +3999,9 @@ public class CarrierConfigManager { "mmi_two_digit_number_pattern_string_array"; /** - * Holds the list of carrier certificate hashes. - * Note that each carrier has its own certificates. + * Holds the list of carrier certificate hashes, followed by optional package names. + * Format: "sha1/256" or "sha1/256:package1,package2,package3..." + * Note that each carrier has its own hashes. */ public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY = "carrier_certificate_string_array"; @@ -4146,6 +4147,16 @@ public class CarrierConfigManager { public static final String KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL = "network_temp_not_metered_supported_bool"; + /** + * Indicates the allowed APN types that can be used for LTE initial attach. The order of APN + * types in the configuration is the order of APN types that will be used for initial attach. + * Empty list indicates that no APN types are allowed for initial attach. + * + * @hide + */ + public static final String KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY = + "allowed_initial_attach_apn_types_string_array"; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -4697,6 +4708,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false); sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, false); sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0); + sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY, + new String[]{"ia", "default", "ims", "mms", "dun", "emergency"}); } /** diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java index 12bb36647f8f..2765349f3bf3 100644 --- a/telephony/java/android/telephony/UiccAccessRule.java +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -35,6 +35,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -52,6 +53,16 @@ public final class UiccAccessRule implements Parcelable { private static final int ENCODING_VERSION = 1; + /** + * Delimiter used to decode {@link CarrierConfigManager#KEY_CARRIER_CERTIFICATE_STRING_ARRAY}. + */ + private static final String DELIMITER_CERTIFICATE_HASH_PACKAGE_NAMES = ":"; + + /** + * Delimiter used to decode {@link CarrierConfigManager#KEY_CARRIER_CERTIFICATE_STRING_ARRAY}. + */ + private static final String DELIMITER_INDIVIDUAL_PACKAGE_NAMES = ","; + public static final @android.annotation.NonNull Creator<UiccAccessRule> CREATOR = new Creator<UiccAccessRule>() { @Override public UiccAccessRule createFromParcel(Parcel in) { @@ -98,6 +109,36 @@ public final class UiccAccessRule implements Parcelable { } /** + * Decodes {@link CarrierConfigManager#KEY_CARRIER_CERTIFICATE_STRING_ARRAY} values. + * @hide + */ + @Nullable + public static UiccAccessRule[] decodeRulesFromCarrierConfig(@Nullable String[] certs) { + if (certs == null) { + return null; + } + List<UiccAccessRule> carrierConfigAccessRulesArray = new ArrayList(); + for (String cert : certs) { + String[] splitStr = cert.split(DELIMITER_CERTIFICATE_HASH_PACKAGE_NAMES); + byte[] certificateHash = IccUtils.hexStringToBytes(splitStr[0]); + if (splitStr.length == 1) { + // The value is a certificate hash, without any package name + carrierConfigAccessRulesArray.add(new UiccAccessRule(certificateHash, null, 0)); + } else { + // The value is composed of the certificate hash followed by at least one + // package name + String[] packageNames = splitStr[1].split(DELIMITER_INDIVIDUAL_PACKAGE_NAMES); + for (String packageName : packageNames) { + carrierConfigAccessRulesArray.add( + new UiccAccessRule(certificateHash, packageName, 0)); + } + } + } + return carrierConfigAccessRulesArray.toArray( + new UiccAccessRule[carrierConfigAccessRulesArray.size()]); + } + + /** * Decodes a byte array generated with {@link #encodeRules}. * @hide */ @@ -214,6 +255,14 @@ public final class UiccAccessRule implements Parcelable { return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; } + /** + * Returns true if the given certificate and package name match this rule's values. + * @hide + */ + public boolean matches(@Nullable String certHash, @Nullable String packageName) { + return matches(IccUtils.hexStringToBytes(certHash), packageName); + } + private boolean matches(byte[] certHash, String packageName) { return certHash != null && Arrays.equals(this.mCertificateHash, certHash) && (TextUtils.isEmpty(this.mPackageName) || this.mPackageName.equals(packageName)); diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 46ec4a39fd21..46940dc6a0a5 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.LinkAddress; +import android.net.LinkProperties; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.DataFailureCause; @@ -274,9 +275,11 @@ public final class DataCallResponse implements Parcelable { } /** - * @return The network suggested data retry duration in milliseconds. {@code Long.MAX_VALUE} - * indicates data retry should not occur. {@link #RETRY_DURATION_UNDEFINED} indicates network - * did not suggest any retry duration. + * @return The network suggested data retry duration in milliseconds as specified in + * 3GPP TS 24.302 section 8.2.9.1. The APN associated to this data call will be throttled for + * the specified duration unless {@link DataServiceCallback#onApnUnthrottled} is called. + * {@code Long.MAX_VALUE} indicates data retry should not occur. + * {@link #RETRY_DURATION_UNDEFINED} indicates network did not suggest any retry duration. */ public long getRetryDurationMillis() { return mSuggestedRetryTime; diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index 52bf15fd16c3..f56c19b78a16 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -250,7 +250,11 @@ public class DataServiceCallback { } /** - * Indicates that the specified APN is no longer throttled. + * The APN is throttled for the duration specified in + * {@link DataCallResponse#getRetryDurationMillis}. Calling this method unthrottles that + * APN. + * <p/> + * see: {@link DataCallResponse#getRetryDurationMillis} * * @param apn Access Point Name defined by the carrier. */ diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl index 2904082616e7..ba2b62d14bec 100644 --- a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl +++ b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl @@ -17,7 +17,7 @@ package android.telephony.data; import android.telephony.data.IQualifiedNetworksServiceCallback; -import android.telephony.data.ApnThrottleStatus; +import android.telephony.data.ThrottleStatus; /** * {@hide} @@ -26,5 +26,5 @@ interface IQualifiedNetworksService { oneway void createNetworkAvailabilityProvider(int slotId, IQualifiedNetworksServiceCallback callback); oneway void removeNetworkAvailabilityProvider(int slotId); - oneway void reportApnThrottleStatusChanged(int slotId, in List<ApnThrottleStatus> statuses); + oneway void reportThrottleStatusChanged(int slotId, in List<ThrottleStatus> statuses); } diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java index 4af63b4cf981..4e85d8926f11 100644 --- a/telephony/java/android/telephony/data/QualifiedNetworksService.java +++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java @@ -168,8 +168,8 @@ public abstract class QualifiedNetworksService extends Service { * * @param statuses the statuses that have changed */ - public void reportApnThrottleStatusChanged(@NonNull List<ApnThrottleStatus> statuses) { - Log.d(TAG, "reportApnThrottleStatusChanged: statuses size=" + statuses.size()); + public void reportThrottleStatusChanged(@NonNull List<ThrottleStatus> statuses) { + Log.d(TAG, "reportThrottleStatusChanged: statuses size=" + statuses.size()); } /** @@ -212,8 +212,8 @@ public abstract class QualifiedNetworksService extends Service { break; case QNS_APN_THROTTLE_STATUS_CHANGED: if (provider != null) { - List<ApnThrottleStatus> statuses = (List<ApnThrottleStatus>) message.obj; - provider.reportApnThrottleStatusChanged(statuses); + List<ThrottleStatus> statuses = (List<ThrottleStatus>) message.obj; + provider.reportThrottleStatusChanged(statuses); } break; @@ -307,8 +307,8 @@ public abstract class QualifiedNetworksService extends Service { } @Override - public void reportApnThrottleStatusChanged(int slotIndex, - List<ApnThrottleStatus> statuses) { + public void reportThrottleStatusChanged(int slotIndex, + List<ThrottleStatus> statuses) { mHandler.obtainMessage(QNS_APN_THROTTLE_STATUS_CHANGED, slotIndex, 0, statuses) .sendToTarget(); } diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.aidl b/telephony/java/android/telephony/data/ThrottleStatus.aidl index 46bc4abde159..f75f35709816 100644 --- a/telephony/java/android/telephony/data/ApnThrottleStatus.aidl +++ b/telephony/java/android/telephony/data/ThrottleStatus.aidl @@ -17,4 +17,4 @@ /** @hide */ package android.telephony.data; -parcelable ApnThrottleStatus; +parcelable ThrottleStatus; diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.java b/telephony/java/android/telephony/data/ThrottleStatus.java index 51461d17690a..0335c6868340 100644 --- a/telephony/java/android/telephony/data/ApnThrottleStatus.java +++ b/telephony/java/android/telephony/data/ThrottleStatus.java @@ -35,7 +35,7 @@ import java.util.Objects; * @hide */ @SystemApi -public final class ApnThrottleStatus implements Parcelable { +public final class ThrottleStatus implements Parcelable { /** * The APN type is not throttled. */ @@ -43,14 +43,14 @@ public final class ApnThrottleStatus implements Parcelable { /** * The APN type is throttled until {@link android.os.SystemClock#elapsedRealtime()} - * has reached {@link ApnThrottleStatus#getThrottleExpiryTimeMillis} + * has reached {@link ThrottleStatus#getThrottleExpiryTimeMillis} */ public static final int THROTTLE_TYPE_ELAPSED_TIME = 2; /** {@hide} */ @IntDef(flag = true, prefix = {"THROTTLE_TYPE_"}, value = { - ApnThrottleStatus.THROTTLE_TYPE_NONE, - ApnThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME, + ThrottleStatus.THROTTLE_TYPE_NONE, + ThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME, }) public @interface ThrottleType { } @@ -72,9 +72,9 @@ public final class ApnThrottleStatus implements Parcelable { /** {@hide} */ @IntDef(flag = true, prefix = {"RETRY_TYPE_"}, value = { - ApnThrottleStatus.RETRY_TYPE_NONE, - ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION, - ApnThrottleStatus.RETRY_TYPE_HANDOVER, + ThrottleStatus.RETRY_TYPE_NONE, + ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, + ThrottleStatus.RETRY_TYPE_HANDOVER, }) public @interface RetryType { } @@ -141,7 +141,7 @@ public final class ApnThrottleStatus implements Parcelable { * {@link SystemClock#elapsedRealtime}. * * This value only applies when the throttle type is set to - * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. + * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. * * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely. * @@ -152,7 +152,7 @@ public final class ApnThrottleStatus implements Parcelable { return mThrottleExpiryTimeMillis; } - private ApnThrottleStatus(int slotIndex, + private ThrottleStatus(int slotIndex, @AccessNetworkConstants.TransportType int transportType, @Annotation.ApnType int apnTypes, @ThrottleType int throttleType, @@ -166,7 +166,7 @@ public final class ApnThrottleStatus implements Parcelable { mRetryType = retryType; } - private ApnThrottleStatus(@NonNull Parcel source) { + private ThrottleStatus(@NonNull Parcel source) { mSlotIndex = source.readInt(); mTransportType = source.readInt(); mApnType = source.readInt(); @@ -185,16 +185,16 @@ public final class ApnThrottleStatus implements Parcelable { dest.writeInt(mThrottleType); } - public static final @NonNull Parcelable.Creator<ApnThrottleStatus> CREATOR = - new Parcelable.Creator<ApnThrottleStatus>() { + public static final @NonNull Parcelable.Creator<ThrottleStatus> CREATOR = + new Parcelable.Creator<ThrottleStatus>() { @Override - public ApnThrottleStatus createFromParcel(@NonNull Parcel source) { - return new ApnThrottleStatus(source); + public ThrottleStatus createFromParcel(@NonNull Parcel source) { + return new ThrottleStatus(source); } @Override - public ApnThrottleStatus[] newArray(int size) { - return new ApnThrottleStatus[size]; + public ThrottleStatus[] newArray(int size) { + return new ThrottleStatus[size]; } }; @@ -213,8 +213,8 @@ public final class ApnThrottleStatus implements Parcelable { public boolean equals(Object obj) { if (obj == null) { return false; - } else if (obj instanceof ApnThrottleStatus) { - ApnThrottleStatus other = (ApnThrottleStatus) obj; + } else if (obj instanceof ThrottleStatus) { + ThrottleStatus other = (ThrottleStatus) obj; return this.mSlotIndex == other.mSlotIndex && this.mApnType == other.mApnType && this.mRetryType == other.mRetryType @@ -228,7 +228,7 @@ public final class ApnThrottleStatus implements Parcelable { @Override public String toString() { - return "ApnThrottleStatus{" + return "ThrottleStatus{" + "mSlotIndex=" + mSlotIndex + ", mTransportType=" + mTransportType + ", mApnType=" + ApnSetting.getApnTypeString(mApnType) @@ -239,18 +239,18 @@ public final class ApnThrottleStatus implements Parcelable { } /** - * Provides a convenient way to set the fields of an {@link ApnThrottleStatus} when creating a + * Provides a convenient way to set the fields of an {@link ThrottleStatus} when creating a * new instance. * - * <p>The example below shows how you might create a new {@code ApnThrottleStatus}: + * <p>The example below shows how you might create a new {@code ThrottleStatus}: * * <pre><code> * - * DataCallResponseApnThrottleStatus = new ApnThrottleStatus.Builder() + * ThrottleStatus = new ThrottleStatus.Builder() * .setSlotIndex(1) * .setApnType({@link ApnSetting#TYPE_EMERGENCY}) * .setNoThrottle() - * .setRetryType({@link ApnThrottleStatus#RETRY_TYPE_NEW_CONNECTION}) + * .setRetryType({@link ThrottleStatus#RETRY_TYPE_NEW_CONNECTION}) * .build(); * </code></pre> */ @@ -261,6 +261,10 @@ public final class ApnThrottleStatus implements Parcelable { private long mThrottleExpiryTimeMillis; private @RetryType int mRetryType; private @ThrottleType int mThrottleType; + + /** + * @hide + */ public static final long NO_THROTTLE_EXPIRY_TIME = DataCallResponse.RETRY_DURATION_UNDEFINED; @@ -312,7 +316,7 @@ public final class ApnThrottleStatus implements Parcelable { * {@link SystemClock#elapsedRealtime}. * * When setting this value, the throttle type is set to - * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. + * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. * * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely. * @@ -338,7 +342,7 @@ public final class ApnThrottleStatus implements Parcelable { * Sets the status of the APN type as not being throttled. * * When setting this value, the throttle type is set to - * {@link ApnThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to + * {@link ThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to * {@link Builder#NO_THROTTLE_EXPIRY_TIME}. * * @return The same instance of the builder. @@ -365,13 +369,13 @@ public final class ApnThrottleStatus implements Parcelable { } /** - * Build the {@link ApnThrottleStatus} + * Build the {@link ThrottleStatus} * - * @return the {@link ApnThrottleStatus} object + * @return the {@link ThrottleStatus} object */ @NonNull - public ApnThrottleStatus build() { - return new ApnThrottleStatus( + public ThrottleStatus build() { + return new ThrottleStatus( mSlotIndex, mTransportType, mApnType, diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index bd623e055743..5f4e1e6f3148 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -21,6 +21,7 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.os.Binder; @@ -39,6 +40,8 @@ import android.util.Log; import com.android.internal.telephony.IIntegerConsumer; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -77,31 +80,49 @@ public class ImsRcsManager { "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; /** - * Receives RCS Feature availability status updates from the ImsService. - * - * @see #isAvailable(int) - * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) - * @see #unregisterRcsAvailabilityCallback(AvailabilityCallback) + * An application can use {@link #addOnAvailabilityChangedListener} to register a + * {@link OnAvailabilityChangedListener}, which will notify the user when the RCS feature + * availability status updates from the ImsService. * @hide */ - public static class AvailabilityCallback { + @SystemApi + public interface OnAvailabilityChangedListener { + /** + * The availability of the feature's capabilities has changed to either available or + * unavailable. + * <p> + * If unavailable, the feature does not support the capability at the current time. This may + * be due to network or subscription provisioning changes, such as the IMS registration + * being lost, network type changing, or OMA-DM provisioning updates. + * + * @param capabilities The new availability of the capabilities. + */ + void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities); + } - private static class CapabilityBinder extends IImsCapabilityCallback.Stub { + /** + * Receive the availability status changed from the ImsService and pass the status change to + * the associated {@link OnAvailabilityChangedListener} + */ + private static class AvailabilityCallbackAdapter { - private final AvailabilityCallback mLocalCallback; - private Executor mExecutor; + private static class CapabilityBinder extends IImsCapabilityCallback.Stub { + private final OnAvailabilityChangedListener mOnAvailabilityChangedListener; + private final Executor mExecutor; - CapabilityBinder(AvailabilityCallback c) { - mLocalCallback = c; + CapabilityBinder(OnAvailabilityChangedListener listener, Executor executor) { + mExecutor = executor; + mOnAvailabilityChangedListener = listener; } @Override public void onCapabilitiesStatusChanged(int config) { - if (mLocalCallback == null) return; + if (mOnAvailabilityChangedListener == null) return; long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config)); + mExecutor.execute(() -> + mOnAvailabilityChangedListener.onAvailabilityChanged(config)); } finally { restoreCallingIdentity(callingIdentity); } @@ -110,48 +131,34 @@ public class ImsRcsManager { @Override public void onQueryCapabilityConfiguration(int capability, int radioTech, boolean isEnabled) { - // This is not used for public interfaces. + // This is not used. } @Override public void onChangeCapabilityConfigurationError(int capability, int radioTech, @ImsFeature.ImsCapabilityError int reason) { - // This is not used for public interfaces - } - - private void setExecutor(Executor executor) { - mExecutor = executor; + // This is not used. } } - private final CapabilityBinder mBinder = new CapabilityBinder(this); + private final CapabilityBinder mBinder; - /** - * The availability of the feature's capabilities has changed to either available or - * unavailable. - * <p> - * If unavailable, the feature does not support the capability at the current time. This may - * be due to network or subscription provisioning changes, such as the IMS registration - * being lost, network type changing, or OMA-DM provisioning updates. - * - * @param capabilities The new availability of the capabilities. - */ - public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { + AvailabilityCallbackAdapter(@NonNull Executor executor, + @NonNull OnAvailabilityChangedListener listener) { + mBinder = new CapabilityBinder(listener, executor); } /**@hide*/ public final IImsCapabilityCallback getBinder() { return mBinder; } - - private void setExecutor(Executor executor) { - mBinder.setExecutor(executor); - } } private final int mSubId; private final Context mContext; private final BinderCacheManager<IImsRcsController> mBinderCache; + private final Map<OnAvailabilityChangedListener, AvailabilityCallbackAdapter> + mAvailabilityChangedCallbacks; /** * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class. @@ -162,6 +169,7 @@ public class ImsRcsManager { mSubId = subId; mContext = context; mBinderCache = binderCache; + mAvailabilityChangedCallbacks = new HashMap<>(); } /** @@ -174,10 +182,23 @@ public class ImsRcsManager { } /** - * @hide + * Registers a {@link RegistrationManager.RegistrationCallback} with the system. When the + * callback is registered, it will initiate the callback c to be called with the current + * registration state. + * + * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * + * @param executor The executor the callback events should be run on. + * @param c The {@link RegistrationManager.RegistrationCallback} to be added. + * @see #unregisterImsRegistrationCallback(RegistrationManager.RegistrationCallback) + * @throws ImsException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed + * reason. */ - // @Override add back to RegistrationManager interface once public. - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerImsRegistrationCallback( @NonNull @CallbackExecutor Executor executor, @NonNull RegistrationManager.RegistrationCallback c) @@ -191,7 +212,7 @@ public class ImsRcsManager { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Register registration callback: IImsRcsController is null"); + Log.w(TAG, "Register registration callback: IImsRcsController is null"); throw new ImsException("Cannot find remote IMS service", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } @@ -207,10 +228,21 @@ public class ImsRcsManager { } /** - * @hide + * Removes an existing {@link RegistrationManager.RegistrationCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. + * + * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * + * @param c The {@link RegistrationManager.RegistrationCallback} to be removed. + * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener + * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) */ - // @Override add back to RegistrationManager interface once public. - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public void unregisterImsRegistrationCallback( @NonNull RegistrationManager.RegistrationCallback c) { if (c == null) { @@ -219,7 +251,7 @@ public class ImsRcsManager { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Unregister registration callback: IImsRcsController is null"); + Log.w(TAG, "Unregister registration callback: IImsRcsController is null"); throw new IllegalStateException("Cannot find remote IMS service"); } @@ -231,10 +263,21 @@ public class ImsRcsManager { } /** - * @hide + * Gets the registration state of the IMS service. + * + * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * + * @param executor The {@link Executor} that will be used to call the IMS registration state + * callback. + * @param stateCallback A callback called on the supplied {@link Executor} that will contain the + * registration state of the IMS service, which will be one of the + * following: {@link RegistrationManager#REGISTRATION_STATE_NOT_REGISTERED}, + * {@link RegistrationManager#REGISTRATION_STATE_REGISTERING}, or + * {@link RegistrationManager#REGISTRATION_STATE_REGISTERED}. */ - // @Override add back to RegistrationManager interface once public. - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, @NonNull @RegistrationManager.ImsRegistrationState Consumer<Integer> stateCallback) { if (stateCallback == null) { @@ -246,7 +289,7 @@ public class ImsRcsManager { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Get registration state error: IImsRcsController is null"); + Log.w(TAG, "Get registration state error: IImsRcsController is null"); throw new IllegalStateException("Cannot find remote IMS service"); } @@ -263,9 +306,20 @@ public class ImsRcsManager { } /** - * @hide + * Gets the Transport Type associated with the current IMS registration. + * + * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * + * @param executor The {@link Executor} that will be used to call the transportTypeCallback. + * @param transportTypeCallback The transport type associated with the current IMS registration, + * which will be one of following: + * {@see AccessNetworkConstants#TRANSPORT_TYPE_WWAN}, + * {@see AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or + * {@see AccessNetworkConstants#TRANSPORT_TYPE_INVALID}. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback) { @@ -278,7 +332,7 @@ public class ImsRcsManager { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Get registration transport type error: IImsRcsController is null"); + Log.w(TAG, "Get registration transport type error: IImsRcsController is null"); throw new IllegalStateException("Cannot find remote IMS service"); } @@ -296,31 +350,33 @@ public class ImsRcsManager { } /** - * Registers an {@link AvailabilityCallback} with the system, which will provide RCS + * Add an {@link OnAvailabilityChangedListener} with the system, which will provide RCS * availability updates for the subscription specified. * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call - * {@link #unregisterRcsAvailabilityCallback(AvailabilityCallback)} to clean up after a - * subscription is removed. + * {@link #removeOnAvailabilityChangedListener(OnAvailabilityChangedListener)} to clean up + * after a subscription is removed. * <p> - * When the callback is registered, it will initiate the callback c to be called with the - * current capabilities. + * When the listener is registered, it will initiate the callback listener to be called with + * the current capabilities. * * @param executor The executor the callback events should be run on. - * @param c The RCS {@link AvailabilityCallback} to be registered. - * @see #unregisterRcsAvailabilityCallback(AvailabilityCallback) + * @param listener The RCS {@link OnAvailabilityChangedListener} to be registered. + * @see #removeOnAvailabilityChangedListener(OnAvailabilityChangedListener) * @throws ImsException if the subscription associated with this instance of * {@link ImsRcsManager} is valid, but the ImsService associated with the subscription is not * available. This can happen if the ImsService has crashed, for example, or if the subscription * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void registerRcsAvailabilityCallback(@NonNull @CallbackExecutor Executor executor, - @NonNull AvailabilityCallback c) throws ImsException { - if (c == null) { - throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + public void addOnAvailabilityChangedListener(@NonNull @CallbackExecutor Executor executor, + @NonNull OnAvailabilityChangedListener listener) throws ImsException { + if (listener == null) { + throw new IllegalArgumentException("Must include a non-null" + + "OnAvailabilityChangedListener."); } if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); @@ -328,56 +384,61 @@ public class ImsRcsManager { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Register availability callback: IImsRcsController is null"); + Log.w(TAG, "Add availability changed listener: IImsRcsController is null"); throw new ImsException("Cannot find remote IMS service", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } - c.setExecutor(executor); + AvailabilityCallbackAdapter adapter = + addAvailabilityChangedListenerToCollection(executor, listener); try { - imsRcsController.registerRcsAvailabilityCallback(mSubId, c.getBinder()); - + imsRcsController.registerRcsAvailabilityCallback(mSubId, adapter.getBinder()); } catch (ServiceSpecificException e) { throw new ImsException(e.toString(), e.errorCode); } catch (RemoteException e) { - Log.e(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e); + Log.w(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e); throw new ImsException("Remote IMS Service is not available", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } - /** - * Removes an existing RCS {@link AvailabilityCallback}. + /** + * Removes an existing RCS {@link OnAvailabilityChangedListener}. * <p> * When the subscription associated with this callback is removed (SIM removed, ESIM swap, * etc...), this callback will automatically be unregistered. If this method is called for an * inactive subscription, it will result in a no-op. - * @param c The RCS {@link AvailabilityCallback} to be removed. - * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) + * @param listener The RCS {@link OnAvailabilityChangedListener} to be removed. + * @see #addOnAvailabilityChangedListener(Executor, OnAvailabilityChangedListener) * @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 */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c) - throws ImsException { - if (c == null) { - throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + public void removeOnAvailabilityChangedListener( + @NonNull OnAvailabilityChangedListener listener) { + if (listener == null) { + throw new IllegalArgumentException("Must include a non-null" + + "OnAvailabilityChangedListener."); } IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "Unregister availability callback: IImsRcsController is null"); - throw new ImsException("Cannot find remote IMS service", - ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + Log.w(TAG, "Remove availability changed listener: IImsRcsController is null"); + return; + } + + AvailabilityCallbackAdapter callback = + removeAvailabilityChangedListenerFromCollection(listener); + if (callback == null) { + return; } try { - imsRcsController.unregisterRcsAvailabilityCallback(mSubId, c.getBinder()); + imsRcsController.unregisterRcsAvailabilityCallback(mSubId, callback.getBinder()); } catch (RemoteException e) { - Log.e(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e); - throw new ImsException("Remote IMS Service is not available", - ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + Log.w(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e); } } @@ -388,25 +449,24 @@ public class ImsRcsManager { * RCS capabilities provided over-the-top by applications. * * @param capability The RCS capability to query. - * @param radioTech The radio tech that this capability failed for, defined as - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}. + * @param radioTech The radio technology type that we are querying. * @return true if the RCS capability is capable for this subscription, false otherwise. This * does not necessarily mean that we are registered for IMS and the capability is available, but * rather the subscription is capable of this service over IMS. - * @see #isAvailable(int) + * @see #isAvailable(int, int) * @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL * @see android.telephony.CarrierConfigManager.Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL * @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 */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "isCapable: IImsRcsController is null"); + Log.w(TAG, "isCapable: IImsRcsController is null"); throw new ImsException("Cannot find remote IMS service", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } @@ -414,7 +474,7 @@ public class ImsRcsManager { try { return imsRcsController.isCapable(mSubId, capability, radioTech); } catch (RemoteException e) { - Log.e(TAG, "Error calling IImsRcsController#isCapable", e); + Log.w(TAG, "Error calling IImsRcsController#isCapable", e); throw new ImsException("Remote IMS Service is not available", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } @@ -427,6 +487,7 @@ public class ImsRcsManager { * RCS capabilities provided by over-the-top by applications. * * @param capability the RCS capability to query. + * @param radioTech The radio technology type that we are querying. * @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. @@ -435,25 +496,57 @@ public class ImsRcsManager { * See {@link ImsException#getCode()} for more information on the error codes. * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability) + public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { - Log.e(TAG, "isAvailable: IImsRcsController is null"); + Log.w(TAG, "isAvailable: IImsRcsController is null"); throw new ImsException("Cannot find remote IMS service", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } try { - return imsRcsController.isAvailable(mSubId, capability); + return imsRcsController.isAvailable(mSubId, capability, radioTech); } catch (RemoteException e) { - Log.e(TAG, "Error calling IImsRcsController#isAvailable", e); + Log.w(TAG, "Error calling IImsRcsController#isAvailable", e); throw new ImsException("Remote IMS Service is not available", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } + /** + * Add the {@link OnAvailabilityChangedListener} to collection for tracking. + * @param executor The executor that will be used when the publish state is changed and the + * {@link OnAvailabilityChangedListener} is called. + * @param listener The {@link OnAvailabilityChangedListener} to call the publish state changed. + * @return The {@link AvailabilityCallbackAdapter} to wrapper the + * {@link OnAvailabilityChangedListener} + */ + private AvailabilityCallbackAdapter addAvailabilityChangedListenerToCollection( + @NonNull Executor executor, @NonNull OnAvailabilityChangedListener listener) { + AvailabilityCallbackAdapter adapter = new AvailabilityCallbackAdapter(executor, listener); + synchronized (mAvailabilityChangedCallbacks) { + mAvailabilityChangedCallbacks.put(listener, adapter); + } + return adapter; + } + + /** + * Remove the existing {@link OnAvailabilityChangedListener} from the collection. + * @param listener The {@link OnAvailabilityChangedListener} to remove from the collection. + * @return The wrapper class {@link AvailabilityCallbackAdapter} associated with the + * {@link OnAvailabilityChangedListener}. + */ + private AvailabilityCallbackAdapter removeAvailabilityChangedListenerFromCollection( + @NonNull OnAvailabilityChangedListener listener) { + synchronized (mAvailabilityChangedCallbacks) { + return mAvailabilityChangedCallbacks.remove(listener); + } + } + private IImsRcsController getIImsRcsController() { IBinder binder = TelephonyFrameworkInitializer .getTelephonyServiceManager() diff --git a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl new file mode 100644 index 000000000000..0830ff2ff050 --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +parcelable ImsRegistrationAttributes; diff --git a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java new file mode 100644 index 000000000000..a36f54953e63 --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.AccessNetworkConstants; +import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.util.ArraySet; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Objects; +import java.util.Set; + +/** + * Contains the attributes associated with the current IMS registration. + */ +public final class ImsRegistrationAttributes implements Parcelable { + + /** + * Builder for creating {@link ImsRegistrationAttributes} instances. + * @hide + */ + @SystemApi + public static final class Builder { + private final int mRegistrationTech; + private Set<String> mFeatureTags = Collections.emptySet(); + + /** + * Build a new instance of {@link ImsRegistrationAttributes}. + * + * @param registrationTech The Radio Access Technology that IMS is registered on. + */ + public Builder(@ImsRegistrationImplBase.ImsRegistrationTech int registrationTech) { + mRegistrationTech = registrationTech; + } + + /** + * Optional IMS feature tags included in this IMS registration. + * @param tags A set of Strings containing the MMTEL and RCS feature tags associated with + * the IMS registration. This information is used for services such as the UCE + * service to ascertain the complete IMS registration state to ensure the SIP + * PUBLISH is accurate. The format of the set of feature tags must be one feature + * tag key and value per entry. Each feature tag will contain the feature tag name + * and string value (if applicable), even if they have the same feature tag name. + * For example, + * {@code +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg, + * urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", +g.gsma.callcomposer} must + * be split into three feature tag entries: + * {@code {+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg", + * +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", + * +g.gsma.callcomposer}}. + */ + public @NonNull Builder setFeatureTags(@NonNull Set<String> tags) { + if (tags == null) { + throw new IllegalArgumentException("feature tag set must not be null"); + } + mFeatureTags = new ArraySet<>(tags); + return this; + } + + /** + * @return A new instance created from this builder. + */ + public @NonNull ImsRegistrationAttributes build() { + return new ImsRegistrationAttributes(mRegistrationTech, + RegistrationManager.getAccessType(mRegistrationTech), + 0 /* No attributes in AOSP */, mFeatureTags); + } + + } + + private final int mRegistrationTech; + private final int mTransportType; + private final int mImsAttributeFlags; + private final ArrayList<String> mFeatureTags; + + /** + * Create a new {@link ImsRegistrationAttributes} instance. + * + * @param registrationTech The technology that IMS has been registered on. + * @param transportType The transport type that IMS has been registered on. + * @param imsAttributeFlags The attributes associated with the IMS registration. + * @param featureTags The feature tags included in the IMS registration. + * @see Builder + * @hide + */ + public ImsRegistrationAttributes( + @ImsRegistrationImplBase.ImsRegistrationTech int registrationTech, + @AccessNetworkConstants.TransportType int transportType, + int imsAttributeFlags, + @Nullable Set<String> featureTags) { + mRegistrationTech = registrationTech; + mTransportType = transportType; + mImsAttributeFlags = imsAttributeFlags; + mFeatureTags = new ArrayList<>(featureTags); + } + + /**@hide*/ + public ImsRegistrationAttributes(Parcel source) { + mRegistrationTech = source.readInt(); + mTransportType = source.readInt(); + mImsAttributeFlags = source.readInt(); + mFeatureTags = new ArrayList<>(); + source.readList(mFeatureTags, null /*classloader*/); + } + + /** + * @return The Radio Access Technology that the IMS registration has been registered over. + * @hide + */ + @SystemApi + public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTechnology() { + return mRegistrationTech; + } + + /** + * @return The access network transport type that IMS has been registered over. + */ + public @AccessNetworkConstants.TransportType int getTransportType() { + return mTransportType; + } + + /** + * @return A bit-mask containing attributes associated with the IMS registration. + */ + public int getAttributeFlags() { + return mImsAttributeFlags; + } + + /** + * Gets the Set of feature tags associated with the current IMS registration, if the IMS + * service supports supplying this information. + * <p> + * The format of the set of feature tags will be one feature tag key and value per entry and + * will potentially contain MMTEL and RCS feature tags, depending the configuration of the IMS + * service associated with the registration indications. Each feature tag will contain the + * feature tag name and string value (if applicable), even if they have the same feature tag + * name. For example, {@code +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg, + * urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", +g.gsma.callcomposer} will be split + * into three feature tag entries: + * {@code {+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg", + * +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", + * +g.gsma.callcomposer}}. + * @return The Set of feature tags associated with the current IMS registration. + */ + public @NonNull Set<String> getFeatureTags() { + if (mFeatureTags == null) { + return Collections.emptySet(); + } + return new ArraySet<>(mFeatureTags); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mRegistrationTech); + dest.writeInt(mTransportType); + dest.writeInt(mImsAttributeFlags); + dest.writeList(mFeatureTags); + } + + public static final @NonNull Creator<ImsRegistrationAttributes> CREATOR = + new Creator<ImsRegistrationAttributes>() { + @Override + public ImsRegistrationAttributes createFromParcel(Parcel source) { + return new ImsRegistrationAttributes(source); + } + + @Override + public ImsRegistrationAttributes[] newArray(int size) { + return new ImsRegistrationAttributes[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ImsRegistrationAttributes that = (ImsRegistrationAttributes) o; + return mRegistrationTech == that.mRegistrationTech + && mTransportType == that.mTransportType + && mImsAttributeFlags == that.mImsAttributeFlags + && Objects.equals(mFeatureTags, that.mFeatureTags); + } + + @Override + public int hashCode() { + return Objects.hash(mRegistrationTech, mTransportType, mImsAttributeFlags, mFeatureTags); + } + + @Override + public String toString() { + return "ImsRegistrationAttributes { transportType= " + mTransportType + ", attributeFlags=" + + mImsAttributeFlags + ", featureTags=[" + mFeatureTags + "]}"; + } +} diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index 2c75368b86bf..c49121f4dc5d 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -71,7 +71,6 @@ public interface RegistrationManager { */ int REGISTRATION_STATE_REGISTERED = 2; - /**@hide*/ // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN // and WWAN are more accurate constants. @@ -79,7 +78,8 @@ public interface RegistrationManager { new HashMap<Integer, Integer>() {{ // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE // case, since it is defined. - put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1); + put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, + AccessNetworkConstants.TRANSPORT_TYPE_INVALID); put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, @@ -103,6 +103,20 @@ public interface RegistrationManager { } /** + * @param regtech The registration technology. + * @return The Access Network type from registration technology. + * @hide + */ + static int getAccessType(int regtech) { + if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regtech)) { + Log.w("RegistrationManager", "getAccessType - invalid regType returned: " + + regtech); + return AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + } + return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regtech); + } + + /** * Callback class for receiving IMS network Registration callback events. * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) * @see #unregisterImsRegistrationCallback(RegistrationCallback) @@ -119,26 +133,24 @@ public interface RegistrationManager { } @Override - public void onRegistered(int imsRadioTech) { + public void onRegistered(ImsRegistrationAttributes attr) { if (mLocalCallback == null) return; long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> - mLocalCallback.onRegistered(getAccessType(imsRadioTech))); + mExecutor.execute(() -> mLocalCallback.onRegistered(attr)); } finally { restoreCallingIdentity(callingIdentity); } } @Override - public void onRegistering(int imsRadioTech) { + public void onRegistering(ImsRegistrationAttributes attr) { if (mLocalCallback == null) return; long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> - mLocalCallback.onRegistering(getAccessType(imsRadioTech))); + mExecutor.execute(() -> mLocalCallback.onRegistering(attr)); } finally { restoreCallingIdentity(callingIdentity); } @@ -183,15 +195,6 @@ public interface RegistrationManager { private void setExecutor(Executor executor) { mExecutor = executor; } - - private static int getAccessType(int regType) { - if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) { - Log.w("RegistrationManager", "RegistrationBinder - invalid regType returned: " - + regType); - return -1; - } - return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regType); - } } private final RegistrationBinder mBinder = new RegistrationBinder(this); @@ -200,19 +203,42 @@ public interface RegistrationManager { * Notifies the framework when the IMS Provider is registered to the IMS network. * * @param imsTransportType the radio access technology. + * @deprecated Use {@link #onRegistered(ImsRegistrationAttributes)} instead. */ public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { } /** + * Notifies the framework when the IMS Provider is registered to the IMS network + * with corresponding attributes. + * + * @param attributes The attributes associated with this IMS registration. + */ + public void onRegistered(@NonNull ImsRegistrationAttributes attributes) { + // Default impl to keep backwards compatibility with old implementations + onRegistered(attributes.getTransportType()); + } + + /** * Notifies the framework when the IMS Provider is trying to register the IMS network. * * @param imsTransportType the radio access technology. + * @deprecated Use {@link #onRegistering(ImsRegistrationAttributes)} instead. */ public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { } /** + * Notifies the framework when the IMS Provider is trying to register the IMS network. + * + * @param attributes The attributes associated with this IMS registration. + */ + public void onRegistering(@NonNull ImsRegistrationAttributes attributes) { + // Default impl to keep backwards compatibility with old implementations + onRegistering(attributes.getTransportType()); + } + + /** * Notifies the framework when the IMS Provider is unregistered from the IMS network. * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. @@ -298,10 +324,10 @@ public interface RegistrationManager { * @param executor The {@link Executor} that will be used to call the IMS registration state * callback. * @param stateCallback A callback called on the supplied {@link Executor} that will contain the - * registration state of the IMS service, which will be one of the - * following: {@link #REGISTRATION_STATE_NOT_REGISTERED}, - * {@link #REGISTRATION_STATE_REGISTERING}, or - * {@link #REGISTRATION_STATE_REGISTERED}. + * registration state of the IMS service, which will be one of the + * following: {@link #REGISTRATION_STATE_NOT_REGISTERED}, + * {@link #REGISTRATION_STATE_REGISTERING}, or + * {@link #REGISTRATION_STATE_REGISTERED}. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) void getRegistrationState(@NonNull @CallbackExecutor Executor executor, diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java index 4435640e008c..a217d1321342 100644 --- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; +import android.telephony.ims.ImsException; import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.stub.CapabilityExchangeEventListener; import android.util.Log; @@ -47,7 +48,7 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis * Receives the request of publishing capabilities from the network and deliver this request * to the framework via the registered capability exchange event listener. */ - public void onRequestPublishCapabilities(int publishTriggerType) { + public void onRequestPublishCapabilities(int publishTriggerType) throws ImsException { ICapabilityExchangeEventListener listener = mListenerBinder; if (listener == null) { return; @@ -56,13 +57,15 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis listener.onRequestPublishCapabilities(publishTriggerType); } catch (RemoteException e) { Log.w(LOG_TAG, "request publish capabilities exception: " + e); + throw new ImsException("Remote is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } /** * Receives the unpublish notification and deliver this callback to the framework. */ - public void onUnpublish() { + public void onUnpublish() throws ImsException { ICapabilityExchangeEventListener listener = mListenerBinder; if (listener == null) { return; @@ -71,6 +74,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis listener.onUnpublish(); } catch (RemoteException e) { Log.w(LOG_TAG, "Unpublish exception: " + e); + throw new ImsException("Remote is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } @@ -79,7 +84,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis * request to the framework. */ public void onRemoteCapabilityRequest(@NonNull Uri contactUri, - @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback) { + @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback) + throws ImsException { ICapabilityExchangeEventListener listener = mListenerBinder; if (listener == null) { return; @@ -87,10 +93,11 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis IOptionsRequestCallback internalCallback = new IOptionsRequestCallback.Stub() { @Override - public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities) { + public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities, + boolean isBlocked) { final long callingIdentity = Binder.clearCallingIdentity(); try { - callback.onRespondToCapabilityRequest(ownCapabilities); + callback.onRespondToCapabilityRequest(ownCapabilities, isBlocked); } finally { restoreCallingIdentity(callingIdentity); } @@ -110,6 +117,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback); } catch (RemoteException e) { Log.w(LOG_TAG, "Remote capability request exception: " + e); + throw new ImsException("Remote is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } } diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index 7a6c28bddd09..8931a78709ed 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -47,7 +47,7 @@ interface IImsRcsController { void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback c); void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback c); boolean isCapable(int subId, int capability, int radioTech); - boolean isAvailable(int subId, int capability); + boolean isAvailable(int subId, int capability, int radioTech); // ImsUceAdapter specific void requestCapabilities(int subId, String callingPackage, String callingFeatureId, diff --git a/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl index 749b1916962e..179407c983e5 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl @@ -21,6 +21,7 @@ import android.net.Uri; import android.telephony.ims.stub.ImsFeatureConfiguration; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; /** * See {@link ImsManager#RegistrationCallback} for more information. @@ -28,8 +29,8 @@ import android.telephony.ims.ImsReasonInfo; * {@hide} */ oneway interface IImsRegistrationCallback { - void onRegistered(int imsRadioTech); - void onRegistering(int imsRadioTech); + void onRegistered(in ImsRegistrationAttributes attr); + void onRegistering(in ImsRegistrationAttributes attr); void onDeregistered(in ImsReasonInfo info); void onTechnologyChangeFailed(int imsRadioTech, in ImsReasonInfo info); void onSubscriberAssociatedUriChanged(in Uri[] uris); diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl index d4d5301f38fa..8eecbca7e6a7 100644 --- a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl @@ -27,8 +27,9 @@ oneway interface IOptionsRequestCallback { * Respond to a remote capability request from the contact specified with the capabilities * of this device. * @param ownCapabilities The capabilities of this device. + * @param isBlocked True if the user has blocked the number sending this request. */ - void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities); + void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities, boolean isBlocked); /** * Respond to a remote capability request from the contact specified with the diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 87a6873d00b2..47c56e13f829 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -36,12 +36,9 @@ import java.util.Set; public final class CapabilityChangeRequest implements Parcelable { /** - * Contains a feature capability, defined as - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}, - * along with an associated technology, defined as + * Contains a MMTEL feature capability {@link MmTelFeature.MmTelCapabilities} and RCS feature + * capability {@link RcsFeature.RcsImsCapabilities}, along with an associated technology, + * defined as * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} */ @@ -49,7 +46,7 @@ public final class CapabilityChangeRequest implements Parcelable { private final int mCapability; private final int radioTech; - public CapabilityPair(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, + public CapabilityPair(int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { this.mCapability = capability; this.radioTech = radioTech; @@ -80,13 +77,10 @@ public final class CapabilityChangeRequest implements Parcelable { } /** - * @return The stored capability, defined as - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} + * @return The stored capability, defined as {@link MmTelFeature.MmTelCapabilities} and + * {@link RcsFeature.RcsImsCapabilities} */ - public @MmTelFeature.MmTelCapabilities.MmTelCapability int getCapability() { + public int getCapability() { return mCapability; } @@ -123,12 +117,11 @@ public final class CapabilityChangeRequest implements Parcelable { * Add one or many capabilities to the request to be enabled. * * @param capabilities A bitfield of capabilities to enable, valid values are defined in - * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}. + * {@link MmTelFeature.MmTelCapabilities} and {@link RcsFeature.RcsImsCapabilities}. * @param radioTech the radio tech that these capabilities should be enabled for, valid * values are in {@link ImsRegistrationImplBase.ImsRegistrationTech}. */ - public void addCapabilitiesToEnableForTech( - @MmTelFeature.MmTelCapabilities.MmTelCapability int capabilities, + public void addCapabilitiesToEnableForTech(int capabilities, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { addAllCapabilities(mCapabilitiesToEnable, capabilities, radioTech); } @@ -136,12 +129,11 @@ public final class CapabilityChangeRequest implements Parcelable { /** * Add one or many capabilities to the request to be disabled. * @param capabilities A bitfield of capabilities to diable, valid values are defined in - * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}. + * {@link MmTelFeature.MmTelCapabilities} and {@link RcsFeature.RcsImsCapabilities}. * @param radioTech the radio tech that these capabilities should be disabled for, valid * values are in {@link ImsRegistrationImplBase.ImsRegistrationTech}. */ - public void addCapabilitiesToDisableForTech( - @MmTelFeature.MmTelCapabilities.MmTelCapability int capabilities, + public void addCapabilitiesToDisableForTech(int capabilities, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { addAllCapabilities(mCapabilitiesToDisable, capabilities, radioTech); } diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 22df921c4214..85703f8de5e5 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -194,7 +194,6 @@ public class RcsFeature extends ImsFeature { * of the capability and notify the capability status as true using * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the * framework that the capability is available for usage. - * @hide */ public static class RcsImsCapabilities extends Capabilities { /** @hide*/ @@ -226,12 +225,21 @@ public class RcsFeature extends ImsFeature { */ public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; + /** + * Create a new {@link RcsImsCapabilities} instance with the provided capabilities. + * @param capabilities The capabilities that are supported for RCS in the form of a + * bitfield. + */ public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super(capabilities); } - private RcsImsCapabilities(Capabilities c) { - super(c.getMask()); + /** + * Create a new {@link RcsImsCapabilities} instance with the provided capabilities. + * @param capabilities The capabilities instance that are supported for RCS + */ + private RcsImsCapabilities(Capabilities capabilities) { + super(capabilities.getMask()); } @Override @@ -307,7 +315,7 @@ public class RcsFeature extends ImsFeature { * set, the {@link RcsFeature} has brought up the capability and is ready for framework * requests. To change the status of the capabilities * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called. - * @hide + * @return A copy of the current RcsFeature capability status. */ @Override public @NonNull final RcsImsCapabilities queryCapabilityStatus() { @@ -318,13 +326,13 @@ public class RcsFeature extends ImsFeature { * Notify the framework that the capabilities status has changed. If a capability is enabled, * this signals to the framework that the capability has been initialized and is ready. * Call {@link #queryCapabilityStatus()} to return the current capability status. - * @hide + * @param capabilities The current capability status of the RcsFeature. */ - public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities c) { - if (c == null) { + public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) { + if (capabilities == null) { throw new IllegalArgumentException("RcsImsCapabilities must be non-null!"); } - super.notifyCapabilitiesStatusChanged(c); + super.notifyCapabilitiesStatusChanged(capabilities); } /** @@ -333,7 +341,9 @@ public class RcsFeature extends ImsFeature { * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} to * enable or disable capability A, this method should return the correct configuration for * capability A afterwards (until it has changed). - * @hide + * @param capability The capability that we are querying the configuration for. + * @param radioTech The radio technology type that we are querying. + * @return true if the capability is enabled, false otherwise. */ public boolean queryCapabilityConfiguration( @RcsUceAdapter.RcsImsCapabilityFlag int capability, @@ -355,11 +365,12 @@ public class RcsFeature extends ImsFeature { * If for some reason one or more of these capabilities can not be enabled/disabled, * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError(int, int, int)} should * be called for each capability change that resulted in an error. - * @hide + * @param request The request to change the capability. + * @param callback To notify the framework that the result of the capability changes. */ @Override public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, - @NonNull CapabilityCallbackProxy c) { + @NonNull CapabilityCallbackProxy callback) { // Base Implementation - Override to provide functionality } diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java index d9734a7475c0..4967e5da7c9a 100644 --- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java +++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java @@ -16,32 +16,58 @@ package android.telephony.ims.stub; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.net.Uri; import android.telephony.ims.ImsException; import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.RcsFeature; +import android.util.Log; + +import java.util.List; /** - * The interface of the capabilities event listener for ImsService to notify the framework of the - * UCE request and status updated. + * The interface that is used by the framework to listen to events from the vendor RCS stack + * regarding capabilities exchange using presence server and OPTIONS. * @hide */ @SystemApi public interface CapabilityExchangeEventListener { /** * Interface used by the framework to respond to OPTIONS requests. - * @hide */ interface OptionsRequestCallback { /** * Respond to a remote capability request from the contact specified with the * capabilities of this device. * @param ownCapabilities The capabilities of this device. + * @hide */ - void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities); + default void onRespondToCapabilityRequest( + @NonNull RcsContactUceCapability ownCapabilities) {} + + /** + * Respond to a remote capability request from the contact specified with the + * capabilities of this device. + * @param ownCapabilities The capabilities of this device. + * @param isBlocked Whether or not the user has blocked the number requesting the + * capabilities of this device. If true, the device should respond to the OPTIONS + * request with a 200 OK response and no capabilities. + */ + default void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities, + boolean isBlocked) { + Log.w("CapabilityExchangeEventListener", "implement " + + "onRespondToCapabilityRequest(RcsContactUceCapability, boolean) instead!"); + // Fall back to old implementation + if (isBlocked) { + onRespondToCapabilityRequestWithError(200, "OK"); + } else { + onRespondToCapabilityRequest(ownCapabilities); + } + } /** * Respond to a remote capability request from the contact specified with the @@ -49,7 +75,8 @@ public interface CapabilityExchangeEventListener { * @param code The SIP response code to respond with. * @param reason A non-null String containing the reason associated with the SIP code. */ - void onRespondToCapabilityRequestWithError(int code, @NonNull String reason); + void onRespondToCapabilityRequestWithError(@IntRange(from = 100, to = 699) int code, + @NonNull String reason); } /** @@ -59,8 +86,7 @@ public interface CapabilityExchangeEventListener { * This is typically used when trying to generate an initial PUBLISH for a new subscription to * the network. The device will cache all presence publications after boot until this method is * called the first time. - * @param publishTriggerType {@link RcsUceAdapter#StackPublishTriggerType} The reason for the - * capability update request. + * @param publishTriggerType The reason for the capability update request. * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not currently * connected to the framework. This can happen if the {@link RcsFeature} is not * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the @@ -81,4 +107,25 @@ public interface CapabilityExchangeEventListener { * Telephony stack has crashed. */ void onUnpublish() throws ImsException; + + /** + * Inform the framework of an OPTIONS query from a remote device for this device's UCE + * capabilities. + * <p> + * The framework will respond via the + * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or + * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}. + * @param contactUri The URI associated with the remote contact that is + * requesting capabilities. + * @param remoteCapabilities The remote contact's capability information. + * @param callback The callback of this request which is sent from the remote user. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not + * currently connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + */ + void onRemoteCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> remoteCapabilities, + @NonNull OptionsRequestCallback callback) throws ImsException; } diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 088a7e26a9d0..23032f0c4d38 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -18,17 +18,18 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.IntRange; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; import android.os.RemoteException; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.RegistrationManager; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsRegistrationCallback; import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.util.RemoteCallbackListExt; import com.android.internal.util.ArrayUtils; @@ -83,7 +84,10 @@ public class ImsRegistrationImplBase { @Override public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException { - return getConnectionType(); + synchronized (mLock) { + return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE + : mRegistrationAttributes.getRegistrationTechnology(); + } } @Override @@ -116,8 +120,7 @@ public class ImsRegistrationImplBase { new RemoteCallbackListExt<>(); private final Object mLock = new Object(); // Locked on mLock - private @ImsRegistrationTech - int mConnectionType = REGISTRATION_TECH_NONE; + private ImsRegistrationAttributes mRegistrationAttributes; // Locked on mLock private int mRegistrationState = REGISTRATION_STATE_UNKNOWN; // Locked on mLock, create unspecified disconnect cause. @@ -195,17 +198,24 @@ public class ImsRegistrationImplBase { /** * Notify the framework that the device is connected to the IMS network. * - * @param imsRadioTech the radio access technology. Valid values are defined as - * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}. + * @param imsRadioTech the radio access technology. */ public final void onRegistered(@ImsRegistrationTech int imsRadioTech) { - updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERED); + onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build()); + } + + /** + * Notify the framework that the device is connected to the IMS network. + * + * @param attributes The attributes associated with the IMS registration. + */ + public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) { + updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED); mCallbacks.broadcastAction((c) -> { try { - c.onRegistered(imsRadioTech); + c.onRegistered(attributes); } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "onRegistrationConnected() - Skipping " + - "callback."); + Log.w(LOG_TAG, e + "onRegistered(int, Set) - Skipping callback."); } }); } @@ -213,17 +223,24 @@ public class ImsRegistrationImplBase { /** * Notify the framework that the device is trying to connect the IMS network. * - * @param imsRadioTech the radio access technology. Valid values are defined as - * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}. + * @param imsRadioTech the radio access technology. */ public final void onRegistering(@ImsRegistrationTech int imsRadioTech) { - updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERING); + onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build()); + } + + /** + * Notify the framework that the device is trying to connect the IMS network. + * + * @param attributes The attributes associated with the IMS registration. + */ + public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) { + updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING); mCallbacks.broadcastAction((c) -> { try { - c.onRegistering(imsRadioTech); + c.onRegistering(attributes); } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "onRegistrationProcessing() - Skipping " + - "callback."); + Log.w(LOG_TAG, e + "onRegistering(int, Set) - Skipping callback."); } }); } @@ -252,8 +269,7 @@ public class ImsRegistrationImplBase { try { c.onDeregistered(reasonInfo); } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "onRegistrationDisconnected() - Skipping " + - "callback."); + Log.w(LOG_TAG, e + "onDeregistered() - Skipping callback."); } }); } @@ -272,8 +288,7 @@ public class ImsRegistrationImplBase { try { c.onTechnologyChangeFailed(imsRadioTech, reasonInfo); } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "onRegistrationChangeFailed() - Skipping " + - "callback."); + Log.w(LOG_TAG, e + "onTechnologyChangeFailed() - Skipping callback."); } }); } @@ -297,14 +312,13 @@ public class ImsRegistrationImplBase { try { callback.onSubscriberAssociatedUriChanged(uris); } catch (RemoteException e) { - Log.w(LOG_TAG, e + " " + "onSubscriberAssociatedUriChanged() - Skipping " - + "callback."); + Log.w(LOG_TAG, e + "onSubscriberAssociatedUriChanged() - Skipping callback."); } } - private void updateToState(@ImsRegistrationTech int connType, int newState) { + private void updateToState(ImsRegistrationAttributes attributes, int newState) { synchronized (mLock) { - mConnectionType = connType; + mRegistrationAttributes = attributes; mRegistrationState = newState; mLastDisconnectCause = null; } @@ -316,7 +330,7 @@ public class ImsRegistrationImplBase { mUrisSet = false; mUris = null; - updateToState(REGISTRATION_TECH_NONE, + updateToState(new ImsRegistrationAttributes.Builder(REGISTRATION_TECH_NONE).build(), RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED); if (info != null) { mLastDisconnectCause = info; @@ -328,29 +342,19 @@ public class ImsRegistrationImplBase { } /** - * @return the current registration connection type. Valid values are - * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN} - * @hide - */ - @VisibleForTesting - public final @ImsRegistrationTech int getConnectionType() { - synchronized (mLock) { - return mConnectionType; - } - } - - /** * @param c the newly registered callback that will be updated with the current registration * state. */ private void updateNewCallbackWithState(IImsRegistrationCallback c) throws RemoteException { int state; + ImsRegistrationAttributes attributes; ImsReasonInfo disconnectInfo; boolean urisSet; Uri[] uris; synchronized (mLock) { state = mRegistrationState; + attributes = mRegistrationAttributes; disconnectInfo = mLastDisconnectCause; urisSet = mUrisSet; uris = mUris; @@ -361,11 +365,11 @@ public class ImsRegistrationImplBase { break; } case RegistrationManager.REGISTRATION_STATE_REGISTERING: { - c.onRegistering(getConnectionType()); + c.onRegistering(attributes); break; } case RegistrationManager.REGISTRATION_STATE_REGISTERED: { - c.onRegistered(getConnectionType()); + c.onRegistered(attributes); break; } case REGISTRATION_STATE_UNKNOWN: { diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java index ec98be6e5062..908869beb607 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -19,7 +19,6 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.net.Uri; @@ -141,7 +140,7 @@ public class RcsCapabilityExchangeImplBase { * {@link #publishCapabilities(String, PublishResponseCallback)}. * * If this network response also contains a “Reason” header, then the - * {@link onNetworkResponse(int, String, int, String)} method should be used instead. + * {@link #onNetworkResponse(int, String, int, String)} method should be used instead. * * @param sipCode The SIP response code sent from the network for the operation * token specified. @@ -160,7 +159,7 @@ public class RcsCapabilityExchangeImplBase { /** * Provide the framework with a subsequent network response update to - * {@link #publishCapabilities(RcsContactUceCapability, int)} that also + * {@link #publishCapabilities(String, PublishResponseCallback)} that also * includes a reason provided in the “reason” header. See RFC3326 for more * information. * @@ -186,7 +185,6 @@ public class RcsCapabilityExchangeImplBase { /** * Interface used by the framework to respond to OPTIONS requests. - * @hide */ public interface OptionsResponseCallback { /** @@ -217,7 +215,7 @@ public class RcsCapabilityExchangeImplBase { * cases when the Telephony stack has crashed. */ void onNetworkResponse(int sipCode, @NonNull String reason, - @Nullable List<String> theirCaps) throws ImsException; + @NonNull List<String> theirCaps) throws ImsException; } /** @@ -243,7 +241,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}. + * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}. * <p> * If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the * framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate}, @@ -251,7 +249,7 @@ public class RcsCapabilityExchangeImplBase { * subsequent NOTIFY responses to the subscription. * * If this network response also contains a “Reason” header, then the - * {@link onNetworkResponse(int, String, int, String)} method should be used instead. + * {@link #onNetworkResponse(int, String, int, String)} method should be used instead. * * @param sipCode The SIP response code sent from the network for the operation * token specified. @@ -268,7 +266,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(RcsContactUceCapability, int)} that also + * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also * includes a reason provided in the “reason” header. See RFC3326 for more * information. * @@ -294,7 +292,8 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the latest XML PIDF documents included in the network response * for the requested contacts' capabilities requested by the Framework using - * {@link RcsUceAdapter#requestCapabilities(Executor, List<Uri>, CapabilitiesCallback)}. + * {@link RcsUceAdapter#requestCapabilities(List, Executor, + * RcsUceAdapter.CapabilitiesCallback)}. * <p> * The expected format for the PIDF XML is defined in RFC3861. Each XML document must be a * "application/pidf+xml" object and start with a root <presence> element. For NOTIFY @@ -336,7 +335,8 @@ public class RcsCapabilityExchangeImplBase { /** * The subscription associated with a previous - * {@link RcsUceAdapter#requestCapabilities(Executor, List<Uri>, CapabilitiesCallback)} + * {@link RcsUceAdapter#requestCapabilities(List, Executor, + * RcsUceAdapter.CapabilitiesCallback)} * operation has been terminated. This will mostly be due to the network sending a final * NOTIFY response due to the subscription expiring, but this may also happen due to a * network error. @@ -427,12 +427,11 @@ public class RcsCapabilityExchangeImplBase { * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism * in order to receive the capabilities of the remote user in response. * <p> - * The implementer must call {@link #onNetworkResponse} to send the response of this - * query back to the framework. + * The implementer must use {@link OptionsResponseCallback} to send the response of + * this query from the network back to the framework. * @param contactUri The URI of the remote user that we wish to get the capabilities of. * @param myCapabilities The capabilities of this device to send to the remote user. * @param callback The callback of this request which is sent from the remote user. - * @hide */ // executor used is defined in the constructor. @SuppressLint("ExecutorRegistration") diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java index d79225fe5369..ec1204042260 100644 --- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java @@ -16,6 +16,7 @@ package com.android.internal.telephony.uicc; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; @@ -28,6 +29,7 @@ import com.android.internal.telephony.GsmAlphabet; import com.android.telephony.Rlog; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -253,13 +255,48 @@ public class IccUtils { } if ((b & 0x0f) <= 0x09) { - ret += (b & 0xf); + ret += (b & 0xf); } return ret; } /** + * Encodes a string to be formatted like the EF[ADN] alpha identifier. + * + * <p>See javadoc for {@link #adnStringFieldToString(byte[], int, int)} for more details on + * the relevant specs. + * + * <p>This will attempt to encode using the GSM 7-bit alphabet but will fallback to UCS-2 if + * there are characters that are not supported by it. + * + * @return the encoded string including the prefix byte necessary to identify the encoding. + * @see #adnStringFieldToString(byte[], int, int) + */ + @NonNull + public static byte[] stringToAdnStringField(@NonNull String alphaTag) { + int septets = GsmAlphabet.countGsmSeptetsUsingTables(alphaTag, false, 0, 0); + if (septets != -1) { + byte[] ret = new byte[septets]; + GsmAlphabet.stringToGsm8BitUnpackedField(alphaTag, ret, 0, ret.length); + return ret; + } + + // Strictly speaking UCS-2 disallows surrogate characters but it's much more complicated to + // validate that the string contains only valid UCS-2 characters. Since the read path + // in most modern software will decode "UCS-2" by treating it as UTF-16 this should be fine + // (e.g. the adnStringFieldToString has done this for a long time on Android). Also there's + // already a precedent in SMS applications to ignore the UCS-2/UTF-16 distinction. + byte[] alphaTagBytes = alphaTag.getBytes(StandardCharsets.UTF_16BE); + byte[] ret = new byte[alphaTagBytes.length + 1]; + // 0x80 tags the remaining bytes as UCS-2 + ret[0] = (byte) 0x80; + System.arraycopy(alphaTagBytes, 0, ret, 1, alphaTagBytes.length); + + return ret; + } + + /** * Decodes a string field that's formatted like the EF[ADN] alpha * identifier * @@ -309,7 +346,7 @@ public class IccUtils { ret = new String(data, offset + 1, ucslen * 2, "utf-16be"); } catch (UnsupportedEncodingException ex) { Rlog.e(LOG_TAG, "implausible UnsupportedEncodingException", - ex); + ex); } if (ret != null) { @@ -342,7 +379,7 @@ public class IccUtils { len = length - 4; base = (char) (((data[offset + 2] & 0xFF) << 8) | - (data[offset + 3] & 0xFF)); + (data[offset + 3] & 0xFF)); offset += 4; isucs2 = true; } @@ -366,7 +403,7 @@ public class IccUtils { count++; ret.append(GsmAlphabet.gsm8BitUnpackedToString(data, - offset, count)); + offset, count)); offset += count; len -= count; diff --git a/test-base/Android.bp b/test-base/Android.bp index c7c9fc739189..0b7a3981a403 100644 --- a/test-base/Android.bp +++ b/test-base/Android.bp @@ -19,6 +19,16 @@ // This contains the junit.framework and android.test classes that were in // Android API level 25 excluding those from android.test.runner. // Also contains the com.android.internal.util.Predicate[s] classes. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-CPL-1.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "android.test.base", diff --git a/test-base/hiddenapi/Android.bp b/test-base/hiddenapi/Android.bp index c202467517aa..d4f52d0fc6cd 100644 --- a/test-base/hiddenapi/Android.bp +++ b/test-base/hiddenapi/Android.bp @@ -19,6 +19,15 @@ // UnsupportedAppUsage annotation to tag those methods that are accessible via the hiddenapi. // Relies on the convention that modules with name <x>-hiddenapi provide hiddenapi information for // module <x> that is on the bootclasspath. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "android.test.base-hiddenapi", compile_dex: true, diff --git a/test-legacy/Android.mk b/test-legacy/Android.mk index af26c5b80717..ce5e4cf46695 100644 --- a/test-legacy/Android.mk +++ b/test-legacy/Android.mk @@ -27,6 +27,9 @@ ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) include $(CLEAR_VARS) LOCAL_MODULE := android.test.legacy +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE LOCAL_SDK_VERSION := current diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 7d0f92fac4c7..a2447d71c3bd 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -16,6 +16,15 @@ // Build the android.test.mock library // =================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "android.test.mock", diff --git a/test-runner/Android.bp b/test-runner/Android.bp index 1f6db8403eee..fe007e39f717 100644 --- a/test-runner/Android.bp +++ b/test-runner/Android.bp @@ -16,6 +16,16 @@ // Build the android.test.runner library // ===================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-CPL-1.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_sdk_library { name: "android.test.runner", diff --git a/test-runner/tests/Android.bp b/test-runner/tests/Android.bp index d74cee4937c9..ac21bcb9d124 100644 --- a/test-runner/tests/Android.bp +++ b/test-runner/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworkTestRunnerTests", diff --git a/tests/AccessibilityEventsLogger/Android.bp b/tests/AccessibilityEventsLogger/Android.bp index ead165602254..c403f9bf961e 100644 --- a/tests/AccessibilityEventsLogger/Android.bp +++ b/tests/AccessibilityEventsLogger/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AccessibilityEventsLogger", srcs: ["**/*.java"], diff --git a/tests/AccessoryDisplay/common/Android.bp b/tests/AccessoryDisplay/common/Android.bp index 3ce4c5718d13..fd3af1ecf1c9 100644 --- a/tests/AccessoryDisplay/common/Android.bp +++ b/tests/AccessoryDisplay/common/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Build the application. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_static { name: "AccessoryDisplayCommon", sdk_version: "current", diff --git a/tests/AccessoryDisplay/sink/Android.bp b/tests/AccessoryDisplay/sink/Android.bp index 4e50a81d8c24..d825c60b437f 100644 --- a/tests/AccessoryDisplay/sink/Android.bp +++ b/tests/AccessoryDisplay/sink/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Build the application. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AccessoryDisplaySink", sdk_version: "current", diff --git a/tests/AccessoryDisplay/source/Android.bp b/tests/AccessoryDisplay/source/Android.bp index 6d8087f5e7dd..6ed752ee2c8f 100644 --- a/tests/AccessoryDisplay/source/Android.bp +++ b/tests/AccessoryDisplay/source/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Build the application. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AccessoryDisplaySource", sdk_version: "current", diff --git a/tests/ActivityManagerPerfTests/stub-app/Android.bp b/tests/ActivityManagerPerfTests/stub-app/Android.bp index a3c1f5b2f17d..19225e4c879e 100644 --- a/tests/ActivityManagerPerfTests/stub-app/Android.bp +++ b/tests/ActivityManagerPerfTests/stub-app/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "ActivityManagerPerfTestsStubApp1", static_libs: ["ActivityManagerPerfTestsUtils"], @@ -65,4 +74,3 @@ android_test_helper_app { "--auto-add-overlay", ], } - diff --git a/tests/ActivityManagerPerfTests/test-app/Android.bp b/tests/ActivityManagerPerfTests/test-app/Android.bp index ef9d587581c4..5fd1d5a0ae69 100644 --- a/tests/ActivityManagerPerfTests/test-app/Android.bp +++ b/tests/ActivityManagerPerfTests/test-app/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ActivityManagerPerfTestsTestApp", srcs: ["src/**/*.java"], diff --git a/tests/ActivityManagerPerfTests/tests/Android.bp b/tests/ActivityManagerPerfTests/tests/Android.bp index 2ae2cc49bb7a..c8dbf811c69b 100644 --- a/tests/ActivityManagerPerfTests/tests/Android.bp +++ b/tests/ActivityManagerPerfTests/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ActivityManagerPerfTests", srcs: ["src/**/*.java"], diff --git a/tests/ActivityManagerPerfTests/utils/Android.bp b/tests/ActivityManagerPerfTests/utils/Android.bp index 766c3acf3c09..99c43c8d8fca 100644 --- a/tests/ActivityManagerPerfTests/utils/Android.bp +++ b/tests/ActivityManagerPerfTests/utils/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test { name: "ActivityManagerPerfTestsUtils", sdk_version: "current", diff --git a/tests/ActivityTests/Android.bp b/tests/ActivityTests/Android.bp index 01828624fa4a..be6096fb31cf 100644 --- a/tests/ActivityTests/Android.bp +++ b/tests/ActivityTests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ActivityTest", srcs: ["**/*.java"], diff --git a/tests/ActivityViewTest/Android.bp b/tests/ActivityViewTest/Android.bp index e7b8c8e1d058..95178a0fb9a5 100644 --- a/tests/ActivityViewTest/Android.bp +++ b/tests/ActivityViewTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ActivityViewTest", srcs: ["src/**/*.java"], diff --git a/tests/AmSlam/Android.bp b/tests/AmSlam/Android.bp index a8e575a39da4..cc33d88ba363 100644 --- a/tests/AmSlam/Android.bp +++ b/tests/AmSlam/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AmSlam", srcs: ["**/*.java"], diff --git a/tests/ApkVerityTest/Android.bp b/tests/ApkVerityTest/Android.bp index 02c75edafcd5..0cdb11fe7945 100644 --- a/tests/ApkVerityTest/Android.bp +++ b/tests/ApkVerityTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "ApkVerityTest", srcs: ["src/**/*.java"], diff --git a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp b/tests/ApkVerityTest/ApkVerityTestApp/Android.bp index 69632b215822..adf8f9f9d321 100644 --- a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp +++ b/tests/ApkVerityTest/ApkVerityTestApp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "ApkVerityTestApp", manifest: "AndroidManifest.xml", diff --git a/tests/ApkVerityTest/OWNERS b/tests/ApkVerityTest/OWNERS new file mode 100644 index 000000000000..d67285ede44a --- /dev/null +++ b/tests/ApkVerityTest/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 36824 + +victorhsieh@google.com diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp index 37fbc29470f6..b5a46da402eb 100644 --- a/tests/ApkVerityTest/block_device_writer/Android.bp +++ b/tests/ApkVerityTest/block_device_writer/Android.bp @@ -14,6 +14,15 @@ // This is a cc_test just because it supports test_suites. This should be converted to something // like cc_binary_test_helper once supported, thus auto_gen_config:false below. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test { // Depending on how the test runs, the executable may be uploaded to different location. // Before the bug in the file pusher is fixed, workaround by making the name unique. diff --git a/tests/ApkVerityTest/testdata/Android.bp b/tests/ApkVerityTest/testdata/Android.bp index c10b0cef21d7..ccfc4c99a347 100644 --- a/tests/ApkVerityTest/testdata/Android.bp +++ b/tests/ApkVerityTest/testdata/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "ApkVerityTestKeyPem", srcs: ["ApkVerityTestKey.pem"], @@ -74,4 +85,3 @@ genrule { srcs: [":ApkVerityTestAppSplitDm"], out: ["ApkVerityTestAppSplit.dm.fsv_sig"], } - diff --git a/tests/AppLaunch/Android.bp b/tests/AppLaunch/Android.bp index 75db55122553..f838c5a80c28 100644 --- a/tests/AppLaunch/Android.bp +++ b/tests/AppLaunch/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AppLaunch", // Only compile source java files in this apk. diff --git a/tests/AppLaunchWear/Android.bp b/tests/AppLaunchWear/Android.bp index 8d34b6eb9c0f..e2fc4735a7c2 100644 --- a/tests/AppLaunchWear/Android.bp +++ b/tests/AppLaunchWear/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AppLaunchWear", // Only compile source java files in this apk. diff --git a/tests/AppResourcesLoaders/Android.bp b/tests/AppResourcesLoaders/Android.bp index e5739dbf181c..d882db8b18a2 100644 --- a/tests/AppResourcesLoaders/Android.bp +++ b/tests/AppResourcesLoaders/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AppResourcesLoaders", srcs: ["**/*.java"], diff --git a/tests/AppResourcesLoaders/Overlay/Android.bp b/tests/AppResourcesLoaders/Overlay/Android.bp index 80443f6c3c00..b063023f7d19 100644 --- a/tests/AppResourcesLoaders/Overlay/Android.bp +++ b/tests/AppResourcesLoaders/Overlay/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "AppResourcesLoaders_Overlay", } diff --git a/tests/Assist/Android.bp b/tests/Assist/Android.bp index 216e75109dde..033c14017442 100644 --- a/tests/Assist/Android.bp +++ b/tests/Assist/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "Assist", srcs: ["**/*.java"], diff --git a/tests/AutoVerify/app1/Android.bp b/tests/AutoVerify/app1/Android.bp index 548519fa653b..0e26067d803e 100644 --- a/tests/AutoVerify/app1/Android.bp +++ b/tests/AutoVerify/app1/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AutoVerifyTest", srcs: ["src/**/*.java"], diff --git a/tests/AutoVerify/app2/Android.bp b/tests/AutoVerify/app2/Android.bp index 1c6c97bdf350..5fcff1a70783 100644 --- a/tests/AutoVerify/app2/Android.bp +++ b/tests/AutoVerify/app2/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AutoVerifyTest2", srcs: ["src/**/*.java"], diff --git a/tests/AutoVerify/app3/Android.bp b/tests/AutoVerify/app3/Android.bp index 70a2b77d1000..479f355bc75c 100644 --- a/tests/AutoVerify/app3/Android.bp +++ b/tests/AutoVerify/app3/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AutoVerifyTest3", srcs: ["src/**/*.java"], diff --git a/tests/AutoVerify/app4/Android.bp b/tests/AutoVerify/app4/Android.bp index fbdae1181a7a..dcf8902ee03a 100644 --- a/tests/AutoVerify/app4/Android.bp +++ b/tests/AutoVerify/app4/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AutoVerifyTest4", srcs: ["src/**/*.java"], diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp index a85d129b013a..0a45d5381f84 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp +++ b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BackgroundDexOptServiceIntegrationTests", srcs: ["src/**/*.java"], diff --git a/tests/BandwidthTests/Android.bp b/tests/BandwidthTests/Android.bp index 523f5226cd2c..a7fc89db32e1 100644 --- a/tests/BandwidthTests/Android.bp +++ b/tests/BandwidthTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BandwidthEnforcementTest", platform_apis: true, diff --git a/tests/BatteryWaster/Android.bp b/tests/BatteryWaster/Android.bp index 4698910adb40..1fa4f82cd9f4 100644 --- a/tests/BatteryWaster/Android.bp +++ b/tests/BatteryWaster/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BatteryWaster", srcs: ["**/*.java"], diff --git a/tests/BiDiTests/Android.bp b/tests/BiDiTests/Android.bp index c659e8c1257e..79ae41fb0c82 100644 --- a/tests/BiDiTests/Android.bp +++ b/tests/BiDiTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BiDiTests", // Only compile source java files in this apk. diff --git a/tests/BlobStoreTestUtils/Android.bp b/tests/BlobStoreTestUtils/Android.bp index 53d36389a52a..c4faf7f4fb11 100644 --- a/tests/BlobStoreTestUtils/Android.bp +++ b/tests/BlobStoreTestUtils/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "BlobStoreTestUtils", srcs: ["src/**/*.java"], @@ -21,4 +30,4 @@ java_library { "androidx.test.ext.junit", ], sdk_version: "test_current", -}
\ No newline at end of file +} diff --git a/tests/BootImageProfileTest/Android.bp b/tests/BootImageProfileTest/Android.bp index 1b097a8af0f9..9fb5aa21f985 100644 --- a/tests/BootImageProfileTest/Android.bp +++ b/tests/BootImageProfileTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "BootImageProfileTest", srcs: ["src/**/*.java"], diff --git a/tests/BrowserPowerTest/Android.bp b/tests/BrowserPowerTest/Android.bp index 1d358cbe6e75..a8a9897c0e86 100644 --- a/tests/BrowserPowerTest/Android.bp +++ b/tests/BrowserPowerTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "BrowserPowerTests", libs: [ diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp index 125deb521ddc..b889b0d29a8b 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_test_library { name: "libsmartcamera_jni", sdk_version: "14", diff --git a/tests/CameraPrewarmTest/Android.bp b/tests/CameraPrewarmTest/Android.bp index eaf453b6f3ae..07c49232efc5 100644 --- a/tests/CameraPrewarmTest/Android.bp +++ b/tests/CameraPrewarmTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CameraPrewarmTest", srcs: ["**/*.java"], diff --git a/tests/Codegen/Android.bp b/tests/Codegen/Android.bp index 966c5602959c..ddbf16817b94 100644 --- a/tests/Codegen/Android.bp +++ b/tests/Codegen/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "CodegenTests", srcs: [ diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp index c14e705b09ab..c58c99e1c4f0 100644 --- a/tests/Compatibility/Android.bp +++ b/tests/Compatibility/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "AppCompatibilityTest", static_libs: ["androidx.test.rules"], diff --git a/tests/CoreTests/android/Android.bp b/tests/CoreTests/android/Android.bp index 24134e8fb7f0..e2f194b04437 100644 --- a/tests/CoreTests/android/Android.bp +++ b/tests/CoreTests/android/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "LegacyCoreTests", srcs: ["**/*.java"], diff --git a/tests/DataIdleTest/Android.bp b/tests/DataIdleTest/Android.bp index 19656ce32b29..f9509cc9a4bf 100644 --- a/tests/DataIdleTest/Android.bp +++ b/tests/DataIdleTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "DataIdleTest", platform_apis: true, diff --git a/tests/DozeTest/Android.bp b/tests/DozeTest/Android.bp index f1be029f58d5..36ea91a84a0d 100644 --- a/tests/DozeTest/Android.bp +++ b/tests/DozeTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "DozeTest", // Only compile source java files in this apk. diff --git a/tests/DpiTest/Android.bp b/tests/DpiTest/Android.bp index 7d6a78ba1581..52bb08bbc8ad 100644 --- a/tests/DpiTest/Android.bp +++ b/tests/DpiTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "DensityTest", srcs: ["**/*.java"], diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk index 2d58ce8baddc..bfb5b076237a 100644 --- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk +++ b/tests/DynamicCodeLoggerIntegrationTests/Android.mk @@ -22,6 +22,9 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_MODULE := DynamicCodeLoggerTestLibrary +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl) include $(BUILD_JAVA_LIBRARY) @@ -35,6 +38,9 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp LOCAL_HEADER_LIBRARIES := jni_headers LOCAL_SDK_VERSION := 28 @@ -48,6 +54,9 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_MODULE := DynamicCodeLoggerNativeExecutable +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_SRC_FILES := src/cpp/test_executable.cpp include $(BUILD_EXECUTABLE) diff --git a/tests/FeatureSplit/base/Android.bp b/tests/FeatureSplit/base/Android.bp index ab25464a82fc..89c26d2c2256 100644 --- a/tests/FeatureSplit/base/Android.bp +++ b/tests/FeatureSplit/base/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "FeatureSplitBase", srcs: ["**/*.java"], diff --git a/tests/FeatureSplit/feature1/Android.bp b/tests/FeatureSplit/feature1/Android.bp index 706a4f544393..2f8aa8b6eb28 100644 --- a/tests/FeatureSplit/feature1/Android.bp +++ b/tests/FeatureSplit/feature1/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FeatureSplit1", srcs: ["**/*.java"], diff --git a/tests/FeatureSplit/feature2/Android.bp b/tests/FeatureSplit/feature2/Android.bp index a3634821f6fd..2a5c432d1499 100644 --- a/tests/FeatureSplit/feature2/Android.bp +++ b/tests/FeatureSplit/feature2/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FeatureSplit2", srcs: ["**/*.java"], diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp index 5608a2b5e15d..bd7c701026ba 100644 --- a/tests/FixVibrateSetting/Android.bp +++ b/tests/FixVibrateSetting/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "FixVibrateSetting", srcs: ["**/*.java"], diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp index 05f0a8e7921d..4f463f964c77 100644 --- a/tests/FlickerTests/Android.bp +++ b/tests/FlickerTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FlickerTests", srcs: ["src/**/*.java"], diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS index f35a318acbf7..b5561010e7f9 100644 --- a/tests/FlickerTests/OWNERS +++ b/tests/FlickerTests/OWNERS @@ -1,2 +1,3 @@ +# Bug component: 909476 include /services/core/java/com/android/server/wm/OWNERS natanieljr@google.com
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp index 0bea209a757a..1d5f732ed04f 100644 --- a/tests/FlickerTests/test-apps/flickerapp/Android.bp +++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FlickerTestApp", srcs: ["**/*.java"], diff --git a/tests/FrameworkPerf/Android.bp b/tests/FrameworkPerf/Android.bp index a259ebd05fa8..9be3ab795b86 100644 --- a/tests/FrameworkPerf/Android.bp +++ b/tests/FrameworkPerf/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworkPerf", srcs: ["**/*.java"], diff --git a/tests/GamePerformance/Android.bp b/tests/GamePerformance/Android.bp index 648fd8151b4e..07d0f42e8df2 100644 --- a/tests/GamePerformance/Android.bp +++ b/tests/GamePerformance/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "GamePerformance", // Don't include this package in any target diff --git a/tests/GridLayoutTest/Android.bp b/tests/GridLayoutTest/Android.bp index b4b5ba561c3f..71d884c4111f 100644 --- a/tests/GridLayoutTest/Android.bp +++ b/tests/GridLayoutTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "GridLayoutTest", srcs: ["**/*.java"], diff --git a/tests/HierarchyViewerTest/Android.bp b/tests/HierarchyViewerTest/Android.bp index 814c88328118..9c5d1c09cedd 100644 --- a/tests/HierarchyViewerTest/Android.bp +++ b/tests/HierarchyViewerTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "HierarchyViewerTest", srcs: ["**/*.java"], diff --git a/tests/HugeBackup/Android.bp b/tests/HugeBackup/Android.bp index b44c4578a853..7d4e52acb9b2 100644 --- a/tests/HugeBackup/Android.bp +++ b/tests/HugeBackup/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "HugeBackup", // Only compile source java files in this apk. diff --git a/tests/HwAccelerationTest/Android.bp b/tests/HwAccelerationTest/Android.bp index 37d3f5d4d97f..76063227eac1 100644 --- a/tests/HwAccelerationTest/Android.bp +++ b/tests/HwAccelerationTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "HwAccelerationTest", srcs: ["**/*.java"], diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp index e233fed7e785..8546ec204fff 100644 --- a/tests/Internal/Android.bp +++ b/tests/Internal/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "InternalTests", proto: { diff --git a/tests/JankBench/Android.bp b/tests/JankBench/Android.bp index 166639d2e7db..39dd197bf681 100644 --- a/tests/JankBench/Android.bp +++ b/tests/JankBench/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "JankBench", manifest: "app/src/main/AndroidManifest.xml", diff --git a/tests/JobSchedulerPerfTests/Android.bp b/tests/JobSchedulerPerfTests/Android.bp index 2ae8c33b60a7..eb9b2f636191 100644 --- a/tests/JobSchedulerPerfTests/Android.bp +++ b/tests/JobSchedulerPerfTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "JobSchedulerPerfTests", srcs: ["src/**/*.java"], diff --git a/tests/JobSchedulerTestApp/Android.bp b/tests/JobSchedulerTestApp/Android.bp index bac0220e5591..893a983ca9d9 100644 --- a/tests/JobSchedulerTestApp/Android.bp +++ b/tests/JobSchedulerTestApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "JobSchedulerTestApp", srcs: ["src/**/*.java"], diff --git a/tests/LargeAssetTest/Android.bp b/tests/LargeAssetTest/Android.bp index 499e6a0721a1..2a6de77fb170 100644 --- a/tests/LargeAssetTest/Android.bp +++ b/tests/LargeAssetTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "LargeAssetTest", srcs: ["**/*.java"], diff --git a/tests/LegacyAssistant/Android.bp b/tests/LegacyAssistant/Android.bp index fef924d1cd89..ab8ef8885c45 100644 --- a/tests/LegacyAssistant/Android.bp +++ b/tests/LegacyAssistant/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "LegacyAssistant", srcs: ["**/*.java"], diff --git a/tests/LocalizationTest/Android.bp b/tests/LocalizationTest/Android.bp index c4bfcb1d2261..4e0b0a89d972 100644 --- a/tests/LocalizationTest/Android.bp +++ b/tests/LocalizationTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "LocalizationTest", srcs: ["java/**/*.kt"], diff --git a/tests/LocationTracker/Android.bp b/tests/LocationTracker/Android.bp index f0075a9c37bd..538687c7db45 100644 --- a/tests/LocationTracker/Android.bp +++ b/tests/LocationTracker/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "LocationTracker", srcs: ["**/*.java"], diff --git a/tests/LotsOfApps/Android.bp b/tests/LotsOfApps/Android.bp index 68b9f88ecfd7..5f6c089188c7 100644 --- a/tests/LotsOfApps/Android.bp +++ b/tests/LotsOfApps/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "LotsOfApps", srcs: ["**/*.java"], diff --git a/tests/LowStorageTest/Android.bp b/tests/LowStorageTest/Android.bp index e72e4a5e2559..6dcf39d606dd 100644 --- a/tests/LowStorageTest/Android.bp +++ b/tests/LowStorageTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "lowstoragetest", certificate: "platform", diff --git a/tests/ManagedProfileLifecycleStressTest/Android.bp b/tests/ManagedProfileLifecycleStressTest/Android.bp index 639ce3cfe935..3ef6322a2984 100644 --- a/tests/ManagedProfileLifecycleStressTest/Android.bp +++ b/tests/ManagedProfileLifecycleStressTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "ManagedProfileLifecycleStressTest", srcs: ["src/**/*.java"], diff --git a/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp b/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp index 1f47b03d0074..7a9b6cfb134f 100644 --- a/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp +++ b/tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "DummyDPC", defaults: ["cts_defaults"], diff --git a/tests/MemoryUsage/Android.bp b/tests/MemoryUsage/Android.bp index aeb533882d4f..e30a0a7cd8b5 100644 --- a/tests/MemoryUsage/Android.bp +++ b/tests/MemoryUsage/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "MemoryUsage", // Only compile source java files in this apk. diff --git a/tests/MirrorSurfaceTest/Android.bp b/tests/MirrorSurfaceTest/Android.bp index e359c64cc982..1368f260725f 100644 --- a/tests/MirrorSurfaceTest/Android.bp +++ b/tests/MirrorSurfaceTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "MirrorSurfaceTest", srcs: ["src/**/*.java"], diff --git a/tests/NativeProcessesMemoryTest/Android.bp b/tests/NativeProcessesMemoryTest/Android.bp index f2625bf2db11..b7160e95dbb6 100644 --- a/tests/NativeProcessesMemoryTest/Android.bp +++ b/tests/NativeProcessesMemoryTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "native-processes-memory-test", srcs: ["src/**/*.java"], diff --git a/tests/NetworkSecurityConfigTest/Android.bp b/tests/NetworkSecurityConfigTest/Android.bp index cf8ca57862b4..473eadbcad73 100644 --- a/tests/NetworkSecurityConfigTest/Android.bp +++ b/tests/NetworkSecurityConfigTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NetworkSecurityConfigTests", certificate: "platform", diff --git a/tests/NullHomeTest/Android.bp b/tests/NullHomeTest/Android.bp index 99248bfe1da1..a5720db25a91 100644 --- a/tests/NullHomeTest/Android.bp +++ b/tests/NullHomeTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NullHomeTest", srcs: ["src/**/*.java"], diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp index d86f9cc81a5f..de86498afd27 100644 --- a/tests/OdmApps/Android.bp +++ b/tests/OdmApps/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "OdmAppsTest", srcs: ["src/**/*.java"], diff --git a/tests/OdmApps/app/Android.bp b/tests/OdmApps/app/Android.bp index 5eb8590b6e06..a33a1cf4690e 100644 --- a/tests/OdmApps/app/Android.bp +++ b/tests/OdmApps/app/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TestOdmApp", test_suites: ["device-tests"], diff --git a/tests/OdmApps/priv-app/Android.bp b/tests/OdmApps/priv-app/Android.bp index 9dd477cf6ad3..7527729c8267 100644 --- a/tests/OdmApps/priv-app/Android.bp +++ b/tests/OdmApps/priv-app/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TestOdmPrivApp", test_suites: ["device-tests"], diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp index 11e12f35741c..5c7317735bc7 100644 --- a/tests/OneMedia/Android.bp +++ b/tests/OneMedia/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "OneMedia", srcs: [ diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp index 0b75039cf69f..1e1dc8458560 100644 --- a/tests/PackageWatchdog/Android.bp +++ b/tests/PackageWatchdog/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // PackageWatchdogTest +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PackageWatchdogTest", srcs: ["src/**/*.java"], diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp index 7d918cc4c18b..f0f9c4bdd721 100644 --- a/tests/PlatformCompatGating/Android.bp +++ b/tests/PlatformCompatGating/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "PlatformCompatGating", // Only compile source java files in this apk. diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatCommandNotInstalledTest.kt b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatCommandNotInstalledTest.kt index eb04f6907748..ac9e6817a230 100644 --- a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatCommandNotInstalledTest.kt +++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatCommandNotInstalledTest.kt @@ -76,11 +76,11 @@ class PlatformCompatCommandNotInstalledTest { Params(enableDisable = null, targetSdk = 29, result = false), Params(enableDisable = null, targetSdk = 30, result = true), - Params(enableDisable = true, targetSdk = 29, result = true), + Params(enableDisable = true, targetSdk = 29, result = false), Params(enableDisable = true, targetSdk = 30, result = true), Params(enableDisable = false, targetSdk = 29, result = false), - Params(enableDisable = false, targetSdk = 30, result = false) + Params(enableDisable = false, targetSdk = 30, result = true) ) } diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp index 10fa2dc0d7c6..5f91f9d0e505 100644 --- a/tests/PlatformCompatGating/test-rules/Android.bp +++ b/tests/PlatformCompatGating/test-rules/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "platform-compat-test-rules", srcs: ["src/**/*.java"], @@ -23,4 +32,4 @@ java_library { "truth-prebuilt", "core-compat-test-rules" ], -}
\ No newline at end of file +} diff --git a/tests/ProtoInputStreamTests/Android.bp b/tests/ProtoInputStreamTests/Android.bp index ecc405664128..0029080b5a89 100644 --- a/tests/ProtoInputStreamTests/Android.bp +++ b/tests/ProtoInputStreamTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ProtoInputStreamTests", proto: { diff --git a/tests/RemoteDisplayProvider/Android.bp b/tests/RemoteDisplayProvider/Android.bp index 6c7798fb3faf..55732d14af46 100644 --- a/tests/RemoteDisplayProvider/Android.bp +++ b/tests/RemoteDisplayProvider/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Build the application. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "RemoteDisplayProviderTest", sdk_version: "system_current", diff --git a/tests/RenderThreadTest/Android.bp b/tests/RenderThreadTest/Android.bp index 165977607219..b18b04edb4c4 100644 --- a/tests/RenderThreadTest/Android.bp +++ b/tests/RenderThreadTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "RenderThreadTest", // Only compile source java files in this apk. diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp index 4f5a30502c91..f7dda5798a83 100644 --- a/tests/RollbackTest/Android.bp +++ b/tests/RollbackTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "RollbackTest", manifest: "RollbackTest/AndroidManifest.xml", @@ -95,6 +104,7 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppAv1"], installable: false, + updatable: false, } apex { @@ -105,6 +115,7 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppAv2"], installable: false, + updatable: false, } apex { @@ -115,4 +126,5 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppACrashingV2"], installable: false, -}
\ No newline at end of file + updatable: false, +} diff --git a/tests/SerialChat/Android.bp b/tests/SerialChat/Android.bp index 3c18035a4aab..8719e01031d5 100644 --- a/tests/SerialChat/Android.bp +++ b/tests/SerialChat/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SerialChat", srcs: ["**/*.java"], diff --git a/tests/ServiceCrashTest/Android.bp b/tests/ServiceCrashTest/Android.bp index 40a377de852f..fb98b7631b7e 100644 --- a/tests/ServiceCrashTest/Android.bp +++ b/tests/ServiceCrashTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ServiceCrashTest", // Only compile source java files in this apk. diff --git a/tests/SharedLibrary/client/Android.bp b/tests/SharedLibrary/client/Android.bp index dbf6dc94eb8d..6eab7c2e2dce 100644 --- a/tests/SharedLibrary/client/Android.bp +++ b/tests/SharedLibrary/client/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SharedLibraryClient", srcs: ["**/*.java"], diff --git a/tests/SharedLibrary/lib/Android.bp b/tests/SharedLibrary/lib/Android.bp index f69d388ef0f1..0595cb1e116a 100644 --- a/tests/SharedLibrary/lib/Android.bp +++ b/tests/SharedLibrary/lib/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SharedLibrary", srcs: ["**/*.java"], diff --git a/tests/ShowWhenLockedApp/Android.bp b/tests/ShowWhenLockedApp/Android.bp index dba564c91059..f24834a53a36 100644 --- a/tests/ShowWhenLockedApp/Android.bp +++ b/tests/ShowWhenLockedApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "ShowWhenLocked", srcs: ["**/*.java"], diff --git a/tests/SmokeTest/Android.bp b/tests/SmokeTest/Android.bp index bc45ee6799b4..4c853e3c5267 100644 --- a/tests/SmokeTest/Android.bp +++ b/tests/SmokeTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SmokeTestApp", // This builds "SmokeTestApp" diff --git a/tests/SmokeTest/tests/Android.bp b/tests/SmokeTest/tests/Android.bp index ceb2d193de79..5542dd0119ea 100644 --- a/tests/SmokeTest/tests/Android.bp +++ b/tests/SmokeTest/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SmokeTest", // Include all test java files. diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp index 0feb00040eac..3505fe1c4afb 100644 --- a/tests/SmokeTestApps/Android.bp +++ b/tests/SmokeTestApps/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SmokeTestTriggerApps", srcs: ["src/**/*.java"], diff --git a/tests/SoundTriggerTestApp/Android.bp b/tests/SoundTriggerTestApp/Android.bp index d3a1300b8e12..09f1e10561e3 100644 --- a/tests/SoundTriggerTestApp/Android.bp +++ b/tests/SoundTriggerTestApp/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "SoundTriggerTestApp", srcs: ["**/*.java"], diff --git a/tests/Split/Android.bp b/tests/Split/Android.bp index d8c89bab2857..727b2026461c 100644 --- a/tests/Split/Android.bp +++ b/tests/Split/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "Split", srcs: ["**/*.java"], diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp index 45c1c73afcb0..243c3015b559 100644 --- a/tests/StagedInstallTest/Android.bp +++ b/tests/StagedInstallTest/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "StagedInstallInternalTestApp", manifest: "app/AndroidManifest.xml", @@ -37,4 +46,3 @@ java_test_host { test_suites: ["general-tests"], test_config: "StagedInstallInternalTest.xml", } - diff --git a/tests/StagedInstallTest/StagedInstallInternalTest.xml b/tests/StagedInstallTest/StagedInstallInternalTest.xml index 1b8fa672fe38..1f22cae8f3cf 100644 --- a/tests/StagedInstallTest/StagedInstallInternalTest.xml +++ b/tests/StagedInstallTest/StagedInstallInternalTest.xml @@ -15,7 +15,7 @@ ~ limitations under the License. --> <configuration description="Runs the internal staged install tests"> - <option name="test-suite-tag" value="StagedInstallTest" /> + <option name="test-suite-tag" value="StagedInstallInternalTest" /> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true" /> <option name="test-file-name" value="StagedInstallInternalTestApp.apk" /> diff --git a/tests/StagedInstallTest/TEST_MAPPING b/tests/StagedInstallTest/TEST_MAPPING index 5a7a5a766b88..73094c5db06b 100644 --- a/tests/StagedInstallTest/TEST_MAPPING +++ b/tests/StagedInstallTest/TEST_MAPPING @@ -1,6 +1,16 @@ { "presubmit": [ { + "name": "StagedInstallInternalTest", + "options": [ + { + "exclude-annotation": "android.platform.test.annotations.LargeTest" + } + ] + } + ], + "postsubmit": [ + { "name": "StagedInstallInternalTest" } ] diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index b7c9e59bd3ac..1b5e6dd65540 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; import android.cts.install.lib.host.InstallUtilsHost; +import android.platform.test.annotations.LargeTest; import com.android.ddmlib.Log; import com.android.tests.rollback.host.AbandonSessionsRule; @@ -141,6 +142,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { // Test rollback-app command waits for staged sessions to be ready @Test + @LargeTest public void testAdbRollbackAppWaitsForStagedReady() throws Exception { assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); diff --git a/tests/StatusBar/Android.bp b/tests/StatusBar/Android.bp index 0b650ed3afc8..2fad051300c7 100644 --- a/tests/StatusBar/Android.bp +++ b/tests/StatusBar/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "StatusBarTest", srcs: ["**/*.java"], diff --git a/tests/SurfaceComposition/Android.bp b/tests/SurfaceComposition/Android.bp index 53e4d52b2efd..f5aba8f5a2f2 100644 --- a/tests/SurfaceComposition/Android.bp +++ b/tests/SurfaceComposition/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SurfaceComposition", // Don't include this package in any target diff --git a/tests/SurfaceControlViewHostTest/Android.bp b/tests/SurfaceControlViewHostTest/Android.bp index e4e060010eea..0127ba559500 100644 --- a/tests/SurfaceControlViewHostTest/Android.bp +++ b/tests/SurfaceControlViewHostTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "SurfaceControlViewHostTest", srcs: ["**/*.java"], diff --git a/tests/SystemMemoryTest/device/Android.bp b/tests/SystemMemoryTest/device/Android.bp index 2bf0fec0fd1f..d7cec1aedaed 100644 --- a/tests/SystemMemoryTest/device/Android.bp +++ b/tests/SystemMemoryTest/device/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test_helper_app { name: "SystemMemoryTestDevice", sdk_version: "current", diff --git a/tests/SystemMemoryTest/host/Android.bp b/tests/SystemMemoryTest/host/Android.bp index 3bb5489dab6c..79744625b752 100644 --- a/tests/SystemMemoryTest/host/Android.bp +++ b/tests/SystemMemoryTest/host/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "system-memory-test", srcs: ["src/**/*.java"], diff --git a/tests/SystemUIDemoModeController/Android.bp b/tests/SystemUIDemoModeController/Android.bp index 1e4c43792d70..d952cf6a4b3e 100644 --- a/tests/SystemUIDemoModeController/Android.bp +++ b/tests/SystemUIDemoModeController/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "DemoModeController", srcs: ["**/*.java"], diff --git a/tests/TaskOrganizerTest/Android.bp b/tests/TaskOrganizerTest/Android.bp index 8a13dbc52c66..56d569548006 100644 --- a/tests/TaskOrganizerTest/Android.bp +++ b/tests/TaskOrganizerTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TaskOrganizerTest", srcs: ["**/*.java"], diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp index 4f7569d4f451..a9fbfd97225d 100644 --- a/tests/TelephonyCommonTests/Android.bp +++ b/tests/TelephonyCommonTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TelephonyCommonTests", srcs: [ diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp index 1174bcb0d4d6..3a9e240d9746 100644 --- a/tests/TouchLatency/Android.bp +++ b/tests/TouchLatency/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TouchLatency", manifest: "app/src/main/AndroidManifest.xml", diff --git a/tests/TransformTest/Android.bp b/tests/TransformTest/Android.bp index fd7aaeb35feb..f58fe8f13bda 100644 --- a/tests/TransformTest/Android.bp +++ b/tests/TransformTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TransformTest", srcs: ["**/*.java"], diff --git a/tests/TransitionTests/Android.bp b/tests/TransitionTests/Android.bp index 57f19e38330d..4daa5b84f71e 100644 --- a/tests/TransitionTests/Android.bp +++ b/tests/TransitionTests/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "TransitionTests", // Only compile source java files in this apk. diff --git a/tests/TtsTests/Android.bp b/tests/TtsTests/Android.bp index b137523803a6..b7aa5d4a38aa 100644 --- a/tests/TtsTests/Android.bp +++ b/tests/TtsTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TtsTests", srcs: ["**/*.java"], diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp index e0608e288459..0d2f2ef46cab 100644 --- a/tests/UiBench/Android.bp +++ b/tests/UiBench/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UiBench", sdk_version: "current", diff --git a/tests/UsageReportingTest/Android.bp b/tests/UsageReportingTest/Android.bp index 0bac5a224b26..dfce0705df59 100644 --- a/tests/UsageReportingTest/Android.bp +++ b/tests/UsageReportingTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsageReportingTest", // Only compile source java files in this apk. diff --git a/tests/UsageStatsPerfTests/Android.bp b/tests/UsageStatsPerfTests/Android.bp index 3991fb8366ac..0e372a3ef95a 100644 --- a/tests/UsageStatsPerfTests/Android.bp +++ b/tests/UsageStatsPerfTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsageStatsPerfTests", srcs: ["src/**/*.java"], diff --git a/tests/UsageStatsTest/Android.bp b/tests/UsageStatsTest/Android.bp index 0808b05ec053..afb266bf326d 100644 --- a/tests/UsageStatsTest/Android.bp +++ b/tests/UsageStatsTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsageStatsTest", // Only compile source java files in this apk. diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp index c7e9df0fe9cf..9133baed7179 100644 --- a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp +++ b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp @@ -16,6 +16,15 @@ //################################################# +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AoapTestDeviceApp", srcs: ["src/**/*.java"], diff --git a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp index 6fa58cb5c682..68930023de96 100644 --- a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp +++ b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp @@ -16,6 +16,15 @@ //################################################# +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AoapTestHostApp", srcs: ["src/**/*.java"], diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp index edd4205968b3..2fca4d35fe01 100644 --- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp +++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp @@ -17,6 +17,15 @@ //################################################# // TODO: should this be android_helper_test_app? +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "UsbHostExternalManagementTestApp", srcs: ["src/**/*.java"], diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp index a03c6e223b74..97fbf5b32035 100644 --- a/tests/UsbManagerTests/Android.bp +++ b/tests/UsbManagerTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsbManagerTests", srcs: ["src/**/*.java"], diff --git a/tests/UsbManagerTests/lib/Android.bp b/tests/UsbManagerTests/lib/Android.bp index 3c5d91b326d0..994484cd63bf 100644 --- a/tests/UsbManagerTests/lib/Android.bp +++ b/tests/UsbManagerTests/lib/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "UsbManagerTestLib", srcs: ["src/**/*.java"], diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp index 7c2be9b63ac3..9328b67795cb 100644 --- a/tests/UsbTests/Android.bp +++ b/tests/UsbTests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsbTests", srcs: ["**/*.java"], diff --git a/tests/UsesFeature2Test/Android.bp b/tests/UsesFeature2Test/Android.bp index a1b77d07ccdc..624e4ec7ebd8 100644 --- a/tests/UsesFeature2Test/Android.bp +++ b/tests/UsesFeature2Test/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "UsesFeature2Test", srcs: ["**/*.java"], diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp index 13f318ef7c42..9da7c5fdbb17 100644 --- a/tests/VectorDrawableTest/Android.bp +++ b/tests/VectorDrawableTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VectorDrawableTest", srcs: ["**/*.java"], diff --git a/tests/VoiceEnrollment/Android.bp b/tests/VoiceEnrollment/Android.bp index e43b38c5a034..b5d62bbd68a8 100644 --- a/tests/VoiceEnrollment/Android.bp +++ b/tests/VoiceEnrollment/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "VoiceEnrollment", srcs: ["**/*.java"], diff --git a/tests/VoiceInteraction/Android.bp b/tests/VoiceInteraction/Android.bp index 7059473fb63f..1aa7fafcd37c 100644 --- a/tests/VoiceInteraction/Android.bp +++ b/tests/VoiceInteraction/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "VoiceInteraction", srcs: ["**/*.java"], diff --git a/tests/WallpaperTest/Android.bp b/tests/WallpaperTest/Android.bp index f68b6ec2452d..b009af25f9da 100644 --- a/tests/WallpaperTest/Android.bp +++ b/tests/WallpaperTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "WallpaperTest", srcs: ["src/**/*.java"], diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp index 50b2297386cc..ed86aa5f90ea 100644 --- a/tests/WindowAnimationJank/Android.bp +++ b/tests/WindowAnimationJank/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "WindowAnimationJank", srcs: ["src/**/*.java"], diff --git a/tests/WindowInsetsTests/Android.bp b/tests/WindowInsetsTests/Android.bp index 7272152dc257..b1f4819fc0bb 100644 --- a/tests/WindowInsetsTests/Android.bp +++ b/tests/WindowInsetsTests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "WindowInsetsTests", srcs: ["src/**/*.java"], @@ -24,4 +33,3 @@ android_test { "com.google.android.material_material", ], } - diff --git a/tests/appwidgets/AppWidgetHostTest/Android.bp b/tests/appwidgets/AppWidgetHostTest/Android.bp index 24b76136c045..a3838e5405d1 100644 --- a/tests/appwidgets/AppWidgetHostTest/Android.bp +++ b/tests/appwidgets/AppWidgetHostTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AppWidgetHostTest", srcs: ["**/*.java"], diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.bp b/tests/appwidgets/AppWidgetProviderTest/Android.bp index a1a599177a01..a9ee7ad93663 100644 --- a/tests/appwidgets/AppWidgetProviderTest/Android.bp +++ b/tests/appwidgets/AppWidgetProviderTest/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "AppWidgetProvider", srcs: ["**/*.java"], diff --git a/tests/backup/Android.mk b/tests/backup/Android.mk index e9618300fc48..9b155c930871 100644 --- a/tests/backup/Android.mk +++ b/tests/backup/Android.mk @@ -24,6 +24,9 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := -Wall -Werror LOCAL_MODULE_TAGS := optional LOCAL_MODULE := backup_helper_test +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) LOCAL_SHARED_LIBRARIES := libandroidfw libutils diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp index f16ddb9bc68e..f87ca2ef928b 100644 --- a/tests/benchmarks/Android.bp +++ b/tests/benchmarks/Android.bp @@ -15,6 +15,15 @@ // build framework base core benchmarks // ============================================================ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "networkStatsFactory-benchmarks", installable: true, diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp index 66a1f83dc308..a8ce8a4cd956 100644 --- a/tests/libs-permissions/Android.bp +++ b/tests/libs-permissions/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "com.android.test.libs.product", installable: true, diff --git a/tests/net/Android.bp b/tests/net/Android.bp index ffde68eab578..81224957b2c7 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -1,6 +1,15 @@ //######################################################################## // Build FrameworksNetTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_defaults { name: "FrameworksNetTests-jni-defaults", jni_libs: [ diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml index 009f817af407..d08b2f8d40dd 100644 --- a/tests/net/AndroidManifest.xml +++ b/tests/net/AndroidManifest.xml @@ -48,6 +48,7 @@ <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.NETWORK_FACTORY" /> <uses-permission android:name="android.permission.NETWORK_STATS_PROVIDER" /> + <uses-permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp index c271f49ee537..babb81c5fa34 100644 --- a/tests/net/common/Android.bp +++ b/tests/net/common/Android.bp @@ -16,6 +16,15 @@ // Tests in this folder are included both in unit tests and CTS. // They must be fast and stable, and exercise public or test APIs. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "FrameworksNetCommonTests", srcs: ["java/**/*.java", "java/**/*.kt"], diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt index b2bcfeb9019d..ad5bbf220d57 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -54,12 +54,26 @@ class CaptivePortalDataTest { } .build() + private val dataFromPasspoint = CaptivePortalData.Builder() + .setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + .setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + .setCaptive(true) + .apply { + if (SdkLevel.isAtLeastS()) { + setVenueFriendlyName("venue friendly name") + } + } + .build() + private fun makeBuilder() = CaptivePortalData.Builder(data) @Test fun testParcelUnparcel() { - val fieldCount = if (SdkLevel.isAtLeastS()) 8 else 7 + val fieldCount = if (SdkLevel.isAtLeastS()) 10 else 7 assertParcelSane(data, fieldCount) + assertParcelSane(dataFromPasspoint, fieldCount) assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build()) assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build()) @@ -83,6 +97,27 @@ class CaptivePortalDataTest { assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } } + + assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build()) + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint")) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/other"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/passpoint")) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/other"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } } @Test @@ -130,6 +165,22 @@ class CaptivePortalDataTest { assertEquals("venue friendly name", data.venueFriendlyName) } + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + fun testGetVenueInfoUrlSource() { + assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER, + data.venueInfoUrlSource) + assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT, + dataFromPasspoint.venueInfoUrlSource) + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + fun testGetUserPortalUrlSource() { + assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER, + data.userPortalUrlSource) + assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT, + dataFromPasspoint.userPortalUrlSource) + } + private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) = CaptivePortalData.Builder(this).apply { mutator(this) }.build() diff --git a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java index d232a507454d..fd29a9539de8 100644 --- a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java +++ b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java @@ -40,7 +40,7 @@ import java.util.Map; @SmallTest public class OemNetworkPreferencesTest { - private static final int TEST_PREF = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_DEFAULT; + private static final int TEST_PREF = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; private static final String TEST_PACKAGE = "com.google.apps.contacts"; private final OemNetworkPreferences.Builder mBuilder = new OemNetworkPreferences.Builder(); @@ -54,7 +54,7 @@ public class OemNetworkPreferencesTest { @Test public void testBuilderRemoveNetworkPreferenceRequiresNonNullPackageName() { assertThrows(NullPointerException.class, - () -> mBuilder.removeNetworkPreference(null)); + () -> mBuilder.clearNetworkPreference(null)); } @Test @@ -129,7 +129,7 @@ public class OemNetworkPreferencesTest { assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - mBuilder.removeNetworkPreference(TEST_PACKAGE); + mBuilder.clearNetworkPreference(TEST_PACKAGE); networkPreferences = mBuilder.build().getNetworkPreferences(); assertFalse(networkPreferences.containsKey(TEST_PACKAGE)); diff --git a/tests/net/deflake/Android.bp b/tests/net/deflake/Android.bp index b1b017131c64..58ece37ef647 100644 --- a/tests/net/deflake/Android.bp +++ b/tests/net/deflake/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "FrameworksNetDeflakeTest", srcs: ["src/**/*.kt"], diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp index 69742b9bf7b2..4d1e3371e0a7 100644 --- a/tests/net/integration/Android.bp +++ b/tests/net/integration/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksNetIntegrationTests", platform_apis: true, 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 083c8c8741da..9ed55f098a16 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 @@ -38,6 +38,7 @@ import android.net.metrics.IpConnectivityLog import android.os.ConditionVariable import android.os.IBinder import android.os.INetworkManagementService +import android.os.SystemConfigManager import android.os.UserHandle import android.testing.TestableContext import android.util.Log @@ -57,6 +58,7 @@ import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith import org.mockito.AdditionalAnswers +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.anyInt @@ -94,6 +96,8 @@ class ConnectivityServiceIntegrationTest { private lateinit var netd: INetd @Mock private lateinit var dnsResolver: IDnsResolver + @Mock + private lateinit var systemConfigManager: SystemConfigManager @Spy private var context = TestableContext(realContext) @@ -151,6 +155,11 @@ class ConnectivityServiceIntegrationTest { doReturn(UserHandle.ALL).`when`(asUserCtx).user doReturn(asUserCtx).`when`(context).createContextAsUser(eq(UserHandle.ALL), anyInt()) doNothing().`when`(context).sendStickyBroadcast(any(), any()) + doReturn(Context.SYSTEM_CONFIG_SERVICE).`when`(context) + .getSystemServiceName(SystemConfigManager::class.java) + doReturn(systemConfigManager).`when`(context) + .getSystemService(Context.SYSTEM_CONFIG_SERVICE) + doReturn(IntArray(0)).`when`(systemConfigManager).getSystemPermissionUids(anyString()) networkStackClient = TestNetworkStackClient(realContext) networkStackClient.init() diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index e1da3d0ae2b3..dc9e587332cb 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -17,7 +17,6 @@ package com.android.server; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; @@ -85,7 +84,6 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { final String typeName = ConnectivityManager.getNetworkTypeName(type); mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities(); mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); mNetworkCapabilities.addTransportType(transport); switch (transport) { case TRANSPORT_ETHERNET: diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java index fcfb4aa9b864..6a09b0237a38 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/tests/net/java/android/net/ConnectivityManagerTest.java @@ -35,6 +35,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.REQUEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; +import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -329,6 +330,9 @@ public class ConnectivityManagerTest { mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); }); mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); }); + mustFail(() -> { manager.registerSystemDefaultNetworkCallback(null, handler); }); + mustFail(() -> { manager.registerSystemDefaultNetworkCallback(callback, null); }); + mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); }); mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); }); mustFail(() -> { manager.releaseNetworkRequest(nullIntent); }); @@ -377,6 +381,13 @@ public class ConnectivityManagerTest { eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), eq(testPkgName), eq(testAttributionTag)); reset(mService); + + Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); + manager.registerSystemDefaultNetworkCallback(callback, handler); + verify(mService).requestNetwork(eq(null), + eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(testPkgName), eq(testAttributionTag)); + reset(mService); } static Message makeMessage(NetworkRequest req, int messageType) { diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt index 1f8f6f311069..b39555d15dcb 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -65,7 +65,7 @@ class NetworkTemplateTest { setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) setSSID(ssid) } - return NetworkState(type, lp, caps, mock(Network::class.java), subscriberId, ssid) + return NetworkState(type, lp, caps, mock(Network::class.java), subscriberId) } private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) = diff --git a/tests/net/java/android/net/VpnManagerTest.java b/tests/net/java/android/net/VpnManagerTest.java index 95a794235a2e..c548e30761c9 100644 --- a/tests/net/java/android/net/VpnManagerTest.java +++ b/tests/net/java/android/net/VpnManagerTest.java @@ -49,7 +49,7 @@ public class VpnManagerTest { private static final String IDENTITY_STRING = "Identity"; private static final byte[] PSK_BYTES = "preSharedKey".getBytes(); - private IConnectivityManager mMockCs; + private IVpnManager mMockService; private VpnManager mVpnManager; private final MockContext mMockContext = new MockContext() { @@ -61,24 +61,26 @@ public class VpnManagerTest { @Before public void setUp() throws Exception { - mMockCs = mock(IConnectivityManager.class); - mVpnManager = new VpnManager(mMockContext, mMockCs); + mMockService = mock(IVpnManager.class); + mVpnManager = new VpnManager(mMockContext, mMockService); } @Test public void testProvisionVpnProfilePreconsented() throws Exception { final PlatformVpnProfile profile = getPlatformVpnProfile(); - when(mMockCs.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))).thenReturn(true); + when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))) + .thenReturn(true); // Expect there to be no intent returned, as consent has already been granted. assertNull(mVpnManager.provisionVpnProfile(profile)); - verify(mMockCs).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); + verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); } @Test public void testProvisionVpnProfileNeedsConsent() throws Exception { final PlatformVpnProfile profile = getPlatformVpnProfile(); - when(mMockCs.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))).thenReturn(false); + when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))) + .thenReturn(false); // Expect intent to be returned, as consent has not already been granted. final Intent intent = mVpnManager.provisionVpnProfile(profile); @@ -88,25 +90,25 @@ public class VpnManagerTest { ComponentName.unflattenFromString( "com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog"); assertEquals(expectedComponentName, intent.getComponent()); - verify(mMockCs).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); + verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); } @Test public void testDeleteProvisionedVpnProfile() throws Exception { mVpnManager.deleteProvisionedVpnProfile(); - verify(mMockCs).deleteVpnProfile(eq(PKG_NAME)); + verify(mMockService).deleteVpnProfile(eq(PKG_NAME)); } @Test public void testStartProvisionedVpnProfile() throws Exception { mVpnManager.startProvisionedVpnProfile(); - verify(mMockCs).startVpnProfile(eq(PKG_NAME)); + verify(mMockService).startVpnProfile(eq(PKG_NAME)); } @Test public void testStopProvisionedVpnProfile() throws Exception { mVpnManager.stopProvisionedVpnProfile(); - verify(mMockCs).stopVpnProfile(eq(PKG_NAME)); + verify(mMockService).stopVpnProfile(eq(PKG_NAME)); } private Ikev2VpnProfile getPlatformVpnProfile() throws Exception { diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java new file mode 100644 index 000000000000..866f38c84333 --- /dev/null +++ b/tests/net/java/android/net/VpnTransportInfoTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static com.android.testutils.ParcelUtils.assertParcelSane; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class VpnTransportInfoTest { + + @Test + public void testParceling() { + VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); + assertParcelSane(v, 1 /* fieldCount */); + } + + @Test + public void testEqualsAndHashCode() { + VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); + VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE); + VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); + assertNotEquals(v1, v2); + assertEquals(v1, v3); + assertEquals(v1.hashCode(), v3.hashCode()); + } +}
\ No newline at end of file diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index edc2c636e0ee..88ccf8ec77b3 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -66,6 +66,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; +import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; @@ -82,6 +84,11 @@ import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; 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.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; @@ -169,6 +176,7 @@ import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.INetworkPolicyListener; import android.net.INetworkStatsService; +import android.net.IOnSetOemNetworkPreferenceListener; import android.net.IQosCallback; import android.net.InetAddresses; import android.net.InterfaceConfigurationParcel; @@ -192,6 +200,7 @@ import android.net.NetworkStack; import android.net.NetworkStackClient; import android.net.NetworkState; import android.net.NetworkTestResultParcelable; +import android.net.OemNetworkPreferences; import android.net.ProxyInfo; import android.net.QosCallbackException; import android.net.QosFilter; @@ -200,11 +209,13 @@ import android.net.ResolverParamsParcel; import android.net.RouteInfo; import android.net.RouteInfoParcel; import android.net.SocketKeepalive; +import android.net.TransportInfo; import android.net.UidRange; import android.net.UidRangeParcel; import android.net.UnderlyingNetworkInfo; import android.net.Uri; import android.net.VpnManager; +import android.net.VpnTransportInfo; import android.net.metrics.IpConnectivityLog; import android.net.shared.NetworkMonitorUtils; import android.net.shared.PrivateDnsConfig; @@ -227,6 +238,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.SystemClock; +import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -298,6 +310,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -348,6 +361,7 @@ public class ConnectivityServiceTest { private static final long TIMESTAMP = 1234L; private static final int NET_ID = 110; + private static final int OEM_PREF_ANY_NET_ID = -1; // Set a non-zero value to verify the flow to set tcp init rwnd value. private static final int TEST_TCP_INIT_RWND = 60; @@ -357,17 +371,26 @@ public class ConnectivityServiceTest { private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; private static final String VPN_IFNAME = "tun10042"; private static final String TEST_PACKAGE_NAME = "com.android.test.package"; + private static final int TEST_PACKAGE_UID = 123; private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn"; private static final String INTERFACE_NAME = "interface"; - private static final String TEST_VENUE_URL_NA = "https://android.com/"; + private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/"; + private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/"; + private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT = + "https://android.com/terms/"; + private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER = + "https://example.com/terms/"; private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/"; + private static final String TEST_USER_PORTAL_API_URL_CAPPORT = + "https://android.com/user/api/capport/"; private static final String TEST_FRIENDLY_NAME = "Network friendly name"; private static final String TEST_REDIRECT_URL = "http://example.com/firstPath"; private MockContext mServiceContext; private HandlerThread mCsHandlerThread; + private HandlerThread mVMSHandlerThread; private ConnectivityService.Dependencies mDeps; private ConnectivityService mService; private WrappedConnectivityManager mCm; @@ -382,6 +405,7 @@ public class ConnectivityServiceTest { private TestNetIdManager mNetIdManager; private QosCallbackMockHelper mQosCallbackMockHelper; private QosCallbackTracker mQosCallbackTracker; + private VpnManagerService mVpnManagerService; // State variables required to emulate NetworkPolicyManagerService behaviour. private int mUidRules = RULE_NONE; @@ -407,6 +431,7 @@ public class ConnectivityServiceTest { @Mock EthernetManager mEthernetManager; @Mock NetworkPolicyManager mNetworkPolicyManager; @Mock KeyStore mKeyStore; + @Mock SystemConfigManager mSystemConfigManager; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -503,6 +528,7 @@ public class ConnectivityServiceTest { if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager; if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager; + if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager; return super.getSystemService(name); } @@ -976,10 +1002,12 @@ public class ConnectivityServiceTest { // Used to collect the networks requests managed by this factory. This is a duplicate of // the internal information stored in the NetworkFactory (which is private). private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); + private final HandlerThread mHandlerSendingRequests; public MockNetworkFactory(Looper looper, Context context, String logTag, - NetworkCapabilities filter) { + NetworkCapabilities filter, HandlerThread threadSendingRequests) { super(looper, context, logTag, filter); + mHandlerSendingRequests = threadSendingRequests; } public int getMyRequestCount() { @@ -1033,7 +1061,8 @@ public class ConnectivityServiceTest { public void terminate() { super.terminate(); // Make sure there are no remaining requests unaccounted for. - assertNull(mRequestHistory.poll(TIMEOUT_MS, r -> true)); + HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS); + assertNull(mRequestHistory.poll(0, r -> true)); } // Trigger releasing the request as unfulfillable @@ -1110,7 +1139,7 @@ public class ConnectivityServiceTest { } @Override - public int getActiveAppVpnType() { + public int getActiveVpnType() { return mVpnType; } @@ -1123,10 +1152,12 @@ public class ConnectivityServiceTest { private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp) throws Exception { if (mAgentRegistered) throw new IllegalStateException("already registered"); + updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent"); mConfig = new VpnConfig(); setUids(uids); if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); mInterface = VPN_IFNAME; + mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType())); mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, mNetworkCapabilities); mMockNetworkAgent.waitForIdle(TIMEOUT_MS); @@ -1252,24 +1283,55 @@ public class ConnectivityServiceTest { r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new); } - private void mockVpn(int uid) { - synchronized (mService.mVpns) { - int userId = UserHandle.getUserId(uid); - mMockVpn = new MockVpn(userId); - // This has no effect unless the VPN is actually connected, because things like - // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN - // netId, and check if that network is actually connected. - mService.mVpns.put(userId, mMockVpn); - } + private VpnManagerService makeVpnManagerService() { + final VpnManagerService.Dependencies deps = new VpnManagerService.Dependencies() { + public int getCallingUid() { + return mDeps.getCallingUid(); + } + + public HandlerThread makeHandlerThread() { + return mVMSHandlerThread; + } + + public KeyStore getKeyStore() { + return mKeyStore; + } + + public INetd getNetd() { + return mMockNetd; + } + + public INetworkManagementService getINetworkManagementService() { + return mNetworkManagementService; + } + }; + return new VpnManagerService(mServiceContext, deps); + } + + private void assertVpnTransportInfo(NetworkCapabilities nc, int type) { + assertNotNull(nc); + final TransportInfo ti = nc.getTransportInfo(); + assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti, + ti instanceof VpnTransportInfo); + assertEquals(type, ((VpnTransportInfo) ti).type); + } private void processBroadcastForVpn(Intent intent) { - // The BroadcastReceiver for this broadcast checks it is being run on the handler thread. - final Handler handler = new Handler(mCsHandlerThread.getLooper()); - handler.post(() -> mServiceContext.sendBroadcast(intent)); + mServiceContext.sendBroadcast(intent); + HandlerUtils.waitForIdle(mVMSHandlerThread, TIMEOUT_MS); waitForIdle(); } + private void mockVpn(int uid) { + synchronized (mVpnManagerService.mVpns) { + int userId = UserHandle.getUserId(uid); + mMockVpn = new MockVpn(userId); + // Every running user always has a Vpn in the mVpns array, even if no VPN is running. + mVpnManagerService.mVpns.put(userId, mMockVpn); + } + } + private void mockUidNetworkingBlocked() { doAnswer(i -> mContext.getSystemService(NetworkPolicyManager.class) .checkUidNetworkingBlocked(i.getArgument(0) /* uid */, mUidRules, @@ -1373,6 +1435,7 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. // http://b/25897652 . @@ -1384,6 +1447,7 @@ public class ConnectivityServiceTest { FakeSettingsProvider.clearSettingsProvider(); mServiceContext = new MockContext(InstrumentationRegistry.getContext(), new FakeSettingsProvider()); + mServiceContext.setUseRegisteredHandlers(true); LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); LocalServices.addService( NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class)); @@ -1393,6 +1457,7 @@ public class ConnectivityServiceTest { initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler()); mCsHandlerThread = new HandlerThread("TestConnectivityService"); + mVMSHandlerThread = new HandlerThread("TestVpnManagerService"); mDeps = makeDependencies(); returnRealCallingUid(); mService = new ConnectivityService(mServiceContext, @@ -1415,6 +1480,8 @@ public class ConnectivityServiceTest { // getSystemService() correctly. mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService); mService.systemReadyInternal(); + mVpnManagerService = makeVpnManagerService(); + mVpnManagerService.systemReady(); mockVpn(Process.myUid()); mCm.bindProcessToNetwork(null); mQosCallbackTracker = mock(QosCallbackTracker.class); @@ -1442,7 +1509,6 @@ public class ConnectivityServiceTest { doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); doReturn(mBatteryStatsService).when(deps).getBatteryStatsService(); - doReturn(mKeyStore).when(deps).getKeyStore(); doAnswer(inv -> { mPolicyTracker = new WrappedMultinetworkPolicyTracker( inv.getArgument(0), inv.getArgument(1), inv.getArgument(2)); @@ -1555,10 +1621,13 @@ public class ConnectivityServiceTest { } switch (transport) { case TRANSPORT_WIFI: - assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); break; case TRANSPORT_CELLULAR: - assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + break; + case TRANSPORT_ETHERNET: + assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); break; default: break; @@ -1567,6 +1636,7 @@ public class ConnectivityServiceTest { assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); + assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid())); // Test getNetworkCapabilities(Network) assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); @@ -2104,6 +2174,24 @@ public class ConnectivityServiceTest { } } + static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) { + for (TestNetworkCallback c : callbacks) { + c.expectCallback(CallbackEntry.LOST, network); + } + } + + static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network, + NetworkSpecifier specifier, TestNetworkCallback ... callbacks) { + for (TestNetworkCallback c : callbacks) { + c.expectCallback(CallbackEntry.AVAILABLE, network); + c.expectCapabilitiesThat(network, (nc) -> + !nc.hasCapability(NET_CAPABILITY_VALIDATED) + && Objects.equals(specifier, nc.getNetworkSpecifier())); + c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network); + c.expectCallback(CallbackEntry.BLOCKED_STATUS, network); + } + } + @Test public void testStateChangeNetworkCallbacks() throws Exception { final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); @@ -2707,14 +2795,10 @@ public class ConnectivityServiceTest { NetworkCapabilities filter = new NetworkCapabilities(); filter.addCapability(capability); - // Add NOT_VCN_MANAGED capability into filter unconditionally since some request will add - // NOT_VCN_MANAGED automatically but not for NetworkCapabilities, - // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details. - filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); handlerThread.start(); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); ConditionVariable cv = testFactory.getNetworkStartedCV(); testFactory.register(); @@ -2822,7 +2906,7 @@ public class ConnectivityServiceTest { // does not crash. for (int i = 0; i < 100; i++) { final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); // Register the factory and don't be surprised when the default request arrives. testFactory.register(); testFactory.expectRequestAdd(); @@ -3286,39 +3370,68 @@ public class ConnectivityServiceTest { } private class CaptivePortalTestData { - CaptivePortalTestData(CaptivePortalData naData, CaptivePortalData capportData, - CaptivePortalData expectedMergedData) { - mNaData = naData; + CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData, + CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData, + CaptivePortalData expectedMergedOtherData) { + mNaPasspointData = naPasspointData; mCapportData = capportData; - mExpectedMergedData = expectedMergedData; + mNaOtherData = naOtherData; + mExpectedMergedPasspointData = expectedMergedPasspointData; + mExpectedMergedOtherData = expectedMergedOtherData; } - public final CaptivePortalData mNaData; + public final CaptivePortalData mNaPasspointData; public final CaptivePortalData mCapportData; - public final CaptivePortalData mExpectedMergedData; + public final CaptivePortalData mNaOtherData; + public final CaptivePortalData mExpectedMergedPasspointData; + public final CaptivePortalData mExpectedMergedOtherData; + } private CaptivePortalTestData setupCaptivePortalData() { final CaptivePortalData capportData = new CaptivePortalData.Builder() .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT)) + .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT)) .setExpiryTime(1000000L) .setBytesRemaining(12345L) .build(); - final CaptivePortalData naData = new CaptivePortalData.Builder() + final CaptivePortalData naPasspointData = new CaptivePortalData.Builder() + .setBytesRemaining(80802L) + .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); + + final CaptivePortalData naOtherData = new CaptivePortalData.Builder() .setBytesRemaining(80802L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA)) + .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) + .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - final CaptivePortalData expectedMergedData = new CaptivePortalData.Builder() + final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder() .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) .setBytesRemaining(12345L) .setExpiryTime(1000000L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA)) + .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - return new CaptivePortalTestData(naData, capportData, expectedMergedData); + final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder() + .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) + .setBytesRemaining(12345L) + .setExpiryTime(1000000L) + .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT)) + .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT)) + .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); + return new CaptivePortalTestData(naPasspointData, capportData, naOtherData, + expectedMergedPasspointData, expectedMergedOtherData); } @Test @@ -3332,15 +3445,26 @@ public class ConnectivityServiceTest { captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())); - // Venue URL and friendly name from Network agent, confirm that API data gets precedence - // on the bytes remaining. + // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm + // that API data gets precedence on the bytes remaining. final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setCaptivePortalData(captivePortalTestData.mNaData); + linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData); mWiFiNetworkAgent.sendLinkProperties(linkProperties); // Make sure that the capport data is merged captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedData.equals(lp.getCaptivePortalData())); + lp -> captivePortalTestData.mExpectedMergedPasspointData + .equals(lp.getCaptivePortalData())); + + // Now send this information from non-Passpoint source, confirm that Capport data takes + // precedence + linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData); + mWiFiNetworkAgent.sendLinkProperties(linkProperties); + + // Make sure that the capport data is merged + captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, + lp -> captivePortalTestData.mExpectedMergedOtherData + .equals(lp.getCaptivePortalData())); // Create a new LP with no Network agent capport data final LinkProperties newLps = new LinkProperties(); @@ -3357,12 +3481,12 @@ public class ConnectivityServiceTest { captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> lp.getCaptivePortalData() == null); - newLps.setCaptivePortalData(captivePortalTestData.mNaData); + newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData); mWiFiNetworkAgent.sendLinkProperties(newLps); // Make sure that only the network agent capport data is available captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mNaData.equals(lp.getCaptivePortalData())); + lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData())); } @Test @@ -3373,12 +3497,12 @@ public class ConnectivityServiceTest { // Venue URL and friendly name from Network agent, confirm that API data gets precedence // on the bytes remaining. final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setCaptivePortalData(captivePortalTestData.mNaData); + linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData); mWiFiNetworkAgent.sendLinkProperties(linkProperties); // Make sure that the data is saved correctly captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mNaData.equals(lp.getCaptivePortalData())); + lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData())); // Expected merged data: Network agent data is preferred, and values that are not used by // it are merged from capport data @@ -3386,7 +3510,8 @@ public class ConnectivityServiceTest { // Make sure that the Capport data is merged correctly captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedData.equals(lp.getCaptivePortalData())); + lp -> captivePortalTestData.mExpectedMergedPasspointData.equals( + lp.getCaptivePortalData())); // Now set the naData to null linkProperties.setCaptivePortalData(null); @@ -3397,6 +3522,32 @@ public class ConnectivityServiceTest { lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())); } + @Test + public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport() + throws Exception { + final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi(); + final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData(); + + // Venue URL and friendly name from Network agent, confirm that API data gets precedence + // on the bytes remaining. + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData); + mWiFiNetworkAgent.sendLinkProperties(linkProperties); + + // Make sure that the data is saved correctly + captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, + lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData())); + + // Expected merged data: Network agent data is preferred, and values that are not used by + // it are merged from capport data + mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData); + + // Make sure that the Capport data is merged correctly + captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, + lp -> captivePortalTestData.mExpectedMergedOtherData.equals( + lp.getCaptivePortalData())); + } + private NetworkRequest.Builder newWifiRequestBuilder() { return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); } @@ -3404,11 +3555,9 @@ public class ConnectivityServiceTest { /** * Verify request matching behavior with network specifiers. * - * Note: this test is somewhat problematic since it involves removing capabilities from - * agents - i.e. agents rejecting requests which they previously accepted. This is flagged - * as a WTF bug in - * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but - * does work. + * This test does not check updating the specifier on a live network because the specifier is + * immutable and this triggers a WTF in + * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}. */ @Test public void testNetworkSpecifier() throws Exception { @@ -3493,60 +3642,49 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, + cEmpty1, cEmpty2, cEmpty3, cEmpty4); assertNoCallbacks(cFoo, cBar); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); - cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); - } - cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + cBar.assertNoCallback(); assertEquals(nsFoo, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cFoo.assertNoCallback(); + assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(nsBar); - cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsBar)); - } - cBar.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsBar)); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); + cFoo.assertNoCallback(); assertEquals(nsBar, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cBar.assertNoCallback(); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); + cFoo.assertNoCallback(); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); - cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c : emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); - } - cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); - cBar.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); assertNull( mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cFoo.assertNoCallback(); - cBar.assertNoCallback(); - mWiFiNetworkAgent.setNetworkSpecifier(null); - cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent); - } - - assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } /** @@ -3649,10 +3787,19 @@ public class ConnectivityServiceTest { @Test public void testRegisterDefaultNetworkCallback() throws Exception { + // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback. + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, + PERMISSION_GRANTED); + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultNetworkCallback); defaultNetworkCallback.assertNoCallback(); + final Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); + final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); + mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler); + systemDefaultCallback.assertNoCallback(); + // Create a TRANSPORT_CELLULAR request to keep the mobile interface up // whenever Wi-Fi is up. Without this, the mobile network agent is // reaped before any other activity can take place. @@ -3667,27 +3814,35 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(true); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); // Bring up wifi and expect CALLBACK_AVAILABLE. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); cellNetworkCallback.assertNoCallback(); defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); // Bring down cell. Expect no default network callback, since it wasn't the default. mCellNetworkAgent.disconnect(); cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); defaultNetworkCallback.assertNoCallback(); + systemDefaultCallback.assertNoCallback(); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); // Bring up cell. Expect no default network callback, since it won't be the default. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); defaultNetworkCallback.assertNoCallback(); + systemDefaultCallback.assertNoCallback(); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); // Bring down wifi. Expect the default network callback to notified of LOST wifi // followed by AVAILABLE cell. @@ -3695,19 +3850,25 @@ public class ConnectivityServiceTest { cellNetworkCallback.assertNoCallback(); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); + systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); mCellNetworkAgent.disconnect(); cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); waitForIdle(); assertEquals(null, mCm.getActiveNetwork()); mMockVpn.establishForMyUid(); assertUidRangesUpdatedForMyUid(true); defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + systemDefaultCallback.assertNoCallback(); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(null, systemDefaultCallback.getLastAvailableNetwork()); mMockVpn.disconnect(); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); + systemDefaultCallback.assertNoCallback(); waitForIdle(); assertEquals(null, mCm.getActiveNetwork()); } @@ -3773,6 +3934,24 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(cellNetworkCallback); } + @Test + public void testRegisterSystemDefaultCallbackRequiresNetworkSettings() throws Exception { + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(false /* validated */); + + final Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); + final TestNetworkCallback callback = new TestNetworkCallback(); + assertThrows(SecurityException.class, + () -> mCm.registerSystemDefaultNetworkCallback(callback, handler)); + callback.assertNoCallback(); + + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, + PERMISSION_GRANTED); + mCm.registerSystemDefaultNetworkCallback(callback, handler); + callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + mCm.unregisterNetworkCallback(callback); + } + private void setCaptivePortalMode(int mode) { ContentResolver cr = mServiceContext.getContentResolver(); Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); @@ -3962,10 +4141,9 @@ public class ConnectivityServiceTest { handlerThread.start(); NetworkCapabilities filter = new NetworkCapabilities() .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .addCapability(NET_CAPABILITY_INTERNET); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); // Register the factory and expect it to start looking for a network. @@ -4013,6 +4191,7 @@ public class ConnectivityServiceTest { // ... and cell data to be torn down after nascent network timeout. cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, mService.mNascentDelayMs + TEST_CALLBACK_TIMEOUT_MS); + waitForIdle(); assertLength(1, mCm.getAllNetworks()); } finally { testFactory.terminate(); @@ -4312,7 +4491,7 @@ public class ConnectivityServiceTest { .addTransportType(TRANSPORT_WIFI) .addCapability(NET_CAPABILITY_INTERNET); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); // Register the factory and expect it to receive the default request. @@ -5866,7 +6045,6 @@ public class ConnectivityServiceTest { .addTransportType(TRANSPORT_CELLULAR) .addCapability(NET_CAPABILITY_INTERNET) .addCapability(NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .setLinkDownstreamBandwidthKbps(10); final NetworkCapabilities wifiNc = new NetworkCapabilities() .addTransportType(TRANSPORT_WIFI) @@ -5875,7 +6053,6 @@ public class ConnectivityServiceTest { .addCapability(NET_CAPABILITY_NOT_ROAMING) .addCapability(NET_CAPABILITY_NOT_CONGESTED) .addCapability(NET_CAPABILITY_NOT_SUSPENDED) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .setLinkUpstreamBandwidthKbps(20); mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */); mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */); @@ -6134,6 +6311,10 @@ public class ConnectivityServiceTest { @Test public void testVpnNetworkActive() throws Exception { + // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback. + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, + PERMISSION_GRANTED); + final int uid = Process.myUid(); final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); @@ -6141,6 +6322,7 @@ public class ConnectivityServiceTest { final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build(); final NetworkRequest genericRequest = new NetworkRequest.Builder() .removeCapability(NET_CAPABILITY_NOT_VPN).build(); @@ -6154,6 +6336,8 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); mCm.registerDefaultNetworkCallback(defaultCallback); + mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, + new Handler(ConnectivityThread.getInstanceLooper())); defaultCallback.assertNoCallback(); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -6163,6 +6347,7 @@ public class ConnectivityServiceTest { genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); vpnNetworkCallback.assertNoCallback(); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); @@ -6183,7 +6368,10 @@ public class ConnectivityServiceTest { wifiNetworkCallback.assertNoCallback(); vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + systemDefaultCallback.assertNoCallback(); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + assertEquals(mWiFiNetworkAgent.getNetwork(), + systemDefaultCallback.getLastAvailableNetwork()); ranges.clear(); mMockVpn.setUids(ranges); @@ -6200,6 +6388,7 @@ public class ConnectivityServiceTest { // much, but that is the reason the test here has to check for an update to the // capabilities instead of the expected LOST then AVAILABLE. defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); + systemDefaultCallback.assertNoCallback(); ranges.add(new UidRange(uid, uid)); mMockVpn.setUids(ranges); @@ -6211,6 +6400,7 @@ public class ConnectivityServiceTest { // TODO : Here like above, AVAILABLE would be correct, but because this can't actually // happen outside of the test, ConnectivityService does not rematch callbacks. defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); + systemDefaultCallback.assertNoCallback(); mWiFiNetworkAgent.disconnect(); @@ -6219,6 +6409,7 @@ public class ConnectivityServiceTest { wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); vpnNetworkCallback.assertNoCallback(); defaultCallback.assertNoCallback(); + systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); mMockVpn.disconnect(); @@ -6227,12 +6418,14 @@ public class ConnectivityServiceTest { wifiNetworkCallback.assertNoCallback(); vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); + systemDefaultCallback.assertNoCallback(); assertEquals(null, mCm.getActiveNetwork()); mCm.unregisterNetworkCallback(genericNetworkCallback); mCm.unregisterNetworkCallback(wifiNetworkCallback); mCm.unregisterNetworkCallback(vpnNetworkCallback); mCm.unregisterNetworkCallback(defaultCallback); + mCm.unregisterNetworkCallback(systemDefaultCallback); } @Test @@ -6368,6 +6561,8 @@ public class ConnectivityServiceTest { assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED)); assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + + assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); } private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) { @@ -6407,6 +6602,7 @@ public class ConnectivityServiceTest { assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); // A VPN without underlying networks is not suspended. assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); final int userId = UserHandle.getUserId(Process.myUid()); assertDefaultNetworkCapabilities(userId /* no networks */); @@ -6570,6 +6766,7 @@ public class ConnectivityServiceTest { // By default, VPN is set to track default network (i.e. its underlying networks is null). // In case of no default network, VPN is considered metered. assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); // Connect to Cell; Cell is the default network. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); @@ -6627,6 +6824,7 @@ public class ConnectivityServiceTest { NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); assertNotNull("nc=" + nc, nc.getUids()); assertEquals(nc.getUids(), uidRangesForUid(uid)); + assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); // Set an underlying network and expect to see the VPN transports change. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -6642,6 +6840,7 @@ public class ConnectivityServiceTest { .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)); final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); // Send a USER_ADDED broadcast for it. @@ -6668,6 +6867,7 @@ public class ConnectivityServiceTest { // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); processBroadcastForVpn(removedIntent); @@ -6709,8 +6909,8 @@ public class ConnectivityServiceTest { // Enable always-on VPN lockdown. The main user loses network access because no VPN is up. final ArrayList<String> allowList = new ArrayList<>(); - mService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE, true /* lockdown */, - allowList); + mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE, + true /* lockdown */, allowList); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); // This is arguably overspecified: a UID that is not running doesn't have an active network. @@ -6725,6 +6925,7 @@ public class ConnectivityServiceTest { RESTRICTED_USER_INFO)); // TODO: check that VPN app within restricted profile still has access, etc. final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); processBroadcastForVpn(addedIntent); assertNull(mCm.getActiveNetworkForUid(uid)); @@ -6735,12 +6936,14 @@ public class ConnectivityServiceTest { // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); processBroadcastForVpn(removedIntent); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); - mService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */, + allowList); waitForIdle(); } @@ -7116,7 +7319,8 @@ public class ConnectivityServiceTest { final int uid = Process.myUid(); final int userId = UserHandle.getUserId(uid); final ArrayList<String> allowList = new ArrayList<>(); - mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, + allowList); waitForIdle(); UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1); @@ -7138,7 +7342,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); // Disable lockdown, expect to see the network unblocked. - mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); vpnUidCallback.assertNoCallback(); @@ -7151,7 +7355,8 @@ public class ConnectivityServiceTest { // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked. allowList.add(TEST_PACKAGE_NAME); - mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, + allowList); callback.assertNoCallback(); defaultCallback.assertNoCallback(); vpnUidCallback.assertNoCallback(); @@ -7184,11 +7389,12 @@ public class ConnectivityServiceTest { // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown. // Everything should now be blocked. - mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); waitForIdle(); expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3); allowList.clear(); - mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, + allowList); waitForIdle(); expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent); @@ -7201,7 +7407,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); // Disable lockdown. Everything is unblocked. - mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent); vpnUidCallback.assertNoCallback(); @@ -7213,7 +7419,8 @@ public class ConnectivityServiceTest { // Enable and disable an always-on VPN package without lockdown. Expect no changes. reset(mMockNetd); - mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, + allowList); inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); callback.assertNoCallback(); defaultCallback.assertNoCallback(); @@ -7224,7 +7431,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); callback.assertNoCallback(); defaultCallback.assertNoCallback(); @@ -7236,7 +7443,8 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); // Enable lockdown and connect a VPN. The VPN is not blocked. - mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, + allowList); defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent); assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent); vpnUidCallback.assertNoCallback(); @@ -7282,10 +7490,14 @@ public class ConnectivityServiceTest { when(mKeyStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile); } - private void establishLegacyLockdownVpn() throws Exception { + private void establishLegacyLockdownVpn(Network underlying) throws Exception { + // The legacy lockdown VPN only supports userId 0, and must have an underlying network. + assertNotNull(underlying); + mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY); // The legacy lockdown VPN only supports userId 0. final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); mMockVpn.registerAgent(ranges); + mMockVpn.setUnderlyingNetworks(new Network[]{underlying}); mMockVpn.connect(true); } @@ -7293,6 +7505,9 @@ public class ConnectivityServiceTest { public void testLegacyLockdownVpn() throws Exception { mServiceContext.setPermission( Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); + // For LockdownVpnTracker to call registerSystemDefaultNetworkCallback. + mServiceContext.setPermission( + Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); final TestNetworkCallback callback = new TestNetworkCallback(); @@ -7301,6 +7516,10 @@ public class ConnectivityServiceTest { final TestNetworkCallback defaultCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultCallback); + final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); + mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, + new Handler(ConnectivityThread.getInstanceLooper())); + // Pretend lockdown VPN was configured. setupLegacyLockdownVpn(); @@ -7312,6 +7531,7 @@ public class ConnectivityServiceTest { // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker. final int userId = UserHandle.getUserId(Process.myUid()); final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); processBroadcastForVpn(addedIntent); @@ -7330,6 +7550,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false /* validated */); callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); + systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); waitForIdle(); assertNull(mMockVpn.getAgent()); @@ -7341,6 +7562,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); + systemDefaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, + mCellNetworkAgent); waitForIdle(); assertNull(mMockVpn.getAgent()); @@ -7350,6 +7573,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.disconnect(); callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); b1.expectBroadcast(); // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten @@ -7359,6 +7583,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false /* validated */); callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); + systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); b1.expectBroadcast(); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); @@ -7381,9 +7606,10 @@ public class ConnectivityServiceTest { mMockVpn.expectStartLegacyVpnRunner(); b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED); ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED); - establishLegacyLockdownVpn(); + establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork()); callback.expectAvailableThenValidatedCallbacks(mMockVpn); defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + systemDefaultCallback.assertNoCallback(); NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); b1.expectBroadcast(); b2.expectBroadcast(); @@ -7395,6 +7621,7 @@ public class ConnectivityServiceTest { assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR)); assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI)); assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED)); + assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY); // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect. final LinkProperties wifiLp = new LinkProperties(); @@ -7422,11 +7649,10 @@ public class ConnectivityServiceTest { // fact that a VPN is connected should only result in the VPN itself being unblocked, not // any other network. Bug in isUidBlockedByVpn? callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCapabilitiesThat(mMockVpn, nc -> nc.hasTransport(TRANSPORT_WIFI)); callback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectCapabilitiesThat(mMockVpn, nc -> nc.hasTransport(TRANSPORT_WIFI)); defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // While the VPN is reconnecting on the new network, everything is blocked. assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); @@ -7437,9 +7663,10 @@ public class ConnectivityServiceTest { // The VPN comes up again on wifi. b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED); b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - establishLegacyLockdownVpn(); + establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork()); callback.expectAvailableThenValidatedCallbacks(mMockVpn); defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + systemDefaultCallback.assertNoCallback(); b1.expectBroadcast(); b2.expectBroadcast(); assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); @@ -7453,14 +7680,10 @@ public class ConnectivityServiceTest { assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED)); // Disconnect cell. Nothing much happens since it's not the default network. - // Whenever LockdownVpnTracker is connected, it will send a connected broadcast any time any - // NetworkInfo is updated. This is probably a bug. - // TODO: consider fixing this. - b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); mCellNetworkAgent.disconnect(); - b1.expectBroadcast(); callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); defaultCallback.assertNoCallback(); + systemDefaultCallback.assertNoCallback(); assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); @@ -7470,6 +7693,7 @@ public class ConnectivityServiceTest { b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); + systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); b1.expectBroadcast(); callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI)); b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED); @@ -7521,13 +7745,19 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.removeCapability(testCap); callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent); callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent); - verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mMockNetd); + // TODO: Test default network changes for NOT_VCN_MANAGED once the default request has + // it. + if (testCap == NET_CAPABILITY_TRUSTED) { + verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); + reset(mMockNetd); + } mCellNetworkAgent.removeCapability(testCap); callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); callbackWithoutCap.assertNoCallback(); - verify(mMockNetd).networkClearDefault(); + if (testCap == NET_CAPABILITY_TRUSTED) { + verify(mMockNetd).networkClearDefault(); + } mCm.unregisterNetworkCallback(callbackWithCap); mCm.unregisterNetworkCallback(callbackWithoutCap); @@ -8002,8 +8232,8 @@ public class ConnectivityServiceTest { reset(mNetworkManagementService); mCellNetworkAgent.connect(true); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_CELLULAR)); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); final LinkProperties wifiLp = new LinkProperties(); @@ -8011,25 +8241,27 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.sendLinkProperties(wifiLp); // Network switch - reset(mNetworkManagementService); mWiFiNetworkAgent.connect(true); networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_WIFI)); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME)); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // Disconnect wifi and switch back to cell - reset(mNetworkManagementService); + reset(mMockNetd); mWiFiNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); assertNoCallbacks(networkCallback); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_CELLULAR)); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // reconnect wifi + reset(mMockNetd); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); wifiLp.setInterfaceName(WIFI_IFNAME); mWiFiNetworkAgent.sendLinkProperties(wifiLp); @@ -8037,9 +8269,12 @@ public class ConnectivityServiceTest { networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // Disconnect cell - reset(mNetworkManagementService); reset(mMockNetd); mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); @@ -8047,17 +8282,18 @@ public class ConnectivityServiceTest { // sent as network being switched. Ensure rule removal for cell will not be triggered // unexpectedly before network being removed. waitForIdle(); - verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); + verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); verify(mMockDnsResolver, times(1)) .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); // Disconnect wifi ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); - reset(mNetworkManagementService); mWiFiNetworkAgent.disconnect(); b.expectBroadcast(); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); // Clean up mCm.unregisterNetworkCallback(networkCallback); @@ -8521,11 +8757,7 @@ public class ConnectivityServiceTest { final int myUid = Process.myUid(); setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM); - try { - mService.getConnectionOwnerUid(getTestConnectionInfo()); - fail("Expected SecurityException for non-VpnService app"); - } catch (SecurityException expected) { - } + assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo())); } @Test @@ -8533,11 +8765,7 @@ public class ConnectivityServiceTest { final int myUid = Process.myUid(); setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE); - try { - mService.getConnectionOwnerUid(getTestConnectionInfo()); - fail("Expected SecurityException for non-VpnService app"); - } catch (SecurityException expected) { - } + assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo())); } @Test @@ -9234,4 +9462,884 @@ public class ConnectivityServiceTest { } fail("TOO_MANY_REQUESTS never thrown"); } + + private void mockGetApplicationInfo(@NonNull final String packageName, @NonNull final int uid) + throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.uid = uid; + when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockHasSystemFeature(@NonNull final String featureName, + @NonNull final boolean hasFeature) { + when(mPackageManager.hasSystemFeature(eq(featureName))) + .thenReturn(hasFeature); + } + + private UidRange getNriFirstUidRange( + @NonNull final ConnectivityService.NetworkRequestInfo nri) { + return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next(); + } + + private OemNetworkPreferences createDefaultOemNetworkPreferences( + @OemNetworkPreferences.OemNetworkPreference final int preference) + throws Exception { + // Arrange PackageManager mocks + mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); + + // Build OemNetworkPreferences object + return new OemNetworkPreferences.Builder() + .addNetworkPreference(TEST_PACKAGE_NAME, preference) + .build(); + } + + @Test + public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() + throws PackageManager.NameNotFoundException { + @OemNetworkPreferences.OemNetworkPreference final int prefToTest = + OEM_NETWORK_PREFERENCE_UNINITIALIZED; + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + assertThrows(IllegalArgumentException.class, + () -> mService.new OemNetworkRequestFactory() + .createNrisFromOemNetworkPreferences( + createDefaultOemNetworkPreferences(prefToTest))); + } + + @Test + public void testOemNetworkRequestFactoryPreferenceOemPaid() + throws Exception { + // Expectations + final int expectedNumOfNris = 1; + final int expectedNumOfRequests = 3; + + @OemNetworkPreferences.OemNetworkPreference final int prefToTest = + OEM_NETWORK_PREFERENCE_OEM_PAID; + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory() + .createNrisFromOemNetworkPreferences( + createDefaultOemNetworkPreferences(prefToTest)); + + final List<NetworkRequest> mRequests = nris.iterator().next().mRequests; + assertEquals(expectedNumOfNris, nris.size()); + assertEquals(expectedNumOfRequests, mRequests.size()); + assertTrue(mRequests.get(0).isListen()); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED)); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED)); + assertTrue(mRequests.get(1).isRequest()); + assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID)); + assertTrue(mRequests.get(2).isRequest()); + assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities( + mRequests.get(2).networkCapabilities)); + } + + @Test + public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback() + throws Exception { + // Expectations + final int expectedNumOfNris = 1; + final int expectedNumOfRequests = 2; + + @OemNetworkPreferences.OemNetworkPreference final int prefToTest = + OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory() + .createNrisFromOemNetworkPreferences( + createDefaultOemNetworkPreferences(prefToTest)); + + final List<NetworkRequest> mRequests = nris.iterator().next().mRequests; + assertEquals(expectedNumOfNris, nris.size()); + assertEquals(expectedNumOfRequests, mRequests.size()); + assertTrue(mRequests.get(0).isListen()); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED)); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED)); + assertTrue(mRequests.get(1).isRequest()); + assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID)); + } + + @Test + public void testOemNetworkRequestFactoryPreferenceOemPaidOnly() + throws Exception { + // Expectations + final int expectedNumOfNris = 1; + final int expectedNumOfRequests = 1; + + @OemNetworkPreferences.OemNetworkPreference final int prefToTest = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory() + .createNrisFromOemNetworkPreferences( + createDefaultOemNetworkPreferences(prefToTest)); + + final List<NetworkRequest> mRequests = nris.iterator().next().mRequests; + assertEquals(expectedNumOfNris, nris.size()); + assertEquals(expectedNumOfRequests, mRequests.size()); + assertTrue(mRequests.get(0).isRequest()); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID)); + } + + @Test + public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly() + throws Exception { + // Expectations + final int expectedNumOfNris = 1; + final int expectedNumOfRequests = 1; + + @OemNetworkPreferences.OemNetworkPreference final int prefToTest = + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory() + .createNrisFromOemNetworkPreferences( + createDefaultOemNetworkPreferences(prefToTest)); + + final List<NetworkRequest> mRequests = nris.iterator().next().mRequests; + assertEquals(expectedNumOfNris, nris.size()); + assertEquals(expectedNumOfRequests, mRequests.size()); + assertTrue(mRequests.get(0).isRequest()); + assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE)); + assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID)); + } + + @Test + public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris() + throws Exception { + // Expectations + final int expectedNumOfNris = 2; + + // Arrange PackageManager mocks + final String testPackageName2 = "com.google.apps.dialer"; + mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); + mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID); + + // Build OemNetworkPreferences object + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) + .addNetworkPreference(testPackageName2, testOemPref2) + .build(); + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref); + + assertNotNull(nris); + assertEquals(expectedNumOfNris, nris.size()); + } + + @Test + public void testOemNetworkRequestFactoryCorrectlySetsUids() + throws Exception { + // Arrange PackageManager mocks + final String testPackageName2 = "com.google.apps.dialer"; + final int testPackageNameUid2 = 456; + mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); + mockGetApplicationInfo(testPackageName2, testPackageNameUid2); + + // Build OemNetworkPreferences object + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) + .addNetworkPreference(testPackageName2, testOemPref2) + .build(); + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final List<ConnectivityService.NetworkRequestInfo> nris = + new ArrayList<>( + mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences( + pref)); + + // Sort by uid to access nris by index + nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start)); + assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start); + assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop); + assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start); + assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop); + } + + @Test + public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference() + throws Exception { + // Expectations + final int expectedNumOfNris = 1; + final int expectedNumOfAppUids = 2; + + // Arrange PackageManager mocks + final String testPackageName2 = "com.google.apps.dialer"; + final int testPackageNameUid2 = 456; + mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); + mockGetApplicationInfo(testPackageName2, testPackageNameUid2); + + // Build OemNetworkPreferences object + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) + .addNetworkPreference(testPackageName2, testOemPref) + .build(); + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final ArraySet<ConnectivityService.NetworkRequestInfo> nris = + mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref); + + assertEquals(expectedNumOfNris, nris.size()); + assertEquals(expectedNumOfAppUids, + nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size()); + } + + @Test + public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() { + mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); + + // Act on ConnectivityService.setOemNetworkPreference() + assertThrows(NullPointerException.class, + () -> mService.setOemNetworkPreference( + null, + null)); + } + + @Test + public void testSetOemNetworkPreferenceFailsForNonAutomotive() + throws Exception { + mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false); + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + + // Act on ConnectivityService.setOemNetworkPreference() + assertThrows(UnsupportedOperationException.class, + () -> mService.setOemNetworkPreference( + createDefaultOemNetworkPreferences(networkPref), + new TestOemListenerCallback())); + } + + private void setOemNetworkPreferenceAgentConnected(final int transportType, + final boolean connectAgent) throws Exception { + switch(transportType) { + // Corresponds to a metered cellular network. Will be used for the default network. + case TRANSPORT_CELLULAR: + if (!connectAgent) { + mCellNetworkAgent.disconnect(); + break; + } + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); + mCellNetworkAgent.connect(true); + break; + // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE. + case TRANSPORT_ETHERNET: + if (!connectAgent) { + stopOemManagedNetwork(); + break; + } + startOemManagedNetwork(true); + break; + // Corresponds to unmetered Wi-Fi. + case TRANSPORT_WIFI: + if (!connectAgent) { + mWiFiNetworkAgent.disconnect(); + break; + } + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.connect(true); + break; + default: + throw new AssertionError("Unsupported transport type passed in."); + + } + waitForIdle(); + } + + private void startOemManagedNetwork(final boolean isOemPaid) throws Exception { + mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); + mEthernetNetworkAgent.addCapability( + isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE); + mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + mEthernetNetworkAgent.connect(true); + } + + private void stopOemManagedNetwork() { + mEthernetNetworkAgent.disconnect(); + waitForIdle(); + } + + private void verifyMultipleDefaultNetworksTracksCorrectly( + final int expectedOemRequestsSize, + @NonNull final Network expectedDefaultNetwork, + @NonNull final Network expectedPerAppNetwork) { + // The current test setup assumes two tracked default network requests; one for the default + // network and the other for the OEM network preference being tested. This will be validated + // each time to confirm it doesn't change under test. + final int expectedDefaultNetworkRequestsSize = 2; + assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size()); + for (final ConnectivityService.NetworkRequestInfo defaultRequest + : mService.mDefaultNetworkRequests) { + final Network defaultNetwork = defaultRequest.getSatisfier() == null + ? null : defaultRequest.getSatisfier().network(); + // If this is the default request. + if (defaultRequest == mService.mDefaultRequest) { + assertEquals( + expectedDefaultNetwork, + defaultNetwork); + // Make sure this value doesn't change. + assertEquals(1, defaultRequest.mRequests.size()); + continue; + } + assertEquals(expectedPerAppNetwork, defaultNetwork); + assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size()); + } + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) + throws Exception { + final int testPackageNameUid = 123; + final String testPackageName = "per.app.defaults.package"; + setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + networkPrefToSetup, testPackageNameUid, testPackageName); + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) + throws Exception { + final int testPackageNameUid = Process.myUid(); + final String testPackageName = "per.app.defaults.package"; + setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + networkPrefToSetup, testPackageNameUid, testPackageName); + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, + final int testPackageUid, @NonNull final String testPackageName) throws Exception { + // Only the default request should be included at start. + assertEquals(1, mService.mDefaultNetworkRequests.size()); + + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageUid)); + setupSetOemNetworkPreferenceForPreferenceTest( + networkPrefToSetup, uidRanges, testPackageName); + } + + private void setupSetOemNetworkPreferenceForPreferenceTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, + @NonNull final UidRangeParcel[] uidRanges, + @NonNull final String testPackageName) + throws Exception { + mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); + + // These tests work off a single UID therefore using 'start' is valid. + mockGetApplicationInfo(testPackageName, uidRanges[0].start); + + // Build OemNetworkPreferences object + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(testPackageName, networkPrefToSetup) + .build(); + + // Act on ConnectivityService.setOemNetworkPreference() + final TestOemListenerCallback mOnSetOemNetworkPreferenceTestListener = + new TestOemListenerCallback(); + mService.setOemNetworkPreference(pref, mOnSetOemNetworkPreferenceTestListener); + + // Verify call returned successfully + mOnSetOemNetworkPreferenceTestListener.expectOnComplete(); + } + + private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener { + final CompletableFuture<Object> mDone = new CompletableFuture<>(); + + @Override + public void onComplete() { + mDone.complete(new Object()); + } + + void expectOnComplete() throws Exception { + try { + mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms"); + } + } + + @Override + public IBinder asBinder() { + return null; + } + } + + @Test + public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active network for the default should be null at this point as this is a retricted + // network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // Verify that the active network is correct + verifyActiveNetwork(TRANSPORT_ETHERNET); + } + + @Test + public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Returns true by default when no network is available. + assertTrue(mCm.isActiveNetworkMetered()); + + // Connect to an unmetered restricted network that will only be available to the OEM pref. + mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); + mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID); + mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + mEthernetNetworkAgent.connect(true); + waitForIdle(); + + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + assertFalse(mCm.isActiveNetworkMetered()); + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + + // Register the default network callback before the pref is already set. This means that + // the policy will be applied to the callback on setOemNetworkPreference(). + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // At this point with a restricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Now bring down the default network which should trigger a LOST callback. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // At this point, with no network is available, the lost callback should trigger + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Register the default network callback after the pref is already set. This means that + // the policy will be applied to the callback on requestNetwork(). + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // At this point with a restricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Now bring down the default network which should trigger a LOST callback. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // At this point, with no network is available, the lost callback should trigger + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + final int userId = UserHandle.getUserId(Process.myUid()); + + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Setup a process different than the test process to use the default network. This means + // that the defaultNetworkCallback won't be tracked by the per-app policy. + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // As this callback does not have access to the OEM_PAID network, it will not fire. + defaultNetworkCallback.assertNoCallback(); + assertDefaultNetworkCapabilities(userId /* no networks */); + + // Bring up unrestricted cellular. This should now satisfy the default network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // At this point with an unrestricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mCellNetworkAgent.getNetwork()); + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent); + + // Now bring down the per-app network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // Since the callback didn't use the per-app network, no callback should fire. + defaultNetworkCallback.assertNoCallback(); + + // Now bring down the default network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + + // As this callback was tracking the default, this should now trigger. + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + private void verifySetOemNetworkPreferenceForPreference( + @NonNull final UidRangeParcel[] uidRanges, + final int addUidRangesNetId, + final int addUidRangesTimes, + final int removeUidRangesNetId, + final int removeUidRangesTimes, + final boolean shouldDestroyNetwork) throws RemoteException { + final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId; + final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId; + + // Validate netd. + verify(mMockNetd, times(addUidRangesTimes)) + .networkAddUidRanges( + (useAnyIdForAdd ? anyInt() : eq(addUidRangesNetId)), eq(uidRanges)); + verify(mMockNetd, times(removeUidRangesTimes)) + .networkRemoveUidRanges( + (useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)), eq(uidRanges)); + if (shouldDestroyNetwork) { + verify(mMockNetd, times(1)) + .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId))); + } + reset(mMockNetd); + } + + /** + * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference(). + * @throws Exception + */ + @Test + public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception { + @OemNetworkPreferences.OemNetworkPreference int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testPackageUid = 123; + final String testPackageName = "com.google.apps.contacts"; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageUid)); + + // Validate the starting requests only includes the fallback request. + assertEquals(1, mService.mDefaultNetworkRequests.size()); + + // Add an OEM default network request to track. + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); + + // Two requests should exist, one for the fallback and one for the pref. + assertEquals(2, mService.mDefaultNetworkRequests.size()); + + networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); + + // Two requests should still exist validating the previous per-app request was replaced. + assertEquals(2, mService.mDefaultNetworkRequests.size()); + } + + /** + * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID following in order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback + * @throws Exception + */ + @Test + public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + + // Arrange PackageManager mocks + final int testPackageNameUid = 123; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageNameUid)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. No networks should be connected. + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + // netd should not be called as default networks haven't changed. + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting unmetered should put PANS on lowest priority fallback request. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + + // Disconnecting the fallback network should result in no connectivity. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + mCellNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK following in order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID + * @throws Exception + */ + @Test + public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + + // Arrange PackageManager mocks + final int testPackageNameUid = 123; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageNameUid)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + // This preference should not use this network as it doesn't support fallback usage. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting unmetered should put PANS on OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should result in no connectivity. + // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY following in order: + * NET_CAPABILITY_OEM_PAID + * This preference should only apply to OEM_PAID networks. + * @throws Exception + */ + @Test + public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + + // Arrange PackageManager mocks + final int testPackageNameUid = 123; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageNameUid)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up metered cellular. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should result in no connectivity. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY following in order: + * NET_CAPABILITY_OEM_PRIVATE + * This preference should only apply to OEM_PRIVATE networks. + * @throws Exception + */ + @Test + public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + + // Arrange PackageManager mocks + final int testPackageNameUid = 123; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUid(testPackageNameUid)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up metered cellular. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE. + startOemManagedNetwork(false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PRIVATE should result in no connectivity. + stopOemManagedNetwork(); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } } diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 799bcc82d2a9..32c95f149979 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -16,12 +16,16 @@ package com.android.server; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.INetd.IF_STATE_DOWN; +import static android.net.INetd.IF_STATE_UP; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; @@ -33,8 +37,10 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; import android.net.INetd; import android.net.InetAddresses; +import android.net.InterfaceConfigurationParcel; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; @@ -44,15 +50,17 @@ import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.Network; import android.os.Binder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.system.Os; import android.test.mock.MockContext; import androidx.test.filters.SmallTest; +import com.android.server.IpSecService.TunnelInterfaceRecord; + import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -109,6 +117,7 @@ public class IpSecServiceParameterizedTest { }; AppOpsManager mMockAppOps = mock(AppOpsManager.class); + ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class); MockContext mMockContext = new MockContext() { @Override @@ -116,12 +125,22 @@ public class IpSecServiceParameterizedTest { switch(name) { case Context.APP_OPS_SERVICE: return mMockAppOps; + case Context.CONNECTIVITY_SERVICE: + return mMockConnectivityMgr; default: return null; } } @Override + public String getSystemServiceName(Class<?> serviceClass) { + if (ConnectivityManager.class == serviceClass) { + return Context.CONNECTIVITY_SERVICE; + } + return null; + } + + @Override public PackageManager getPackageManager() { return mMockPkgMgr; } @@ -133,10 +152,17 @@ public class IpSecServiceParameterizedTest { } throw new SecurityException("Unavailable permission requested"); } + + @Override + public int checkCallingOrSelfPermission(String permission) { + if (android.Manifest.permission.NETWORK_STACK.equals(permission)) { + return PERMISSION_GRANTED; + } + throw new UnsupportedOperationException(); + } }; INetd mMockNetd; - INetworkManagementService mNetworkManager; PackageManager mMockPkgMgr; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -151,6 +177,10 @@ public class IpSecServiceParameterizedTest { new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); private static final int REMOTE_ENCAP_PORT = 4500; + private static final String BLESSED_PACKAGE = "blessedPackage"; + private static final String SYSTEM_PACKAGE = "systemPackage"; + private static final String BAD_PACKAGE = "badPackage"; + public IpSecServiceParameterizedTest( String sourceAddr, String destAddr, String localInnerAddr, int family) { mSourceAddr = sourceAddr; @@ -162,10 +192,9 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { mMockNetd = mock(INetd.class); - mNetworkManager = mock(INetworkManagementService.class); mMockPkgMgr = mock(PackageManager.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mNetworkManager, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -174,15 +203,15 @@ public class IpSecServiceParameterizedTest { when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true); // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage"))) - .thenReturn(AppOpsManager.MODE_ALLOWED); + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BLESSED_PACKAGE))) + .thenReturn(AppOpsManager.MODE_ALLOWED); // A system package will not be granted the app op, so this should fall back to // a permissions check, which should pass. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage"))) - .thenReturn(AppOpsManager.MODE_DEFAULT); + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(SYSTEM_PACKAGE))) + .thenReturn(AppOpsManager.MODE_DEFAULT); // A mismatch between the package name and the UID will return MODE_IGNORED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage"))) - .thenReturn(AppOpsManager.MODE_IGNORED); + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BAD_PACKAGE))) + .thenReturn(AppOpsManager.MODE_IGNORED); } //TODO: Add a test to verify SPI. @@ -338,7 +367,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); @@ -352,7 +381,7 @@ public class IpSecServiceParameterizedTest { ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); @@ -370,14 +399,14 @@ public class IpSecServiceParameterizedTest { if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } @@ -396,14 +425,14 @@ public class IpSecServiceParameterizedTest { if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } @@ -417,12 +446,12 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); assertEquals(IpSecManager.Status.OK, createTransformResp.status); // Attempting to create transform a second time with the same SPIs should throw an error... try { - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); fail("IpSecService should have thrown an error for reuse of SPI"); } catch (IllegalStateException expected) { } @@ -430,7 +459,7 @@ public class IpSecServiceParameterizedTest { // ... even if the transform is deleted mIpSecService.deleteTransform(createTransformResp.resourceId); try { - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); fail("IpSecService should have thrown an error for reuse of SPI"); } catch (IllegalStateException expected) { } @@ -443,7 +472,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); @@ -467,7 +496,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); mIpSecService.deleteTransform(createTransformResp.resourceId); verify(mMockNetd, times(1)) @@ -515,7 +544,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); IpSecService.RefcountedResource refcountedRecord = @@ -562,7 +591,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); if (closeSpiBeforeApply) { mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); @@ -592,7 +621,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); // Close SPI record mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); @@ -625,7 +654,10 @@ public class IpSecServiceParameterizedTest { } private IpSecTunnelInterfaceResponse createAndValidateTunnel( - String localAddr, String remoteAddr, String pkgName) { + String localAddr, String remoteAddr, String pkgName) throws Exception { + final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); + config.flags = new String[] {IF_STATE_DOWN}; + when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config); IpSecTunnelInterfaceResponse createTunnelResp = mIpSecService.createTunnelInterface( mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); @@ -638,7 +670,7 @@ public class IpSecServiceParameterizedTest { @Test public void testCreateTunnelInterface() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); // Check that we have stored the tracking object, and retrieve it IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); @@ -655,17 +687,18 @@ public class IpSecServiceParameterizedTest { anyInt(), anyInt(), anyInt()); - verify(mNetworkManager).setInterfaceUp(createTunnelResp.interfaceName); + verify(mMockNetd).interfaceSetCfg(argThat( + config -> Arrays.asList(config.flags).contains(IF_STATE_UP))); } @Test public void testDeleteTunnelInterface() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage"); + mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, BLESSED_PACKAGE); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); @@ -678,10 +711,73 @@ public class IpSecServiceParameterizedTest { } } + private Network createFakeUnderlyingNetwork(String interfaceName) { + final Network fakeNetwork = new Network(1000); + final LinkProperties fakeLp = new LinkProperties(); + fakeLp.setInterfaceName(interfaceName); + when(mMockConnectivityMgr.getLinkProperties(eq(fakeNetwork))).thenReturn(fakeLp); + return fakeNetwork; + } + + @Test + public void testSetNetworkForTunnelInterface() throws Exception { + final IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); + final Network newFakeNetwork = createFakeUnderlyingNetwork("newFakeNetworkInterface"); + final int tunnelIfaceResourceId = createTunnelResp.resourceId; + mIpSecService.setNetworkForTunnelInterface( + tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); + + final IpSecService.UserRecord userRecord = + mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); + + final TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); + assertEquals(newFakeNetwork, tunnelInterfaceInfo.getUnderlyingNetwork()); + } + + @Test + public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception { + final IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); + final Network newFakeNetwork = new Network(1000); + + try { + mIpSecService.setNetworkForTunnelInterface( + IpSecManager.INVALID_RESOURCE_ID, newFakeNetwork, BLESSED_PACKAGE); + fail("Expected an IllegalArgumentException for invalid resource ID."); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork() throws Exception { + final IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); + final int tunnelIfaceResourceId = createTunnelResp.resourceId; + final IpSecService.UserRecord userRecord = + mIpSecService.mUserResourceTracker.getUserRecord(mUid); + final TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); + + final Network newFakeNetwork = + createFakeUnderlyingNetwork(tunnelInterfaceInfo.getInterfaceName()); + + try { + mIpSecService.setNetworkForTunnelInterface( + tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); + fail( + "Expected an IllegalArgumentException because the underlying network is the" + + " network being exposed by this tunnel."); + } catch (IllegalArgumentException expected) { + } + } + @Test public void testTunnelInterfaceBinderDeath() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); IpSecService.RefcountedResource refcountedRecord = @@ -718,9 +814,9 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); if (closeSpiBeforeApply) { mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); @@ -728,8 +824,8 @@ public class IpSecServiceParameterizedTest { int transformResourceId = createTransformResp.resourceId; int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, - transformResourceId, "blessedPackage"); + mIpSecService.applyTunnelModeTransform( + tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE); for (int selAddrFamily : ADDRESS_FAMILIES) { verify(mMockNetd) @@ -758,17 +854,17 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); // Close SPI record mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); int transformResourceId = createTransformResp.resourceId; int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, - transformResourceId, "blessedPackage"); + mIpSecService.applyTunnelModeTransform( + tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE); for (int selAddrFamily : ADDRESS_FAMILIES) { verify(mMockNetd) @@ -790,7 +886,7 @@ public class IpSecServiceParameterizedTest { @Test public void testAddRemoveAddressFromTunnelInterface() throws Exception { - for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) { + for (String pkgName : new String[] {BLESSED_PACKAGE, SYSTEM_PACKAGE}) { IpSecTunnelInterfaceResponse createTunnelResp = createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName); mIpSecService.addAddressToTunnelInterface( @@ -816,7 +912,7 @@ public class IpSecServiceParameterizedTest { public void testAddTunnelFailsForBadPackageName() throws Exception { try { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage"); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, BAD_PACKAGE); fail("Expected a SecurityException for badPackage."); } catch (SecurityException expected) { } @@ -830,7 +926,7 @@ public class IpSecServiceParameterizedTest { try { String addr = Inet4Address.getLoopbackAddress().getHostAddress(); mIpSecService.createTunnelInterface( - addr, addr, new Network(0), new Binder(), "blessedPackage"); + addr, addr, new Network(0), new Binder(), BLESSED_PACKAGE); fail("Expected UnsupportedOperationException for disabled feature"); } catch (UnsupportedOperationException expected) { } diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java index 788e4efe097e..22a2c94fc194 100644 --- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.os.Binder; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.RemoteException; import androidx.test.filters.SmallTest; @@ -62,8 +61,7 @@ public class IpSecServiceRefcountedResourceTest { public void setUp() throws Exception { mMockContext = mock(Context.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService( - mMockContext, mock(INetworkManagementService.class), mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); } private void assertResourceState( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 536e98327e1f..f97eabf6366d 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -42,7 +42,6 @@ import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecUdpEncapResponse; import android.os.Binder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.Process; import android.system.ErrnoException; @@ -116,7 +115,6 @@ public class IpSecServiceTest { } Context mMockContext; - INetworkManagementService mMockNetworkManager; INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -124,10 +122,9 @@ public class IpSecServiceTest { @Before public void setUp() throws Exception { mMockContext = mock(Context.class); - mMockNetworkManager = mock(INetworkManagementService.class); mMockNetd = mock(INetd.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockNetworkManager, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -135,7 +132,7 @@ public class IpSecServiceTest { @Test public void testIpSecServiceCreate() throws InterruptedException { - IpSecService ipSecSrv = IpSecService.create(mMockContext, mMockNetworkManager); + IpSecService ipSecSrv = IpSecService.create(mMockContext); assertNotNull(ipSecSrv); } @@ -608,7 +605,7 @@ public class IpSecServiceTest { public void testOpenUdpEncapSocketTagsSocket() throws Exception { IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class); IpSecService testIpSecService = new IpSecService( - mMockContext, mMockNetworkManager, mMockIpSecSrvConfig, mockTagger); + mMockContext, mMockIpSecSrvConfig, mockTagger); IpSecUdpEncapResponse udpEncapResp = testIpSecService.openUdpEncapsulationSocket(0, new Binder()); diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index b47be97ed002..ff8c632833f2 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -46,7 +46,10 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.AdditionalAnswers; @@ -63,6 +66,8 @@ import java.util.List; @SmallTest public class NetworkNotificationManagerTest { + private static final String TEST_SSID = "Test SSID"; + private static final String TEST_EXTRA_INFO = "extra"; static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities(); static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities(); static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities(); @@ -72,6 +77,7 @@ public class NetworkNotificationManagerTest { WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + WIFI_CAPABILITIES.setSSID(TEST_SSID); // Set the underyling network to wifi. VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); @@ -112,7 +118,7 @@ public class NetworkNotificationManagerTest { when(mCtx.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE))) .thenReturn(mNotificationManager); - when(mNetworkInfo.getExtraInfo()).thenReturn("extra"); + when(mNetworkInfo.getExtraInfo()).thenReturn(TEST_EXTRA_INFO); when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B); mManager = new NetworkNotificationManager(mCtx, mTelephonyManager); @@ -125,11 +131,11 @@ public class NetworkNotificationManagerTest { .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any()); final int transportType = NetworkNotificationManager.approximateTransportType(nai); if (transportType == NetworkCapabilities.TRANSPORT_WIFI) { - verify(mResources, times(1)).getString(title, eq(any())); + verify(mResources, times(1)).getString(eq(title), eq(TEST_EXTRA_INFO)); } else { verify(mResources, times(1)).getString(title); } - verify(mResources, times(1)).getString(R.string.private_dns_broken_detailed); + verify(mResources, times(1)).getString(eq(R.string.private_dns_broken_detailed)); } @Test @@ -178,6 +184,9 @@ public class NetworkNotificationManagerTest { } @Test + @Ignore + // Ignored because the code under test calls Log.wtf, which crashes the tests on eng builds. + // TODO: re-enable after fixing this (e.g., turn Log.wtf into exceptions that this test catches) public void testNoInternetNotificationsNotShownForCellular() { mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false); mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false); diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 3556c72776dc..e4e24b464838 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -61,6 +61,7 @@ import android.content.pm.PackageManagerInternal; import android.net.INetd; import android.net.UidRange; import android.os.Build; +import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; import android.util.SparseIntArray; @@ -89,8 +90,8 @@ import java.util.Set; @RunWith(AndroidJUnit4.class) @SmallTest public class PermissionMonitorTest { - private static final int MOCK_USER1 = 0; - private static final int MOCK_USER2 = 1; + private static final UserHandle MOCK_USER1 = UserHandle.of(0); + private static final UserHandle MOCK_USER2 = UserHandle.of(1); private static final int MOCK_UID1 = 10001; private static final int MOCK_UID2 = 10086; private static final int SYSTEM_UID1 = 1000; @@ -114,6 +115,7 @@ public class PermissionMonitorTest { @Mock private PackageManagerInternal mMockPmi; @Mock private UserManager mUserManager; @Mock private PermissionMonitor.Dependencies mDeps; + @Mock private SystemConfigManager mSystemConfigManager; private PermissionMonitor mPermissionMonitor; @@ -123,10 +125,12 @@ public class PermissionMonitorTest { when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mUserManager.getUserHandles(eq(true))).thenReturn( - Arrays.asList(new UserHandle[] { - new UserHandle(MOCK_USER1), - new UserHandle(MOCK_USER2), - })); + Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 })); + when(mContext.getSystemServiceName(SystemConfigManager.class)) + .thenReturn(Context.SYSTEM_CONFIG_SERVICE); + when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE)) + .thenReturn(mSystemConfigManager); + when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); @@ -184,7 +188,8 @@ public class PermissionMonitorTest { return packageInfo; } - private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) { + private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, + UserHandle user) { final PackageInfo pkgInfo; if (hasSystemPermission) { pkgInfo = systemPackageInfoWithPermissions( @@ -192,7 +197,7 @@ public class PermissionMonitorTest { } else { pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, ""); } - pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); + pkgInfo.applicationInfo.uid = UserHandle.getUid(user, UserHandle.getAppId(uid)); return pkgInfo; } @@ -382,8 +387,8 @@ public class PermissionMonitorTest { }).when(mockNetd).networkClearPermissionForUser(any(int[].class)); } - public void expectPermission(Boolean permission, int[] users, int[] apps) { - for (final int user : users) { + public void expectPermission(Boolean permission, UserHandle[] users, int[] apps) { + for (final UserHandle user : users) { for (final int app : apps) { final int uid = UserHandle.getUid(user, app); if (!mApps.containsKey(uid)) { @@ -396,8 +401,8 @@ public class PermissionMonitorTest { } } - public void expectNoPermission(int[] users, int[] apps) { - for (final int user : users) { + public void expectNoPermission(UserHandle[] users, int[] apps) { + for (final UserHandle user : users) { for (final int app : apps) { final int uid = UserHandle.getUid(user, app); if (mApps.containsKey(uid)) { @@ -425,46 +430,48 @@ public class PermissionMonitorTest { // Add SYSTEM_PACKAGE2, expect only have network permission. mPermissionMonitor.onUserAdded(MOCK_USER1); - addPackageForUsers(new int[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID); - mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1}, new int[]{SYSTEM_UID}); + addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID); + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID}); // Add SYSTEM_PACKAGE1, expect permission escalate. - addPackageForUsers(new int[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID); - mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1}, new int[]{SYSTEM_UID}); + addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID}); mPermissionMonitor.onUserAdded(MOCK_USER2); - mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1, MOCK_USER2}, + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{SYSTEM_UID}); - addPackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1, MOCK_USER2}, + addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{SYSTEM_UID}); - mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1, MOCK_USER2}, + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{MOCK_UID1}); // Remove MOCK_UID1, expect no permission left for all user. mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - removePackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2}, new int[]{MOCK_UID1}); + removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, + new int[]{MOCK_UID1}); // Remove SYSTEM_PACKAGE1, expect permission downgrade. when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{SYSTEM_PACKAGE2}); - removePackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE1, SYSTEM_UID); - mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1, MOCK_USER2}, + removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, + SYSTEM_PACKAGE1, SYSTEM_UID); + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{SYSTEM_UID}); mPermissionMonitor.onUserRemoved(MOCK_USER1); - mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER2}, new int[]{SYSTEM_UID}); + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER2}, new int[]{SYSTEM_UID}); // Remove all packages, expect no permission left. when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{}); - removePackageForUsers(new int[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID); - mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2}, + removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID); + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{SYSTEM_UID, MOCK_UID1}); // Remove last user, expect no redundant clearPermission is invoked. mPermissionMonitor.onUserRemoved(MOCK_USER2); - mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2}, + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, new int[]{SYSTEM_UID, MOCK_UID1}); } @@ -548,14 +555,14 @@ public class PermissionMonitorTest { // Normal package add/remove operations will trigger multiple intent for uids corresponding to // each user. To simulate generic package operations, the onPackageAdded/Removed will need to be // called multiple times with the uid corresponding to each user. - private void addPackageForUsers(int[] users, String packageName, int uid) { - for (final int user : users) { + private void addPackageForUsers(UserHandle[] users, String packageName, int uid) { + for (final UserHandle user : users) { mPermissionMonitor.onPackageAdded(packageName, UserHandle.getUid(user, uid)); } } - private void removePackageForUsers(int[] users, String packageName, int uid) { - for (final int user : users) { + private void removePackageForUsers(UserHandle[] users, String packageName, int uid) { + for (final UserHandle user : users) { mPermissionMonitor.onPackageRemoved(packageName, UserHandle.getUid(user, uid)); } } @@ -747,4 +754,20 @@ public class PermissionMonitorTest { GET_PERMISSIONS | MATCH_ANY_USER); assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); } + + @Test + public void testUpdateUidPermissionsFromSystemConfig() throws Exception { + final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); + when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>()); + when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET))) + .thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 }); + when(mSystemConfigManager.getSystemPermissionUids(eq(UPDATE_DEVICE_STATS))) + .thenReturn(new int[]{ MOCK_UID2 }); + + mPermissionMonitor.startMonitoring(); + mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{ MOCK_UID1 }); + mNetdServiceMonitor.expectPermission( + INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, + new int[]{ MOCK_UID2 }); + } } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 73cc9f129e79..6576daf5ab9a 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -21,10 +21,13 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static android.content.pm.UserInfo.FLAG_PRIMARY; import static android.content.pm.UserInfo.FLAG_RESTRICTED; import static android.net.ConnectivityManager.NetworkCallback; +import static android.net.INetd.IF_STATE_DOWN; +import static android.net.INetd.IF_STATE_UP; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -61,6 +64,7 @@ import android.net.ConnectivityManager; import android.net.INetd; import android.net.Ikev2VpnProfile; import android.net.InetAddresses; +import android.net.InterfaceConfigurationParcel; import android.net.IpPrefix; import android.net.IpSecManager; import android.net.IpSecTunnelInterfaceResponse; @@ -74,6 +78,7 @@ import android.net.UidRange; import android.net.UidRangeParcel; import android.net.VpnManager; import android.net.VpnService; +import android.net.VpnTransportInfo; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.exceptions.IkeProtocolException; import android.os.Build.VERSION_CODES; @@ -870,17 +875,28 @@ public class VpnTest { eq(AppOpsManager.MODE_IGNORED)); } - private NetworkCallback triggerOnAvailableAndGetCallback() { + private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception { final ArgumentCaptor<NetworkCallback> networkCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class); verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) .requestNetwork(any(), networkCallbackCaptor.capture()); + // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be + // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException. + final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); + config.flags = new String[] {IF_STATE_DOWN}; + when(mNetd.interfaceGetCfg(anyString())).thenReturn(config); final NetworkCallback cb = networkCallbackCaptor.getValue(); cb.onAvailable(TEST_NETWORK); return cb; } + private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception { + // Add a timeout for waiting for interfaceSetCfg to be called. + verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat( + config -> Arrays.asList(config.flags).contains(flag))); + } + @Test public void testStartPlatformVpnAuthenticationFailed() throws Exception { final ArgumentCaptor<IkeSessionCallback> captor = @@ -892,6 +908,8 @@ public class VpnTest { final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile)); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); + verifyInterfaceSetCfgWithFlags(IF_STATE_UP); + // Wait for createIkeSession() to be called before proceeding in order to ensure consistent // state verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) @@ -910,6 +928,8 @@ public class VpnTest { final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); + verifyInterfaceSetCfgWithFlags(IF_STATE_UP); + // Wait for createIkeSession() to be called before proceeding in order to ensure consistent // state verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); @@ -984,6 +1004,13 @@ public class VpnTest { startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve } + private void assertTransportInfoMatches(NetworkCapabilities nc, int type) { + assertNotNull(nc); + VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo(); + assertNotNull(ti); + assertEquals(type, ti.type); + } + public void startRacoon(final String serverAddr, final String expectedAddr) throws Exception { final ConditionVariable legacyRunnerReady = new ConditionVariable(); @@ -1020,8 +1047,10 @@ public class VpnTest { // Now wait for the runner to be ready before testing for the route. ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); + ArgumentCaptor<NetworkCapabilities> ncCaptor = + ArgumentCaptor.forClass(NetworkCapabilities.class); verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), - lpCaptor.capture(), any(), anyInt(), any(), anyInt()); + lpCaptor.capture(), ncCaptor.capture(), anyInt(), any(), anyInt()); // In this test the expected address is always v4 so /32. // Note that the interface needs to be specified because RouteInfo objects stored in @@ -1031,6 +1060,8 @@ public class VpnTest { final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes(); assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes, actualRoutes.contains(expectedRoute)); + + assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY); } finally { // Now interrupt the thread, unblock the runner and clean up. vpn.mVpnRunner.exitVpnRunner(); diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 214c82da17dc..d644739ea25e 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -1461,7 +1461,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); capabilities.setSSID(TEST_SSID); - return new NetworkState(TYPE_WIFI, prop, capabilities, WIFI_NETWORK, null, TEST_SSID); + return new NetworkState(TYPE_WIFI, prop, capabilities, WIFI_NETWORK, null); } private static NetworkState buildMobile3gState(String subscriberId) { @@ -1475,8 +1475,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - return new NetworkState( - TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId, null); + return new NetworkState(TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId); } private NetworkStats buildEmptyStats() { @@ -1486,7 +1485,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private static NetworkState buildVpnState() { final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TUN_IFACE); - return new NetworkState(TYPE_VPN, prop, new NetworkCapabilities(), VPN_NETWORK, null, null); + return new NetworkState(TYPE_VPN, prop, new NetworkCapabilities(), VPN_NETWORK, null); } private long getElapsedRealtime() { diff --git a/tests/net/jni/Android.bp b/tests/net/jni/Android.bp index 9225ffb24bd8..22a04f5c0945 100644 --- a/tests/net/jni/Android.bp +++ b/tests/net/jni/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libnetworkstatsfactorytestjni", diff --git a/tests/net/smoketest/Android.bp b/tests/net/smoketest/Android.bp index 84ae2b5d845e..1535f3ddcb38 100644 --- a/tests/net/smoketest/Android.bp +++ b/tests/net/smoketest/Android.bp @@ -9,6 +9,15 @@ // // TODO: remove this hack when there is a better solution for jni_libs that includes // dependent libraries. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksNetSmokeTests", defaults: ["FrameworksNetTests-jni-defaults"], @@ -19,4 +28,4 @@ android_test { "mockito-target-minus-junit4", "services.core", ], -}
\ No newline at end of file +} diff --git a/tests/notification/Android.bp b/tests/notification/Android.bp index f05edafbf8b7..1c1b5a231e86 100644 --- a/tests/notification/Android.bp +++ b/tests/notification/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "NotificationTests", // Include all test java files. diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp index bd07009de7b3..bbc2358d206e 100644 --- a/tests/permission/Android.bp +++ b/tests/permission/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworkPermissionTests", // Include all test java files. diff --git a/tests/privapp-permissions/Android.bp b/tests/privapp-permissions/Android.bp index b6618508d95d..082b08dea91f 100644 --- a/tests/privapp-permissions/Android.bp +++ b/tests/privapp-permissions/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_app { name: "PrivAppPermissionTest", sdk_version: "current", diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp index eb6811cf490e..c0e3d630d1ab 100644 --- a/tests/testables/Android.bp +++ b/tests/testables/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "testables", srcs: ["src/**/*.java"], diff --git a/tests/testables/tests/Android.bp b/tests/testables/tests/Android.bp index e1a58be7bd68..ba323d3fe47a 100644 --- a/tests/testables/tests/Android.bp +++ b/tests/testables/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "TestablesTests", platform_apis: true, diff --git a/tests/utils/StubIME/Android.bp b/tests/utils/StubIME/Android.bp index 668c92c86c51..d86068cef8b4 100644 --- a/tests/utils/StubIME/Android.bp +++ b/tests/utils/StubIME/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "StubIME", srcs: ["src/**/*.java"], diff --git a/tests/utils/hostutils/Android.bp b/tests/utils/hostutils/Android.bp index c9ad70280aa6..05f3c74218c6 100644 --- a/tests/utils/hostutils/Android.bp +++ b/tests/utils/hostutils/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_host { name: "frameworks-base-hostutils", diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp index a6625ab9c17f..af9786b92f40 100644 --- a/tests/utils/testutils/Android.bp +++ b/tests/utils/testutils/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library { name: "frameworks-base-testutils", diff --git a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java index 1102624da031..4a1f96d145bd 100644 --- a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java +++ b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java @@ -42,6 +42,8 @@ public class BroadcastInterceptingContext extends ContextWrapper { private final List<BroadcastInterceptor> mInterceptors = new ArrayList<>(); + private boolean mUseRegisteredHandlers; + public abstract class FutureIntent extends FutureTask<Intent> { public FutureIntent() { super( @@ -61,17 +63,24 @@ public class BroadcastInterceptingContext extends ContextWrapper { public class BroadcastInterceptor extends FutureIntent { private final BroadcastReceiver mReceiver; private final IntentFilter mFilter; + private final Handler mHandler; - public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) { + public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter, + Handler handler) { mReceiver = receiver; mFilter = filter; + mHandler = mUseRegisteredHandlers ? handler : null; } public boolean dispatchBroadcast(Intent intent) { if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { if (mReceiver != null) { final Context context = BroadcastInterceptingContext.this; - mReceiver.onReceive(context, intent); + if (mHandler == null) { + mReceiver.onReceive(context, intent); + } else { + mHandler.post(() -> mReceiver.onReceive(context, intent)); + } return false; } else { set(intent); @@ -116,25 +125,38 @@ public class BroadcastInterceptingContext extends ContextWrapper { } public FutureIntent nextBroadcastIntent(IntentFilter filter) { - final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter); + final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter, null); synchronized (mInterceptors) { mInterceptors.add(interceptor); } return interceptor; } - @Override - public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + /** + * Whether to send broadcasts to registered handlers. By default, receivers are called + * synchronously by sendBroadcast. If this method is called with {@code true}, the receiver is + * instead called by a runnable posted to the Handler specified when the receiver was + * registered. This method applies only to future registrations, already-registered receivers + * are unaffected. + */ + public void setUseRegisteredHandlers(boolean use) { synchronized (mInterceptors) { - mInterceptors.add(new BroadcastInterceptor(receiver, filter)); + mUseRegisteredHandlers = use; } - return null; + } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + return registerReceiver(receiver, filter, null, null); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { - return registerReceiver(receiver, filter); + synchronized (mInterceptors) { + mInterceptors.add(new BroadcastInterceptor(receiver, filter, scheduler)); + } + return null; } @Override diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp index c04ddd78e69b..41f73cd9c706 100644 --- a/tests/vcn/Android.bp +++ b/tests/vcn/Android.bp @@ -2,6 +2,15 @@ // Build FrameworksVcnTests package //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksVcnTests", srcs: [ @@ -21,7 +30,6 @@ android_test { "services.core", ], libs: [ - "android.net.ipsec.ike.stubs.module_lib", "android.test.runner", "android.test.base", "android.test.mock", diff --git a/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java b/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java new file mode 100644 index 000000000000..36f5e41462e8 --- /dev/null +++ b/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP; +import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12; +import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.ipsec.ike.ChildSaProposal; +import android.net.ipsec.ike.IkeFqdnIdentification; +import android.net.ipsec.ike.IkeSaProposal; +import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.SaProposal; +import android.net.ipsec.ike.TunnelModeChildSessionParams; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class VcnControlPlaneIkeConfigTest { + private static final IkeSessionParams IKE_PARAMS; + private static final TunnelModeChildSessionParams CHILD_PARAMS; + + static { + IkeSaProposal ikeProposal = + new IkeSaProposal.Builder() + .addEncryptionAlgorithm( + ENCRYPTION_ALGORITHM_AES_GCM_12, SaProposal.KEY_LEN_AES_128) + .addDhGroup(DH_GROUP_2048_BIT_MODP) + .addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC) + .build(); + + Context mockContext = mock(Context.class); + ConnectivityManager mockConnectManager = mock(ConnectivityManager.class); + doReturn(mockConnectManager) + .when(mockContext) + .getSystemService(Context.CONNECTIVITY_SERVICE); + doReturn(mock(Network.class)).when(mockConnectManager).getActiveNetwork(); + + final String serverHostname = "192.0.2.100"; + final String testLocalId = "test.client.com"; + final String testRemoteId = "test.server.com"; + final byte[] psk = "psk".getBytes(); + + IKE_PARAMS = + new IkeSessionParams.Builder(mockContext) + .setServerHostname(serverHostname) + .addSaProposal(ikeProposal) + .setLocalIdentification(new IkeFqdnIdentification(testLocalId)) + .setRemoteIdentification(new IkeFqdnIdentification(testRemoteId)) + .setAuthPsk(psk) + .build(); + + ChildSaProposal childProposal = + new ChildSaProposal.Builder() + .addEncryptionAlgorithm( + ENCRYPTION_ALGORITHM_AES_GCM_12, SaProposal.KEY_LEN_AES_128) + .build(); + CHILD_PARAMS = + new TunnelModeChildSessionParams.Builder().addSaProposal(childProposal).build(); + } + + // Package private for use in VcnGatewayConnectionConfigTest + static VcnControlPlaneIkeConfig buildTestConfig() { + return new VcnControlPlaneIkeConfig(IKE_PARAMS, CHILD_PARAMS); + } + + @Test + public void testGetters() { + final VcnControlPlaneIkeConfig config = buildTestConfig(); + assertEquals(IKE_PARAMS, config.getIkeSessionParams()); + assertEquals(CHILD_PARAMS, config.getChildSessionParams()); + } + + @Test + public void testConstructConfigWithoutIkeParams() { + try { + new VcnControlPlaneIkeConfig(null, CHILD_PARAMS); + fail("Expect to fail because ikeParams was null"); + } catch (NullPointerException expected) { + } + } + + @Test + public void testBuilderConfigWithoutChildParams() { + try { + new VcnControlPlaneIkeConfig(IKE_PARAMS, null); + fail("Expect to fail because childParams was null"); + } catch (NullPointerException expected) { + } + } +} diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index 3e659d0bc128..5b17aadc50a6 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -18,6 +18,7 @@ package android.net.vcn; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; import android.net.NetworkCapabilities; @@ -57,17 +58,22 @@ public class VcnGatewayConnectionConfigTest { }; public static final int MAX_MTU = 1360; + public static final VcnControlPlaneConfig CONTROL_PLANE_CONFIG = + VcnControlPlaneIkeConfigTest.buildTestConfig(); + // Public for use in VcnGatewayConnectionTest public static VcnGatewayConnectionConfig buildTestConfig() { return buildTestConfigWithExposedCaps(EXPOSED_CAPS); } + private static VcnGatewayConnectionConfig.Builder newBuilder() { + return new VcnGatewayConnectionConfig.Builder(CONTROL_PLANE_CONFIG); + } + // Public for use in VcnGatewayConnectionTest public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) { final VcnGatewayConnectionConfig.Builder builder = - new VcnGatewayConnectionConfig.Builder() - .setRetryInterval(RETRY_INTERVALS_MS) - .setMaxMtu(MAX_MTU); + newBuilder().setRetryInterval(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU); for (int caps : exposedCaps) { builder.addExposedCapability(caps); @@ -81,9 +87,19 @@ public class VcnGatewayConnectionConfigTest { } @Test + public void testBuilderRequiresNonNullControlPlaneConfig() { + try { + new VcnGatewayConnectionConfig.Builder(null).build(); + + fail("Expected exception due to invalid control plane config"); + } catch (NullPointerException e) { + } + } + + @Test public void testBuilderRequiresNonEmptyExposedCaps() { try { - new VcnGatewayConnectionConfig.Builder() + newBuilder() .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build(); @@ -95,9 +111,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonEmptyUnderlyingCaps() { try { - new VcnGatewayConnectionConfig.Builder() - .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); + newBuilder().addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); fail("Expected exception due to invalid required underlying capabilities"); } catch (IllegalArgumentException e) { @@ -107,7 +121,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonNullRetryInterval() { try { - new VcnGatewayConnectionConfig.Builder().setRetryInterval(null); + newBuilder().setRetryInterval(null); fail("Expected exception due to invalid retryIntervalMs"); } catch (IllegalArgumentException e) { } @@ -116,7 +130,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonEmptyRetryInterval() { try { - new VcnGatewayConnectionConfig.Builder().setRetryInterval(new long[0]); + newBuilder().setRetryInterval(new long[0]); fail("Expected exception due to invalid retryIntervalMs"); } catch (IllegalArgumentException e) { } @@ -125,8 +139,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresValidMtu() { try { - new VcnGatewayConnectionConfig.Builder() - .setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1); + newBuilder().setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1); fail("Expected exception due to invalid mtu"); } catch (IllegalArgumentException e) { } @@ -144,6 +157,9 @@ public class VcnGatewayConnectionConfigTest { Arrays.sort(underlyingCaps); assertArrayEquals(UNDERLYING_CAPS, underlyingCaps); + assertEquals(CONTROL_PLANE_CONFIG, config.getControlPlaneConfig()); + assertFalse(CONTROL_PLANE_CONFIG == config.getControlPlaneConfig()); + assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMs()); assertEquals(MAX_MTU, config.getMaxMtu()); } diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java index f9db408462b7..ce8a898de2ed 100644 --- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java +++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java @@ -22,28 +22,40 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.content.Context; import android.net.LinkProperties; import android.net.NetworkCapabilities; +import android.net.vcn.VcnManager.VcnStatusCallback; +import android.net.vcn.VcnManager.VcnStatusCallbackBinder; import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener; +import android.os.ParcelUuid; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import java.net.UnknownHostException; +import java.util.UUID; import java.util.concurrent.Executor; public class VcnManagerTest { + private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0)); + private static final int[] UNDERLYING_NETWORK_CAPABILITIES = { + NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_INTERNET + }; private static final Executor INLINE_EXECUTOR = Runnable::run; private IVcnManagementService mMockVcnManagementService; private VcnUnderlyingNetworkPolicyListener mMockPolicyListener; + private VcnStatusCallback mMockStatusCallback; private Context mContext; private VcnManager mVcnManager; @@ -52,6 +64,7 @@ public class VcnManagerTest { public void setUp() { mMockVcnManagementService = mock(IVcnManagementService.class); mMockPolicyListener = mock(VcnUnderlyingNetworkPolicyListener.class); + mMockStatusCallback = mock(VcnStatusCallback.class); mContext = getContext(); mVcnManager = new VcnManager(mContext, mMockVcnManagementService); @@ -65,7 +78,7 @@ public class VcnManagerTest { ArgumentCaptor.forClass(IVcnUnderlyingNetworkPolicyListener.class); verify(mMockVcnManagementService).addVcnUnderlyingNetworkPolicyListener(captor.capture()); - assertTrue(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener)); + assertTrue(VcnManager.getAllPolicyListeners().containsKey(mMockPolicyListener)); IVcnUnderlyingNetworkPolicyListener listenerWrapper = captor.getValue(); listenerWrapper.onPolicyChanged(); @@ -78,7 +91,7 @@ public class VcnManagerTest { mVcnManager.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); - assertFalse(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener)); + assertFalse(VcnManager.getAllPolicyListeners().containsKey(mMockPolicyListener)); verify(mMockVcnManagementService) .addVcnUnderlyingNetworkPolicyListener( any(IVcnUnderlyingNetworkPolicyListener.class)); @@ -88,7 +101,7 @@ public class VcnManagerTest { public void testRemoveVcnUnderlyingNetworkPolicyListenerUnknownListener() throws Exception { mVcnManager.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); - assertFalse(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener)); + assertFalse(VcnManager.getAllPolicyListeners().containsKey(mMockPolicyListener)); verify(mMockVcnManagementService, never()) .addVcnUnderlyingNetworkPolicyListener( any(IVcnUnderlyingNetworkPolicyListener.class)); @@ -132,4 +145,74 @@ public class VcnManagerTest { public void testGetUnderlyingNetworkPolicyNullLinkProperties() throws Exception { mVcnManager.getUnderlyingNetworkPolicy(new NetworkCapabilities(), null); } + + @Test + public void testRegisterVcnStatusCallback() throws Exception { + mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback); + + verify(mMockVcnManagementService) + .registerVcnStatusCallback(eq(SUB_GROUP), notNull(), any()); + } + + @Test(expected = IllegalStateException.class) + public void testRegisterVcnStatusCallbackAlreadyRegistered() throws Exception { + mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback); + mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback); + } + + @Test(expected = NullPointerException.class) + public void testRegisterVcnStatusCallbackNullSubscriptionGroup() throws Exception { + mVcnManager.registerVcnStatusCallback(null, INLINE_EXECUTOR, mMockStatusCallback); + } + + @Test(expected = NullPointerException.class) + public void testRegisterVcnStatusCallbackNullExecutor() throws Exception { + mVcnManager.registerVcnStatusCallback(SUB_GROUP, null, mMockStatusCallback); + } + + @Test(expected = NullPointerException.class) + public void testRegisterVcnStatusCallbackNullCallback() throws Exception { + mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, null); + } + + @Test + public void testUnregisterVcnStatusCallback() throws Exception { + mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback); + + mVcnManager.unregisterVcnStatusCallback(mMockStatusCallback); + + verify(mMockVcnManagementService).unregisterVcnStatusCallback(any()); + } + + @Test + public void testUnregisterUnknownVcnStatusCallback() throws Exception { + mVcnManager.unregisterVcnStatusCallback(mMockStatusCallback); + + verifyNoMoreInteractions(mMockVcnManagementService); + } + + @Test(expected = NullPointerException.class) + public void testUnregisterNullVcnStatusCallback() throws Exception { + mVcnManager.unregisterVcnStatusCallback(null); + } + + @Test + public void testVcnStatusCallbackBinder() throws Exception { + IVcnStatusCallback cbBinder = + new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback); + + cbBinder.onEnteredSafeMode(); + verify(mMockStatusCallback).onEnteredSafeMode(); + + cbBinder.onGatewayConnectionError( + UNDERLYING_NETWORK_CAPABILITIES, + VcnManager.VCN_ERROR_CODE_NETWORK_ERROR, + UnknownHostException.class.getName(), + "exception_message"); + verify(mMockStatusCallback) + .onGatewayConnectionError( + eq(UNDERLYING_NETWORK_CAPABILITIES), + eq(VcnManager.VCN_ERROR_CODE_NETWORK_ERROR), + any(UnknownHostException.class)); + } } diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java index 3ba0a1f53a9f..a674425efea3 100644 --- a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java +++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java @@ -46,6 +46,6 @@ public class VcnUnderlyingNetworkPolicyTest { @Test public void testParcelUnparcel() { - assertParcelSane(SAMPLE_NETWORK_POLICY, 2); + assertParcelSane(SAMPLE_NETWORK_POLICY, 1); } } diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java new file mode 100644 index 000000000000..2110d6ee7c86 --- /dev/null +++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkSpecifierTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import static com.android.testutils.ParcelUtils.assertParcelSane; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.net.TelephonyNetworkSpecifier; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class VcnUnderlyingNetworkSpecifierTest { + private static final int[] TEST_SUB_IDS = new int[] {1, 2, 3, 5}; + + @Test + public void testGetSubIds() { + final VcnUnderlyingNetworkSpecifier specifier = + new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS); + + assertEquals(TEST_SUB_IDS, specifier.getSubIds()); + } + + @Test + public void testParceling() { + final VcnUnderlyingNetworkSpecifier specifier = + new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS); + assertParcelSane(specifier, 1); + } + + @Test + public void testCanBeSatisfiedByTelephonyNetworkSpecifier() { + final TelephonyNetworkSpecifier telSpecifier = + new TelephonyNetworkSpecifier(TEST_SUB_IDS[0]); + + final VcnUnderlyingNetworkSpecifier specifier = + new VcnUnderlyingNetworkSpecifier(TEST_SUB_IDS); + assertTrue(specifier.canBeSatisfiedBy(telSpecifier)); + } +} diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 485964487fda..45b2381ce06d 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -16,12 +16,17 @@ package com.android.server; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; + import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; import static com.android.server.vcn.VcnTestUtils.setupSystemService; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -38,9 +43,11 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; import android.net.ConnectivityManager; @@ -48,6 +55,7 @@ import android.net.LinkProperties; import android.net.NetworkCapabilities; import android.net.NetworkCapabilities.Transport; import android.net.TelephonyNetworkSpecifier; +import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; import android.net.vcn.VcnConfigTest; @@ -66,7 +74,9 @@ import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.server.VcnManagementService.VcnSafemodeCallback; +import com.android.internal.util.LocationPermissionChecker; +import com.android.server.VcnManagementService.VcnCallback; +import com.android.server.VcnManagementService.VcnStatusCallbackInfo; import com.android.server.vcn.TelephonySubscriptionTracker; import com.android.server.vcn.Vcn; import com.android.server.vcn.VcnContext; @@ -106,6 +116,7 @@ public class VcnManagementServiceTest { Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG)); private static final int TEST_SUBSCRIPTION_ID = 1; + private static final int TEST_SUBSCRIPTION_ID_2 = 2; private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO = new SubscriptionInfo( TEST_SUBSCRIPTION_ID /* id */, @@ -142,14 +153,17 @@ public class VcnManagementServiceTest { mock(PersistableBundleUtils.LockingReadWriteHelper.class); private final TelephonySubscriptionTracker mSubscriptionTracker = mock(TelephonySubscriptionTracker.class); + private final LocationPermissionChecker mLocationPermissionChecker = + mock(LocationPermissionChecker.class); - private final ArgumentCaptor<VcnSafemodeCallback> mSafemodeCallbackCaptor = - ArgumentCaptor.forClass(VcnSafemodeCallback.class); + private final ArgumentCaptor<VcnCallback> mVcnCallbackCaptor = + ArgumentCaptor.forClass(VcnCallback.class); private final VcnManagementService mVcnMgmtSvc; private final IVcnUnderlyingNetworkPolicyListener mMockPolicyListener = mock(IVcnUnderlyingNetworkPolicyListener.class); + private final IVcnStatusCallback mMockStatusCallback = mock(IVcnStatusCallback.class); private final IBinder mMockIBinder = mock(IBinder.class); public VcnManagementServiceTest() throws Exception { @@ -166,6 +180,7 @@ public class VcnManagementServiceTest { doReturn(TEST_PACKAGE_NAME).when(mMockContext).getOpPackageName(); + doReturn(mMockContext).when(mVcnContext).getContext(); doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper(); doReturn(TEST_UID).when(mMockDeps).getBinderCallingUid(); doReturn(mVcnContext) @@ -183,6 +198,9 @@ public class VcnManagementServiceTest { doReturn(mConfigReadWriteHelper) .when(mMockDeps) .newPersistableBundleLockingReadWriteHelper(any()); + doReturn(mLocationPermissionChecker) + .when(mMockDeps) + .newLocationPermissionChecker(eq(mMockContext)); // Setup VCN instance generation doAnswer((invocation) -> { @@ -201,6 +219,7 @@ public class VcnManagementServiceTest { mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps); doReturn(mMockIBinder).when(mMockPolicyListener).asBinder(); + doReturn(mMockIBinder).when(mMockStatusCallback).asBinder(); // Make sure the profiles are loaded. mTestLooper.dispatchAll(); @@ -537,59 +556,121 @@ public class VcnManagementServiceTest { Collections.singleton(subGroup), Collections.singletonMap(subId, subGroup)); } - private void verifyMergedNetworkCapabilitiesIsVcnManaged( - NetworkCapabilities mergedCapabilities, @Transport int transportType) { + private void verifyMergedNetworkCapabilities( + NetworkCapabilities mergedCapabilities, + @Transport int transportType, + boolean isVcnManaged, + boolean isRestricted) { assertTrue(mergedCapabilities.hasTransport(transportType)); - assertFalse( + assertEquals( + !isVcnManaged, mergedCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)); + assertEquals( + !isRestricted, + mergedCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)); + } + + private void setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive) { + setUpVcnSubscription(subId, subGrp); + final Vcn vcn = startAndGetVcnInstance(subGrp); + doReturn(isVcnActive).when(vcn).isActive(); + } + + private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( + int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { + setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); + + final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder(); + ncBuilder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); + if (transport == TRANSPORT_CELLULAR) { + ncBuilder + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID)); + } else if (transport == TRANSPORT_WIFI) { + WifiInfo wifiInfo = mock(WifiInfo.class); + when(wifiInfo.makeCopy(anyBoolean())).thenReturn(wifiInfo); + when(mMockDeps.getSubIdForWifiInfo(eq(wifiInfo))).thenReturn(TEST_SUBSCRIPTION_ID); + + ncBuilder + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setTransportInfo(wifiInfo); + } else { + throw new IllegalArgumentException("Unknown transport"); + } + + return mVcnMgmtSvc.getUnderlyingNetworkPolicy(ncBuilder.build(), new LinkProperties()); } @Test public void testGetUnderlyingNetworkPolicyCellular() throws Exception { - setUpVcnSubscription(TEST_SUBSCRIPTION_ID, TEST_UUID_2); + final VcnUnderlyingNetworkPolicy policy = + startVcnAndGetPolicyForTransport( + TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_CELLULAR); - NetworkCapabilities nc = - new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID)) - .build(); + assertFalse(policy.isTeardownRequested()); + verifyMergedNetworkCapabilities( + policy.getMergedNetworkCapabilities(), + TRANSPORT_CELLULAR, + true /* isVcnManaged */, + false /* isRestricted */); + } - VcnUnderlyingNetworkPolicy policy = - mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties()); + @Test + public void testGetUnderlyingNetworkPolicyCellular_safeMode() throws Exception { + final VcnUnderlyingNetworkPolicy policy = + startVcnAndGetPolicyForTransport( + TEST_SUBSCRIPTION_ID, + TEST_UUID_2, + false /* isActive */, + TRANSPORT_CELLULAR); assertFalse(policy.isTeardownRequested()); - verifyMergedNetworkCapabilitiesIsVcnManaged( - policy.getMergedNetworkCapabilities(), NetworkCapabilities.TRANSPORT_CELLULAR); + verifyMergedNetworkCapabilities( + policy.getMergedNetworkCapabilities(), + NetworkCapabilities.TRANSPORT_CELLULAR, + false /* isVcnManaged */, + false /* isRestricted */); } @Test public void testGetUnderlyingNetworkPolicyWifi() throws Exception { - setUpVcnSubscription(TEST_SUBSCRIPTION_ID, TEST_UUID_2); + final VcnUnderlyingNetworkPolicy policy = + startVcnAndGetPolicyForTransport( + TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_WIFI); - WifiInfo wifiInfo = mock(WifiInfo.class); - when(wifiInfo.makeCopy(anyBoolean())).thenReturn(wifiInfo); - when(mMockDeps.getSubIdForWifiInfo(eq(wifiInfo))).thenReturn(TEST_SUBSCRIPTION_ID); - NetworkCapabilities nc = - new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .setTransportInfo(wifiInfo) - .build(); + assertFalse(policy.isTeardownRequested()); + verifyMergedNetworkCapabilities( + policy.getMergedNetworkCapabilities(), + NetworkCapabilities.TRANSPORT_WIFI, + true /* isVcnManaged */, + true /* isRestricted */); + } - VcnUnderlyingNetworkPolicy policy = - mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties()); + @Test + public void testGetUnderlyingNetworkPolicyVcnWifi_safeMode() throws Exception { + final VcnUnderlyingNetworkPolicy policy = + startVcnAndGetPolicyForTransport( + TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI); assertFalse(policy.isTeardownRequested()); - verifyMergedNetworkCapabilitiesIsVcnManaged( - policy.getMergedNetworkCapabilities(), NetworkCapabilities.TRANSPORT_WIFI); + verifyMergedNetworkCapabilities( + policy.getMergedNetworkCapabilities(), + NetworkCapabilities.TRANSPORT_WIFI, + false /* isVcnManaged */, + true /* isRestricted */); } @Test public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception { + setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */); + NetworkCapabilities nc = new NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID)) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) + .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID_2)) .build(); VcnUnderlyingNetworkPolicy policy = @@ -640,24 +721,138 @@ public class VcnManagementServiceTest { verify(mMockPolicyListener).onPolicyChanged(); } - @Test - public void testVcnSafemodeCallbackOnEnteredSafemode() throws Exception { - TelephonySubscriptionSnapshot snapshot = - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + private void verifyVcnCallback( + @NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot) + throws Exception { verify(mMockDeps) .newVcn( eq(mVcnContext), - eq(TEST_UUID_1), + eq(subGroup), eq(TEST_VCN_CONFIG), eq(snapshot), - mSafemodeCallbackCaptor.capture()); + mVcnCallbackCaptor.capture()); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); - VcnSafemodeCallback safemodeCallback = mSafemodeCallbackCaptor.getValue(); - safemodeCallback.onEnteredSafemode(); + VcnCallback vcnCallback = mVcnCallbackCaptor.getValue(); + vcnCallback.onEnteredSafeMode(); - assertFalse(mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1).isActive()); verify(mMockPolicyListener).onPolicyChanged(); } + + @Test + public void testVcnCallbackOnEnteredSafeMode() throws Exception { + TelephonySubscriptionSnapshot snapshot = + triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + + verifyVcnCallback(TEST_UUID_1, snapshot); + } + + private void triggerVcnStatusCallbackOnEnteredSafeMode( + @NonNull ParcelUuid subGroup, + @NonNull String pkgName, + int uid, + boolean hasPermissionsforSubGroup, + boolean hasLocationPermission) + throws Exception { + TelephonySubscriptionSnapshot snapshot = + triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup)); + + doReturn(hasPermissionsforSubGroup) + .when(snapshot) + .packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName)); + + doReturn(hasLocationPermission) + .when(mLocationPermissionChecker) + .checkLocationPermission(eq(pkgName), any(), eq(uid), any()); + + mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName); + + // Trigger systemReady() to set up LocationPermissionChecker + mVcnMgmtSvc.systemReady(); + + verifyVcnCallback(subGroup, snapshot); + } + + @Test + public void testVcnStatusCallbackOnEnteredSafeModeWithCarrierPrivileges() throws Exception { + triggerVcnStatusCallbackOnEnteredSafeMode( + TEST_UUID_1, + TEST_PACKAGE_NAME, + TEST_UID, + true /* hasPermissionsforSubGroup */, + true /* hasLocationPermission */); + + verify(mMockStatusCallback, times(1)).onEnteredSafeMode(); + } + + @Test + public void testVcnStatusCallbackOnEnteredSafeModeWithoutCarrierPrivileges() throws Exception { + triggerVcnStatusCallbackOnEnteredSafeMode( + TEST_UUID_1, + TEST_PACKAGE_NAME, + TEST_UID, + false /* hasPermissionsforSubGroup */, + true /* hasLocationPermission */); + + verify(mMockStatusCallback, never()).onEnteredSafeMode(); + } + + @Test + public void testVcnStatusCallbackOnEnteredSafeModeWithoutLocationPermission() throws Exception { + triggerVcnStatusCallbackOnEnteredSafeMode( + TEST_UUID_1, + TEST_PACKAGE_NAME, + TEST_UID, + true /* hasPermissionsforSubGroup */, + false /* hasLocationPermission */); + + verify(mMockStatusCallback, never()).onEnteredSafeMode(); + } + + @Test + public void testRegisterVcnStatusCallback() throws Exception { + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + + Map<IBinder, VcnStatusCallbackInfo> callbacks = mVcnMgmtSvc.getAllStatusCallbacks(); + VcnStatusCallbackInfo cbInfo = callbacks.get(mMockIBinder); + + assertNotNull(cbInfo); + assertEquals(TEST_UUID_1, cbInfo.mSubGroup); + assertEquals(mMockStatusCallback, cbInfo.mCallback); + assertEquals(TEST_PACKAGE_NAME, cbInfo.mPkgName); + assertEquals(TEST_UID, cbInfo.mUid); + verify(mMockIBinder).linkToDeath(eq(cbInfo), anyInt()); + } + + @Test(expected = IllegalStateException.class) + public void testRegisterVcnStatusCallbackDuplicate() { + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + } + + @Test + public void testUnregisterVcnStatusCallback() { + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + Map<IBinder, VcnStatusCallbackInfo> callbacks = mVcnMgmtSvc.getAllStatusCallbacks(); + VcnStatusCallbackInfo cbInfo = callbacks.get(mMockIBinder); + + mVcnMgmtSvc.unregisterVcnStatusCallback(mMockStatusCallback); + assertTrue(mVcnMgmtSvc.getAllStatusCallbacks().isEmpty()); + verify(mMockIBinder).unlinkToDeath(eq(cbInfo), anyInt()); + } + + @Test(expected = SecurityException.class) + public void testRegisterVcnStatusCallbackInvalidPackage() { + doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, TEST_PACKAGE_NAME); + + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + } + + @Test + public void testUnregisterVcnStatusCallbackNeverRegistered() { + mVcnMgmtSvc.unregisterVcnStatusCallback(mMockStatusCallback); + + assertTrue(mVcnMgmtSvc.getAllStatusCallbacks().isEmpty()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 278d93a1b17b..69c21b967917 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -20,6 +20,9 @@ import static android.net.IpSecManager.DIRECTION_IN; import static android.net.IpSecManager.DIRECTION_OUT; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR; +import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR; import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; @@ -34,9 +37,16 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import android.net.LinkProperties; +import android.net.NetworkAgent; import android.net.NetworkCapabilities; +import android.net.ipsec.ike.exceptions.AuthenticationFailedException; +import android.net.ipsec.ike.exceptions.IkeException; +import android.net.ipsec.ike.exceptions.IkeInternalException; +import android.net.ipsec.ike.exceptions.TemporaryFailureException; +import android.net.vcn.VcnManager.VcnErrorCode; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -46,6 +56,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import java.io.IOException; +import java.net.UnknownHostException; import java.util.Collections; /** Tests for VcnGatewayConnection.ConnectedState */ @@ -73,6 +85,11 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection } @Test + public void testEnterStateDoesNotCancelSafeModeAlarm() { + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); + } + + @Test public void testNullNetworkDoesNotTriggerDisconnect() throws Exception { mGatewayConnection .getUnderlyingNetworkTrackerCallback() @@ -81,6 +98,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); verify(mIkeSession, never()).close(); + verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -120,7 +138,24 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection } @Test + public void testMigratedTransformsAreApplied() throws Exception { + getChildSessionCallback() + .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); + mTestLooper.dispatchAll(); + + for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) { + verify(mIpSecSvc) + .applyTunnelModeTransform( + eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any()); + } + assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); + } + + @Test public void testChildOpenedRegistersNetwork() throws Exception { + // Verify scheduled but not canceled when entering ConnectedState + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); + final VcnChildSessionConfiguration mMockChildSessionConfig = mock(VcnChildSessionConfiguration.class); doReturn(Collections.singletonList(TEST_INTERNAL_ADDR)) @@ -162,22 +197,97 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection for (int cap : mConfig.getAllExposedCapabilities()) { assertTrue(nc.hasCapability(cap)); } + + // Now that Vcn Network is up, notify it as validated and verify the SafeMode alarm is + // canceled + mGatewayConnection.mNetworkAgent.onValidationStatus( + NetworkAgent.VALIDATION_STATUS_VALID, null /* redirectUri */); + verify(mSafeModeTimeoutAlarm).cancel(); } @Test public void testChildSessionClosedTriggersDisconnect() throws Exception { + // Verify scheduled but not canceled when entering ConnectedState + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); + getChildSessionCallback().onClosed(); mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); + + // Since network never validated, verify mSafeModeTimeoutAlarm not canceled + verifyNoMoreInteractions(mSafeModeTimeoutAlarm); + + // The child session was closed without exception, so verify that the GatewayStatusCallback + // was not notified + verifyNoMoreInteractions(mGatewayStatusCallback); + } + + @Test + public void testChildSessionClosedExceptionallyNotifiesGatewayStatusCallback() + throws Exception { + final IkeInternalException exception = new IkeInternalException(mock(IOException.class)); + getChildSessionCallback().onClosedExceptionally(exception); + mTestLooper.dispatchAll(); + + verify(mGatewayStatusCallback) + .onGatewayConnectionError( + eq(mConfig.getRequiredUnderlyingCapabilities()), + eq(VCN_ERROR_CODE_INTERNAL_ERROR), + any(), + any()); } @Test public void testIkeSessionClosedTriggersDisconnect() throws Exception { + // Verify scheduled but not canceled when entering ConnectedState + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); + getIkeSessionCallback().onClosed(); mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState()); verify(mIkeSession).close(); + + // Since network never validated, verify mSafeModeTimeoutAlarm not canceled + verifyNoMoreInteractions(mSafeModeTimeoutAlarm); + + // IkeSession closed with no error, so verify that the GatewayStatusCallback was not + // notified + verifyNoMoreInteractions(mGatewayStatusCallback); + } + + private void verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( + IkeException cause, @VcnErrorCode int expectedErrorType) { + getIkeSessionCallback().onClosedExceptionally(cause); + mTestLooper.dispatchAll(); + + verify(mIkeSession).close(); + + verify(mGatewayStatusCallback) + .onGatewayConnectionError( + eq(mConfig.getRequiredUnderlyingCapabilities()), + eq(expectedErrorType), + any(), + any()); + } + + @Test + public void testIkeSessionClosedExceptionallyAuthenticationFailure() throws Exception { + verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( + new AuthenticationFailedException("vcn test"), VCN_ERROR_CODE_CONFIG_ERROR); + } + + @Test + public void testIkeSessionClosedExceptionallyDnsFailure() throws Exception { + verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( + new IkeInternalException(new UnknownHostException()), VCN_ERROR_CODE_NETWORK_ERROR); + } + + @Test + public void testIkeSessionClosedExceptionallyInternalFailure() throws Exception { + verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( + new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index d936183e5a0b..17ae19e086cf 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -61,6 +61,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); verify(mIkeSession).kill(); + verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -73,6 +74,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); verify(mIkeSession).close(); verify(mIkeSession, never()).kill(); + verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -92,6 +94,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); verify(mIkeSession).close(); + verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -101,5 +104,11 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState()); verify(mIkeSession).close(); + verifyTeardownTimeoutAlarmAndGetCallback(true /* expectCanceled */); + } + + @Test + public void testSafeModeTimeoutNotifiesCallback() { + verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java index 8643d8a2ea8a..9ea641f52e48 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java @@ -16,12 +16,18 @@ package com.android.server.vcn; +import static android.net.IpSecManager.IpSecTunnelInterface; + +import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; +import android.net.IpSecManager; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -37,7 +43,13 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect public void setUp() throws Exception { super.setUp(); - mGatewayConnection.transitionTo(mGatewayConnection.mDisconnectedState); + final IpSecTunnelInterface tunnelIface = + mContext.getSystemService(IpSecManager.class) + .createIpSecTunnelInterface( + DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network); + mGatewayConnection.setTunnelInterface(tunnelIface); + + // Don't need to transition to DisconnectedState because it is the starting state mTestLooper.dispatchAll(); } @@ -67,6 +79,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState()); + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -77,6 +90,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */); } @Test @@ -86,5 +100,6 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect assertNull(mGatewayConnection.getCurrentState()); verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any()); + verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index d0fec55a6827..7385204993c0 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -16,9 +16,9 @@ package com.android.server.vcn; -import static com.android.server.vcn.VcnGatewayConnection.TEARDOWN_TIMEOUT_SECONDS; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import androidx.test.filters.SmallTest; @@ -28,8 +28,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.concurrent.TimeUnit; - /** Tests for VcnGatewayConnection.DisconnectedState */ @RunWith(AndroidJUnit4.class) @SmallTest @@ -40,6 +38,9 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec mGatewayConnection.setIkeSession(mGatewayConnection.buildIkeSession()); + // ensure that mGatewayConnection has an underlying Network before entering + // DisconnectingState + mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_2); mGatewayConnection.transitionTo(mGatewayConnection.mDisconnectingState); mTestLooper.dispatchAll(); } @@ -49,12 +50,22 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec getIkeSessionCallback().onClosed(); mTestLooper.dispatchAll(); - assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState()); + verify(mMockIkeSession).close(); + verify(mMockIkeSession, never()).kill(); + verifyTeardownTimeoutAlarmAndGetCallback(true /* expectCanceled */); } @Test public void testTimeoutExpired() throws Exception { - mTestLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(TEARDOWN_TIMEOUT_SECONDS)); + Runnable delayedEvent = + verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); + + // Can't use mTestLooper to advance the time since VcnGatewayConnection uses WakeupMessages + // (which are mocked here). Directly invoke the runnable instead. This is still sufficient, + // since verifyTeardownTimeoutAlarmAndGetCallback() verifies the WakeupMessage was scheduled + // with the correct delay. + delayedEvent.run(); mTestLooper.dispatchAll(); verify(mMockIkeSession).kill(); @@ -67,5 +78,11 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec // Should do nothing; already tearing down. assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); + } + + @Test + public void testSafeModeTimeoutNotifiesCallback() { + verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java index 3f2b47cd58fd..5b0850b03f1a 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java @@ -29,10 +29,14 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnectionTestBase { + private long mFirstRetryInterval; + @Before public void setUp() throws Exception { super.setUp(); + mFirstRetryInterval = mConfig.getRetryInterval()[0]; + mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1); mGatewayConnection.transitionTo(mGatewayConnection.mRetryTimeoutState); mTestLooper.dispatchAll(); @@ -46,6 +50,7 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState()); + verifyRetryTimeoutAlarmAndGetCallback(mFirstRetryInterval, true /* expectCanceled */); } @Test @@ -56,6 +61,7 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState()); + verifyRetryTimeoutAlarmAndGetCallback(mFirstRetryInterval, false /* expectCanceled */); } @Test @@ -66,13 +72,28 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + verifyRetryTimeoutAlarmAndGetCallback(mFirstRetryInterval, true /* expectCanceled */); } @Test public void testTimeoutElapsingTriggersRetry() throws Exception { - mTestLooper.moveTimeForward(mConfig.getRetryIntervalsMs()[0]); + final Runnable delayedEvent = + verifyRetryTimeoutAlarmAndGetCallback( + mFirstRetryInterval, false /* expectCanceled */); + + // Can't use mTestLooper to advance the time since VcnGatewayConnection uses WakeupMessages + // (which are mocked here). Directly invoke the runnable instead. This is still sufficient, + // since verifyRetryTimeoutAlarmAndGetCallback() verifies the WakeupMessage was scheduled + // with the correct delay. + delayedEvent.run(); mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState()); + verifyRetryTimeoutAlarmAndGetCallback(mFirstRetryInterval, true /* expectCanceled */); + } + + @Test + public void testSafeModeTimeoutNotifiesCallback() { + verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index bc6bee28d14f..748c7924685d 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -132,10 +132,32 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { @Test public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() { + verifyWakeLockSetUp(); + final TelephonySubscriptionSnapshot updatedSnapshot = mock(TelephonySubscriptionSnapshot.class); mGatewayConnection.updateSubscriptionSnapshot(updatedSnapshot); verify(mUnderlyingNetworkTracker).updateSubscriptionSnapshot(eq(updatedSnapshot)); + verifyWakeLockAcquired(); + + mTestLooper.dispatchAll(); + + verifyWakeLockReleased(); + } + + @Test + public void testNonNullUnderlyingNetworkRecordUpdateCancelsAlarm() { + mGatewayConnection + .getUnderlyingNetworkTrackerCallback() + .onSelectedUnderlyingNetworkChanged(null); + + verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */); + + mGatewayConnection + .getUnderlyingNetworkTrackerCallback() + .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); + + verify(mDisconnectRequestAlarm).cancel(); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index d449eab494f6..a660735470a4 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -20,10 +20,16 @@ import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkR import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static com.android.server.vcn.VcnTestUtils.setupIpSecManager; +import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import android.annotation.NonNull; import android.content.Context; @@ -42,12 +48,16 @@ import android.net.ipsec.ike.IkeSessionCallback; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; +import android.os.PowerManager; import android.os.test.TestLooper; +import com.android.internal.util.State; +import com.android.internal.util.WakeupMessage; import com.android.server.IpSecService; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback; +import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock; import org.junit.Before; import org.mockito.ArgumentCaptor; @@ -55,6 +65,7 @@ import org.mockito.ArgumentCaptor; import java.net.InetAddress; import java.util.Collections; import java.util.UUID; +import java.util.concurrent.TimeUnit; public class VcnGatewayConnectionTestBase { protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID()); @@ -68,6 +79,7 @@ public class VcnGatewayConnectionTestBase { protected static final int TEST_IPSEC_TRANSFORM_RESOURCE_ID = 2; protected static final int TEST_IPSEC_TUNNEL_RESOURCE_ID = 3; protected static final int TEST_SUB_ID = 5; + protected static final long ELAPSED_REAL_TIME = 123456789L; protected static final String TEST_IPSEC_TUNNEL_IFACE = "IPSEC_IFACE"; protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_1 = new UnderlyingNetworkRecord( @@ -94,6 +106,11 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback; @NonNull protected final VcnGatewayConnection.Dependencies mDeps; @NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker; + @NonNull protected final VcnWakeLock mWakeLock; + @NonNull protected final WakeupMessage mTeardownTimeoutAlarm; + @NonNull protected final WakeupMessage mDisconnectRequestAlarm; + @NonNull protected final WakeupMessage mRetryTimeoutAlarm; + @NonNull protected final WakeupMessage mSafeModeTimeoutAlarm; @NonNull protected final IpSecService mIpSecSvc; @NonNull protected final ConnectivityManager mConnMgr; @@ -110,6 +127,11 @@ public class VcnGatewayConnectionTestBase { mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class); mDeps = mock(VcnGatewayConnection.Dependencies.class); mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class); + mWakeLock = mock(VcnWakeLock.class); + mTeardownTimeoutAlarm = mock(WakeupMessage.class); + mDisconnectRequestAlarm = mock(WakeupMessage.class); + mRetryTimeoutAlarm = mock(WakeupMessage.class); + mSafeModeTimeoutAlarm = mock(WakeupMessage.class); mIpSecSvc = mock(IpSecService.class); setupIpSecManager(mContext, mIpSecSvc); @@ -125,6 +147,20 @@ public class VcnGatewayConnectionTestBase { doReturn(mUnderlyingNetworkTracker) .when(mDeps) .newUnderlyingNetworkTracker(any(), any(), any(), any(), any()); + doReturn(mWakeLock) + .when(mDeps) + .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); + + setUpWakeupMessage(mTeardownTimeoutAlarm, VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM); + setUpWakeupMessage(mDisconnectRequestAlarm, VcnGatewayConnection.DISCONNECT_REQUEST_ALARM); + setUpWakeupMessage(mRetryTimeoutAlarm, VcnGatewayConnection.RETRY_TIMEOUT_ALARM); + setUpWakeupMessage(mSafeModeTimeoutAlarm, VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM); + + doReturn(ELAPSED_REAL_TIME).when(mDeps).getElapsedRealTime(); + } + + private void setUpWakeupMessage(@NonNull WakeupMessage msg, @NonNull String cmdName) { + doReturn(msg).when(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(cmdName), any()); } @Before @@ -166,4 +202,80 @@ public class VcnGatewayConnectionTestBase { verify(mDeps).newIkeSession(any(), any(), any(), any(), captor.capture()); return (VcnChildSessionCallback) captor.getValue(); } + + protected void verifyWakeLockSetUp() { + verify(mDeps).newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); + verifyNoMoreInteractions(mWakeLock); + } + + protected void verifyWakeLockAcquired() { + verify(mWakeLock).acquire(); + verifyNoMoreInteractions(mWakeLock); + } + + protected void verifyWakeLockReleased() { + verify(mWakeLock).release(); + verifyNoMoreInteractions(mWakeLock); + } + + private Runnable verifyWakeupMessageSetUpAndGetCallback( + @NonNull String tag, + @NonNull WakeupMessage msg, + long delayInMillis, + boolean expectCanceled) { + ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(tag), runnableCaptor.capture()); + + verify(mDeps, atLeastOnce()).getElapsedRealTime(); + verify(msg).schedule(ELAPSED_REAL_TIME + delayInMillis); + verify(msg, expectCanceled ? times(1) : never()).cancel(); + + return runnableCaptor.getValue(); + } + + protected Runnable verifyTeardownTimeoutAlarmAndGetCallback(boolean expectCanceled) { + return verifyWakeupMessageSetUpAndGetCallback( + VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM, + mTeardownTimeoutAlarm, + TimeUnit.SECONDS.toMillis(VcnGatewayConnection.TEARDOWN_TIMEOUT_SECONDS), + expectCanceled); + } + + protected Runnable verifyDisconnectRequestAlarmAndGetCallback(boolean expectCanceled) { + return verifyWakeupMessageSetUpAndGetCallback( + VcnGatewayConnection.DISCONNECT_REQUEST_ALARM, + mDisconnectRequestAlarm, + TimeUnit.SECONDS.toMillis( + VcnGatewayConnection.NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS), + expectCanceled); + } + + protected Runnable verifyRetryTimeoutAlarmAndGetCallback( + long delayInMillis, boolean expectCanceled) { + return verifyWakeupMessageSetUpAndGetCallback( + VcnGatewayConnection.RETRY_TIMEOUT_ALARM, + mRetryTimeoutAlarm, + delayInMillis, + expectCanceled); + } + + protected Runnable verifySafeModeTimeoutAlarmAndGetCallback(boolean expectCanceled) { + return verifyWakeupMessageSetUpAndGetCallback( + VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM, + mSafeModeTimeoutAlarm, + TimeUnit.SECONDS.toMillis(VcnGatewayConnection.SAFEMODE_TIMEOUT_SECONDS), + expectCanceled); + } + + protected void verifySafeModeTimeoutNotifiesCallback(@NonNull State expectedState) { + // SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial + // state) + final Runnable delayedEvent = + verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */); + delayedEvent.run(); + mTestLooper.dispatchAll(); + + verify(mGatewayStatusCallback).onEnteredSafeMode(); + assertEquals(expectedState, mGatewayConnection.getCurrentState()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java index 66cbf84619ab..9d3368271243 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java @@ -34,7 +34,7 @@ import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; import android.os.test.TestLooper; -import com.android.server.VcnManagementService.VcnSafemodeCallback; +import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener; @@ -56,7 +56,7 @@ public class VcnTest { private VcnContext mVcnContext; private TelephonySubscriptionSnapshot mSubscriptionSnapshot; private VcnNetworkProvider mVcnNetworkProvider; - private VcnSafemodeCallback mVcnSafemodeCallback; + private VcnCallback mVcnCallback; private Vcn.Dependencies mDeps; private ArgumentCaptor<VcnGatewayStatusCallback> mGatewayStatusCallbackCaptor; @@ -72,7 +72,7 @@ public class VcnTest { mVcnContext = mock(VcnContext.class); mSubscriptionSnapshot = mock(TelephonySubscriptionSnapshot.class); mVcnNetworkProvider = mock(VcnNetworkProvider.class); - mVcnSafemodeCallback = mock(VcnSafemodeCallback.class); + mVcnCallback = mock(VcnCallback.class); mDeps = mock(Vcn.Dependencies.class); mTestLooper = new TestLooper(); @@ -104,7 +104,7 @@ public class VcnTest { TEST_SUB_GROUP, mConfig, mSubscriptionSnapshot, - mVcnSafemodeCallback, + mVcnCallback, mDeps); } @@ -148,7 +148,7 @@ public class VcnTest { } @Test - public void testGatewayEnteringSafemodeNotifiesVcn() { + public void testGatewayEnteringSafeModeNotifiesVcn() { final NetworkRequestListener requestListener = verifyAndGetRequestListener(); for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { startVcnGatewayWithCapabilities(requestListener, capability); @@ -168,16 +168,17 @@ public class VcnTest { any(), mGatewayStatusCallbackCaptor.capture()); - // Doesn't matter which callback this gets - any Gateway entering Safemode should shut down + // Doesn't matter which callback this gets - any Gateway entering safe mode should shut down // all Gateways final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); - statusCallback.onEnteredSafemode(); + statusCallback.onEnteredSafeMode(); mTestLooper.dispatchAll(); + assertFalse(mVcn.isActive()); for (final VcnGatewayConnection gatewayConnection : gatewayConnections) { verify(gatewayConnection).teardownAsynchronously(); } verify(mVcnNetworkProvider).unregisterListener(requestListener); - verify(mVcnSafemodeCallback).onEnteredSafemode(); + verify(mVcnCallback).onEnteredSafeMode(); } } diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp index a594e5bf0ce1..c75ba71c4432 100644 --- a/tools/aapt/Android.bp +++ b/tools/aapt/Android.bp @@ -19,6 +19,23 @@ // targets here. // ========================================================== +package { + default_applicable_licenses: ["frameworks_base_tools_aapt_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_base_tools_aapt_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "aapt_defaults", diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index ade0dc4d9c42..5c5b3c32876c 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + toolSources = [ "cmd/Command.cpp", "cmd/Compile.cpp", diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp index 79fb5734cd68..bfd35083366e 100644 --- a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp +++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AaptAutoVersionTest", sdk_version: "current", diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp index a94a01f12c9e..7db9d2698cc7 100644 --- a/tools/aapt2/integration-tests/BasicTest/Android.bp +++ b/tools/aapt2/integration-tests/BasicTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AaptBasicTest", sdk_version: "current", diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk index 7bf8cf84426c..c084849a9d28 100644 --- a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk +++ b/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk @@ -20,9 +20,12 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_AAPT_NAMESPACES := true LOCAL_MODULE := AaptTestMergeOnly_LeafLib +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE LOCAL_SDK_VERSION := current LOCAL_MODULE_TAGS := tests LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_MIN_SDK_VERSION := 21 LOCAL_AAPT_FLAGS := --merge-only -include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk index ba781c56a913..699ad79ecf1a 100644 --- a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk +++ b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk @@ -20,9 +20,12 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_AAPT_NAMESPACES := true LOCAL_MODULE := AaptTestMergeOnly_LocalLib +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE LOCAL_SDK_VERSION := current LOCAL_MODULE_TAGS := tests LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_MIN_SDK_VERSION := 21 LOCAL_AAPT_FLAGS := --merge-only -include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk index c723d905db5b..dd4170234258 100644 --- a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk +++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk @@ -20,6 +20,9 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_AAPT_NAMESPACES := true LOCAL_MODULE := AaptTestNamespace_LibOne +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE LOCAL_SDK_VERSION := current LOCAL_MODULE_TAGS := tests LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk index 90a7f627e591..0d11bcbda64d 100644 --- a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk +++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk @@ -20,6 +20,9 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_AAPT_NAMESPACES := true LOCAL_MODULE := AaptTestNamespace_LibTwo +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE LOCAL_SDK_VERSION := current LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp index 9aadff3d619e..80404eeb8d8e 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AaptTestStaticLib_App", diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp index 4c8181343a33..a84da43c70c8 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "AaptTestStaticLib_LibOne", sdk_version: "current", diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp index 7c4f7ed90e69..d386c3a35d20 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_library { name: "AaptTestStaticLib_LibTwo", sdk_version: "current", diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp index 68e6148e480c..1e8cf86ed811 100644 --- a/tools/aapt2/integration-tests/SymlinkTest/Android.bp +++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "AaptSymlinkTest", sdk_version: "current", diff --git a/tools/bit/Android.bp b/tools/bit/Android.bp index a8062719d586..f6aa0fb8f3f0 100644 --- a/tools/bit/Android.bp +++ b/tools/bit/Android.bp @@ -17,6 +17,15 @@ // ========================================================== // Build the host executable: bit // ========================================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "bit", diff --git a/tools/codegen/Android.bp b/tools/codegen/Android.bp index 677bee2cce81..e53ba3e18a86 100644 --- a/tools/codegen/Android.bp +++ b/tools/codegen/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary_host { name: "codegen_cli", manifest: "manifest.txt", diff --git a/tools/dump-coverage/Android.bp b/tools/dump-coverage/Android.bp index 94356ebac035..f38177390972 100644 --- a/tools/dump-coverage/Android.bp +++ b/tools/dump-coverage/Android.bp @@ -15,6 +15,15 @@ // // Build variants {target,host} x {32,64} +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library { name: "libdumpcoverage", srcs: ["dump_coverage.cc"], diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py deleted file mode 100755 index 28ff606d0381..000000000000 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ /dev/null @@ -1,383 +0,0 @@ -#!/usr/bin/env python -# -# 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. -"""Generate API lists for non-SDK API enforcement.""" -import argparse -from collections import defaultdict, namedtuple -import functools -import os -import re -import sys - -# Names of flags recognized by the `hiddenapi` tool. -FLAG_SDK = 'sdk' -FLAG_UNSUPPORTED = 'unsupported' -FLAG_BLOCKED = 'blocked' -FLAG_MAX_TARGET_O = 'max-target-o' -FLAG_MAX_TARGET_P = 'max-target-p' -FLAG_MAX_TARGET_Q = 'max-target-q' -FLAG_MAX_TARGET_R = 'max-target-r' -FLAG_CORE_PLATFORM_API = 'core-platform-api' -FLAG_PUBLIC_API = 'public-api' -FLAG_SYSTEM_API = 'system-api' -FLAG_TEST_API = 'test-api' - -# List of all known flags. -FLAGS_API_LIST = [ - FLAG_SDK, - FLAG_UNSUPPORTED, - FLAG_BLOCKED, - FLAG_MAX_TARGET_O, - FLAG_MAX_TARGET_P, - FLAG_MAX_TARGET_Q, - FLAG_MAX_TARGET_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) - -# Option specified after one of FLAGS_API_LIST to indicate that -# only known and otherwise unassigned entries should be assign the -# given flag. -# For example, the max-target-P list is checked in as it was in P, -# but signatures have changes since then. The flag instructs this -# script to skip any entries which do not exist any more. -FLAG_IGNORE_CONFLICTS = "ignore-conflicts" - -# Option specified after one of FLAGS_API_LIST to express that all -# apis within a given set of packages should be assign the given flag. -FLAG_PACKAGES = "packages" - -# Option specified after one of FLAGS_API_LIST to indicate an extra -# tag that should be added to the matching APIs. -FLAG_TAG = "tag" - -# Regex patterns of fields/methods used in serialization. These are -# considered public API despite being hidden. -SERIALIZATION_PATTERNS = [ - r'readObject\(Ljava/io/ObjectInputStream;\)V', - r'readObjectNoData\(\)V', - r'readResolve\(\)Ljava/lang/Object;', - r'serialVersionUID:J', - r'serialPersistentFields:\[Ljava/io/ObjectStreamField;', - r'writeObject\(Ljava/io/ObjectOutputStream;\)V', - r'writeReplace\(\)Ljava/lang/Object;', -] - -# Single regex used to match serialization API. It combines all the -# SERIALIZATION_PATTERNS into a single regular expression. -SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r')$') - -# Predicates to be used with filter_apis. -HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags) -IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) - - -class StoreOrderedOptions(argparse.Action): - """An argparse action that stores a number of option arguments in the order that - they were specified. - """ - def __call__(self, parser, args, values, option_string = None): - items = getattr(args, self.dest, None) - if items is None: - items = [] - items.append([option_string.lstrip('-'), values]) - setattr(args, self.dest, items) - -def get_args(): - """Parses command line arguments. - - Returns: - Namespace: dictionary of parsed arguments - """ - parser = argparse.ArgumentParser() - parser.add_argument('--output', required=True) - parser.add_argument('--csv', nargs='*', default=[], metavar='CSV_FILE', - help='CSV files to be merged into output') - - for flag in ALL_FLAGS: - parser.add_argument('--' + flag, dest='ordered_flags', metavar='TXT_FILE', - action=StoreOrderedOptions, help='lists of entries with flag "' + flag + '"') - parser.add_argument('--' + FLAG_IGNORE_CONFLICTS, dest='ordered_flags', nargs=0, - action=StoreOrderedOptions, help='Indicates that only known and otherwise unassigned ' - 'entries should be assign the given flag. Must follow a list of entries and applies ' - 'to the preceding such list.') - parser.add_argument('--' + FLAG_PACKAGES, dest='ordered_flags', nargs=0, - action=StoreOrderedOptions, help='Indicates that the previous list of entries ' - 'is a list of packages. All members in those packages will be given the flag. ' - 'Must follow a list of entries and applies to the preceding such list.') - parser.add_argument('--' + FLAG_TAG, dest='ordered_flags', nargs=1, - action=StoreOrderedOptions, help='Adds an extra tag to the previous list of entries. ' - 'Must follow a list of entries and applies to the preceding such list.') - - return parser.parse_args() - - -def read_lines(filename): - """Reads entire file and return it as a list of lines. - - Lines which begin with a hash are ignored. - - Args: - filename (string): Path to the file to read from. - - Returns: - Lines of the file as a list of string. - """ - with open(filename, 'r') as f: - lines = f.readlines(); - lines = filter(lambda line: not line.startswith('#'), lines) - lines = map(lambda line: line.strip(), lines) - return set(lines) - - -def write_lines(filename, lines): - """Writes list of lines into a file, overwriting the file if it exists. - - Args: - filename (string): Path to the file to be writting into. - lines (list): List of strings to write into the file. - """ - lines = map(lambda line: line + '\n', lines) - with open(filename, 'w') as f: - f.writelines(lines) - - -def extract_package(signature): - """Extracts the package from a signature. - - Args: - signature (string): JNI signature of a method or field. - - Returns: - The package name of the class containing the field/method. - """ - full_class_name = signature.split(";->")[0] - # Example: Landroid/hardware/radio/V1_2/IRadio$Proxy - if (full_class_name[0] != "L"): - raise ValueError("Expected to start with 'L': %s" % full_class_name) - full_class_name = full_class_name[1:] - # If full_class_name doesn't contain '/', then package_name will be ''. - package_name = full_class_name.rpartition("/")[0] - return package_name.replace('/', '.') - - -class FlagsDict: - def __init__(self): - self._dict_keyset = set() - self._dict = defaultdict(set) - - def _check_entries_set(self, keys_subset, source): - assert isinstance(keys_subset, set) - assert keys_subset.issubset(self._dict_keyset), ( - "Error: {} specifies signatures not present in code:\n" - "{}" - "Please visit go/hiddenapi for more information.").format( - source, "".join(map(lambda x: " " + str(x) + "\n", keys_subset - self._dict_keyset))) - - def _check_flags_set(self, flags_subset, source): - assert isinstance(flags_subset, set) - assert flags_subset.issubset(ALL_FLAGS_SET), ( - "Error processing: {}\n" - "The following flags were not recognized: \n" - "{}\n" - "Please visit go/hiddenapi for more information.").format( - source, "\n".join(flags_subset - ALL_FLAGS_SET)) - - def filter_apis(self, filter_fn): - """Returns APIs which match a given predicate. - - This is a helper function which allows to filter on both signatures (keys) and - flags (values). The built-in filter() invokes the lambda only with dict's keys. - - Args: - filter_fn : Function which takes two arguments (signature/flags) and returns a boolean. - - Returns: - A set of APIs which match the predicate. - """ - return set(filter(lambda x: filter_fn(x, self._dict[x]), self._dict_keyset)) - - def get_valid_subset_of_unassigned_apis(self, api_subset): - """Sanitizes a key set input to only include keys which exist in the dictionary - and have not been assigned any API list flags. - - Args: - entries_subset (set/list): Key set to be sanitized. - - Returns: - Sanitized key set. - """ - assert isinstance(api_subset, set) - return api_subset.intersection(self.filter_apis(HAS_NO_API_LIST_ASSIGNED)) - - def generate_csv(self): - """Constructs CSV entries from a dictionary. - - Old versions of flags are used to generate the file. - - Returns: - List of lines comprising a CSV file. See "parse_and_merge_csv" for format description. - """ - lines = [] - for api in self._dict: - flags = sorted(self._dict[api]) - lines.append(",".join([api] + flags)) - return sorted(lines) - - def parse_and_merge_csv(self, csv_lines, source = "<unknown>"): - """Parses CSV entries and merges them into a given dictionary. - - The expected CSV format is: - <api signature>,<flag1>,<flag2>,...,<flagN> - - Args: - csv_lines (list of strings): Lines read from a CSV file. - source (string): Origin of `csv_lines`. Will be printed in error messages. - - Throws: - AssertionError if parsed flags are invalid. - """ - # Split CSV lines into arrays of values. - csv_values = [ line.split(',') for line in csv_lines ] - - # Update the full set of API signatures. - self._dict_keyset.update([ csv[0] for csv in csv_values ]) - - # Check that all flags are known. - csv_flags = set() - for csv in csv_values: - csv_flags.update(csv[1:]) - self._check_flags_set(csv_flags, source) - - # Iterate over all CSV lines, find entry in dict and append flags to it. - for csv in csv_values: - flags = csv[1:] - if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags): - flags.append(FLAG_SDK) - self._dict[csv[0]].update(flags) - - def assign_flag(self, flag, apis, source="<unknown>", tag = None): - """Assigns a flag to given subset of entries. - - Args: - flag (string): One of ALL_FLAGS. - apis (set): Subset of APIs to receive the flag. - source (string): Origin of `entries_subset`. Will be printed in error messages. - - Throws: - AssertionError if parsed API signatures of flags are invalid. - """ - # Check that all APIs exist in the dict. - self._check_entries_set(apis, source) - - # Check that the flag is known. - self._check_flags_set(set([ flag ]), source) - - # Iterate over the API subset, find each entry in dict and assign the flag to it. - for api in apis: - self._dict[api].add(flag) - if tag: - self._dict[api].add(tag) - - -FlagFile = namedtuple('FlagFile', ('flag', 'file', 'ignore_conflicts', 'packages', 'tag')) - -def parse_ordered_flags(ordered_flags): - r = [] - currentflag, file, ignore_conflicts, packages, tag = None, None, False, False, None - for flag_value in ordered_flags: - flag, value = flag_value[0], flag_value[1] - if flag in ALL_FLAGS_SET: - if currentflag: - r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) - ignore_conflicts, packages, tag = False, False, None - currentflag = flag - file = value - else: - if currentflag is None: - raise argparse.ArgumentError('--%s is only allowed after one of %s' % ( - flag, ' '.join(['--%s' % f for f in ALL_FLAGS_SET]))) - if flag == FLAG_IGNORE_CONFLICTS: - ignore_conflicts = True - elif flag == FLAG_PACKAGES: - packages = True - elif flag == FLAG_TAG: - tag = value[0] - - - if currentflag: - r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) - return r - - -def main(argv): - # Parse arguments. - args = vars(get_args()) - flagfiles = parse_ordered_flags(args['ordered_flags']) - - # Initialize API->flags dictionary. - flags = FlagsDict() - - # Merge input CSV files into the dictionary. - # Do this first because CSV files produced by parsing API stubs will - # contain the full set of APIs. Subsequent additions from text files - # will be able to detect invalid entries, and/or filter all as-yet - # unassigned entries. - for filename in args["csv"]: - flags.parse_and_merge_csv(read_lines(filename), filename) - - # Combine inputs which do not require any particular order. - # (1) Assign serialization API to SDK. - flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION)) - - # (2) Merge text files with a known flag into the dictionary. - for info in flagfiles: - if (not info.ignore_conflicts) and (not info.packages): - flags.assign_flag(info.flag, read_lines(info.file), info.file, info.tag) - - # Merge text files where conflicts should be ignored. - # This will only assign the given flag if: - # (a) the entry exists, and - # (b) it has not been assigned any other flag. - # Because of (b), this must run after all strict assignments have been performed. - for info in flagfiles: - if info.ignore_conflicts: - valid_entries = flags.get_valid_subset_of_unassigned_apis(read_lines(info.file)) - flags.assign_flag(info.flag, valid_entries, filename, info.tag) - - # All members in the specified packages will be assigned the appropriate flag. - for info in flagfiles: - if info.packages: - packages_needing_list = set(read_lines(info.file)) - should_add_signature_to_list = lambda sig,lists: extract_package( - sig) in packages_needing_list and not lists - valid_entries = flags.filter_apis(should_add_signature_to_list) - flags.assign_flag(info.flag, valid_entries, info.file, info.tag) - - # Mark all remaining entries as blocked. - flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) - - # Write output. - write_lines(args["output"], flags.generate_csv()) - -if __name__ == "__main__": - main(sys.argv) diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py deleted file mode 100755 index 82d117fbbbab..000000000000 --- a/tools/hiddenapi/generate_hiddenapi_lists_test.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python -# -# 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. -"""Unit tests for Hidden API list generation.""" -import unittest -from generate_hiddenapi_lists import * - -class TestHiddenapiListGeneration(unittest.TestCase): - - def test_filter_apis(self): - # Initialize flags so that A and B are put on the whitelist and - # C, D, E are left unassigned. Try filtering for the unassigned ones. - flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK, - 'C', 'D', 'E']) - filter_set = flags.filter_apis(lambda api, flags: not flags) - self.assertTrue(isinstance(filter_set, set)) - self.assertEqual(filter_set, set([ 'C', 'D', 'E' ])) - - def test_get_valid_subset_of_unassigned_keys(self): - # Create flags where only A is unassigned. - flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C']) - flags.assign_flag(FLAG_UNSUPPORTED, set(['C'])) - self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_SDK, 'B', 'C,' + FLAG_UNSUPPORTED ]) - - # Check three things: - # (1) B is selected as valid unassigned - # (2) A is not selected because it is assigned 'whitelist' - # (3) D is not selected because it is not a valid key - self.assertEqual( - flags.get_valid_subset_of_unassigned_apis(set(['A', 'B', 'D'])), set([ 'B' ])) - - def test_parse_and_merge_csv(self): - flags = FlagsDict() - - # Test empty CSV entry. - self.assertEqual(flags.generate_csv(), []) - - # Test new additions. - flags.parse_and_merge_csv([ - 'A,' + FLAG_UNSUPPORTED, - 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O, - 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API, - 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, - 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, - ]) - self.assertEqual(flags.generate_csv(), [ - 'A,' + FLAG_UNSUPPORTED, - 'B,' + FLAG_BLOCKED + "," + FLAG_MAX_TARGET_O, - 'C,' + FLAG_SYSTEM_API + ',' + FLAG_SDK, - 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, - 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, - ]) - - # Test unknown flag. - with self.assertRaises(AssertionError): - flags.parse_and_merge_csv([ 'Z,foo' ]) - - def test_assign_flag(self): - flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B']) - - # Test new additions. - flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ])) - self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_UNSUPPORTED + "," + FLAG_SDK, 'B,' + FLAG_UNSUPPORTED ]) - - # Test invalid API signature. - with self.assertRaises(AssertionError): - flags.assign_flag(FLAG_SDK, set([ 'C' ])) - - # Test invalid flag. - with self.assertRaises(AssertionError): - flags.assign_flag('foo', set([ 'A' ])) - - def test_extract_package(self): - signature = 'Lcom/foo/bar/Baz;->method1()Lcom/bar/Baz;' - expected_package = 'com.foo.bar' - self.assertEqual(extract_package(signature), expected_package) - - signature = 'Lcom/foo1/bar/MyClass;->method2()V' - expected_package = 'com.foo1.bar' - self.assertEqual(extract_package(signature), expected_package) - - signature = 'Lcom/foo_bar/baz/MyClass;->method3()V' - expected_package = 'com.foo_bar.baz' - self.assertEqual(extract_package(signature), expected_package) - -if __name__ == '__main__': - unittest.main() diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py deleted file mode 100755 index 6a5b0e1347b2..000000000000 --- a/tools/hiddenapi/merge_csv.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -# 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. -""" -Merge multiple CSV files, possibly with different columns. -""" - -import argparse -import csv -import io - -from zipfile import ZipFile - -args_parser = argparse.ArgumentParser(description='Merge given CSV files into a single one.') -args_parser.add_argument('--header', help='Comma separated field names; ' - 'if missing determines the header from input files.') -args_parser.add_argument('--zip_input', help='ZIP archive with all CSV files to merge.') -args_parser.add_argument('--output', help='Output file for merged CSV.', - default='-', type=argparse.FileType('w')) -args_parser.add_argument('files', nargs=argparse.REMAINDER) -args = args_parser.parse_args() - - -def dict_reader(input): - return csv.DictReader(input, delimiter=',', quotechar='|') - - -if args.zip_input and len(args.files) > 0: - raise ValueError('Expecting either a single ZIP with CSV files' - ' or a list of CSV files as input; not both.') - -csv_readers = [] -if len(args.files) > 0: - for file in args.files: - csv_readers.append(dict_reader(open(file, 'r'))) -elif args.zip_input: - with ZipFile(args.zip_input) as zip: - for entry in zip.namelist(): - if entry.endswith('.uau'): - csv_readers.append(dict_reader(io.TextIOWrapper(zip.open(entry, 'r')))) - -headers = set() -if args.header: - fieldnames = args.header.split(',') -else: - # Build union of all columns from source files: - for reader in csv_readers: - headers = headers.union(reader.fieldnames) - fieldnames = sorted(headers) - -# Concatenate all files to output: -writer = csv.DictWriter(args.output, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, - dialect='unix', fieldnames=fieldnames) -writer.writeheader() -for reader in csv_readers: - for row in reader: - writer.writerow(row) diff --git a/tools/incident_report/Android.bp b/tools/incident_report/Android.bp index f2d0d0f3e553..fe519c7edff4 100644 --- a/tools/incident_report/Android.bp +++ b/tools/incident_report/Android.bp @@ -17,6 +17,15 @@ // ========================================================== // Build the host executable: incident_report // ========================================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "incident_report", diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp index 0c7797eacf09..8227b60d6c09 100644 --- a/tools/incident_section_gen/Android.bp +++ b/tools/incident_section_gen/Android.bp @@ -17,6 +17,15 @@ // ========================================================== // Build the host executable: incident-section-gen // ========================================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "incident-section-gen", cflags: [ diff --git a/tools/lock_agent/Android.bp b/tools/lock_agent/Android.bp index 7b2ca9a65242..cabe1398903e 100644 --- a/tools/lock_agent/Android.bp +++ b/tools/lock_agent/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library { name: "liblockagent", host_supported: false, diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp index 5f81a2eeb130..98c0e69cbf8e 100644 --- a/tools/locked_region_code_injection/Android.bp +++ b/tools/locked_region_code_injection/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary_host { name: "lockedregioncodeinjection", manifest: "manifest.txt", diff --git a/tools/obbtool/Android.bp b/tools/obbtool/Android.bp index f87965860ce1..1c50d18ed32b 100644 --- a/tools/obbtool/Android.bp +++ b/tools/obbtool/Android.bp @@ -4,6 +4,15 @@ // Opaque Binary Blob (OBB) Tool // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "obbtool", diff --git a/tools/powermodel/Android.bp b/tools/powermodel/Android.bp index f597aab0f464..35c135614027 100644 --- a/tools/powermodel/Android.bp +++ b/tools/powermodel/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_host { name: "powermodel", srcs: [ @@ -23,4 +32,3 @@ java_test_host { "mockito", ], } - diff --git a/tools/preload-check/Android.bp b/tools/preload-check/Android.bp index aaa6d76b39e3..73caac694cb4 100644 --- a/tools/preload-check/Android.bp +++ b/tools/preload-check/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_host { name: "PreloadCheck", srcs: ["src/**/*.java"], diff --git a/tools/preload-check/device/Android.bp b/tools/preload-check/device/Android.bp index f40d8ba5a287..2a866c426336 100644 --- a/tools/preload-check/device/Android.bp +++ b/tools/preload-check/device/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test_helper_library { name: "preload-check-device", host_supported: false, diff --git a/tools/preload/Android.bp b/tools/preload/Android.bp index 809ee474969a..fad015ae35e0 100644 --- a/tools/preload/Android.bp +++ b/tools/preload/Android.bp @@ -1,3 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_host { name: "preload", srcs: [ diff --git a/tools/preload/loadclass/Android.bp b/tools/preload/loadclass/Android.bp index 6f12015dae2b..ba36061e5fb6 100644 --- a/tools/preload/loadclass/Android.bp +++ b/tools/preload/loadclass/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_test { name: "loadclass", srcs: ["**/*.java"], diff --git a/tools/processors/staledataclass/Android.bp b/tools/processors/staledataclass/Android.bp index 58a7d346ce1f..1e5097662a0a 100644 --- a/tools/processors/staledataclass/Android.bp +++ b/tools/processors/staledataclass/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_plugin { name: "staledataclass-annotation-processor", processor_class: "android.processor.staledataclass.StaleDataclassProcessor", diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp index 069e61f5b921..ea9974f06a64 100644 --- a/tools/processors/view_inspector/Android.bp +++ b/tools/processors/view_inspector/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_plugin { name: "view-inspector-annotation-processor", diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp index ce551bd0cc10..56351e3275f6 100644 --- a/tools/protologtool/Android.bp +++ b/tools/protologtool/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_library_host { name: "protologtool-lib", srcs: [ diff --git a/tools/sdkparcelables/Android.bp b/tools/sdkparcelables/Android.bp index 00fb8aa20b18..9d773e44faea 100644 --- a/tools/sdkparcelables/Android.bp +++ b/tools/sdkparcelables/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + java_binary_host { name: "sdkparcelables", manifest: "manifest.txt", diff --git a/tools/split-select/Android.bp b/tools/split-select/Android.bp index ee822b7d7fa7..c12fc6a7f253 100644 --- a/tools/split-select/Android.bp +++ b/tools/split-select/Android.bp @@ -19,6 +19,15 @@ // targets here. // ========================================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "split-select_defaults", diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp index 1390f63248f9..1ec83a360048 100644 --- a/tools/streaming_proto/Android.bp +++ b/tools/streaming_proto/Android.bp @@ -17,6 +17,15 @@ // ========================================================== // Build the host executable: protoc-gen-javastream // ========================================================== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_defaults { name: "protoc-gen-stream-defaults", srcs: [ diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp index 819e75ba1fed..9fcf034536fc 100644 --- a/tools/validatekeymaps/Android.bp +++ b/tools/validatekeymaps/Android.bp @@ -4,6 +4,15 @@ // Keymap validation tool. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_binary_host { name: "validatekeymaps", diff --git a/wifi/java/Android.bp b/wifi/java/Android.bp index b35b4be55818..225e750923fd 100644 --- a/wifi/java/Android.bp +++ b/wifi/java/Android.bp @@ -16,6 +16,15 @@ // updatable), and are generally only called by the Wifi module. // necessary since we only want the `path` property to only refer to these files +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-wifi-non-updatable-sources-internal", srcs: ["src/**/*.java"], diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp index 3f5cacff017f..c9105f7454e4 100644 --- a/wifi/tests/Android.bp +++ b/wifi/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + android_test { name: "FrameworksWifiNonUpdatableApiTests", |