diff options
Diffstat (limited to 'services/tests')
183 files changed, 4955 insertions, 1070 deletions
diff --git a/services/tests/PackageManager/OWNERS b/services/tests/PackageManager/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/PackageManager/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS 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/PackageManagerComponentOverrideTests/OWNERS b/services/tests/PackageManagerComponentOverrideTests/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/PackageManagerComponentOverrideTests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS 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/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..c0f0ce047da6 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS @@ -0,0 +1,3 @@ +per-file *Alarm* = file:/apex/jobscheduler/OWNERS +per-file *AppStateTracker* = file:/apex/jobscheduler/OWNERS +per-file *DeviceIdleController* = file:/apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS new file mode 100644 index 000000000000..65bb6b8a5423 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS @@ -0,0 +1 @@ +include /apex/blobstore/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/display/OWNERS b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS new file mode 100644 index 000000000000..6ce1ee4d3de2 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/display/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/job/OWNERS b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java index e724e60b3ae5..d4e4caa906a1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java @@ -19,6 +19,7 @@ package com.android.server.job.controllers; 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_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -364,7 +365,7 @@ public class ConnectivityControllerTest { .setAppIdleWhitelist(eq(UID_BLUE), anyBoolean()); assertTrue(controller.isStandbyExceptionRequestedLocked(UID_RED)); assertFalse(controller.isStandbyExceptionRequestedLocked(UID_BLUE)); - // Whitelisting doesn't need to be requested again. + // Allowlisting doesn't need to be requested again. controller.requestStandbyExceptionLocked(red); inOrder.verify(mNetPolicyManagerInternal, never()) .setAppIdleWhitelist(eq(UID_RED), anyBoolean()); @@ -434,7 +435,7 @@ public class ConnectivityControllerTest { .setAppIdleWhitelist(eq(UID_BLUE), anyBoolean()); assertTrue(controller.isStandbyExceptionRequestedLocked(UID_RED)); assertFalse(controller.isStandbyExceptionRequestedLocked(UID_BLUE)); - // Whitelisting doesn't need to be requested again. + // Allowlisting doesn't need to be requested again. controller.evaluateStateLocked(red); inOrder.verify(mNetPolicyManagerInternal, never()) .setAppIdleWhitelist(eq(UID_RED), anyBoolean()); @@ -473,7 +474,7 @@ public class ConnectivityControllerTest { assertFalse(controller.isStandbyExceptionRequestedLocked(UID_RED)); assertFalse(controller.isStandbyExceptionRequestedLocked(UID_BLUE)); - // Test that a currently whitelisted uid is now removed. + // Test that a currently allowlisted uid is now removed. controller.requestStandbyExceptionLocked(blue); inOrder.verify(mNetPolicyManagerInternal, times(1)) .setAppIdleWhitelist(eq(UID_BLUE), eq(true)); @@ -626,6 +627,7 @@ public class ConnectivityControllerTest { private static NetworkCapabilities createCapabilities() { return new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .addCapability(NET_CAPABILITY_VALIDATED); } diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java index d8874e40a760..1cf133a2bbf2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java @@ -302,7 +302,7 @@ public class QuotaControllerTest { // Make sure tests aren't passing just because the default bucket is likely ACTIVE. js.setStandbyBucket(FREQUENT_INDEX); // Make sure Doze and background-not-restricted don't affect tests. - js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* whitelisted */false); + js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* allowlisted */false); js.setBackgroundNotRestrictedConstraintSatisfied(true); return js; } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationFudgerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationFudgerTest.java index f2246dac01ca..d67edddb30e6 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/LocationFudgerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationFudgerTest.java @@ -79,7 +79,7 @@ public class LocationFudgerTest { Location coarse = mFudger.createCoarse(fine); assertThat(coarse).isNotNull(); - assertThat(coarse).isNotSameAs(fine); + assertThat(coarse).isNotSameInstanceAs(fine); assertThat(coarse.hasBearing()).isFalse(); assertThat(coarse.hasSpeed()).isFalse(); assertThat(coarse.hasAltitude()).isFalse(); @@ -148,7 +148,7 @@ public class LocationFudgerTest { // accurate the coarsened average will be. we use 70% as a lower bound by -very- roughly // taking the area within a grid where we expect a reasonable percentage of points generated // by step() to fall in another grid square. this likely doesn't have much mathematical - // validity, but it serves as a sanity test as least. + // validity, but it serves as a validity test as least. assertThat(passed / (double) iterations).isGreaterThan(.70); } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/OWNERS b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS new file mode 100644 index 000000000000..696a0c22c605 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS @@ -0,0 +1 @@ +file:/location/java/android/location/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS 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 979f4e179e95..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", @@ -82,7 +91,7 @@ android_test { "libui", "libunwindstack", "libutils", - "netd_aidl_interface-cpp", + "netd_aidl_interface-V5-cpp", ], dxflags: ["--multi-dex"], 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/OWNERS b/services/tests/servicestests/apks/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/apks/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS 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/apks/install_uses_sdk/res/values/strings.xml b/services/tests/servicestests/apks/install_uses_sdk/res/values/strings.xml index 3b8b3b1af9b5..fcab92b84879 100644 --- a/services/tests/servicestests/apks/install_uses_sdk/res/values/strings.xml +++ b/services/tests/servicestests/apks/install_uses_sdk/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="dummy">dummy</string> </resources> diff --git a/services/tests/servicestests/assets/NetworkPolicy/OWNERS b/services/tests/servicestests/assets/NetworkPolicy/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/assets/NetworkPolicy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml index 597600303acb..597600303acb 100644 --- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowed-restrict-background-off.xml index 196ca28192e4..196ca28192e4 100644 --- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowed-restrict-background-off.xml diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowed-restrict-background-on.xml index 4b7724c05d8d..4b7724c05d8d 100644 --- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowed-restrict-background-on.xml diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denied-restrict-background-off.xml index 5b1c03ce170e..5b1c03ce170e 100644 --- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denied-restrict-background-off.xml diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denied-restrict-background-on.xml index bec2371cff6f..bec2371cff6f 100644 --- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denied-restrict-background-on.xml diff --git a/services/tests/servicestests/src/com/android/internal/location/timezone/OWNERS b/services/tests/servicestests/src/com/android/internal/location/timezone/OWNERS new file mode 100644 index 000000000000..28aff188dbd8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/internal/location/timezone/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +nfuller@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java index 968a402ff3b7..3ace3f4c79dc 100644 --- a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +++ b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java @@ -27,8 +27,6 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; -import com.android.server.BluetoothAirplaneModeListener.AirplaneModeHelper; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -41,7 +39,7 @@ public class BluetoothAirplaneModeListenerTest { private Context mContext; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; private BluetoothAdapter mBluetoothAdapter; - private AirplaneModeHelper mHelper; + private BluetoothModeChangeHelper mHelper; @Mock BluetoothManagerService mBluetoothManagerService; @@ -49,7 +47,7 @@ public class BluetoothAirplaneModeListenerTest { public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); - mHelper = mock(AirplaneModeHelper.class); + mHelper = mock(BluetoothModeChangeHelper.class); when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT)) .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT); doNothing().when(mHelper).setSettingsInt(anyString(), anyInt()); diff --git a/services/tests/servicestests/src/com/android/server/CertBlacklisterTest.java b/services/tests/servicestests/src/com/android/server/CertBlacklisterTest.java index 10b9e7cf1218..90df786e5970 100644 --- a/services/tests/servicestests/src/com/android/server/CertBlacklisterTest.java +++ b/services/tests/servicestests/src/com/android/server/CertBlacklisterTest.java @@ -50,14 +50,14 @@ public class CertBlacklisterTest extends AndroidTestCase { public void testClearBlacklistPubkey() throws Exception { // clear the gservices setting for a clean slate overrideSettings(PUBKEY_KEY, ""); - // read the contents of the pubkey blacklist + // read the contents of the pubkey denylist String blacklist = IoUtils.readFileAsString(PUBKEY_PATH); // Verify that it's empty assertEquals("", blacklist); } public void testSetBlacklistPubkey() throws Exception { - // build a new thing to blacklist + // build a new thing to denylist String badPubkey = "7ccabd7db47e94a5759901b6a7dfd45d1c091ccc"; // add the gservices override overrideSettings(PUBKEY_KEY, badPubkey); @@ -110,14 +110,14 @@ public class CertBlacklisterTest extends AndroidTestCase { public void testClearBlacklistSerial() throws Exception { // clear the gservices setting for a clean slate overrideSettings(SERIAL_KEY, ""); - // read the contents of the pubkey blacklist + // read the contents of the pubkey denylist String blacklist = IoUtils.readFileAsString(SERIAL_PATH); // Verify that it's empty assertEquals("", blacklist); } public void testSetBlacklistSerial() throws Exception { - // build a new thing to blacklist + // build a new thing to denylist String badSerial = "22e514121e61c643b1e9b06bd4b9f7d0"; // add the gservices override overrideSettings(SERIAL_KEY, badSerial); 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/NetworkManagementInternalTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java deleted file mode 100644 index ebbebcb02923..000000000000 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.net.INetd.FIREWALL_CHAIN_DOZABLE; -import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE; -import static android.net.INetd.FIREWALL_CHAIN_STANDBY; -import static android.net.INetd.FIREWALL_RULE_ALLOW; -import static android.net.INetd.FIREWALL_RULE_DENY; -import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; -import static android.util.DebugUtils.valueToString; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.NetworkPolicyManager; -import android.util.ArrayMap; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.function.BiFunction; - -/** - * Test class for {@link NetworkManagementInternal}. - * - * To run the tests, use - * - * runtest -c com.android.server.NetworkManagementInternalTest frameworks-services - * - * or the following steps: - * - * Build: m FrameworksServicesTests - * Install: adb install -r \ - * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk - * Run: adb shell am instrument -e class com.android.server.NetworkManagementInternalTest -w \ - * com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class NetworkManagementInternalTest { - private static final int TEST_UID = 111; - - private NetworkManagementService.Injector mInjector; - private NetworkManagementInternal mNmi; - - @Before - public void setUp() { - final NetworkManagementService service = new NetworkManagementService(); - mInjector = service.getInjector(); - mNmi = service.new LocalService(); - } - - @Test - public void testIsNetworkRestrictedForUid() { - // No firewall chains enabled - assertFalse(mNmi.isNetworkRestrictedForUid(TEST_UID)); - - // Restrict usage of mobile data in background - mInjector.setUidOnMeteredNetworkList(true, TEST_UID, true); - assertTrue("Should be true since mobile data usage is restricted", - mNmi.isNetworkRestrictedForUid(TEST_UID)); - mInjector.reset(); - - // Data saver is on and uid is not whitelisted - mInjector.setDataSaverMode(true); - mInjector.setUidOnMeteredNetworkList(false, TEST_UID, false); - assertTrue("Should be true since data saver is on and the uid is not whitelisted", - mNmi.isNetworkRestrictedForUid(TEST_UID)); - mInjector.reset(); - - // Data saver is on and uid is whitelisted - mInjector.setDataSaverMode(true); - mInjector.setUidOnMeteredNetworkList(false, TEST_UID, true); - assertFalse("Should be false since data saver is on and the uid is whitelisted", - mNmi.isNetworkRestrictedForUid(TEST_UID)); - mInjector.reset(); - - final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>(); - // Dozable chain - final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>(); - isRestrictedForDozable.put(FIREWALL_RULE_DEFAULT, true); - isRestrictedForDozable.put(FIREWALL_RULE_ALLOW, false); - isRestrictedForDozable.put(FIREWALL_RULE_DENY, true); - expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable); - // Powersaver chain - final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>(); - isRestrictedForPowerSave.put(FIREWALL_RULE_DEFAULT, true); - isRestrictedForPowerSave.put(FIREWALL_RULE_ALLOW, false); - isRestrictedForPowerSave.put(FIREWALL_RULE_DENY, true); - expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave); - // Standby chain - final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>(); - isRestrictedForStandby.put(FIREWALL_RULE_DEFAULT, false); - isRestrictedForStandby.put(FIREWALL_RULE_ALLOW, false); - isRestrictedForStandby.put(FIREWALL_RULE_DENY, true); - expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby); - - final int[] chains = { - FIREWALL_CHAIN_STANDBY, - FIREWALL_CHAIN_POWERSAVE, - FIREWALL_CHAIN_DOZABLE - }; - final int[] states = { - FIREWALL_RULE_ALLOW, - FIREWALL_RULE_DENY, - FIREWALL_RULE_DEFAULT - }; - BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> { - return String.format("Unexpected value for chain: %s and state: %s", - valueToString(NetworkPolicyManager.class, "FIREWALL_CHAIN_", chain), - valueToString(NetworkPolicyManager.class, "FIREWALL_RULE_", state)); - }; - for (int chain : chains) { - final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain); - mInjector.setFirewallChainState(chain, true); - for (int state : states) { - mInjector.setFirewallRule(chain, TEST_UID, state); - assertEquals(errorMsg.apply(chain, state), - expectedValues.get(state), mNmi.isNetworkRestrictedForUid(TEST_UID)); - } - mInjector.reset(); - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..6561778cb47d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/OWNERS @@ -0,0 +1,7 @@ +per-file *Alarm* = file:/apex/jobscheduler/OWNERS +per-file *AppOp* = file:/core/java/android/permission/OWNERS +per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS +per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS +per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS +per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java deleted file mode 100644 index d192748762fe..000000000000 --- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.server; - -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; -import android.os.storage.StorageManagerInternal; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class StorageManagerServiceTest { - - private StorageManagerService mService; - - @Mock private Context mContext; - @Mock private PackageManager mPm; - @Mock private PackageManagerInternal mPmi; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - LocalServices.removeServiceForTest(StorageManagerInternal.class); - - LocalServices.removeServiceForTest(PackageManagerInternal.class); - LocalServices.addService(PackageManagerInternal.class, mPmi); - - when(mContext.getPackageManager()).thenReturn(mPm); - - mService = new StorageManagerService(mContext); - } -} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/OWNERS b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS new file mode 100644 index 000000000000..b74281edbf52 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/accessibility/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/accounts/OWNERS b/services/tests/servicestests/src/com/android/server/accounts/OWNERS new file mode 100644 index 000000000000..df1b4f432cd6 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/OWNERS @@ -0,0 +1 @@ +include /core/java/android/accounts/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/adb/OWNERS b/services/tests/servicestests/src/com/android/server/adb/OWNERS new file mode 100644 index 000000000000..b97f7956d115 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/adb/OWNERS @@ -0,0 +1 @@ +include platform/packages/modules/adb:/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/am/OWNERS b/services/tests/servicestests/src/com/android/server/am/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java new file mode 100644 index 000000000000..07f67327b2bf --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -0,0 +1,243 @@ +/* + * 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.apphibernation; + +import static android.content.pm.PackageManager.MATCH_ANY_USER; + +import static org.junit.Assert.assertTrue; +import static org.mockito.AdditionalAnswers.returnsArgAt; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.intThat; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import android.app.IActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; +import android.content.pm.ParceledListSlice; +import android.content.pm.UserInfo; +import android.net.Uri; +import android.os.RemoteException; +import android.os.UserManager; + +import androidx.test.filters.SmallTest; + +import com.android.server.SystemService; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tests for {@link com.android.server.apphibernation.AppHibernationService} + */ +@SmallTest +public final class AppHibernationServiceTest { + private static final String PACKAGE_SCHEME = "package"; + private static final String PACKAGE_NAME_1 = "package1"; + private static final String PACKAGE_NAME_2 = "package2"; + private static final int USER_ID_1 = 1; + private static final int USER_ID_2 = 2; + + private final List<UserInfo> mUserInfos = new ArrayList<>(); + + private AppHibernationService mAppHibernationService; + private BroadcastReceiver mBroadcastReceiver; + @Mock + private Context mContext; + @Mock + private IPackageManager mIPackageManager; + @Mock + private IActivityManager mIActivityManager; + @Mock + private UserManager mUserManager; + @Mock + private HibernationStateDiskStore<UserLevelState> mHibernationStateDiskStore; + @Captor + private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor; + + @Before + public void setUp() throws RemoteException { + // Share class loader to allow access to package-private classes + System.setProperty("dexmaker.share_classloader", "true"); + MockitoAnnotations.initMocks(this); + doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt()); + + mAppHibernationService = new AppHibernationService(new MockInjector(mContext)); + + verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); + mBroadcastReceiver = mReceiverCaptor.getValue(); + + doReturn(mUserInfos).when(mUserManager).getUsers(); + + doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(), + anyInt(), anyBoolean(), anyBoolean(), any(), any()); + + List<PackageInfo> packages = new ArrayList<>(); + packages.add(makePackageInfo(PACKAGE_NAME_1)); + doReturn(new ParceledListSlice<>(packages)).when(mIPackageManager).getInstalledPackages( + intThat(arg -> (arg & MATCH_ANY_USER) != 0), anyInt()); + mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); + + UserInfo userInfo = addUser(USER_ID_1); + mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); + doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1); + + mAppHibernationService.mIsServiceEnabled = true; + } + + @Test + public void testSetHibernatingForUser_packageIsHibernating() { + // WHEN we hibernate a package for a user + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); + + // THEN the package is marked hibernating for the user + assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); + } + + @Test + public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() { + // WHEN a new package is added and it is hibernated + Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, + Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); + intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1); + mBroadcastReceiver.onReceive(mContext, intent); + + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_1, true); + + // THEN the new package is hibernated + assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_1)); + } + + @Test + public void testSetHibernatingForUser_newUserUnlocked_packageIsHibernating() + throws RemoteException { + // WHEN a new user is added and a package from the user is hibernated + UserInfo user2 = addUser(USER_ID_2); + mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); + doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); + + // THEN the new user's package is hibernated + assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2)); + } + + @Test + public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() { + // GIVEN a package is currently hibernated + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); + + // WHEN the package is removed but marked as replacing + Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED, + Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); + intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1); + intent.putExtra(Intent.EXTRA_REPLACING, true); + mBroadcastReceiver.onReceive(mContext, intent); + + // THEN the package is still hibernating + assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); + } + + @Test + public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException { + // WHEN we hibernate a package + mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); + + // THEN the package is marked hibernating for the user + assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); + } + + /** + * Add a mock user with one package. + */ + private UserInfo addUser(int userId) throws RemoteException { + return addUser(userId, new String[]{PACKAGE_NAME_1}); + } + + /** + * Add a mock user with the packages specified. + */ + private UserInfo addUser(int userId, String[] packageNames) throws RemoteException { + UserInfo userInfo = new UserInfo(userId, "user_" + userId, 0 /* flags */); + mUserInfos.add(userInfo); + List<PackageInfo> userPackages = new ArrayList<>(); + for (String pkgName : packageNames) { + userPackages.add(makePackageInfo(pkgName)); + } + doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) + .getInstalledPackages(intThat(arg -> (arg & MATCH_ANY_USER) == 0), eq(userId)); + return userInfo; + } + + private static PackageInfo makePackageInfo(String packageName) { + PackageInfo pkg = new PackageInfo(); + pkg.packageName = packageName; + return pkg; + } + + private class MockInjector implements AppHibernationService.Injector { + private final Context mContext; + + MockInjector(Context context) { + mContext = context; + } + + @Override + public IActivityManager getActivityManager() { + return mIActivityManager; + } + + @Override + public Context getContext() { + return mContext; + } + + @Override + public IPackageManager getPackageManager() { + return mIPackageManager; + } + + @Override + public UserManager getUserManager() { + return mUserManager; + } + + @Override + public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() { + return Mockito.mock(HibernationStateDiskStore.class); + } + + @Override + public HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId) { + return Mockito.mock(HibernationStateDiskStore.class); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java new file mode 100644 index 000000000000..59f3c35f2137 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java @@ -0,0 +1,236 @@ +/* + * 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.apphibernation; + +import static org.junit.Assert.assertEquals; + +import android.os.FileUtils; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + +@SmallTest +public class HibernationStateDiskStoreTest { + private static final String STATES_FILE_NAME = "states"; + private final MockScheduledExecutorService mMockScheduledExecutorService = + new MockScheduledExecutorService(); + + private File mFile; + private HibernationStateDiskStore<String> mHibernationStateDiskStore; + + + @Before + public void setUp() { + mFile = new File(InstrumentationRegistry.getContext().getCacheDir(), "test"); + mHibernationStateDiskStore = new HibernationStateDiskStore<>(mFile, + new MockProtoReadWriter(), mMockScheduledExecutorService, STATES_FILE_NAME); + } + + @After + public void tearDown() { + FileUtils.deleteContentsAndDir(mFile); + } + + @Test + public void testScheduleWriteHibernationStates_writesDataThatCanBeRead() { + // GIVEN some data to be written + List<String> toWrite = new ArrayList<>(Arrays.asList("A", "B")); + + // WHEN the data is written + mHibernationStateDiskStore.scheduleWriteHibernationStates(toWrite); + mMockScheduledExecutorService.executeScheduledTask(); + + // THEN the read data is equal to what was written + List<String> storedStrings = mHibernationStateDiskStore.readHibernationStates(); + for (int i = 0; i < toWrite.size(); i++) { + assertEquals(toWrite.get(i), storedStrings.get(i)); + } + } + + @Test + public void testScheduleWriteHibernationStates_laterWritesOverwritePrevious() { + // GIVEN store has some data it is scheduled to write + mHibernationStateDiskStore.scheduleWriteHibernationStates( + new ArrayList<>(Arrays.asList("C", "D"))); + + // WHEN a write is scheduled with new data + List<String> toWrite = new ArrayList<>(Arrays.asList("A", "B")); + mHibernationStateDiskStore.scheduleWriteHibernationStates(toWrite); + mMockScheduledExecutorService.executeScheduledTask(); + + // THEN the written data is the last scheduled data + List<String> storedStrings = mHibernationStateDiskStore.readHibernationStates(); + for (int i = 0; i < toWrite.size(); i++) { + assertEquals(toWrite.get(i), storedStrings.get(i)); + } + } + + /** + * Mock proto read / writer that just writes and reads a list of String data. + */ + private final class MockProtoReadWriter implements ProtoReadWriter<List<String>> { + private static final long FIELD_ID = 1; + + @Override + public void writeToProto(@NonNull ProtoOutputStream stream, + @NonNull List<String> data) { + for (int i = 0, size = data.size(); i < size; i++) { + stream.write(FIELD_ID, data.get(i)); + } + } + + @Nullable + @Override + public List<String> readFromProto(@NonNull ProtoInputStream stream) + throws IOException { + ArrayList<String> list = new ArrayList<>(); + while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + list.add(stream.readString(FIELD_ID)); + } + return list; + } + } + + /** + * Mock scheduled executor service that has minimum implementation and can synchronously + * execute scheduled tasks. + */ + private final class MockScheduledExecutorService implements ScheduledExecutorService { + + Runnable mScheduledRunnable = null; + + @Override + public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { + mScheduledRunnable = command; + return Mockito.mock(ScheduledFuture.class); + } + + @Override + public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { + throw new UnsupportedOperationException(); + } + + @Override + public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, + long period, TimeUnit unit) { + throw new UnsupportedOperationException(); + } + + @Override + public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, + long delay, TimeUnit unit) { + throw new UnsupportedOperationException(); + } + + @Override + public void shutdown() { + throw new UnsupportedOperationException(); + } + + @Override + public List<Runnable> shutdownNow() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isShutdown() { + return false; + } + + @Override + public boolean isTerminated() { + return false; + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public <T> Future<T> submit(Callable<T> task) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> Future<T> submit(Runnable task, T result) { + throw new UnsupportedOperationException(); + } + + @Override + public Future<?> submit(Runnable task) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) + throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, + TimeUnit unit) throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public <T> T invokeAny(Collection<? extends Callable<T>> tasks) + throws InterruptedException, ExecutionException { + throw new UnsupportedOperationException(); + } + + @Override + public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + throw new UnsupportedOperationException(); + } + + @Override + public void execute(Runnable command) { + throw new UnsupportedOperationException(); + } + + void executeScheduledTask() { + mScheduledRunnable.run(); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/OWNERS b/services/tests/servicestests/src/com/android/server/apphibernation/OWNERS new file mode 100644 index 000000000000..c2e27e084c8c --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/apphibernation/OWNERS @@ -0,0 +1 @@ +include /core/java/android/apphibernation/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/appop/OWNERS b/services/tests/servicestests/src/com/android/server/appop/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appop/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/appsearch/OWNERS b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS new file mode 100644 index 000000000000..ebe9e4ec087f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS @@ -0,0 +1 @@ +include /apex/appsearch/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java index 8871348d0027..9a5c6337824a 100644 --- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java @@ -176,7 +176,7 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { } /** - * Sends dummy widget updates to {@link #mManager}. + * Sends placeholder widget updates to {@link #mManager}. * @param widgetId widget to update * @param viewIds a list of view ids for which * {@link AppWidgetManager#notifyAppWidgetViewDataChanged} will be called diff --git a/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java b/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java index 803119f4c5fa..fd99b21c9538 100644 --- a/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java +++ b/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java @@ -21,7 +21,7 @@ import android.content.Context; import android.content.Intent; /** - * Dummy widget for testing + * Placeholder widget for testing */ public class DummyAppWidget extends BroadcastReceiver { diff --git a/services/tests/servicestests/src/com/android/server/attention/OWNERS b/services/tests/servicestests/src/com/android/server/attention/OWNERS new file mode 100644 index 000000000000..51fc9bd09e4f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/attention/OWNERS @@ -0,0 +1 @@ +include /core/java/android/attention/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java index a9cef20268f4..8d706cb960e9 100644 --- a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java +++ b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java @@ -21,6 +21,8 @@ import android.media.AudioDeviceAttributes; import android.media.AudioSystem; import android.util.Log; +import java.util.List; + /** * Provides an adapter for AudioSystem that does nothing. * Overridden methods can be configured. @@ -66,13 +68,30 @@ public class NoOpAudioSystemAdapter extends AudioSystemAdapter { } @Override - public int setPreferredDeviceForStrategy(int strategy, - @NonNull AudioDeviceAttributes device) { + public int setDevicesRoleForStrategy(int strategy, int role, + @NonNull List<AudioDeviceAttributes> devices) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override + public int removeDevicesRoleForStrategy(int strategy, int role) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override + public int setDevicesRoleForCapturePreset(int capturePreset, int role, + @NonNull List<AudioDeviceAttributes> devices) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override + public int removeDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devicesToRemove) { return AudioSystem.AUDIO_STATUS_OK; } @Override - public int removePreferredDeviceForStrategy(int strategy) { + public int clearDevicesRoleForCapturePreset(int capturePreset, int role) { return AudioSystem.AUDIO_STATUS_OK; } diff --git a/services/tests/servicestests/src/com/android/server/audio/OWNERS b/services/tests/servicestests/src/com/android/server/audio/OWNERS new file mode 100644 index 000000000000..894a1f5c25d0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/audio/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/audio/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/backup/OWNERS b/services/tests/servicestests/src/com/android/server/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java index ad0b092b5543..6167d0debb50 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java @@ -80,7 +80,7 @@ public class AuthServiceTest { public void setUp() { MockitoAnnotations.initMocks(this); - // Dummy test config + // Placeholder test config final String[] config = { "0:2:15", // ID0:Fingerprint:Strong "1:4:15", // ID1:Iris:Strong 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/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java index 2cbe7be8ac33..f00edcc85404 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java @@ -39,63 +39,90 @@ class CompatConfigBuilder { return new CompatConfigBuilder(buildClassifier, context); } - CompatConfigBuilder addTargetSdkChangeWithId(int sdk, long id) { - mChanges.add(new CompatChange(id, "", sdk, false, false, "")); + CompatConfigBuilder addEnableAfterSdkChangeWithId(int sdk, long id) { + mChanges.add(new CompatChange(id, "", sdk, -1, false, false, "", false)); return this; } - CompatConfigBuilder addTargetSdkDisabledChangeWithId(int sdk, long id) { - mChanges.add(new CompatChange(id, "", sdk, true, false, "")); + CompatConfigBuilder addEnableAfterSdkChangeWithIdAndName(int sdk, long id, String name) { + mChanges.add(new CompatChange(id, name, sdk, -1, false, false, "", false)); return this; } - CompatConfigBuilder addTargetSdkChangeWithIdAndName(int sdk, long id, String name) { - mChanges.add(new CompatChange(id, name, sdk, false, false, "")); + CompatConfigBuilder addEnableAfterSdkChangeWithIdDefaultDisabled(int sdk, long id) { + mChanges.add(new CompatChange(id, "", sdk, -1, true, false, "", false)); return this; } - CompatConfigBuilder addTargetSdkChangeWithIdAndDescription(int sdk, long id, + CompatConfigBuilder addEnableAfterSdkChangeWithIdAndDescription(int sdk, long id, String description) { - mChanges.add(new CompatChange(id, "", sdk, false, false, description)); + mChanges.add(new CompatChange(id, "", sdk, -1, false, false, description, false)); + return this; + } + + CompatConfigBuilder addEnableSinceSdkChangeWithId(int sdk, long id) { + mChanges.add(new CompatChange(id, "", -1, sdk, false, false, "", false)); + return this; + } + + CompatConfigBuilder addEnableSinceSdkChangeWithIdAndName(int sdk, long id, String name) { + mChanges.add(new CompatChange(id, name, -1, sdk, false, false, "", false)); + return this; + } + + CompatConfigBuilder addEnableSinceSdkChangeWithIdDefaultDisabled(int sdk, long id) { + mChanges.add(new CompatChange(id, "", -1, sdk, true, false, "", false)); + return this; + } + + CompatConfigBuilder addEnableSinceSdkChangeWithIdAndDescription(int sdk, long id, + String description) { + mChanges.add(new CompatChange(id, "", -1, sdk, false, false, description, false)); return this; } CompatConfigBuilder addEnabledChangeWithId(long id) { - mChanges.add(new CompatChange(id, "", -1, false, false, "")); + mChanges.add(new CompatChange(id, "", -1, -1, false, false, "", false)); return this; } CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) { - mChanges.add(new CompatChange(id, name, -1, false, false, "")); + mChanges.add(new CompatChange(id, name, -1, -1, false, false, "", false)); return this; } CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) { - mChanges.add(new CompatChange(id, "", -1, false, false, description)); + mChanges.add(new CompatChange(id, "", -1, -1, false, false, description, false)); return this; } CompatConfigBuilder addDisabledChangeWithId(long id) { - mChanges.add(new CompatChange(id, "", -1, true, false, "")); + mChanges.add(new CompatChange(id, "", -1, -1, true, false, "", false)); return this; } CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) { - mChanges.add(new CompatChange(id, name, -1, true, false, "")); + mChanges.add(new CompatChange(id, name, -1, -1, true, false, "", false)); return this; } CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) { - mChanges.add(new CompatChange(id, "", -1, true, false, description)); + mChanges.add(new CompatChange(id, "", -1, -1, true, false, description, false)); return this; } CompatConfigBuilder addLoggingOnlyChangeWithId(long id) { - mChanges.add(new CompatChange(id, "", -1, false, true, "")); + mChanges.add(new CompatChange(id, "", -1, -1, false, true, "", false)); + return this; + } + + CompatConfigBuilder addOverridableChangeWithId(long id) { + mChanges.add(new CompatChange(id, "", -1, -1, false, true, "", true)); return this; } CompatConfig build() { CompatConfig config = new CompatConfig(mBuildClassifier, mContext); + config.forceNonDebuggableFinalForTest(false); for (CompatChange change : mChanges) { config.addChange(change); } 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 8be9213fd925..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,13 +26,16 @@ 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; +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; @@ -43,6 +47,9 @@ import java.io.File; import java.io.FileOutputStream; 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) @@ -68,6 +75,10 @@ public class CompatConfigTest { os.close(); } + private String readFile(File file) throws IOException { + return new String(Files.readAllBytes(Paths.get(file.toURI()))); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -76,11 +87,15 @@ public class CompatConfigTest { when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); ChangeIdStateCache.disable(); + when(mPackageManager.getApplicationInfo(anyString(), anyInt())) + .thenThrow(new NameNotFoundException()); } @Test public void testUnknownChangeEnabled() throws Exception { CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build())) .isTrue(); } @@ -98,7 +113,7 @@ public class CompatConfigTest { @Test public void testTargetSdkChangeDisabled() throws Exception { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) - .addTargetSdkChangeWithId(2, 1234L) + .addEnableAfterSdkChangeWithId(2, 1234L) .build(); assertThat(compatConfig.isChangeEnabled(1234L, @@ -109,7 +124,7 @@ public class CompatConfigTest { @Test public void testTargetSdkChangeEnabled() throws Exception { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) - .addTargetSdkChangeWithId(2, 1234L) + .addEnableAfterSdkChangeWithId(2, 1234L) .build(); assertThat(compatConfig.isChangeEnabled(1234L, @@ -119,7 +134,7 @@ public class CompatConfigTest { @Test public void testDisabledOverrideTargetSdkChange() throws Exception { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) - .addTargetSdkDisabledChangeWithId(2, 1234L) + .addEnableAfterSdkChangeWithIdDefaultDisabled(2, 1234L) .build(); assertThat(compatConfig.isChangeEnabled(1234L, @@ -154,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); @@ -168,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); @@ -180,6 +203,12 @@ public class CompatConfigTest { @Test public void testPackageOverrideUnknownPackage() throws Exception { 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); @@ -190,6 +219,22 @@ public class CompatConfigTest { } @Test + public void testIsChangeEnabledForInvalidApp() throws Exception { + final long disabledChangeId = 1234L; + final long enabledChangeId = 1235L; + final long targetSdkChangeId = 1236L; + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addEnabledChangeWithId(enabledChangeId) + .addDisabledChangeWithId(disabledChangeId) + .addEnableSinceSdkChangeWithId(42, targetSdkChangeId) + .build(); + + assertThat(compatConfig.isChangeEnabled(enabledChangeId, null)).isTrue(); + assertThat(compatConfig.isChangeEnabled(disabledChangeId, null)).isFalse(); + assertThat(compatConfig.isChangeEnabled(targetSdkChangeId, null)).isTrue(); + } + + @Test public void testPreventAddOverride() throws Exception { final long changeId = 1234L; CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) @@ -214,6 +259,148 @@ public class CompatConfigTest { } @Test + public void testApplyDeferredOverridesAfterInstallingApp() throws Exception { + ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() + .withPackageName("com.notinstalled.foo") + .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. + compatConfig.addOverride(1234L, "com.notinstalled.foo", true); + 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)).isTrue(); + } + + @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") + .debuggable().build(); + when(mPackageManager.getApplicationInfo(eq("com.installedapp.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 when app is installed. + compatConfig.addOverride(1234L, "com.installedapp.foo", true); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue(); + + // Pretend the app is now uninstalled. + when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt())) + .thenThrow(new NameNotFoundException()); + + compatConfig.recheckOverrides("com.installedapp.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); + } + + @Test + public void testApplyDeferredOverrideClearsOverrideAfterChange() throws Exception { + ApplicationInfo debuggableApp = ApplicationInfoBuilder.create() + .withPackageName("com.installedapp.foo") + .debuggable().build(); + ApplicationInfo releaseApp = ApplicationInfoBuilder.create() + .withPackageName("com.installedapp.foo") + .build(); + when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt())) + .thenReturn(debuggableApp); + + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1234L).build(); + when(mBuildClassifier.isDebuggableBuild()).thenReturn(false); + when(mBuildClassifier.isFinalBuild()).thenReturn(true); + + // Add override for debuggable app. + compatConfig.addOverride(1234L, "com.installedapp.foo", true); + assertThat(compatConfig.isChangeEnabled(1234L, debuggableApp)).isTrue(); + + // Pretend the app now is no longer debuggable, but has the same package. + when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt())) + .thenReturn(releaseApp); + + compatConfig.recheckOverrides("com.installedapp.foo"); + assertThat(compatConfig.isChangeEnabled(1234L, releaseApp)).isFalse(); + } + + @Test public void testLoggingOnlyChangePreventAddOverride() throws Exception { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addLoggingOnlyChangeWithId(1234L) @@ -243,7 +430,7 @@ public class CompatConfigTest { // Reject all override attempts. // Force the validator to prevent overriding the change by using a user build. when(mBuildClassifier.isDebuggableBuild()).thenReturn(false); - when(mBuildClassifier.isFinalBuild()).thenReturn(true); + when(mBuildClassifier.isFinalBuild()).thenReturn(false); // Try to turn off change, but validator prevents it. assertThrows(SecurityException.class, () -> compatConfig.removeOverride(1234L, "com.some.package")); @@ -280,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(); @@ -293,13 +482,15 @@ public class CompatConfigTest { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addEnabledChangeWithId(1L) .addDisabledChangeWithId(2L) - .addTargetSdkChangeWithId(3, 3L) - .addTargetSdkChangeWithId(4, 4L) + .addEnableSinceSdkChangeWithId(3, 3L) + .addEnableSinceSdkChangeWithId(4, 4L) .build(); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .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(); @@ -314,14 +505,15 @@ public class CompatConfigTest { CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addEnabledChangeWithId(1L) .addDisabledChangeWithId(2L) - .addTargetSdkChangeWithId(3, 3L) - .addTargetSdkChangeWithId(4, 4L) + .addEnableSinceSdkChangeWithId(3, 3L) + .addEnableSinceSdkChangeWithId(4, 4L) .build(); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .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(); @@ -344,6 +536,8 @@ public class CompatConfigTest { @Test public void testLookupChangeIdNotPresent() throws Exception { CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(-1L); } @@ -358,6 +552,8 @@ public class CompatConfigTest { File dir = createTempDir(); writeToFile(dir, "platform_compat_config.xml", configXml); CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + compatConfig.initConfigFromLib(dir); assertThat(compatConfig.isChangeEnabled(1234L, @@ -384,6 +580,8 @@ public class CompatConfigTest { writeToFile(dir, "libcore_platform_compat_config.xml", configXml1); writeToFile(dir, "frameworks_platform_compat_config.xml", configXml2); CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + compatConfig.initConfigFromLib(dir); assertThat(compatConfig.isChangeEnabled(1234L, @@ -395,4 +593,178 @@ public class CompatConfigTest { assertThat(compatConfig.isChangeEnabled(1236L, ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue(); } + + @Test + public void testSaveOverrides() 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); + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName("foo.bar") + .debuggable() + .build()); + when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) + .thenThrow(new NameNotFoundException()); + + compatConfig.addOverride(1L, "foo.bar", true); + compatConfig.addOverride(2L, "bar.baz", false); + + assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + + "<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"); + } + + @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 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) + // Change 2 is disabled for bar.baz (deferred) + String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>" + + "<change-overrides changeId=\"1\">" + + "<deferred/>" + + "<validated>" + + "<override-value packageName=\"foo.bar\" enabled=\"true\"/>" + + "</validated>" + + "</change-overrides>" + + "<change-overrides changeId=\"2\">" + + "<deferred>" + + "<override-value packageName=\"bar.baz\" enabled=\"false\"/>" + + "</deferred>" + + "<validated/>" + + "</change-overrides>" + + "</overrides>"; + 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") + .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(); + } } diff --git a/services/tests/servicestests/src/com/android/server/compat/OWNERS b/services/tests/servicestests/src/com/android/server/compat/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/compat/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java index d45589d90ce3..0fd6445fbeeb 100644 --- a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java @@ -17,6 +17,7 @@ package com.android.server.compat; import static com.android.internal.compat.OverrideAllowedState.ALLOWED; +import static com.android.internal.compat.OverrideAllowedState.DEFERRED_VERIFICATION; import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK; import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE; import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH; @@ -31,6 +32,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import androidx.test.runner.AndroidJUnit4; @@ -87,9 +89,9 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_debugBuildAnyChangeDebugApp_allowOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) .addEnabledChangeWithId(4) .addDisabledChangeWithId(5) .addLoggingOnlyChangeWithId(6).build(); @@ -131,9 +133,9 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_debugBuildAnyChangeReleaseApp_allowOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) .addEnabledChangeWithId(4) .addDisabledChangeWithId(5) .addLoggingOnlyChangeWithId(6).build(); @@ -174,9 +176,9 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_betaBuildTargetSdkChangeDebugApp_allowOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) .addDisabledChangeWithId(4).build(); IOverrideValidator overrideValidator = config.getOverrideValidator(); when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) @@ -245,9 +247,9 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_betaBuildAnyChangeReleaseApp_rejectOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) .addEnabledChangeWithId(4) .addDisabledChangeWithId(5) .addLoggingOnlyChangeWithId(6).build(); @@ -288,8 +290,8 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptin_allowOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2).build(); + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2).build(); IOverrideValidator overrideValidator = config.getOverrideValidator(); when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenReturn(ApplicationInfoBuilder.create() @@ -313,7 +315,7 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptout_rejectOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1).build(); + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1).build(); IOverrideValidator overrideValidator = config.getOverrideValidator(); when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenReturn(ApplicationInfoBuilder.create() @@ -371,9 +373,9 @@ public class OverrideValidatorImplTest { public void getOverrideAllowedState_finalBuildAnyChangeReleaseApp_rejectOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) - .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1) - .addTargetSdkChangeWithId(TARGET_SDK, 2) - .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) .addEnabledChangeWithId(4) .addDisabledChangeWithId(5) .addLoggingOnlyChangeWithId(6).build(); @@ -409,4 +411,216 @@ public class OverrideValidatorImplTest { assertThat(stateDLoggingOnlyChange) .isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1)); } + @Test + public void getOverrideAllowedState_finalBuildAnyChangeNotInstalledApp_deferOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnabledChangeWithId(4) + .addDisabledChangeWithId(5) + .addLoggingOnlyChangeWithId(6).build(); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenThrow(new NameNotFoundException()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkEqualChange = + overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkAfterChange = + overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME); + OverrideAllowedState stateEnabledChange = + overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME); + OverrideAllowedState stateDisabledChange = + overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME); + OverrideAllowedState stateDLoggingOnlyChange = + overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME); + + assertThat(stateTargetSdkLessChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateTargetSdkEqualChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateTargetSdkAfterChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateEnabledChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateDisabledChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateDLoggingOnlyChange) + .isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1)); + } + + @Test + public void getOverrideAllowedState_forceFinalBuildTargetSdkChangeDebugAppOptin_allowOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .debuggable() + .withTargetSdk(TARGET_SDK) + .withPackageName(PACKAGE_NAME).build()); + + OverrideAllowedState stateTargetSdkGreaterChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkEqualChange = + overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME); + + assertThat(stateTargetSdkGreaterChange) + .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER)); + + assertThat(stateTargetSdkEqualChange) + .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK)); + } + + @Test + public void getOverrideAllowedState_forceFinalBldTargetSdkChangeDebugAppOptout_rejectOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .withTargetSdk(TARGET_SDK) + .debuggable() + .build()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + + assertThat(stateTargetSdkLessChange).isEqualTo( + new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK, + TARGET_SDK_BEFORE)); + } + + @Test + public void getOverrideAllowedState_forceFinalBuildEnabledChangeDebugApp_rejectOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addEnabledChangeWithId(1).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .debuggable().build()); + + OverrideAllowedState allowedState = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + + assertThat(allowedState) + .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1)); + } + + @Test + public void getOverrideAllowedState_forceFinalBuildDisabledChangeDebugApp_allowOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addDisabledChangeWithId(1).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .withTargetSdk(TARGET_SDK) + .debuggable().build()); + + OverrideAllowedState allowedState = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + + assertThat(allowedState) + .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, -1)); + } + + @Test + public void getOverrideAllowedState_forceFinalBuildAnyChangeReleaseApp_rejectOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnabledChangeWithId(4) + .addDisabledChangeWithId(5) + .addLoggingOnlyChangeWithId(6).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .withTargetSdk(TARGET_SDK).build()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkEqualChange = + overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkAfterChange = + overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME); + OverrideAllowedState stateEnabledChange = + overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME); + OverrideAllowedState stateDisabledChange = + overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME); + OverrideAllowedState stateDLoggingOnlyChange = + overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME); + + assertThat(stateTargetSdkLessChange) + .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1)); + assertThat(stateTargetSdkEqualChange) + .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1)); + assertThat(stateTargetSdkAfterChange) + .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1)); + assertThat(stateEnabledChange) + .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1)); + assertThat(stateDisabledChange) + .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1)); + assertThat(stateDLoggingOnlyChange) + .isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1)); + } + @Test + public void getOverrideAllowedState_forceFinalBuildAnyChangeNotInstalledApp_deferOverride() + throws Exception { + CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext) + .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1) + .addEnableAfterSdkChangeWithId(TARGET_SDK, 2) + .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3) + .addEnabledChangeWithId(4) + .addDisabledChangeWithId(5) + .addLoggingOnlyChangeWithId(6).build(); + config.forceNonDebuggableFinalForTest(true); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenThrow(new NameNotFoundException()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkEqualChange = + overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME); + OverrideAllowedState stateTargetSdkAfterChange = + overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME); + OverrideAllowedState stateEnabledChange = + overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME); + OverrideAllowedState stateDisabledChange = + overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME); + OverrideAllowedState stateDLoggingOnlyChange = + overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME); + + assertThat(stateTargetSdkLessChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateTargetSdkEqualChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateTargetSdkAfterChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateEnabledChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateDisabledChange) + .isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1)); + assertThat(stateDLoggingOnlyChange) + .isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1)); + } } diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index cef02ffc3831..799b06734b54 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.testng.Assert.assertThrows; +import android.compat.Compatibility.ChangeConfig; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; @@ -35,6 +36,7 @@ import android.os.Build; import androidx.test.runner.AndroidJUnit4; import com.android.internal.compat.AndroidBuildClassifier; +import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.LocalServices; @@ -44,6 +46,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.HashSet; +import java.util.Set; + @RunWith(AndroidJUnit4.class) public class PlatformCompatTest { private static final String PACKAGE_NAME = "my.package"; @@ -70,9 +75,12 @@ public class PlatformCompatTest { new PackageManager.NameNotFoundException()); when(mPackageManagerInternal.getPackageUid(eq(PACKAGE_NAME), eq(0), anyInt())) .thenReturn(-1); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenThrow(new PackageManager.NameNotFoundException()); mCompatConfig = new CompatConfig(mBuildClassifier, mContext); mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); // Assume userdebug/eng non-final build + mCompatConfig.forceNonDebuggableFinalForTest(false); when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); LocalServices.removeServiceForTest(PackageManagerInternal.class); @@ -84,22 +92,27 @@ public class PlatformCompatTest { mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addEnabledChangeWithId(1L) .addDisabledChangeWithIdAndName(2L, "change2") - .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description") - .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L) - .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L) - .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L) + .addEnableAfterSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc") + .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.P, 4L) + .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L) + .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L) .addLoggingOnlyChangeWithId(7L) + .addOverridableChangeWithId(8L) .build(); mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly( - new CompatibilityChangeInfo(1L, "", -1, false, false, ""), - new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""), - new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, false, false, - "description"), - new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""), - new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, ""), - new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, false, false, ""), - new CompatibilityChangeInfo(7L, "", -1, false, true, "")); + new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), + new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), + new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, -1, false, false, + "desc", false), + new CompatibilityChangeInfo( + 4L, "", Build.VERSION_CODES.P, -1, false, false, "", false), + new CompatibilityChangeInfo( + 5L, "", Build.VERSION_CODES.Q, -1, false, false, "", false), + new CompatibilityChangeInfo( + 6L, "", Build.VERSION_CODES.R, -1, false, false, "", false), + new CompatibilityChangeInfo(7L, "", -1, -1, false, true, "", false), + new CompatibilityChangeInfo(8L, "", -1, -1, false, true, "", true)); } @Test @@ -107,18 +120,52 @@ public class PlatformCompatTest { mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addEnabledChangeWithId(1L) .addDisabledChangeWithIdAndName(2L, "change2") - .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description") - .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L) - .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L) - .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L) + .addEnableSinceSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc") + .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.P, 4L) + .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.Q, 5L) + .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.R, 6L) .addLoggingOnlyChangeWithId(7L) .build(); mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly( - new CompatibilityChangeInfo(1L, "", -1, false, false, ""), - new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""), - new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""), - new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, "")); + new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), + new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), + new CompatibilityChangeInfo( + 5L, "", Build.VERSION_CODES.P, -1, false, false, "", false), + new CompatibilityChangeInfo( + 6L, "", Build.VERSION_CODES.Q, -1, false, false, "", false)); + } + + @Test + public void testOverrideAtInstallTime() throws Exception { + mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addEnabledChangeWithId(1L) + .addDisabledChangeWithId(2L) + .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.O, 3L) + .build(); + mCompatConfig.forceNonDebuggableFinalForTest(true); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + + // Before adding overrides. + assertThat(mPlatformCompat.isChangeEnabledByPackageName(1, PACKAGE_NAME, 0)).isTrue(); + assertThat(mPlatformCompat.isChangeEnabledByPackageName(2, PACKAGE_NAME, 0)).isFalse(); + assertThat(mPlatformCompat.isChangeEnabledByPackageName(3, PACKAGE_NAME, 0)).isTrue(); + + // Add overrides. + Set<Long> enabled = new HashSet<>(); + enabled.add(2L); + Set<Long> disabled = new HashSet<>(); + disabled.add(1L); + disabled.add(3L); + ChangeConfig changeConfig = new ChangeConfig(enabled, disabled); + CompatibilityChangeConfig compatibilityChangeConfig = + new CompatibilityChangeConfig(changeConfig); + mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, PACKAGE_NAME); + + // After adding overrides. + assertThat(mPlatformCompat.isChangeEnabledByPackageName(1, PACKAGE_NAME, 0)).isFalse(); + assertThat(mPlatformCompat.isChangeEnabledByPackageName(2, PACKAGE_NAME, 0)).isTrue(); + assertThat(mPlatformCompat.isChangeEnabledByPackageName(3, PACKAGE_NAME, 0)).isFalse(); } @Test @@ -149,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); @@ -161,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); @@ -172,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); @@ -197,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); @@ -205,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); @@ -233,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); @@ -252,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); @@ -271,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); @@ -289,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/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index daaabf8141ff..5d06da78fe80 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -30,6 +30,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.PasswordMetrics.computeForPassword; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; +import static android.net.InetAddresses.parseNumericAddress; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; @@ -65,6 +66,8 @@ import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.testng.Assert.assertThrows; +import static java.util.Collections.emptyList; + import android.Manifest.permission; import android.app.Activity; import android.app.AppOpsManager; @@ -118,6 +121,8 @@ import org.mockito.internal.util.collections.Sets; import org.mockito.stubbing.Answer; import java.io.File; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -2246,6 +2251,48 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts); } + public void testGetProxyParameters() throws Exception { + assertThat(dpm.getProxyParameters(inetAddrProxy("192.0.2.1", 1234), emptyList())) + .isEqualTo(new Pair<>("192.0.2.1:1234", "")); + assertThat(dpm.getProxyParameters(inetAddrProxy("192.0.2.1", 1234), + listOf("one.example.com ", " two.example.com "))) + .isEqualTo(new Pair<>("192.0.2.1:1234", "one.example.com,two.example.com")); + assertThat(dpm.getProxyParameters(hostnameProxy("proxy.example.com", 1234), emptyList())) + .isEqualTo(new Pair<>("proxy.example.com:1234", "")); + assertThat(dpm.getProxyParameters(hostnameProxy("proxy.example.com", 1234), + listOf("excluded.example.com"))) + .isEqualTo(new Pair<>("proxy.example.com:1234", "excluded.example.com")); + + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + inetAddrProxy("192.0.2.1", 0), emptyList())); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("", 1234), emptyList())); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("", 0), emptyList())); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("invalid! hostname", 1234), emptyList())); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("proxy.example.com", 1234), listOf("invalid exclusion"))); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("proxy.example.com", -1), emptyList())); + assertThrows(IllegalArgumentException.class, () -> dpm.getProxyParameters( + hostnameProxy("proxy.example.com", 0xFFFF + 1), emptyList())); + } + + private static Proxy inetAddrProxy(String inetAddr, int port) { + return new Proxy( + Proxy.Type.HTTP, new InetSocketAddress(parseNumericAddress(inetAddr), port)); + } + + private static Proxy hostnameProxy(String hostname, int port) { + return new Proxy( + Proxy.Type.HTTP, InetSocketAddress.createUnresolved(hostname, port)); + } + + private static List<String> listOf(String... args) { + return Arrays.asList(args); + } + public void testSetKeyguardDisabledFeaturesWithDO() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); @@ -5153,10 +5200,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertTrue(dpms.isNotificationListenerServicePermitted(packageName, userId)); - // Attempt to set to empty list (which means no listener is whitelisted) + // Attempt to set to empty list (which means no listener is allowlisted) mContext.binder.callingUid = adminUid; assertFalse(dpms.setPermittedCrossProfileNotificationListeners( - admin1, Collections.emptyList())); + admin1, emptyList())); assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1)); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; @@ -5227,7 +5274,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpms.isNotificationListenerServicePermitted( systemListener, MANAGED_PROFILE_USER_ID)); - // Setting only one package in the whitelist + // Setting only one package in the allowlist mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; assertTrue(dpms.setPermittedCrossProfileNotificationListeners( admin1, Collections.singletonList(permittedListener))); @@ -5241,14 +5288,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { permittedListener, MANAGED_PROFILE_USER_ID)); assertFalse(dpms.isNotificationListenerServicePermitted( notPermittedListener, MANAGED_PROFILE_USER_ID)); - // System packages are always allowed (even if not in the whitelist) + // System packages are always allowed (even if not in the allowlist) assertTrue(dpms.isNotificationListenerServicePermitted( systemListener, MANAGED_PROFILE_USER_ID)); - // Setting an empty whitelist - only system listeners allowed + // Setting an empty allowlist - only system listeners allowed mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; assertTrue(dpms.setPermittedCrossProfileNotificationListeners( - admin1, Collections.emptyList())); + admin1, emptyList())); assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size()); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; @@ -5256,11 +5303,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { permittedListener, MANAGED_PROFILE_USER_ID)); assertFalse(dpms.isNotificationListenerServicePermitted( notPermittedListener, MANAGED_PROFILE_USER_ID)); - // System packages are always allowed (even if not in the whitelist) + // System packages are always allowed (even if not in the allowlist) assertTrue(dpms.isNotificationListenerServicePermitted( systemListener, MANAGED_PROFILE_USER_ID)); - // Setting a null whitelist - all listeners allowed + // Setting a null allowlist - all listeners allowed mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; assertTrue(dpms.setPermittedCrossProfileNotificationListeners(admin1, null)); assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1)); @@ -5308,11 +5355,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpms.isNotificationListenerServicePermitted( systemListener, UserHandle.USER_SYSTEM)); - // Setting an empty whitelist - only system listeners allowed in managed profile, but + // Setting an empty allowlist - only system listeners allowed in managed profile, but // all allowed in primary profile mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; assertTrue(dpms.setPermittedCrossProfileNotificationListeners( - admin1, Collections.emptyList())); + admin1, emptyList())); assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size()); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OWNERS b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS new file mode 100644 index 000000000000..d9b0e2e5ffa5 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/devicestate/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java index e8e6dedaa258..df672c9f248d 100644 --- a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java @@ -294,7 +294,7 @@ public class AmbientBrightnessStatsTrackerTest { AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker(); ArrayList<AmbientBrightnessDayStats> userStats; float[] expectedStats; - // Generate some dummy data + // Generate some placeholder data // Data: very old which should not be read statsTracker.start(); statsTracker.add(0, 0.05f); diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java index 48dda019f570..ae966aaf2b58 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -466,7 +466,7 @@ public class BrightnessMappingStrategyTest { Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); - // Let's start with a sanity check: + // Let's start with a validity check: assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); @@ -494,7 +494,7 @@ public class BrightnessMappingStrategyTest { Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); - // Sanity check: + // Validity check: assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); @@ -540,7 +540,7 @@ public class BrightnessMappingStrategyTest { Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); - // Sanity, as per tradition: + // Validity, as per tradition: assertEquals(y0, strategy.getBrightness(x0), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */); diff --git a/services/tests/servicestests/src/com/android/server/display/OWNERS b/services/tests/servicestests/src/com/android/server/display/OWNERS new file mode 100644 index 000000000000..6ce1ee4d3de2 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/display/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/display/color/GlobalSaturationTintControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/GlobalSaturationTintControllerTest.java index 7b88a0e012de..4f0cb324f17f 100644 --- a/services/tests/servicestests/src/com/android/server/display/color/GlobalSaturationTintControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/color/GlobalSaturationTintControllerTest.java @@ -32,9 +32,11 @@ public class GlobalSaturationTintControllerTest { public void setAndGetMatrix() { final GlobalSaturationTintController tintController = new GlobalSaturationTintController(); tintController.setMatrix(50); - assertThat(tintController.getMatrix()).hasValuesWithin(0.00001f) - .of(new float[]{0.6155f, 0.1155f, 0.1155f, 0.0f, 0.3575f, 0.85749996f, 0.3575f, - 0.0f, 0.036f, 0.036f, 0.536f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}); + assertThat(tintController.getMatrix()).usingTolerance(0.00001f) + .containsExactly( + 0.6155f, 0.1155f, 0.1155f, 0.0f, 0.3575f, 0.85749996f, 0.3575f, + 0.0f, 0.036f, 0.036f, 0.536f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f) + .inOrder(); } @Test @@ -43,6 +45,7 @@ public class GlobalSaturationTintControllerTest { tintController.setMatrix(100); final float[] matrix = new float[16]; Matrix.setIdentityM(matrix, 0); - assertThat(tintController.getMatrix()).hasValuesWithin(0.00001f).of(matrix); + assertThat(tintController.getMatrix()).usingTolerance(0.00001f) + .containsExactly(matrix).inOrder(); } } diff --git a/services/tests/servicestests/src/com/android/server/emergency/EmergencyAffordanceServiceTest.java b/services/tests/servicestests/src/com/android/server/emergency/EmergencyAffordanceServiceTest.java index d438a0eb9411..3ecff91d8f96 100644 --- a/services/tests/servicestests/src/com/android/server/emergency/EmergencyAffordanceServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/emergency/EmergencyAffordanceServiceTest.java @@ -448,7 +448,7 @@ public class EmergencyAffordanceServiceTest { List<SubscriptionInfo> subInfos = new ArrayList<>(2); // Test with Multiple SIMs. SIM1 is a non-EA SIM - // Only country iso is valuable, all other info are filled with dummy values + // Only country iso is valuable, all other info are filled with placeholder values SubscriptionInfo subInfo = new SubscriptionInfo(1, "890126042XXXXXXXXXXX", 0, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "226", NON_EMERGENCY_ISO_CODE, false, null, null); diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/OWNERS b/services/tests/servicestests/src/com/android/server/graphics/fonts/OWNERS new file mode 100644 index 000000000000..34ac813f02e0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 24939 + +include /graphics/java/android/graphics/fonts/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java index 5d8131f35eb7..d905b69ce37f 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java @@ -28,6 +28,8 @@ import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import android.content.Context; import android.hardware.tv.cec.V1_0.SendMessageResult; @@ -189,4 +191,19 @@ public class HdmiCecControllerTest { mTestLooper.dispatchAll(); assertEquals(ADDR_UNREGISTERED, mLogicalAddress); } + + @Test + public void testIsLanguage() { + assertTrue(HdmiCecController.isLanguage("en")); + assertTrue(HdmiCecController.isLanguage("eng")); + assertTrue(HdmiCecController.isLanguage("ger")); + assertTrue(HdmiCecController.isLanguage("zh")); + assertTrue(HdmiCecController.isLanguage("zhi")); + assertTrue(HdmiCecController.isLanguage("zho")); + + assertFalse(HdmiCecController.isLanguage(null)); + assertFalse(HdmiCecController.isLanguage("")); + assertFalse(HdmiCecController.isLanguage("e")); + assertFalse(HdmiCecController.isLanguage("一")); // language code must be ASCII + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index 28887fdab00d..09dd3e3e50db 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -75,7 +75,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { private static final int HDMI_3_PHYSICAL_ADDRESS = 0x2300; private int mInvokeDeviceEventState; private HdmiDeviceInfo mDeviceInfo; - private boolean mMutingEnabled; private boolean mArcSupport; private HdmiPortInfo[] mHdmiPortInfo; private boolean mWokenUp; @@ -159,8 +158,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Override boolean readBooleanSystemProperty(String key, boolean defVal) { switch (key) { - case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE: - return mMutingEnabled; case Constants.PROPERTY_ARC_SUPPORT: return mArcSupport; default: @@ -216,7 +213,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); mNativeWrapper.clearResultMessages(); - mMutingEnabled = true; mArcSupport = true; mInvokeDeviceEventState = 0; mDeviceInfo = null; @@ -542,6 +538,15 @@ public class HdmiCecLocalDeviceAudioSystemTest { } @Test + public void setArcStatus() { + mHdmiCecLocalDeviceAudioSystem.setArcStatus(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isTrue(); + + mHdmiCecLocalDeviceAudioSystem.setArcStatus(false); + assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse(); + } + + @Test @Ignore("b/151150320") public void handleSystemAudioModeRequest_fromNonTV_tVNotSupport() { HdmiCecMessage message = diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java new file mode 100644 index 000000000000..ae7f422817e5 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.hdmi; + +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION; +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER; +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT; +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE; +import static com.android.server.hdmi.HdmiCecMessageValidator.OK; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.test.TestLooper; +import android.platform.test.annotations.Presubmit; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; + +import com.google.common.truth.IntegerSubject; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link com.android.server.hdmi.HdmiCecMessageValidator} class. */ +@SmallTest +@Presubmit +@RunWith(JUnit4.class) +public class HdmiCecMessageValidatorTest { + + private HdmiCecMessageValidator mHdmiCecMessageValidator; + private TestLooper mTestLooper = new TestLooper(); + + @Before + public void setUp() throws Exception { + HdmiControlService mHdmiControlService = new HdmiControlService( + InstrumentationRegistry.getTargetContext()); + + mHdmiControlService.setIoLooper(mTestLooper.getLooper()); + mHdmiCecMessageValidator = new HdmiCecMessageValidator(mHdmiControlService); + } + + @Test + public void isValid_unregisteredSource() { + // Message invokes a broadcast response + // <Get Menu Language> + assertMessageValidity("F4:91").isEqualTo(OK); + // <Request Active Source> + assertMessageValidity("FF:85").isEqualTo(OK); + + // Message by CEC Switch + // <Routing Change> + assertMessageValidity("FF:80:00:00:10:00").isEqualTo(OK); + + // <Routing Information> + assertMessageValidity("FF:81:10:00").isEqualTo(OK); + + // Standby + assertMessageValidity("F4:36").isEqualTo(OK); + assertMessageValidity("FF:36").isEqualTo(OK); + + // <Report Physical Address> / <Active Source> + assertMessageValidity("FF:84:10:00:04").isEqualTo(OK); + assertMessageValidity("FF:82:10:00").isEqualTo(OK); + } + + @Test + public void isValid_giveDevicePowerStatus() { + assertMessageValidity("04:8F").isEqualTo(OK); + + assertMessageValidity("0F:8F").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:8F").isEqualTo(ERROR_SOURCE); + } + + @Test + public void isValid_reportPowerStatus() { + assertMessageValidity("04:90:00").isEqualTo(OK); + assertMessageValidity("04:90:03:05").isEqualTo(OK); + + assertMessageValidity("0F:90:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:90").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("04:90:04").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_menuRequest() { + assertMessageValidity("40:8D:00").isEqualTo(OK); + assertMessageValidity("40:8D:02:04").isEqualTo(OK); + + assertMessageValidity("0F:8D:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:8D").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:8D").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:8D:03").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_menuStatus() { + assertMessageValidity("40:8E:00").isEqualTo(OK); + assertMessageValidity("40:8E:01:00").isEqualTo(OK); + + assertMessageValidity("0F:8E:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:8E").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:8E").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:8E:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_systemAudioModeRequest() { + assertMessageValidity("40:70:00:00").isEqualTo(OK); + assertMessageValidity("40:70").isEqualTo(OK); + + assertMessageValidity("F0:70").isEqualTo(ERROR_SOURCE); + // Invalid physical address + assertMessageValidity("40:70:10:10").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setSystemAudioMode() { + assertMessageValidity("40:72:00").isEqualTo(OK); + assertMessageValidity("4F:72:01:03").isEqualTo(OK); + + assertMessageValidity("F0:72").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:72").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:72:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_systemAudioModeStatus() { + assertMessageValidity("40:7E:00").isEqualTo(OK); + assertMessageValidity("40:7E:01:01").isEqualTo(OK); + + assertMessageValidity("0F:7E:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:7E").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:7E").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:7E:02").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setAudioRate() { + assertMessageValidity("40:9A:00").isEqualTo(OK); + assertMessageValidity("40:9A:03").isEqualTo(OK); + assertMessageValidity("40:9A:06:02").isEqualTo(OK); + + assertMessageValidity("0F:9A:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:9A").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:9A").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:9A:07").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setTimerProgramTitle() { + assertMessageValidity("40:67:47:61:6D:65:20:6F:66:20:54:68:72:6F:6E:65:73").isEqualTo(OK); + assertMessageValidity("40:67:4A").isEqualTo(OK); + + assertMessageValidity("4F:67:47:4F:54").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:67:47:4F:54").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:67").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:67:47:9A:54").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setMenuLanguage() { + assertMessageValidity("4F:32:53:50:41").isEqualTo(OK); + assertMessageValidity("0F:32:45:4E:47:8C:49:D3:48").isEqualTo(OK); + + assertMessageValidity("40:32:53:50:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:32").isEqualTo(ERROR_SOURCE); + assertMessageValidity("4F:32:45:55").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("4F:32:19:7F:83").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdString() { + assertMessageValidity("40:64:80:41").isEqualTo(OK); + // Even though the parameter string in this message is longer than 14 bytes, it is accepted + // as this parameter might be extended in future versions. + assertMessageValidity("04:64:00:4C:69:76:69:6E:67:52:6F:6F:6D:20:54:56:C4").isEqualTo(OK); + + assertMessageValidity("4F:64:40:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:64:C0:41").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:64:00").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Display Control + assertMessageValidity("40:64:20:4C:69:76").isEqualTo(ERROR_PARAMETER); + // Invalid ASCII characters + assertMessageValidity("40:64:40:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdName() { + assertMessageValidity("40:47:4C:69:76:69:6E:67:52:6F:6F:6D:54:56").isEqualTo(OK); + assertMessageValidity("40:47:54:56").isEqualTo(OK); + + assertMessageValidity("4F:47:54:56").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:47:54:56").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:47").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:47:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_recordStatus() { + assertMessageValidity("40:0A:01").isEqualTo(OK); + assertMessageValidity("40:0A:13").isEqualTo(OK); + assertMessageValidity("40:0A:1F:04:01").isEqualTo(OK); + + assertMessageValidity("0F:0A:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:0A:01").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:0A").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:0A:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:0A:0F").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:0A:1D").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:0A:30").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setAnalogueTimer_clearAnalogueTimer() { + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:13:AD:06").isEqualTo(OK); + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:03:34").isEqualTo(OK); + + assertMessageValidity("0F:33:0C:08:10:1E:04:30:08:00:13:AD:06") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:34:04:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Broadcast Type + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Frequency + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER); + // Out of range Broadcast System + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setDigitalTimer_clearDigitalTimer() { + // Services identified by Digital IDs - ARIB Broadcast System + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK); + // Service identified by Digital IDs - ATSC Broadcast System + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK); + // Service identified by Digital IDs - DVB Broadcast System + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK); + // Service identified by Channel - 1 part channel number + assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK); + // Service identified by Channel - 2 part channel number + assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK); + + assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:97:0C:08:15:05:04:1E:21:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + + // Invalid Digital Broadcast System + assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER); + // Invalid Channel Number format + assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setExternalTimer_clearExternalTimer() { + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK); + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK); + + assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A1:0C:08:15:05:04:1E:14:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid external source specifier + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid External PLug + assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER); + // Invalid Physical Address + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:10").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerClearedStatus() { + assertMessageValidity("40:43:01:7E").isEqualTo(OK); + assertMessageValidity("40:43:80").isEqualTo(OK); + + assertMessageValidity("4F:43:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:43:80").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:43").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:43:03").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerStatus() { + // Programmed - Space available + assertMessageValidity("40:35:58").isEqualTo(OK); + // Programmed - Not enough space available + assertMessageValidity("40:35:B9:32:1C:4F").isEqualTo(OK); + // Not programmed - Date out of range + assertMessageValidity("40:35:82:3B").isEqualTo(OK); + // Not programmed - Duplicate + assertMessageValidity("40:35:EE:52:0C").isEqualTo(OK); + + assertMessageValidity("4F:35:58").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:35:82").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:35").isEqualTo(ERROR_PARAMETER_SHORT); + // Programmed - Invalid programmed info + assertMessageValidity("40:35:BD").isEqualTo(ERROR_PARAMETER); + // Non programmed - Invalid not programmed error info + assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER); + // Programmed - Might not be enough space available - Invalid duration hours + assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER); + // Not programmed - Duplicate - Invalid duration minutes + assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_deckControl() { + assertMessageValidity("40:42:01:6E").isEqualTo(OK); + assertMessageValidity("40:42:04").isEqualTo(OK); + + assertMessageValidity("4F:42:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:42:04").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:42").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:42:05").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_deckStatus() { + assertMessageValidity("40:1B:11:58").isEqualTo(OK); + assertMessageValidity("40:1B:1F").isEqualTo(OK); + + assertMessageValidity("4F:1B:11").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:1B:1F").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:1B").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:1B:10").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:1B:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_statusRequest() { + assertMessageValidity("40:08:01").isEqualTo(OK); + assertMessageValidity("40:08:02:5C").isEqualTo(OK); + assertMessageValidity("40:1A:01:F8").isEqualTo(OK); + assertMessageValidity("40:1A:03").isEqualTo(OK); + + assertMessageValidity("4F:08:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:08:03").isEqualTo(ERROR_SOURCE); + assertMessageValidity("4F:1A:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:1A:03").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:08").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:1A").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:08:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:08:05").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:1A:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:1A:04").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_play() { + assertMessageValidity("40:41:16:E3").isEqualTo(OK); + assertMessageValidity("40:41:20").isEqualTo(OK); + + assertMessageValidity("4F:41:16").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:41:20").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:41").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:41:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:41:18").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:41:23").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:41:26").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_selectAnalogueService() { + assertMessageValidity("40:92:00:13:0F:00:96").isEqualTo(OK); + assertMessageValidity("40:92:02:EA:60:1F").isEqualTo(OK); + + assertMessageValidity("4F:92:00:13:0F:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:92:02:EA:60:1F").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:92:00:13:0F").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Analogue Broadcast type + assertMessageValidity("40:92:03:EA:60:1F").isEqualTo(ERROR_PARAMETER); + // Invalid Analogue Frequency + assertMessageValidity("40:92:00:FF:FF:00").isEqualTo(ERROR_PARAMETER); + // Invalid Broadcast system + assertMessageValidity("40:92:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_selectDigitalService() { + assertMessageValidity("40:93:00:11:CE:90:0F:00:78").isEqualTo(OK); + assertMessageValidity("40:93:10:13:0B:34:38").isEqualTo(OK); + assertMessageValidity("40:93:9A:06:F9:D3:E6").isEqualTo(OK); + assertMessageValidity("40:93:91:09:F4:40:C8").isEqualTo(OK); + + assertMessageValidity("4F:93:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:93:10:13:0B:34:38").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:93:9A:06:F9").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Digital Broadcast System + assertMessageValidity("40:93:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("40:93:A0:07:95:F1").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("40:93:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("40:93:10:13:0B:34").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("40:93:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER); + // Invalid channel number format + assertMessageValidity("40:93:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("40:93:91:09:F4:40").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_tunerDeviceStatus() { + // Displaying digital tuner + assertMessageValidity("40:07:00:00:11:CE:90:0F:00:78").isEqualTo(OK); + assertMessageValidity("40:07:80:10:13:0B:34:38").isEqualTo(OK); + assertMessageValidity("40:07:00:9A:06:F9:D3:E6").isEqualTo(OK); + assertMessageValidity("40:07:00:91:09:F4:40:C8").isEqualTo(OK); + // Not displaying tuner + assertMessageValidity("40:07:01").isEqualTo(OK); + assertMessageValidity("40:07:81:07:64:B9:02").isEqualTo(OK); + // Displaying analogue tuner + assertMessageValidity("40:07:02:00:13:0F:00:96").isEqualTo(OK); + assertMessageValidity("40:07:82:02:EA:60:1F").isEqualTo(OK); + + assertMessageValidity("4F:07:00:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:07:82:02:EA:60:1F").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:07").isEqualTo(ERROR_PARAMETER_SHORT); + + // Invalid display info + assertMessageValidity("40:07:09:A1:8C:17:51").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:07:A7:0C:29").isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("40:07:00:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("40:07:80:A0:07:95:F1").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("40:07:00:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("40:07:80:10:13:0B:34").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("40:07:00:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER); + // Invalid channel number format + assertMessageValidity("40:07:80:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 1 part channel number + assertMessageValidity("40:07:00:90:04:F7").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("40:07:80:91:09:F4:40").isEqualTo(ERROR_PARAMETER); + // Invalid Analogue Broadcast type + assertMessageValidity("40:07:02:03:EA:60:1F").isEqualTo(ERROR_PARAMETER); + // Invalid Analogue Frequency + assertMessageValidity("40:07:82:00:FF:FF:00").isEqualTo(ERROR_PARAMETER); + // Invalid Broadcast system + assertMessageValidity("40:07:02:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_UserControlPressed() { + assertMessageValidity("40:44:07").isEqualTo(OK); + assertMessageValidity("40:44:52:A7").isEqualTo(OK); + + assertMessageValidity("40:44:60").isEqualTo(OK); + assertMessageValidity("40:44:60:1A").isEqualTo(OK); + + assertMessageValidity("40:44:67").isEqualTo(OK); + assertMessageValidity("40:44:67:04:00:B1").isEqualTo(OK); + assertMessageValidity("40:44:67:09:C8:72:C8").isEqualTo(OK); + + assertMessageValidity("40:44:68").isEqualTo(OK); + assertMessageValidity("40:44:68:93").isEqualTo(OK); + assertMessageValidity("40:44:69").isEqualTo(OK); + assertMessageValidity("40:44:69:7C").isEqualTo(OK); + assertMessageValidity("40:44:6A").isEqualTo(OK); + assertMessageValidity("40:44:6A:B4").isEqualTo(OK); + + assertMessageValidity("40:44:56").isEqualTo(OK); + assertMessageValidity("40:44:56:60").isEqualTo(OK); + + assertMessageValidity("40:44:57").isEqualTo(OK); + assertMessageValidity("40:44:57:A0").isEqualTo(OK); + + assertMessageValidity("4F:44:07").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:44:52:A7").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:44").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:44:67:04:B1").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Play mode + assertMessageValidity("40:44:60:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:44:60:08").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:44:60:26").isEqualTo(ERROR_PARAMETER); + // Invalid Channel Identifier - Channel number format + assertMessageValidity("40:44:67:11:8A:42").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 - part channel number + assertMessageValidity("40:44:67:09:C8:72").isEqualTo(ERROR_PARAMETER); + // Invalid UI Broadcast type + assertMessageValidity("40:44:56:11").isEqualTo(ERROR_PARAMETER); + // Invalid UI Sound Presentation Control + assertMessageValidity("40:44:57:40").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_physicalAddress() { + assertMessageValidity("4F:82:10:00").isEqualTo(OK); + assertMessageValidity("4F:82:12:34").isEqualTo(OK); + assertMessageValidity("0F:82:00:00").isEqualTo(OK); + assertMessageValidity("40:9D:14:00").isEqualTo(OK); + assertMessageValidity("40:9D:10:00").isEqualTo(OK); + assertMessageValidity("0F:81:44:20").isEqualTo(OK); + assertMessageValidity("4F:81:13:10").isEqualTo(OK); + assertMessageValidity("4F:86:14:14").isEqualTo(OK); + assertMessageValidity("0F:86:15:24").isEqualTo(OK); + + assertMessageValidity("4F:82:10").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:9D:14").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:81:44").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:86:15").isEqualTo(ERROR_PARAMETER_SHORT); + + assertMessageValidity("4F:82:10:10").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:82:10:06").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:9D:14:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:9D:10:01").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:81:44:02").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:81:13:05").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:86:10:14").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:86:10:24").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_reportPhysicalAddress() { + assertMessageValidity("4F:84:10:00:04").isEqualTo(OK); + assertMessageValidity("0F:84:00:00:00").isEqualTo(OK); + + assertMessageValidity("4F:84:10:00").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:84:00").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:84:10:00:04").isEqualTo(ERROR_DESTINATION); + // Invalid Physical Address + assertMessageValidity("4F:84:10:10:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:84:00:30:00").isEqualTo(ERROR_PARAMETER); + // Invalid Device Type + assertMessageValidity("4F:84:12:34:08").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_routingChange() { + assertMessageValidity("0F:80:10:00:40:00").isEqualTo(OK); + assertMessageValidity("4F:80:12:00:50:00").isEqualTo(OK); + + assertMessageValidity("0F:80:10:00:40").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:80:12:00:50:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("0F:80:10:01:40:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:80:12:00:50:50").isEqualTo(ERROR_PARAMETER); + } + + private IntegerSubject assertMessageValidity(String message) { + return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message))); + } + + /** + * Build a CEC message from a hex byte string with bytes separated by {@code :}. + * + * <p>This format is used by both cec-client and www.cec-o-matic.com + */ + private static HdmiCecMessage buildMessage(String message) { + String[] parts = message.split(":"); + int src = Integer.parseInt(parts[0].substring(0, 1), 16); + int dest = Integer.parseInt(parts[0].substring(1, 2), 16); + int opcode = Integer.parseInt(parts[1], 16); + byte[] params = new byte[parts.length - 2]; + for (int i = 0; i < params.length; i++) { + params[i] = (byte) Integer.parseInt(parts[i + 2], 16); + } + return new HdmiCecMessage(src, dest, opcode, params); + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OWNERS b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS new file mode 100644 index 000000000000..c3c47eda59d7 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/hdmi/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/input/OWNERS b/services/tests/servicestests/src/com/android/server/input/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/input/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java index e4c9cc3c05d9..1d914ec083fa 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java @@ -88,36 +88,36 @@ public class InputMethodUtilsTest { public void testVoiceImes() throws Exception { // locale: en_US assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); // locale: en_GB assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); // locale: ja_JP assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); } @Test @@ -189,67 +189,67 @@ public class InputMethodUtilsTest { @Test public void testGetImplicitlyApplicableSubtypesLocked() throws Exception { - final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnIN = createDummyInputMethodSubtype("en_IN", + final InputMethodSubtype nonAutoEnIN = createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA", + final InputMethodSubtype nonAutoFrCA = createFakeInputMethodSubtype("fr_CA", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA", + final InputMethodSubtype nonAutoFr = createFakeInputMethodSubtype("fr_CA", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto", + final InputMethodSubtype autoSubtype = createFakeInputMethodSubtype("auto", SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja", + final InputMethodSubtype nonAutoJa = createFakeInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi", + final InputMethodSubtype nonAutoHi = createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoSrCyrl = createDummyInputMethodSubtype("sr", + final InputMethodSubtype nonAutoSrCyrl = createFakeInputMethodSubtype("sr", "sr-Cyrl", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoSrLatn = createDummyInputMethodSubtype("sr_ZZ", + final InputMethodSubtype nonAutoSrLatn = createFakeInputMethodSubtype("sr_ZZ", "sr-Latn", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en", + final InputMethodSubtype nonAutoHandwritingEn = createFakeInputMethodSubtype("en", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingFr = createDummyInputMethodSubtype("fr", + final InputMethodSubtype nonAutoHandwritingFr = createFakeInputMethodSubtype("fr", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingSrCyrl = createDummyInputMethodSubtype("sr", + final InputMethodSubtype nonAutoHandwritingSrCyrl = createFakeInputMethodSubtype("sr", "sr-Cyrl", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingSrLatn = createDummyInputMethodSubtype("sr_ZZ", + final InputMethodSubtype nonAutoHandwritingSrLatn = createFakeInputMethodSubtype("sr_ZZ", "sr-Latn", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype = - createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 = - createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); @@ -266,9 +266,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -290,9 +290,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -314,9 +314,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -339,9 +339,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -360,9 +360,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -382,9 +382,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -404,9 +404,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -421,9 +421,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -438,9 +438,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnUS); subtypes.add(nonAutoHi); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -460,9 +460,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -480,9 +480,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -506,9 +506,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -533,9 +533,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoEnUS); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -551,9 +551,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoJa); subtypes.add(nonAutoEnUS); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -567,9 +567,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -581,9 +581,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -595,9 +595,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -609,9 +609,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -631,9 +631,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoFil); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -649,22 +649,22 @@ public class InputMethodUtilsTest { @Test public void testContainsSubtypeOf() throws Exception { - final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH", + final InputMethodSubtype nonAutoFilPH = createFakeInputMethodSubtype("fil_PH", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); @@ -673,9 +673,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY, @@ -705,9 +705,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -732,9 +732,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoFilPH); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -760,9 +760,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -779,9 +779,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -866,7 +866,7 @@ public class InputMethodUtilsTest { assertEquals(expected.hashCode(), actual.hashCode()); } - private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, + private static InputMethodInfo createFakeInputMethodInfo(String packageName, String name, CharSequence label, boolean isAuxIme, boolean isDefault, List<InputMethodSubtype> subtypes) { final ResolveInfo ri = new ResolveInfo(); @@ -885,15 +885,15 @@ public class InputMethodUtilsTest { return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); } - private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, + private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String mode, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { - return createDummyInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary, + return createFakeInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable, isEnabledWhenDefaultIsNotAsciiCapable); } - private static InputMethodSubtype createDummyInputMethodSubtype(String locale, + private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String languageTag, String mode, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { @@ -920,14 +920,14 @@ public class InputMethodUtilsTest { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", - "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultAutoVoiceIme", + "fake.voice0", "FakeVoice0", IS_AUX, IS_DEFAULT, subtypes)); } preinstalledImes.addAll(getImesWithoutDefaultVoiceIme()); return preinstalledImes; @@ -937,41 +937,41 @@ public class InputMethodUtilsTest { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", - "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme0", + "fake.voice1", "FakeVoice1", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", - "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme1", + "fake.voice2", "FakeVoice2", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", - "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultVoiceIme2", + "fake.voice3", "FakeVoice3", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", - "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultEnKeyboardIme", + "fake.keyboard0", "FakeKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); } return preinstalledImes; } @@ -991,91 +991,91 @@ public class InputMethodUtilsTest { private static ArrayList<InputMethodInfo> getSamplePreinstalledImes(final String localeString) { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); - // a dummy Voice IME + // a fake Voice IME { final boolean isDefaultIme = false; final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice", - "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.voice", + "com.android.inputmethod.voice", "FakeVoiceIme", IS_AUX, isDefaultIme, subtypes)); } - // a dummy Hindi IME + // a fake Hindi IME { final boolean isDefaultIme = contains(new String[]{ "hi", "en-rIN" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); // TODO: This subtype should be marked as IS_ASCII_CAPABLE - subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi", - "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.hindi", + "com.android.inputmethod.hindi", "FakeHindiIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Pinyin IME + // a fake Pinyin IME { final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin", - "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.pinyin", + "com.android.apps.inputmethod.pinyin", "FakePinyinIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Korean IME + // a fake Korean IME { final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean", - "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.korean", + "com.android.apps.inputmethod.korean", "FakeKoreanIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Latin IME + // a fake Latin IME { final boolean isDefaultIme = contains( new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Japanese IME + // a fake Japanese IME { final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese", - "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.japanese", + "com.android.apps.inputmethod.japanese", "FakeJapaneseIme", !IS_AUX, isDefaultIme, subtypes)); } diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java index 41be54ab5b7a..f26e0941e008 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java @@ -194,7 +194,7 @@ public class IntegrityFileManagerTest { assertThat(rulesFetched.size()) .isEqualTo(INDEXING_BLOCK_SIZE * 2 + unindexedRuleCount); assertThat(rulesFetched) - .containsAllOf( + .containsAtLeast( getPackageNameIndexedRule(installedPackageName), getAppCertificateIndexedRule(installedAppCertificate)); } diff --git a/services/tests/servicestests/src/com/android/server/integrity/OWNERS b/services/tests/servicestests/src/com/android/server/integrity/OWNERS new file mode 100644 index 000000000000..653d1c969528 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/integrity/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/integrity/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java index 0488745c2434..441cd4b47c94 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java @@ -178,7 +178,7 @@ public class RuleEvaluationEngineTest { .isEqualTo(IntegrityCheckResult.Effect.DENY); } - /** Returns a builder with all fields filled with some dummy data. */ + /** Returns a builder with all fields filled with some placeholder data. */ private AppInstallMetadata.Builder getAppInstallMetadataBuilder() { return new AppInstallMetadata.Builder() .setPackageName("abc") diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java index cae7b57580bb..deaeb46c4074 100644 --- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java @@ -505,7 +505,7 @@ public class JobStoreTest { first.getTransientExtras().toString(), second.getTransientExtras().toString()); // Since people can forget to add tests here for new fields, do one last - // sanity check based on bits-on-wire equality. + // validity check based on bits-on-wire equality. final byte[] firstBytes = marshall(first); final byte[] secondBytes = marshall(second); if (!Arrays.equals(firstBytes, secondBytes)) { diff --git a/services/tests/servicestests/src/com/android/server/job/OWNERS b/services/tests/servicestests/src/com/android/server/job/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/job/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/lights/OWNERS b/services/tests/servicestests/src/com/android/server/lights/OWNERS new file mode 100644 index 000000000000..cb46a80d9b60 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/lights/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/lights/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 4e1454bd0962..1db5fcc70420 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -150,7 +150,7 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override - public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) { + public RecoverableKeyStoreManager getRecoverableKeyStoreManager() { return mRecoverableKeyStoreManager; } 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/LockSettingsStorageTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java index 1581d9ac1811..691d174f55f8 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java @@ -82,6 +82,11 @@ public class LockSettingsStorageTestable extends LockSettingsStorage { } @Override + String getRebootEscrowServerBlob() { + return makeDirs(mStorageDir, super.getRebootEscrowServerBlob()).getAbsolutePath(); + } + + @Override protected File getSyntheticPasswordDirectoryForUser(int userId) { return makeDirs(mStorageDir, super.getSyntheticPasswordDirectoryForUser( userId).getAbsolutePath()); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/OWNERS b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS new file mode 100644 index 000000000000..0a8dc8c45a9f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/locksettings/OWNERS 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 46f43e7af596..2eedc3251daa 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java @@ -25,16 +25,32 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + /** * atest FrameworksServicesTests:RebootEscrowDataTest */ @RunWith(AndroidJUnit4.class) public class RebootEscrowDataTest { private RebootEscrowKey mKey; + private SecretKey mKeyStoreEncryptionKey; + + // 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 = new SecretKeySpec(TEST_AES_KEY, "AES"); } private static byte[] getTestSp() { @@ -47,36 +63,68 @@ public class RebootEscrowDataTest { @Test(expected = NullPointerException.class) public void fromEntries_failsOnNull() throws Exception { - RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, null); + RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, null, mKeyStoreEncryptionKey); } @Test(expected = NullPointerException.class) public void fromEncryptedData_failsOnNullData() throws Exception { byte[] testSp = getTestSp(); - RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp, + mKeyStoreEncryptionKey); RebootEscrowKey key = RebootEscrowKey.fromKeyBytes(expected.getKey().getKeyBytes()); - RebootEscrowData.fromEncryptedData(key, null); + RebootEscrowData.fromEncryptedData(key, null, mKeyStoreEncryptionKey); } @Test(expected = NullPointerException.class) public void fromEncryptedData_failsOnNullKey() throws Exception { byte[] testSp = getTestSp(); - RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp); - RebootEscrowData.fromEncryptedData(null, expected.getBlob()); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp, + mKeyStoreEncryptionKey); + RebootEscrowData.fromEncryptedData(null, expected.getBlob(), mKeyStoreEncryptionKey); } @Test public void fromEntries_loopback_success() throws Exception { byte[] testSp = getTestSp(); - RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp, + mKeyStoreEncryptionKey); RebootEscrowKey key = RebootEscrowKey.fromKeyBytes(expected.getKey().getKeyBytes()); - RebootEscrowData actual = RebootEscrowData.fromEncryptedData(key, expected.getBlob()); + RebootEscrowData actual = RebootEscrowData.fromEncryptedData(key, expected.getBlob(), + mKeyStoreEncryptionKey); assertThat(actual.getSpVersion(), is(expected.getSpVersion())); - assertThat(actual.getIv(), is(expected.getIv())); assertThat(actual.getKey().getKeyBytes(), is(expected.getKey().getKeyBytes())); assertThat(actual.getBlob(), is(expected.getBlob())); assertThat(actual.getSyntheticPassword(), is(expected.getSyntheticPassword())); } + + @Test + public void aesEncryptedBlob_loopback_success() throws Exception { + byte[] testSp = getTestSp(); + byte [] encrypted = AesEncryptionUtil.encrypt(mKeyStoreEncryptionKey, testSp); + byte [] decrypted = AesEncryptionUtil.decrypt(mKeyStoreEncryptionKey, encrypted); + + 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 c4d121170624..a896f1b0d60f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doNothing; @@ -42,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; @@ -52,6 +54,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.widget.RebootEscrowListener; +import com.android.server.locksettings.ResumeOnRebootServiceProvider.ResumeOnRebootServiceConnection; import org.junit.Before; import org.junit.Test; @@ -61,6 +64,9 @@ import org.mockito.ArgumentCaptor; import java.io.File; import java.util.ArrayList; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) @@ -77,15 +83,26 @@ public class RebootEscrowManagerTests { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }; + // Hex encoding of a randomly generated AES key for test. + private static final byte[] TEST_AES_KEY = new byte[] { + 0x48, 0x19, 0x12, 0x54, 0x13, 0x13, 0x52, 0x31, + 0x44, 0x74, 0x61, 0x54, 0x29, 0x74, 0x37, 0x61, + 0x70, 0x70, 0x75, 0x25, 0x27, 0x31, 0x49, 0x09, + 0x26, 0x52, 0x72, 0x63, 0x63, 0x61, 0x78, 0x23, + }; + private Context mContext; private UserManager mUserManager; private RebootEscrowManager.Callbacks mCallbacks; private IRebootEscrow mRebootEscrow; + private ResumeOnRebootServiceConnection mServiceConnection; + private RebootEscrowKeyStoreManager mKeyStoreManager; LockSettingsStorageTestable mStorage; private MockableRebootEscrowInjected mInjected; private RebootEscrowManager mService; + private SecretKey mAesKey; public interface MockableRebootEscrowInjected { int getBootCount(); @@ -95,25 +112,67 @@ public class RebootEscrowManagerTests { static class MockInjector extends RebootEscrowManager.Injector { private final IRebootEscrow mRebootEscrow; + private final ResumeOnRebootServiceConnection mServiceConnection; + private final RebootEscrowProviderInterface mRebootEscrowProvider; private final UserManager mUserManager; private final MockableRebootEscrowInjected mInjected; + private final RebootEscrowKeyStoreManager mKeyStoreManager; - MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow, + MockInjector(Context context, UserManager userManager, + IRebootEscrow rebootEscrow, + RebootEscrowKeyStoreManager keyStoreManager, + LockSettingsStorageTestable storage, MockableRebootEscrowInjected injected) { - super(context); + super(context, storage); mRebootEscrow = rebootEscrow; + mServiceConnection = null; + RebootEscrowProviderHalImpl.Injector halInjector = + new RebootEscrowProviderHalImpl.Injector() { + @Override + public IRebootEscrow getRebootEscrow() { + return mRebootEscrow; + } + }; + mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector); + mUserManager = userManager; + mKeyStoreManager = keyStoreManager; + mInjected = injected; + } + + MockInjector(Context context, UserManager userManager, + ResumeOnRebootServiceConnection serviceConnection, + RebootEscrowKeyStoreManager keyStoreManager, + LockSettingsStorageTestable storage, + MockableRebootEscrowInjected injected) { + super(context, storage); + mServiceConnection = serviceConnection; + mRebootEscrow = null; + RebootEscrowProviderServerBasedImpl.Injector injector = + new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection); + mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(storage, injector); mUserManager = userManager; + mKeyStoreManager = keyStoreManager; mInjected = injected; } @Override + void post(Handler handler, Runnable runnable) { + runnable.run(); + } + + @Override public UserManager getUserManager() { return mUserManager; } @Override - public IRebootEscrow getRebootEscrow() { - return mRebootEscrow; + public RebootEscrowProviderInterface getRebootEscrowProvider() { + return mRebootEscrowProvider; + } + + @Override + public RebootEscrowKeyStoreManager getKeyStoreManager() { + return mKeyStoreManager; } @Override @@ -133,6 +192,12 @@ public class RebootEscrowManagerTests { mUserManager = mock(UserManager.class); mCallbacks = mock(RebootEscrowManager.Callbacks.class); mRebootEscrow = mock(IRebootEscrow.class); + mServiceConnection = mock(ResumeOnRebootServiceConnection.class); + mKeyStoreManager = mock(RebootEscrowKeyStoreManager.class); + mAesKey = new SecretKeySpec(TEST_AES_KEY, "AES"); + + when(mKeyStoreManager.getKeyStoreEncryptionKey()).thenReturn(mAesKey); + when(mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded()).thenReturn(mAesKey); mStorage = new LockSettingsStorageTestable(mContext, new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); @@ -149,7 +214,12 @@ public class RebootEscrowManagerTests { when(mCallbacks.isUserSecure(SECURE_SECONDARY_USER_ID)).thenReturn(true); mInjected = mock(MockableRebootEscrowInjected.class); mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager, mRebootEscrow, - mInjected), mCallbacks, mStorage); + mKeyStoreManager, mStorage, mInjected), mCallbacks, mStorage); + } + + private void setServerBasedRebootEscrowProvider() throws Exception { + mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager, + mServiceConnection, mKeyStoreManager, mStorage, mInjected), mCallbacks, mStorage); } @Test @@ -165,6 +235,19 @@ public class RebootEscrowManagerTests { } @Test + public void prepareRebootEscrowServerBased_Success() throws Exception { + setServerBasedRebootEscrowProvider(); + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong()); + assertFalse(mStorage.hasRebootEscrowServerBlob()); + } + + @Test public void prepareRebootEscrow_ClearCredentials_Success() throws Exception { RebootEscrowListener mockListener = mock(RebootEscrowListener.class); mService.setRebootEscrowListener(mockListener); @@ -202,9 +285,32 @@ public class RebootEscrowManagerTests { assertNotNull( mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM)); verify(mRebootEscrow).storeKey(any()); + verify(mKeyStoreManager).getKeyStoreEncryptionKey(); + + assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); + assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); + } + + @Test + public void armServiceServerBased_Success() throws Exception { + setServerBasedRebootEscrowProvider(); + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mServiceConnection); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong()); + + when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())) + .thenAnswer(invocation -> invocation.getArgument(0)); + assertTrue(mService.armRebootEscrowIfNeeded()); + verify(mServiceConnection).wrapBlob(any(), anyLong(), anyLong()); assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); + assertTrue(mStorage.hasRebootEscrowServerBlob()); } @Test @@ -269,7 +375,7 @@ public class RebootEscrowManagerTests { @Test public void loadRebootEscrowDataIfAvailable_NothingAvailable_Success() throws Exception { - mService.loadRebootEscrowDataIfAvailable(); + mService.loadRebootEscrowDataIfAvailable(null); } @Test @@ -289,6 +395,7 @@ public class RebootEscrowManagerTests { ArgumentCaptor<byte[]> keyByteCaptor = ArgumentCaptor.forClass(byte[].class); assertTrue(mService.armRebootEscrowIfNeeded()); verify(mRebootEscrow).storeKey(keyByteCaptor.capture()); + verify(mKeyStoreManager).getKeyStoreEncryptionKey(); assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); @@ -300,9 +407,44 @@ 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(); + } + + @Test + public void loadRebootEscrowDataIfAvailable_ServerBased_Success() throws Exception { + setServerBasedRebootEscrowProvider(); + + when(mInjected.getBootCount()).thenReturn(0); + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mServiceConnection); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong()); + + // Use x -> x for both wrap & unwrap functions. + when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())) + .thenAnswer(invocation -> invocation.getArgument(0)); + assertTrue(mService.armRebootEscrowIfNeeded()); + verify(mServiceConnection).wrapBlob(any(), anyLong(), anyLong()); + assertTrue(mStorage.hasRebootEscrowServerBlob()); + + // pretend reboot happens here + when(mInjected.getBootCount()).thenReturn(1); + ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + + when(mServiceConnection.unwrap(any(), anyLong())) + .thenAnswer(invocation -> invocation.getArgument(0)); + mService.loadRebootEscrowDataIfAvailable(null); + verify(mServiceConnection).unwrap(any(), anyLong()); + assertTrue(metricsSuccessCaptor.getValue()); + verify(mKeyStoreManager).clearKeyStoreEncryptionKey(); } @Test @@ -330,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()); } @@ -357,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()); } @@ -391,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)); } @@ -421,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 new file mode 100644 index 000000000000..28b737b412d2 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowProviderServerBasedImplTests.java @@ -0,0 +1,145 @@ +/* + * 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.locksettings; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +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; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.stubbing.Answer; + +import java.io.File; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +@SmallTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class RebootEscrowProviderServerBasedImplTests { + private SecretKey mKeyStoreEncryptionKey; + private RebootEscrowKey mRebootEscrowKey; + private ResumeOnRebootServiceProvider.ResumeOnRebootServiceConnection mServiceConnection; + private LockSettingsStorageTestable mStorage; + private RebootEscrowProviderServerBasedImpl mRebootEscrowProvider; + private Answer<byte[]> mFakeEncryption; + + private static final byte[] TEST_AES_KEY = new byte[] { + 0x48, 0x19, 0x12, 0x54, 0x13, 0x13, 0x52, 0x31, + 0x44, 0x74, 0x61, 0x54, 0x29, 0x74, 0x37, 0x61, + 0x70, 0x70, 0x75, 0x25, 0x27, 0x31, 0x49, 0x09, + 0x26, 0x52, 0x72, 0x63, 0x63, 0x61, 0x78, 0x23, + }; + + @Before + public void setUp() throws Exception { + mKeyStoreEncryptionKey = new SecretKeySpec(TEST_AES_KEY, "AES"); + mRebootEscrowKey = RebootEscrowKey.generate(); + mServiceConnection = mock( + ResumeOnRebootServiceProvider.ResumeOnRebootServiceConnection.class); + + Context context = new ContextWrapper(InstrumentationRegistry.getContext()); + mStorage = new LockSettingsStorageTestable(context, + new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); + mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mStorage, + new RebootEscrowProviderServerBasedImpl.Injector(mServiceConnection)); + + mFakeEncryption = invocation -> { + byte[] secret = invocation.getArgument(0); + for (int i = 0; i < secret.length; i++) { + secret[i] = (byte) (secret[i] ^ 0xf); + } + return secret; + }; + } + + @Test + public void getAndClearRebootEscrowKey_loopback_success() throws Exception { + when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())).thenAnswer(mFakeEncryption); + when(mServiceConnection.unwrap(any(), anyLong())).thenAnswer(mFakeEncryption); + + assertTrue(mRebootEscrowProvider.hasRebootEscrowSupport()); + mRebootEscrowProvider.storeRebootEscrowKey(mRebootEscrowKey, mKeyStoreEncryptionKey); + assertTrue(mStorage.hasRebootEscrowServerBlob()); + + + RebootEscrowKey ks = mRebootEscrowProvider.getAndClearRebootEscrowKey( + mKeyStoreEncryptionKey); + assertThat(ks.getKeyBytes(), is(mRebootEscrowKey.getKeyBytes())); + assertFalse(mStorage.hasRebootEscrowServerBlob()); + } + + @Test + public void getAndClearRebootEscrowKey_WrongDecryptionMethod_failure() throws Exception { + when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())).thenAnswer(mFakeEncryption); + when(mServiceConnection.unwrap(any(), anyLong())).thenAnswer( + invocation -> { + byte[] secret = invocation.getArgument(0); + for (int i = 0; i < secret.length; i++) { + secret[i] = (byte) (secret[i] ^ 0xe); + } + return secret; + } + ); + + assertTrue(mRebootEscrowProvider.hasRebootEscrowSupport()); + mRebootEscrowProvider.storeRebootEscrowKey(mRebootEscrowKey, mKeyStoreEncryptionKey); + assertTrue(mStorage.hasRebootEscrowServerBlob()); + + // Expect to get wrong key bytes + RebootEscrowKey ks = mRebootEscrowProvider.getAndClearRebootEscrowKey( + mKeyStoreEncryptionKey); + assertNotEquals(ks.getKeyBytes(), mRebootEscrowKey.getKeyBytes()); + assertFalse(mStorage.hasRebootEscrowServerBlob()); + } + + @Test + public void getAndClearRebootEscrowKey_ServiceConnectionException_failure() throws Exception { + when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())).thenAnswer(mFakeEncryption); + doThrow(RemoteException.class).when(mServiceConnection).unwrap(any(), anyLong()); + + assertTrue(mRebootEscrowProvider.hasRebootEscrowSupport()); + mRebootEscrowProvider.storeRebootEscrowKey(mRebootEscrowKey, mKeyStoreEncryptionKey); + assertTrue(mStorage.hasRebootEscrowServerBlob()); + + // Expect to get null key bytes when the server service fails to unwrap the blob. + RebootEscrowKey ks = mRebootEscrowProvider.getAndClearRebootEscrowKey( + mKeyStoreEncryptionKey); + assertNull(ks); + assertFalse(mStorage.hasRebootEscrowServerBlob()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java new file mode 100644 index 000000000000..b9af82b64c02 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java @@ -0,0 +1,111 @@ +/* + * 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.locksettings; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.Manifest; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.resumeonreboot.ResumeOnRebootService; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +@SmallTest +@RunWith(JUnit4.class) +public class ResumeOnRebootServiceProviderTests { + + @Mock + Context mMockContext; + @Mock + PackageManager mMockPackageManager; + @Mock + ResolveInfo mMockResolvedInfo; + @Mock + ServiceInfo mMockServiceInfo; + @Mock + ComponentName mMockComponentName; + @Captor + ArgumentCaptor<Intent> mIntentArgumentCaptor; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mMockContext.getUserId()).thenReturn(0); + when(mMockResolvedInfo.serviceInfo).thenReturn(mMockServiceInfo); + when(mMockServiceInfo.getComponentName()).thenReturn(mMockComponentName); + } + + @Test + public void noServiceFound() throws Exception { + when(mMockPackageManager.queryIntentServices(any(), + eq(PackageManager.MATCH_SYSTEM_ONLY))).thenReturn( + null); + assertThat(new ResumeOnRebootServiceProvider(mMockContext, + mMockPackageManager).getServiceConnection()).isNull(); + } + + @Test + public void serviceNotGuardedWithPermission() throws Exception { + ArrayList<ResolveInfo> resultList = new ArrayList<>(); + when(mMockServiceInfo.permission).thenReturn(""); + resultList.add(mMockResolvedInfo); + when(mMockPackageManager.queryIntentServices(any(), any())).thenReturn( + resultList); + assertThat(new ResumeOnRebootServiceProvider(mMockContext, + mMockPackageManager).getServiceConnection()).isNull(); + } + + @Test + public void serviceResolved() throws Exception { + ArrayList<ResolveInfo> resultList = new ArrayList<>(); + resultList.add(mMockResolvedInfo); + when(mMockServiceInfo.permission).thenReturn( + Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE); + when(mMockPackageManager.queryIntentServices(any(), + eq(PackageManager.MATCH_SYSTEM_ONLY))).thenReturn( + resultList); + + assertThat(new ResumeOnRebootServiceProvider(mMockContext, + mMockPackageManager).getServiceConnection()).isNotNull(); + + verify(mMockPackageManager).queryIntentServices(mIntentArgumentCaptor.capture(), + eq(PackageManager.MATCH_SYSTEM_ONLY)); + assertThat(mIntentArgumentCaptor.getValue().getAction()).isEqualTo( + ResumeOnRebootService.SERVICE_INTERFACE); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index 7d3ec030e7a6..a38745f2a66e 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -406,7 +406,7 @@ public class KeySyncTaskTest { mRecoverableKeyStoreDb.setRecoveryServiceCertPath( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); - // Enter test mode with whitelisted credentials + // Enter test mode with allowlisted credentials when(mTestOnlyInsecureCertificateHelper.isTestOnlyCertificateAlias(any())).thenReturn(true); when(mTestOnlyInsecureCertificateHelper.doesCredentialSupportInsecureMode(anyInt(), any())) .thenReturn(true); @@ -415,7 +415,7 @@ public class KeySyncTaskTest { verify(mTestOnlyInsecureCertificateHelper) .getDefaultCertificateAliasIfEmpty(eq(TEST_ROOT_CERT_ALIAS)); - // run whitelist checks + // run allowlist checks verify(mTestOnlyInsecureCertificateHelper) .doesCredentialSupportInsecureMode(anyInt(), any()); verify(mTestOnlyInsecureCertificateHelper) @@ -424,7 +424,7 @@ public class KeySyncTaskTest { KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertNotNull(keyChainSnapshot); // created snapshot List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys(); - assertThat(applicationKeys).hasSize(0); // non whitelisted key is not included + assertThat(applicationKeys).hasSize(0); // non allowlisted key is not included verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt()); } @@ -437,7 +437,7 @@ public class KeySyncTaskTest { mRecoverableKeyStoreDb.setRecoveryServiceCertPath( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); - // Enter test mode with non whitelisted credentials + // Enter test mode with non allowlisted credentials when(mTestOnlyInsecureCertificateHelper.isTestOnlyCertificateAlias(any())).thenReturn(true); when(mTestOnlyInsecureCertificateHelper.doesCredentialSupportInsecureMode(anyInt(), any())) .thenReturn(false); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java index 6921bb27ceb2..8d5687c33419 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java @@ -71,7 +71,7 @@ public class TestOnlyInsecureCertificateHelperTest { Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); - assertThat(filteredKeys.entrySet()).containsAllIn(rawKeys.entrySet()); + assertThat(filteredKeys.entrySet()).containsAtLeastElementsIn(rawKeys.entrySet()); } @Test @@ -85,7 +85,7 @@ public class TestOnlyInsecureCertificateHelperTest { Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); - assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); + assertThat(rawKeys.entrySet()).containsAtLeastElementsIn(filteredKeys.entrySet()); } @Test @@ -100,7 +100,7 @@ public class TestOnlyInsecureCertificateHelperTest { Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); - assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); + assertThat(rawKeys.entrySet()).containsAtLeastElementsIn(filteredKeys.entrySet()); } @Test @@ -122,7 +122,7 @@ public class TestOnlyInsecureCertificateHelperTest { Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); - assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); + assertThat(rawKeys.entrySet()).containsAtLeastElementsIn(filteredKeys.entrySet()); } @Test diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java index 9836c64ea5b5..b0cb2ea85bf4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java @@ -70,7 +70,7 @@ public final class CertXmlTest { CertXml certXml = CertXml.parse(certXmlBytes); List<X509Certificate> endpointCerts = certXml.getAllEndpointCerts(); assertThat(endpointCerts).hasSize(3); - assertThat(endpointCerts).containsAllOf(TestData.LEAF_CERT_1, TestData.LEAF_CERT_2); + assertThat(endpointCerts).containsAtLeast(TestData.LEAF_CERT_1, TestData.LEAF_CERT_2); } @Test diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 7767a2810ac2..401d6e30df13 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -20,11 +20,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.util.ArrayMap; @@ -39,6 +39,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; /** * Unit tests for {@link IpConfigStore} @@ -79,10 +80,11 @@ public class IpConfigStoreTest { StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1)); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); - ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2"); + ProxyInfo proxyInfo = + ProxyInfo.buildDirectProxy("10.10.10.10", 88, Arrays.asList("host1", "host2")); IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC, ProxySettings.STATIC, staticIpConfiguration, proxyInfo); 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 128177b073b0..7d7af03ecd3d 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -16,13 +16,20 @@ package com.android.server.net; +import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; +import static android.Manifest.permission.NETWORK_STACK; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; +import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED; +import static android.net.INetd.FIREWALL_RULE_ALLOW; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; @@ -34,6 +41,7 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; import static android.net.NetworkPolicyManager.uidPoliciesToString; import static android.net.NetworkPolicyManager.uidRulesToString; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; @@ -74,6 +82,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -97,6 +106,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; +import android.content.pm.UserInfo; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; @@ -104,8 +114,6 @@ import android.net.INetworkPolicyListener; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; import android.net.NetworkPolicy; import android.net.NetworkPolicyManager; import android.net.NetworkState; @@ -123,6 +131,7 @@ import android.os.RemoteException; import android.os.SimpleClock; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; @@ -131,6 +140,7 @@ import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.MediumTest; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.DataUnit; import android.util.Log; import android.util.Pair; @@ -187,6 +197,7 @@ import java.util.Calendar; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.TimeZone; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -240,6 +251,7 @@ public class NetworkPolicyManagerServiceTest { private @Mock SubscriptionManager mSubscriptionManager; private @Mock CarrierConfigManager mCarrierConfigManager; private @Mock TelephonyManager mTelephonyManager; + private @Mock UserManager mUserManager; private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); @@ -351,6 +363,8 @@ public class NetworkPolicyManagerServiceTest { return mNotifManager; case Context.CONNECTIVITY_SERVICE: return mConnectivityManager; + case Context.USER_SERVICE: + return mUserManager; default: return super.getSystemService(name); } @@ -407,11 +421,14 @@ public class NetworkPolicyManagerServiceTest { when(mPackageManager.getPackagesForUid(UID_B)).thenReturn(new String[] {PKG_NAME_B}); when(mPackageManager.getPackagesForUid(UID_C)).thenReturn(new String[] {PKG_NAME_C}); when(mPackageManager.getApplicationInfo(eq(PKG_NAME_A), anyInt())) - .thenReturn(buildApplicationInfo(PKG_NAME_A)); + .thenReturn(buildApplicationInfo(PKG_NAME_A, UID_A)); when(mPackageManager.getApplicationInfo(eq(PKG_NAME_B), anyInt())) - .thenReturn(buildApplicationInfo(PKG_NAME_B)); + .thenReturn(buildApplicationInfo(PKG_NAME_B, UID_B)); when(mPackageManager.getApplicationInfo(eq(PKG_NAME_C), anyInt())) - .thenReturn(buildApplicationInfo(PKG_NAME_C)); + .thenReturn(buildApplicationInfo(PKG_NAME_C, UID_C)); + when(mPackageManager.getInstalledApplications(anyInt())).thenReturn( + buildInstalledApplicationInfoList()); + when(mUserManager.getUsers()).thenReturn(buildUserInfoList()); when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true); when(mNetworkManager.setDataSaverModeEnabled(anyBoolean())).thenReturn(true); doNothing().when(mConnectivityManager) @@ -462,7 +479,7 @@ public class NetworkPolicyManagerServiceTest { @Test public void testTurnRestrictBackgroundOn() throws Exception { - assertRestrictBackgroundOff(); // Sanity check. + assertRestrictBackgroundOff(); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); setRestrictBackground(true); assertRestrictBackgroundChangedReceived(futureIntent, null); @@ -471,7 +488,7 @@ public class NetworkPolicyManagerServiceTest { @Test @NetPolicyXml("restrict-background-on.xml") public void testTurnRestrictBackgroundOff() throws Exception { - assertRestrictBackgroundOn(); // Sanity check. + assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); setRestrictBackground(false); @@ -479,28 +496,27 @@ public class NetworkPolicyManagerServiceTest { } /** - * Adds whitelist when restrict background is on - app should receive an intent. + * Adds an app to allowlist when restrict background is on - app should receive an intent. */ @Test @NetPolicyXml("restrict-background-on.xml") - public void testAddRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception { - assertRestrictBackgroundOn(); // Sanity check. + public void testAddRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception { + assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - addRestrictBackgroundWhitelist(true); + addRestrictBackgroundAllowlist(true); } /** - * Adds whitelist when restrict background is off - app should not receive an intent. + * Adds an app to allowlist when restrict background is off - app should not receive an intent. */ @Test - public void testAddRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception { - assertRestrictBackgroundOff(); // Sanity check. - addRestrictBackgroundWhitelist(false); + public void testAddRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception { + assertRestrictBackgroundOff(); + addRestrictBackgroundAllowlist(false); } - private void addRestrictBackgroundWhitelist(boolean expectIntent) throws Exception { - // Sanity checks. - assertWhitelistUids(); + private void addRestrictBackgroundAllowlist(boolean expectIntent) throws Exception { + assertRestrictBackgroundAllowedUids(); assertUidPolicy(UID_A, POLICY_NONE); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); @@ -508,7 +524,7 @@ public class NetworkPolicyManagerServiceTest { mService.setUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND); - assertWhitelistUids(UID_A); + assertRestrictBackgroundAllowedUids(UID_A); assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND); mPolicyListener.waitAndVerify() .onUidPoliciesChanged(APP_ID_A, POLICY_ALLOW_METERED_BACKGROUND); @@ -520,24 +536,25 @@ public class NetworkPolicyManagerServiceTest { } /** - * Removes whitelist when restrict background is on - app should receive an intent. + * Removes an app from allowlist when restrict background is on - app should receive an intent. */ @Test - @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml") - public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception { - assertRestrictBackgroundOn(); // Sanity check. + @NetPolicyXml("uidA-allowed-restrict-background-on.xml") + public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception { + assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - removeRestrictBackgroundWhitelist(true); + removeRestrictBackgroundAllowlist(true); } /** - * Removes whitelist when restrict background is off - app should not receive an intent. + * Removes an app from allowlist when restrict background is off - app should not + * receive an intent. */ @Test - @NetPolicyXml("uidA-whitelisted-restrict-background-off.xml") - public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception { - assertRestrictBackgroundOff(); // Sanity check. - removeRestrictBackgroundWhitelist(false); + @NetPolicyXml("uidA-allowed-restrict-background-off.xml") + public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception { + assertRestrictBackgroundOff(); + removeRestrictBackgroundAllowlist(false); } @Test @@ -688,9 +705,8 @@ public class NetworkPolicyManagerServiceTest { assertFalse(mService.getRestrictBackground()); } - private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception { - // Sanity checks. - assertWhitelistUids(UID_A); + private void removeRestrictBackgroundAllowlist(boolean expectIntent) throws Exception { + assertRestrictBackgroundAllowedUids(UID_A); assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); @@ -698,7 +714,7 @@ public class NetworkPolicyManagerServiceTest { mService.setUidPolicy(UID_A, POLICY_NONE); - assertWhitelistUids(); + assertRestrictBackgroundAllowedUids(); assertUidPolicy(UID_A, POLICY_NONE); mPolicyListener.waitAndVerify().onUidPoliciesChanged(APP_ID_A, POLICY_NONE); if (expectIntent) { @@ -709,27 +725,27 @@ public class NetworkPolicyManagerServiceTest { } /** - * Adds blacklist when restrict background is on - app should not receive an intent. + * Adds an app to denylist when restrict background is on - app should not receive an intent. */ @Test @NetPolicyXml("restrict-background-on.xml") - public void testAddRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception { - assertRestrictBackgroundOn(); // Sanity check. + public void testAddRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception { + assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - addRestrictBackgroundBlacklist(false); + addRestrictBackgroundDenylist(false); } /** - * Adds blacklist when restrict background is off - app should receive an intent. + * Adds an app to denylist when restrict background is off - app should receive an intent. */ @Test - public void testAddRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception { - assertRestrictBackgroundOff(); // Sanity check. - addRestrictBackgroundBlacklist(true); + public void testAddRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception { + assertRestrictBackgroundOff(); + addRestrictBackgroundDenylist(true); } - private void addRestrictBackgroundBlacklist(boolean expectIntent) throws Exception { - assertUidPolicy(UID_A, POLICY_NONE); // Sanity check. + private void addRestrictBackgroundDenylist(boolean expectIntent) throws Exception { + assertUidPolicy(UID_A, POLICY_NONE); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt()); @@ -746,28 +762,30 @@ public class NetworkPolicyManagerServiceTest { } /** - * Removes blacklist when restrict background is on - app should not receive an intent. + * Removes an app from denylist when restrict background is on - app should not + * receive an intent. */ @Test - @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml") - public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception { - assertRestrictBackgroundOn(); // Sanity check. + @NetPolicyXml("uidA-denied-restrict-background-on.xml") + public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception { + assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - removeRestrictBackgroundBlacklist(false); + removeRestrictBackgroundDenylist(false); } /** - * Removes blacklist when restrict background is off - app should receive an intent. + * Removes an app from denylist when restrict background is off - app should + * receive an intent. */ @Test - @NetPolicyXml("uidA-blacklisted-restrict-background-off.xml") - public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception { - assertRestrictBackgroundOff(); // Sanity check. - removeRestrictBackgroundBlacklist(true); + @NetPolicyXml("uidA-denied-restrict-background-off.xml") + public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception { + assertRestrictBackgroundOff(); + removeRestrictBackgroundDenylist(true); } - private void removeRestrictBackgroundBlacklist(boolean expectIntent) throws Exception { - assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); // Sanity check. + private void removeRestrictBackgroundDenylist(boolean expectIntent) throws Exception { + assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt()); @@ -784,9 +802,8 @@ public class NetworkPolicyManagerServiceTest { } @Test - @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml") - public void testBlacklistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception { - // Sanity checks. + @NetPolicyXml("uidA-denied-restrict-background-on.xml") + public void testDeniedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception { assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); @@ -797,12 +814,11 @@ public class NetworkPolicyManagerServiceTest { } @Test - @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml") - public void testWhitelistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception { - // Sanity checks. + @NetPolicyXml("uidA-allowed-restrict-background-on.xml") + public void testAllowedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception { assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - assertWhitelistUids(UID_A); + assertRestrictBackgroundAllowedUids(UID_A); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); setRestrictBackground(true); @@ -810,12 +826,11 @@ public class NetworkPolicyManagerServiceTest { } @Test - @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml") - public void testWhitelistedAppIsNotifiedWhenBlacklisted() throws Exception { - // Sanity checks. + @NetPolicyXml("uidA-allowed-restrict-background-on.xml") + public void testAllowedAppIsNotifiedWhenDenylisted() throws Exception { assertRestrictBackgroundOn(); assertRestrictBackgroundChangedReceived(mFutureIntent, null); - assertWhitelistUids(UID_A); + assertRestrictBackgroundAllowedUids(UID_A); final FutureIntent futureIntent = newRestrictBackgroundChangedFuture(); mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); @@ -823,8 +838,8 @@ public class NetworkPolicyManagerServiceTest { } @Test - @NetPolicyXml("restrict-background-lists-whitelist-format.xml") - public void testRestrictBackgroundLists_whitelistFormat() throws Exception { + @NetPolicyXml("restrict-background-lists-allowlist-format.xml") + public void testRestrictBackgroundLists_allowlistFormat() throws Exception { restrictBackgroundListsTest(); } @@ -835,33 +850,33 @@ public class NetworkPolicyManagerServiceTest { } private void restrictBackgroundListsTest() throws Exception { - // UIds that are whitelisted. - assertWhitelistUids(UID_A, UID_B, UID_C); + // UIds that are in allowlist. + assertRestrictBackgroundAllowedUids(UID_A, UID_B, UID_C); assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND); assertUidPolicy(UID_B, POLICY_ALLOW_METERED_BACKGROUND); assertUidPolicy(UID_C, POLICY_ALLOW_METERED_BACKGROUND); - // UIDs that are blacklisted. + // UIDs that are in denylist. assertUidPolicy(UID_D, POLICY_NONE); assertUidPolicy(UID_E, POLICY_REJECT_METERED_BACKGROUND); // UIDS that have legacy policies. assertUidPolicy(UID_F, 2); // POLICY_ALLOW_BACKGROUND_BATTERY_SAVE - // Remove whitelist. + // Remove an uid from allowlist. mService.setUidPolicy(UID_A, POLICY_NONE); assertUidPolicy(UID_A, POLICY_NONE); - assertWhitelistUids(UID_B, UID_C); + assertRestrictBackgroundAllowedUids(UID_B, UID_C); - // Add whitelist when blacklisted. + // Add an app to allowlist which is currently in denylist. mService.setUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND); assertUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND); - assertWhitelistUids(UID_B, UID_C, UID_E); + assertRestrictBackgroundAllowedUids(UID_B, UID_C, UID_E); - // Add blacklist when whitelisted. + // Add an app to denylist when is currently in allowlist. mService.setUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); - assertWhitelistUids(UID_C, UID_E); + assertRestrictBackgroundAllowedUids(UID_C, UID_E); } /** @@ -870,9 +885,9 @@ public class NetworkPolicyManagerServiceTest { @Test @NetPolicyXml("restrict-background-lists-mixed-format.xml") public void testRestrictBackgroundLists_mixedFormat() throws Exception { - assertWhitelistUids(UID_A, UID_C, UID_D); + assertRestrictBackgroundAllowedUids(UID_A, UID_C, UID_D); assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND); - assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Blacklist prevails. + assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Denylist prevails. assertUidPolicy(UID_C, (POLICY_ALLOW_METERED_BACKGROUND | 2)); assertUidPolicy(UID_D, POLICY_ALLOW_METERED_BACKGROUND); } @@ -1401,7 +1416,7 @@ public class NetworkPolicyManagerServiceTest { actualCycleDay = mService.getCycleDayFromCarrierConfig(null, DEFAULT_CYCLE_DAY); assertEquals(DEFAULT_CYCLE_DAY, actualCycleDay); - // Sane, non-default values + // Valid, non-default values assertCycleDayAsExpected(config, 1, true); assertCycleDayAsExpected(config, cal.getMaximum(Calendar.DAY_OF_MONTH), true); assertCycleDayAsExpected(config, cal.getMinimum(Calendar.DAY_OF_MONTH), true); @@ -1814,11 +1829,11 @@ public class NetworkPolicyManagerServiceTest { } /** - * Exhaustively test isUidNetworkingBlocked to output the expected results based on external + * Exhaustively test checkUidNetworkingBlocked to output the expected results based on external * conditions. */ @Test - public void testIsUidNetworkingBlocked() { + public void testCheckUidNetworkingBlocked() { final ArrayList<Pair<Boolean, Integer>> expectedBlockedStates = new ArrayList<>(); // Metered network. Data saver on. @@ -1862,20 +1877,79 @@ public class NetworkPolicyManagerServiceTest { private void verifyNetworkBlockedState(boolean metered, boolean backgroundRestricted, ArrayList<Pair<Boolean, Integer>> expectedBlockedStateForRules) { - final NetworkPolicyManagerInternal npmi = LocalServices - .getService(NetworkPolicyManagerInternal.class); for (Pair<Boolean, Integer> pair : expectedBlockedStateForRules) { final boolean expectedResult = pair.first; final int rule = pair.second; assertEquals(formatBlockedStateError(UID_A, rule, metered, backgroundRestricted), - expectedResult, - npmi.isUidNetworkingBlocked(UID_A, rule, metered, backgroundRestricted)); + expectedResult, mService.checkUidNetworkingBlocked(UID_A, rule, + metered, backgroundRestricted)); assertFalse(formatBlockedStateError(SYSTEM_UID, rule, metered, backgroundRestricted), - npmi.isUidNetworkingBlocked(SYSTEM_UID, rule, metered, backgroundRestricted)); + mService.checkUidNetworkingBlocked(SYSTEM_UID, rule, metered, + backgroundRestricted)); } } + private void enableRestrictedMode(boolean enable) throws Exception { + mService.mRestrictedNetworkingMode = enable; + mService.updateRestrictedModeAllowlistUL(); + verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_RESTRICTED, + enable); + } + + @Test + public void testUpdateRestrictedModeAllowlist() throws Exception { + // initialization calls setFirewallChainEnabled, so we want to reset the invocations. + clearInvocations(mNetworkManager); + expectHasUseRestrictedNetworksPermission(UID_A, true); + expectHasUseRestrictedNetworksPermission(UID_B, false); + + Map<Integer, Integer> firewallUidRules = new ArrayMap<>(); + doAnswer(arg -> { + int[] uids = arg.getArgument(1); + int[] rules = arg.getArgument(2); + assertTrue(uids.length == rules.length); + + for (int i = 0; i < uids.length; ++i) { + firewallUidRules.put(uids[i], rules[i]); + } + return null; + }).when(mNetworkManager).setFirewallUidRules(eq(FIREWALL_CHAIN_RESTRICTED), + any(int[].class), any(int[].class)); + + enableRestrictedMode(true); + assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_A).intValue()); + assertFalse(mService.isUidNetworkingBlocked(UID_A, false)); + assertTrue(mService.isUidNetworkingBlocked(UID_B, false)); + + enableRestrictedMode(false); + assertFalse(mService.isUidNetworkingBlocked(UID_A, false)); + assertFalse(mService.isUidNetworkingBlocked(UID_B, false)); + } + + @Test + public void testUpdateRestrictedModeForUid() throws Exception { + // initialization calls setFirewallChainEnabled, so we want to reset the invocations. + clearInvocations(mNetworkManager); + expectHasUseRestrictedNetworksPermission(UID_A, true); + expectHasUseRestrictedNetworksPermission(UID_B, false); + enableRestrictedMode(true); + + // UID_D and UID_E are not part of installed applications list, so it won't have any + // firewall rules set yet + expectHasUseRestrictedNetworksPermission(UID_D, false); + mService.updateRestrictedModeForUidUL(UID_D); + verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, UID_D, + FIREWALL_RULE_DEFAULT); + assertTrue(mService.isUidNetworkingBlocked(UID_D, false)); + + expectHasUseRestrictedNetworksPermission(UID_E, true); + mService.updateRestrictedModeForUidUL(UID_E); + verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, UID_E, + FIREWALL_RULE_ALLOW); + assertFalse(mService.isUidNetworkingBlocked(UID_E, false)); + } + private String formatBlockedStateError(int uid, int rule, boolean metered, boolean backgroundRestricted) { return String.format( @@ -1890,17 +1964,25 @@ public class NetworkPolicyManagerServiceTest { .build(); } - private ApplicationInfo buildApplicationInfo(String label) { + private ApplicationInfo buildApplicationInfo(String label, int uid) { final ApplicationInfo ai = new ApplicationInfo(); ai.nonLocalizedLabel = label; + ai.uid = uid; return ai; } - private NetworkInfo buildNetworkInfo() { - final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_MOBILE, - TelephonyManager.NETWORK_TYPE_LTE, null, null); - ni.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); - return ni; + private List<ApplicationInfo> buildInstalledApplicationInfoList() { + final List<ApplicationInfo> installedApps = new ArrayList<>(); + installedApps.add(buildApplicationInfo(PKG_NAME_A, UID_A)); + installedApps.add(buildApplicationInfo(PKG_NAME_B, UID_B)); + installedApps.add(buildApplicationInfo(PKG_NAME_C, UID_C)); + return installedApps; + } + + private List<UserInfo> buildUserInfoList() { + final List<UserInfo> users = new ArrayList<>(); + users.add(new UserInfo(USER_ID, "user1", 0)); + return users; } private LinkProperties buildLinkProperties(String iface) { @@ -1956,12 +2038,12 @@ public class NetworkPolicyManagerServiceTest { } private static NetworkState buildWifi() { - final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null); - info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); final NetworkCapabilities networkCapabilities = new NetworkCapabilities(); - return new NetworkState(info, prop, networkCapabilities, null, null, TEST_SSID); + networkCapabilities.addTransportType(TRANSPORT_WIFI); + networkCapabilities.setSSID(TEST_SSID); + return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null); } private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception { @@ -1969,14 +2051,23 @@ public class NetworkPolicyManagerServiceTest { hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED); } + private void expectHasUseRestrictedNetworksPermission(int uid, boolean hasIt) throws Exception { + when(mIpm.checkUidPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, uid)).thenReturn( + hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED); + when(mIpm.checkUidPermission(NETWORK_STACK, uid)).thenReturn( + PackageManager.PERMISSION_DENIED); + when(mIpm.checkUidPermission(PERMISSION_MAINLINE_NETWORK_STACK, uid)).thenReturn( + PackageManager.PERMISSION_DENIED); + } + private void expectNetworkState(boolean roaming) throws Exception { when(mCarrierConfigManager.getConfigForSubId(eq(TEST_SUB_ID))) .thenReturn(mCarrierConfig); when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] { - new NetworkState(buildNetworkInfo(), + 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) }); } @@ -2045,7 +2136,7 @@ public class NetworkPolicyManagerServiceTest { } } - private void assertWhitelistUids(int... uids) { + private void assertRestrictBackgroundAllowedUids(int... uids) { assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND), uids); } @@ -2133,7 +2224,6 @@ public class NetworkPolicyManagerServiceTest { private void setRestrictBackground(boolean flag) throws Exception { mService.setRestrictBackground(flag); - // Sanity check. assertEquals("restrictBackground not set", flag, mService.getRestrictBackground()); } diff --git a/services/tests/servicestests/src/com/android/server/net/OWNERS b/services/tests/servicestests/src/com/android/server/net/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/net/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java index 9c8a38219a9c..ac9316e7d908 100644 --- a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java @@ -24,6 +24,9 @@ import static org.junit.Assert.fail; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; import android.net.INetdEventCallback; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -106,6 +109,16 @@ public class NetworkWatchlistServiceTests { counter--; return true; } + + // TODO: mark @Override when aosp/1541935 automerges to master. + public void logDefaultNetworkValidity(boolean valid) { + } + + // TODO: mark @Override when aosp/1541935 automerges to master. + public void logDefaultNetworkEvent(Network defaultNetwork, int score, boolean validated, + LinkProperties lp, NetworkCapabilities nc, Network previousDefaultNetwork, + int previousScore, LinkProperties previousLp, NetworkCapabilities previousNc) { + } }; ServiceThread mHandlerThread; diff --git a/services/tests/servicestests/src/com/android/server/om/OWNERS b/services/tests/servicestests/src/com/android/server/om/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/om/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt index e08eea298aaf..08392737350a 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt @@ -160,7 +160,7 @@ class OverlayActorEnforcerTests { private val hasPermission: Boolean = false, private val overlayableInfo: OverlayableInfo? = null, private vararg val packageNames: String = arrayOf("com.test.actor.one") - ) : OverlayableInfoCallback { + ) : PackageManagerHelper { override fun getNamedActors() = if (isActor) { mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME)) @@ -195,6 +195,14 @@ class OverlayActorEnforcerTests { } } + override fun getConfigSignaturePackage(): String { + throw UnsupportedOperationException() + } + + override fun getOverlayPackages(userId: Int): MutableList<PackageInfo> { + throw UnsupportedOperationException() + } + override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean { throw UnsupportedOperationException() } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java index b7692f912e39..5468fba59c10 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java @@ -35,8 +35,8 @@ import java.util.function.BiConsumer; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase { - private static final String OVERLAY = "com.dummy.overlay"; - private static final String TARGET = "com.dummy.target"; + private static final String OVERLAY = "com.test.overlay"; + private static final String TARGET = "com.test.target"; private static final int USER = 0; private static final String OVERLAY2 = OVERLAY + "2"; @@ -44,9 +44,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI @Test public void testUpdateOverlaysForUser() { final OverlayManagerServiceImpl impl = getImpl(); - addSystemPackage(target(TARGET), USER); - addSystemPackage(target("some.other.target"), USER);; - addSystemPackage(overlay(OVERLAY, TARGET), USER); + addPackage(target(TARGET), USER); + addPackage(target("some.other.target"), USER); + addPackage(overlay(OVERLAY, TARGET), USER); // do nothing, expect no change final List<String> a = impl.updateOverlaysForUser(USER); @@ -54,7 +54,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI assertTrue(a.contains(TARGET)); // upgrade overlay, keep target - addSystemPackage(overlay(OVERLAY, TARGET), USER); + addPackage(overlay(OVERLAY, TARGET), USER); final List<String> b = impl.updateOverlaysForUser(USER); assertEquals(1, b.size()); @@ -66,7 +66,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI assertTrue(c.contains(TARGET)); // upgrade overlay, switch to new target - addSystemPackage(overlay(OVERLAY, "some.other.target"), USER); + addPackage(overlay(OVERLAY, "some.other.target"), USER); final List<String> d = impl.updateOverlaysForUser(USER); assertEquals(2, d.size()); assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target"))); @@ -78,7 +78,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testImmutableEnabledChange() { + public void testImmutableEnabledChange() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -106,7 +106,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutableEnabledChangeHasNoEffect() { + public void testMutableEnabledChangeHasNoEffect() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -134,7 +134,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutableEnabledToImmutableEnabled() { + public void testMutableEnabledToImmutableEnabled() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -178,7 +178,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutablePriorityChange() { + public void testMutablePriorityChange() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -218,7 +218,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testImmutablePriorityChange() { + public void testImmutablePriorityChange() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index f4c5506c7001..33dbcc0855be 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -19,13 +19,17 @@ package com.android.server.om; import static android.content.om.OverlayInfo.STATE_DISABLED; import static android.content.om.OverlayInfo.STATE_ENABLED; import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; +import static android.os.OverlayablePolicy.CONFIG_SIGNATURE; 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.testng.Assert.assertThrows; import android.content.om.OverlayInfo; +import android.util.Pair; import androidx.test.runner.AndroidJUnit4; @@ -34,12 +38,13 @@ import org.junit.runner.RunWith; import java.util.List; import java.util.Map; +import java.util.Optional; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { - private static final String OVERLAY = "com.dummy.overlay"; - private static final String TARGET = "com.dummy.target"; + private static final String OVERLAY = "com.test.overlay"; + private static final String TARGET = "com.test.target"; private static final int USER = 0; private static final String OVERLAY2 = OVERLAY + "2"; @@ -49,8 +54,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes private static final String OVERLAY3 = OVERLAY + "3"; private static final int USER3 = USER2 + 1; + private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.test.ref"; + private static final String CERT_CONFIG_OK = "config_certificate_ok"; + private static final String CERT_CONFIG_NOK = "config_certificate_nok"; + @Test - public void testGetOverlayInfo() { + public void testGetOverlayInfo() throws Exception { installNewPackage(overlay(OVERLAY, TARGET), USER); final OverlayManagerServiceImpl impl = getImpl(); @@ -62,7 +71,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testGetOverlayInfosForTarget() { + public void testGetOverlayInfosForTarget() throws Exception { installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY3, TARGET), USER2); @@ -87,7 +96,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testGetOverlayInfosForUser() { + public void testGetOverlayInfosForUser() throws Exception { installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); @@ -114,7 +123,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testPriority() { + public void testPriority() throws Exception { installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY3, TARGET), USER); @@ -126,29 +135,33 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); - assertTrue(impl.setLowestPriority(OVERLAY3, USER)); + assertEquals(impl.setLowestPriority(OVERLAY3, USER), + Optional.of(new PackageAndUser(TARGET, USER))); assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2); - assertTrue(impl.setHighestPriority(OVERLAY3, USER)); + assertEquals(impl.setHighestPriority(OVERLAY3, USER), + Optional.of(new PackageAndUser(TARGET, USER))); assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); - assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER)); + assertEquals(impl.setPriority(OVERLAY, OVERLAY2, USER), + Optional.of(new PackageAndUser(TARGET, USER))); assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3); } @Test - public void testOverlayInfoStateTransitions() { + public void testOverlayInfoStateTransitions() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); assertNull(impl.getOverlayInfo(OVERLAY, USER)); installNewPackage(overlay(OVERLAY, TARGET), USER); assertState(STATE_MISSING_TARGET, OVERLAY, USER); - final DummyDeviceState.PackageBuilder target = target(TARGET); + final FakeDeviceState.PackageBuilder target = target(TARGET); installNewPackage(target, USER); assertState(STATE_DISABLED, OVERLAY, USER); - impl.setEnabled(OVERLAY, true, USER); + assertEquals(impl.setEnabled(OVERLAY, true, USER), + Optional.of(new PackageAndUser(TARGET, USER))); assertState(STATE_ENABLED, OVERLAY, USER); // target upgrades do not change the state of the overlay @@ -163,45 +176,118 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testOnOverlayPackageUpgraded() { - final DummyListener listener = getListener(); - final DummyDeviceState.PackageBuilder target = target(TARGET); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); + public void testOnOverlayPackageUpgraded() throws Exception { + final FakeDeviceState.PackageBuilder target = target(TARGET); + final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); installNewPackage(target, USER); installNewPackage(overlay, USER); - listener.count = 0; upgradePackage(overlay, USER); - assertEquals(2, listener.count); // upgrade to a version where the overlay has changed its target - // expect once for the old target package, once for the new target package - listener.count = 0; - final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target"); - upgradePackage(overlay2, USER); - assertEquals(3, listener.count); - - listener.count = 0; - upgradePackage(overlay2, USER); - assertEquals(2, listener.count); + final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target"); + final Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> pair = + upgradePackage(overlay2, USER); + assertEquals(pair.first, Optional.of(new PackageAndUser(TARGET, USER))); + assertEquals(pair.second, Optional.of(new PackageAndUser("some.other.target", USER))); } @Test - public void testListener() { + public void testSetEnabledAtVariousConditions() throws Exception { final OverlayManagerServiceImpl impl = getImpl(); - final DummyListener listener = getListener(); + assertThrows(OverlayManagerServiceImpl.OperationFailedException.class, + () -> impl.setEnabled(OVERLAY, true, USER)); + + // request succeeded, and there was a change that needs to be + // propagated to the rest of the system + installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); - assertEquals(1, listener.count); - listener.count = 0; + assertEquals(impl.setEnabled(OVERLAY, true, USER), + Optional.of(new PackageAndUser(TARGET, USER))); + + // request succeeded, but nothing changed + assertFalse(impl.setEnabled(OVERLAY, true, USER).isPresent()); + } + + @Test + public void testConfigSignaturePolicyOk() throws Exception { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER); + + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE); + } + + @Test + public void testConfigSignaturePolicyCertNok() throws Exception { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyNoConfig() throws Exception { + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyNoRefPkg() throws Exception { + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); installNewPackage(target(TARGET), USER); - assertEquals(1, listener.count); - listener.count = 0; + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); - impl.setEnabled(OVERLAY, true, USER); - assertEquals(1, listener.count); - listener.count = 0; + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); - impl.setEnabled(OVERLAY, true, USER); - assertEquals(0, listener.count); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index 733310b2508a..2c477c897b30 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -16,6 +16,8 @@ package com.android.server.om; +import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -27,8 +29,10 @@ import android.content.om.OverlayInfo.State; import android.content.om.OverlayableInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Pair; import androidx.annotation.Nullable; @@ -42,23 +46,23 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ class OverlayManagerServiceImplTestsBase { private OverlayManagerServiceImpl mImpl; - private DummyDeviceState mState; - private DummyListener mListener; - private DummyPackageManagerHelper mPackageManager; - private DummyIdmapDaemon mIdmapDaemon; + private FakeDeviceState mState; + private FakePackageManagerHelper mPackageManager; + private FakeIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; + private String mConfigSignaturePackageName; @Before public void setUp() { - mState = new DummyDeviceState(); - mListener = new DummyListener(); - mPackageManager = new DummyPackageManagerHelper(mState); - mIdmapDaemon = new DummyIdmapDaemon(mState); + mState = new FakeDeviceState(); + mPackageManager = new FakePackageManagerHelper(mState); + mIdmapDaemon = new FakeIdmapDaemon(mState); mOverlayConfig = mock(OverlayConfig.class); when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY); when(mOverlayConfig.isEnabled(any())).thenReturn(false); @@ -71,16 +75,23 @@ class OverlayManagerServiceImplTestsBase { new IdmapManager(mIdmapDaemon, mPackageManager), new OverlayManagerSettings(), mOverlayConfig, - new String[0], - mListener); + new String[0]); } OverlayManagerServiceImpl getImpl() { return mImpl; } - DummyListener getListener() { - return mListener; + FakeIdmapDaemon getIdmapd() { + return mIdmapDaemon; + } + + FakeDeviceState getState() { + return mState; + } + + void setConfigSignaturePackageName(String packageName) { + mConfigSignaturePackageName = packageName; } void assertState(@State int expected, final String overlayPackageName, int userId) { @@ -102,22 +113,27 @@ class OverlayManagerServiceImplTestsBase { assertEquals(expected, actual); } - DummyDeviceState.PackageBuilder target(String packageName) { - return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */, - null /* targetOverlayableName */); + FakeDeviceState.PackageBuilder app(String packageName) { + return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */, + null /* targetOverlayableName */, "data"); + } + + FakeDeviceState.PackageBuilder target(String packageName) { + return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */, + null /* targetOverlayableName */, ""); } - DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) { + FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) { return overlay(packageName, targetPackageName, null /* targetOverlayableName */); } - DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName, + FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName, String targetOverlayableName) { - return new DummyDeviceState.PackageBuilder(packageName, targetPackageName, - targetOverlayableName); + return new FakeDeviceState.PackageBuilder(packageName, targetPackageName, + targetOverlayableName, ""); } - void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) { + void addPackage(FakeDeviceState.PackageBuilder pkg, int userId) { mState.add(pkg, userId); } @@ -136,7 +152,8 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is currently installed */ - void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) { + void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) + throws OperationFailedException { if (mState.select(pkg.packageName, userId) != null) { throw new IllegalStateException("package " + pkg.packageName + " already installed"); } @@ -157,23 +174,30 @@ class OverlayManagerServiceImplTestsBase { * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the * {@link android.content.Intent#EXTRA_REPLACING} extra. * + * @return the two Optional<PackageAndUser> objects from starting and finishing the upgrade + * * @throws IllegalStateException if the package is not currently installed */ - void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) { - final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); + Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> upgradePackage( + FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException { + final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); if (replacedPackage == null) { throw new IllegalStateException("package " + pkg.packageName + " not installed"); } + Optional<PackageAndUser> opt1 = Optional.empty(); if (replacedPackage.targetPackageName != null) { - mImpl.onOverlayPackageReplacing(pkg.packageName, userId); + opt1 = mImpl.onOverlayPackageReplacing(pkg.packageName, userId); } mState.add(pkg, userId); + Optional<PackageAndUser> opt2; if (pkg.targetPackage == null) { - mImpl.onTargetPackageReplaced(pkg.packageName, userId); + opt2 = mImpl.onTargetPackageReplaced(pkg.packageName, userId); } else { - mImpl.onOverlayPackageReplaced(pkg.packageName, userId); + opt2 = mImpl.onOverlayPackageReplaced(pkg.packageName, userId); } + + return Pair.create(opt1, opt2); } /** @@ -184,8 +208,8 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is not currently installed */ - void uninstallPackage(String packageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + void uninstallPackage(String packageName, int userId) throws OperationFailedException { + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null) { throw new IllegalStateException("package " + packageName+ " not installed"); } @@ -198,7 +222,7 @@ class OverlayManagerServiceImplTestsBase { } /** Represents the state of packages installed on a fake device. */ - static class DummyDeviceState { + static class FakeDeviceState { private ArrayMap<String, Package> mPackages = new ArrayMap<>(); void add(PackageBuilder pkgBuilder, int userId) { @@ -242,15 +266,17 @@ class OverlayManagerServiceImplTestsBase { private String packageName; private String targetPackage; private String certificate = "[default]"; + private String partition; private int version = 0; private ArrayList<String> overlayableNames = new ArrayList<>(); private String targetOverlayableName; private PackageBuilder(String packageName, String targetPackage, - String targetOverlayableName) { + String targetOverlayableName, String partition) { this.packageName = packageName; this.targetPackage = targetPackage; this.targetOverlayableName = targetOverlayableName; + this.partition = partition; } PackageBuilder setCertificate(String certificate) { @@ -269,9 +295,19 @@ class OverlayManagerServiceImplTestsBase { } Package build() { - final String apkPath = String.format("%s/%s/base.apk", - targetPackage == null ? "/system/app/:" : "/vendor/overlay/:", - packageName); + String path = ""; + if (TextUtils.isEmpty(partition)) { + if (targetPackage == null) { + path = "/system/app"; + } else { + path = "/vendor/overlay"; + } + } else { + String type = targetPackage == null ? "app" : "overlay"; + path = String.format("%s/%s", partition, type); + } + + final String apkPath = String.format("%s/%s/base.apk", path, packageName); final Package newPackage = new Package(packageName, targetPackage, targetOverlayableName, version, apkPath, certificate); newPackage.overlayableNames.addAll(overlayableNames); @@ -302,17 +338,16 @@ class OverlayManagerServiceImplTestsBase { } } - static final class DummyPackageManagerHelper implements PackageManagerHelper, - OverlayableInfoCallback { - private final DummyDeviceState mState; + final class FakePackageManagerHelper implements PackageManagerHelper { + private final FakeDeviceState mState; - private DummyPackageManagerHelper(DummyDeviceState state) { + private FakePackageManagerHelper(FakeDeviceState state) { mState = state; } @Override public PackageInfo getPackageInfo(@NonNull String packageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null) { return null; } @@ -323,15 +358,15 @@ class OverlayManagerServiceImplTestsBase { pi.packageName = pkg.packageName; pi.overlayTarget = pkg.targetPackageName; pi.targetOverlayableName = pkg.targetOverlayableName; - pi.overlayCategory = "dummy-category-" + pkg.targetPackageName; + pi.overlayCategory = "Fake-category-" + pkg.targetPackageName; return pi; } @Override public boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2, int userId) { - final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId); - final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId); + final FakeDeviceState.Package pkg1 = mState.select(packageName1, userId); + final FakeDeviceState.Package pkg2 = mState.select(packageName2, userId); return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate); } @@ -343,11 +378,16 @@ class OverlayManagerServiceImplTestsBase { .collect(Collectors.toList()); } + @Override + public @NonNull String getConfigSignaturePackage() { + return mConfigSignaturePackageName; + } + @Nullable @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, @NonNull String targetOverlayableName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) { return null; } @@ -368,7 +408,7 @@ class OverlayManagerServiceImplTestsBase { @Override public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId); + final FakeDeviceState.Package pkg = mState.select(targetPackageName, userId); return pkg != null && pkg.overlayableNames.contains(targetPackageName); } @@ -378,16 +418,16 @@ class OverlayManagerServiceImplTestsBase { } } - static class DummyIdmapDaemon extends IdmapDaemon { - private final DummyDeviceState mState; + static class FakeIdmapDaemon extends IdmapDaemon { + private final FakeDeviceState mState; private final ArrayMap<String, IdmapHeader> mIdmapFiles = new ArrayMap<>(); - DummyIdmapDaemon(DummyDeviceState state) { + FakeIdmapDaemon(FakeDeviceState state) { this.mState = state; } private int getCrc(@NonNull final String path) { - final DummyDeviceState.Package pkg = mState.selectFromPath(path); + final FakeDeviceState.Package pkg = mState.selectFromPath(path); Assert.assertNotNull(pkg); return pkg.versionCode; } @@ -450,12 +490,4 @@ class OverlayManagerServiceImplTestsBase { } } } - - static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener { - public int count; - - public void onOverlaysChanged(@NonNull String targetPackage, int userId) { - count++; - } - } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java index 146f60aff724..9ef755791c80 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java @@ -50,55 +50,55 @@ public class OverlayManagerSettingsTests { private OverlayManagerSettings mSettings; private static final OverlayInfo OVERLAY_A0 = new OverlayInfo( - "com.dummy.overlay_a", - "com.dummy.target", + "com.test.overlay_a", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_a-1/base.apk", + "/data/app/com.test.overlay_a-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_B0 = new OverlayInfo( - "com.dummy.overlay_b", - "com.dummy.target", + "com.test.overlay_b", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_b-1/base.apk", + "/data/app/com.test.overlay_b-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_C0 = new OverlayInfo( - "com.dummy.overlay_c", - "com.dummy.target", + "com.test.overlay_c", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_c-1/base.apk", + "/data/app/com.test.overlay_c-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_A1 = new OverlayInfo( - "com.dummy.overlay_a", - "com.dummy.target", + "com.test.overlay_a", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_a-1/base.apk", + "/data/app/com.test.overlay_a-1/base.apk", STATE_DISABLED, 1, 0, true); private static final OverlayInfo OVERLAY_B1 = new OverlayInfo( - "com.dummy.overlay_b", - "com.dummy.target", + "com.test.overlay_b", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_b-1/base.apk", + "/data/app/com.test.overlay_b-1/base.apk", STATE_DISABLED, 1, 0, @@ -230,11 +230,11 @@ public class OverlayManagerSettingsTests { assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0); OverlayInfo otherTarget = new OverlayInfo( - "com.dummy.overlay_other", - "com.dummy.some.other.target", + "com.test.overlay_other", + "com.test.some.other.target", null, "some-category", - "/data/app/com.dummy.overlay_other-1/base.apk", + "/data/app/com.test.overlay_other-1/base.apk", STATE_DISABLED, 0, 0, @@ -350,7 +350,7 @@ public class OverlayManagerSettingsTests { ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); mSettings.restore(is); - assertDoesNotContain(mSettings, "com.dummy.overlay", 0); + assertDoesNotContain(mSettings, "com.test.overlay", 0); } @Test @@ -359,27 +359,27 @@ public class OverlayManagerSettingsTests { final String xml = "<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n" + "<overlays version='" + version + "'>\n" - + "<item packageName='com.dummy.overlay'\n" + + "<item packageName='com.test.overlay'\n" + " userId='1234'\n" - + " targetPackageName='com.dummy.target'\n" - + " baseCodePath='/data/app/com.dummy.overlay-1/base.apk'\n" + + " targetPackageName='com.test.target'\n" + + " baseCodePath='/data/app/com.test.overlay-1/base.apk'\n" + " state='" + STATE_DISABLED + "'\n" + " isEnabled='false'\n" - + " category='dummy-category'\n" + + " category='test-category'\n" + " isStatic='false'\n" + " priority='0' />\n" + "</overlays>\n"; ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); mSettings.restore(is); - OverlayInfo oi = mSettings.getOverlayInfo("com.dummy.overlay", 1234); + OverlayInfo oi = mSettings.getOverlayInfo("com.test.overlay", 1234); assertNotNull(oi); - assertEquals("com.dummy.overlay", oi.packageName); - assertEquals("com.dummy.target", oi.targetPackageName); - assertEquals("/data/app/com.dummy.overlay-1/base.apk", oi.baseCodePath); + assertEquals("com.test.overlay", oi.packageName); + assertEquals("com.test.target", oi.targetPackageName); + assertEquals("/data/app/com.test.overlay-1/base.apk", oi.baseCodePath); assertEquals(1234, oi.userId); assertEquals(STATE_DISABLED, oi.state); - assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234)); + assertFalse(mSettings.getEnabled("com.test.overlay", 1234)); } @Test diff --git a/services/tests/servicestests/src/com/android/server/people/OWNERS b/services/tests/servicestests/src/com/android/server/people/OWNERS new file mode 100644 index 000000000000..3198a5e84307 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/people/OWNERS @@ -0,0 +1 @@ +include /services/people/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java index af5a539450ac..37aedac8f28e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java @@ -72,7 +72,6 @@ import java.util.Map; import java.util.Set; import java.util.function.IntFunction; import java.util.stream.Collectors; -import java.util.concurrent.Executor; @Presubmit @RunWith(JUnit4.class) @@ -92,8 +91,6 @@ public class AppsFilterTest { AppsFilter.FeatureConfig mFeatureConfigMock; @Mock AppsFilter.StateProvider mStateProvider; - @Mock - Executor mMockExecutor; private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>(); @@ -190,15 +187,10 @@ public class AppsFilterTest { doAnswer(invocation -> { ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0)) .currentState(mExisting, USER_INFO_LIST); - return new Object(); + return null; }).when(mStateProvider) .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class)); - doAnswer(invocation -> { - ((Runnable) invocation.getArgument(0)).run(); - return new Object(); - }).when(mMockExecutor).execute(any(Runnable.class)); - when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true); when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))).thenAnswer( (Answer<Boolean>) invocation -> @@ -209,8 +201,7 @@ public class AppsFilterTest { @Test public void testSystemReadyPropogates() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); appsFilter.onSystemReady(); verify(mFeatureConfigMock).onSystemReady(); } @@ -218,8 +209,7 @@ public class AppsFilterTest { @Test public void testQueriesAction_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -235,8 +225,7 @@ public class AppsFilterTest { @Test public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); final Signature frameworkSignature = Mockito.mock(Signature.class); final PackageParser.SigningDetails frameworkSigningDetails = new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1); @@ -274,8 +263,7 @@ public class AppsFilterTest { @Test public void testQueriesProvider_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -292,8 +280,7 @@ public class AppsFilterTest { @Test public void testQueriesDifferentProvider_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -310,8 +297,7 @@ public class AppsFilterTest { @Test public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -329,8 +315,7 @@ public class AppsFilterTest { @Test public void testQueriesAction_NoMatchingAction_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -346,8 +331,7 @@ public class AppsFilterTest { @Test public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -367,8 +351,7 @@ public class AppsFilterTest { @Test public void testNoQueries_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -384,8 +367,7 @@ public class AppsFilterTest { @Test public void testForceQueryable_SystemDoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -403,8 +385,7 @@ public class AppsFilterTest { @Test public void testForceQueryable_NonSystemFilters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -421,7 +402,7 @@ public class AppsFilterTest { public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception { final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, - false, null, mMockExecutor); + false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -439,8 +420,7 @@ public class AppsFilterTest { @Test public void testSystemSignedTarget_DoesntFilter() throws CertificateException { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); appsFilter.onSystemReady(); final Signature frameworkSignature = Mockito.mock(Signature.class); @@ -469,7 +449,7 @@ public class AppsFilterTest { public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception { final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, - false, null, mMockExecutor); + false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -487,7 +467,7 @@ public class AppsFilterTest { public void testSystemQueryable_DoesntFilter() throws Exception { final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, - true /* system force queryable */, null, mMockExecutor); + true /* system force queryable */, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -504,8 +484,7 @@ public class AppsFilterTest { @Test public void testQueriesPackage_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -523,8 +502,7 @@ public class AppsFilterTest { when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))) .thenReturn(false); final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -540,8 +518,7 @@ public class AppsFilterTest { @Test public void testSystemUid_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -556,8 +533,7 @@ public class AppsFilterTest { @Test public void testSystemUidSecondaryUser_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -573,8 +549,7 @@ public class AppsFilterTest { @Test public void testNonSystemUid_NoCallingSetting_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -588,8 +563,7 @@ public class AppsFilterTest { @Test public void testNoTargetPackage_filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -647,8 +621,7 @@ public class AppsFilterTest { } return Collections.emptyMap(); } - }, - mMockExecutor); + }); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -720,8 +693,7 @@ public class AppsFilterTest { } return Collections.emptyMap(); } - }, - mMockExecutor); + }); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -746,8 +718,7 @@ public class AppsFilterTest { @Test public void testInitiatingApp_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -763,8 +734,7 @@ public class AppsFilterTest { @Test public void testUninstalledInitiatingApp_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -780,8 +750,7 @@ public class AppsFilterTest { @Test public void testOriginatingApp_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -797,8 +766,7 @@ public class AppsFilterTest { @Test public void testInstallingApp_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -814,8 +782,7 @@ public class AppsFilterTest { @Test public void testInstrumentation_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -837,8 +804,7 @@ public class AppsFilterTest { @Test public void testWhoCanSee() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..e15b5f57069c --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS @@ -0,0 +1,3 @@ +include /services/core/java/com/android/server/pm/OWNERS + +per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index b0b5386a49bd..21b36590e101 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -468,7 +468,7 @@ public class PackageParserTest { ParsedInstrumentation b) { assertComponentsEqual(a, b); - // Sanity check for InstrumentationInfo. + // Validity check for InstrumentationInfo. assertEquals(a.getTargetPackage(), b.getTargetPackage()); assertEquals(a.getTargetProcesses(), b.getTargetProcesses()); assertEquals(a.isHandleProfiling(), b.isHandleProfiling()); @@ -483,7 +483,7 @@ public class PackageParserTest { ) { assertComponentsEqual(a, b); - // Sanity check for ServiceInfo. + // Validity check for ServiceInfo. ServiceInfo aInfo = PackageInfoUtils.generateServiceInfo(aPkg, a, 0, new PackageUserState(), 0, mockPkgSetting(aPkg)); ServiceInfo bInfo = PackageInfoUtils.generateServiceInfo(bPkg, b, 0, @@ -510,7 +510,7 @@ public class PackageParserTest { ) { assertComponentsEqual(a, b); - // Sanity check for ActivityInfo. + // Validity check for ActivityInfo. ActivityInfo aInfo = PackageInfoUtils.generateActivityInfo(aPkg, a, 0, new PackageUserState(), 0, mockPkgSetting(aPkg)); ActivityInfo bInfo = PackageInfoUtils.generateActivityInfo(bPkg, b, 0, @@ -523,7 +523,7 @@ public class PackageParserTest { ParsedPermissionGroup b) { assertComponentsEqual(a, b); - // Sanity check for PermissionGroupInfo. + // Validity check for PermissionGroupInfo. assertEquals(a.getName(), b.getName()); assertEquals(a.getDescriptionRes(), b.getDescriptionRes()); } @@ -666,13 +666,13 @@ public class PackageParserTest { } if (List.class.isAssignableFrom(fieldType)) { - // Sanity check for list fields: Assume they're non-null and contain precisely + // Validity check for list fields: Assume they're non-null and contain precisely // one element. List<?> list = (List<?>) f.get(pkg); assertNotNull("List was null: " + f, list); assertEquals(1, list.size()); } else if (fieldType.getComponentType() != null) { - // Sanity check for array fields: Assume they're non-null and contain precisely + // Validity check for array fields: Assume they're non-null and contain precisely // one element. Object array = f.get(pkg); assertNotNull(Array.get(array, 0)); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 44bb58f62253..22b07157e94e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -639,7 +639,7 @@ public final class UserManagerTest { UserInfo user1 = createUser("User 1", 0); UserInfo user2 = createUser("User 2", 0); long[] serialNumbersOfUsers = mUserManager.getSerialNumbersOfUsers(false); - assertThat(serialNumbersOfUsers).asList().containsAllOf( + assertThat(serialNumbersOfUsers).asList().containsAtLeast( (long) user1.serialNumber, (long) user2.serialNumber); } diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java index 87979fb00021..8e94544707a8 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java @@ -150,7 +150,7 @@ public class UserSystemPackageInstallerTest { ArrayMap<String, Set<String>> r = new ArrayMap<>(); r.put("com.android.package1", new ArraySet<>(Arrays.asList( USER_TYPE_PROFILE_MANAGED, "invalid-garbage2"))); - // com.android.package2 has nothing blacklisted + // com.android.package2 has nothing denylisted r.put("com.android.package3", new ArraySet<>(Arrays.asList("SYSTEM"))); return r; } @@ -196,7 +196,7 @@ public class UserSystemPackageInstallerTest { /** * Test that determineWhitelistedPackagesForUserTypes does not include packages that were never - * whitelisted properly, but does include packages that were whitelisted but then blacklisted. + * allowlisted properly, but does include packages that were allowlisted but then denylisted. */ @Test public void testDetermineWhitelistedPackagesForUserTypes_noNetWhitelisting() { @@ -205,22 +205,22 @@ public class UserSystemPackageInstallerTest { public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() { ArrayMap<String, Set<String>> r = new ArrayMap<>(); r.put("com.android.package1", new ArraySet<>(Arrays.asList("invalid1"))); - // com.android.package2 has no whitelisting + // com.android.package2 has no allowlisting r.put("com.android.package3", new ArraySet<>(Arrays.asList("PROFILE", "FULL"))); r.put("com.android.package4", new ArraySet<>(Arrays.asList("PROFILE"))); r.put("com.android.package5", new ArraySet<>()); - // com.android.package6 has no whitelisting + // com.android.package6 has no allowlisting return r; } @Override public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() { ArrayMap<String, Set<String>> r = new ArrayMap<>(); - // com.android.package1 has no blacklisting + // com.android.package1 has no denylisting r.put("com.android.package2", new ArraySet<>(Arrays.asList("FULL"))); r.put("com.android.package3", new ArraySet<>(Arrays.asList("PROFILE", "FULL"))); r.put("com.android.package4", new ArraySet<>(Arrays.asList("PROFILE", "invalid4"))); - // com.android.package5 has no blacklisting + // com.android.package5 has no denylisting r.put("com.android.package6", new ArraySet<>(Arrays.asList("invalid6"))); return r; } @@ -242,18 +242,18 @@ public class UserSystemPackageInstallerTest { */ @Test public void testShouldInstallPackage() { - final String packageName1 = "pkg1"; // whitelisted - final String packageName2 = "pkg2"; // whitelisted and blacklisted - final String packageName3 = "pkg3"; // whitelisted for a different user type - final String packageName4 = "pkg4"; // not whitelisted nor blacklisted at all + final String packageName1 = "pkg1"; // allowlisted + final String packageName2 = "pkg2"; // allowlisted and denylisted + final String packageName3 = "pkg3"; // allowlisted for a different user type + final String packageName4 = "pkg4"; // not allowlisted nor denylisted at all - // Whitelist: user type bitset for each pkg (for the test, all that matters is 0 vs non-0). + // Allowlist: user type bitset for each pkg (for the test, all that matters is 0 vs non-0). final ArrayMap<String, Long> pkgBitSetMap = new ArrayMap<>(); pkgBitSetMap.put(packageName1, 0b01L); pkgBitSetMap.put(packageName2, 0L); pkgBitSetMap.put(packageName3, 0b10L); - // Whitelist of pkgs for this specific user, i.e. subset of pkgBitSetMap for this user. + // Allowlist of pkgs for this specific user, i.e. subset of pkgBitSetMap for this user. final Set<String> userWhitelist = new ArraySet<>(); userWhitelist.add(packageName1); @@ -266,7 +266,7 @@ public class UserSystemPackageInstallerTest { final AndroidPackage pkg4 = ((ParsedPackage) PackageImpl.forTesting(packageName4) .hideAsParsed()).hideAsFinal(); - // No implicit whitelist, so only install pkg1. + // No implicit allowlist, so only install pkg1. boolean implicit = false; assertTrue(UserSystemPackageInstaller.shouldInstallPackage( pkg1, pkgBitSetMap, userWhitelist, implicit)); @@ -277,7 +277,7 @@ public class UserSystemPackageInstallerTest { assertFalse(UserSystemPackageInstaller.shouldInstallPackage( pkg4, pkgBitSetMap, userWhitelist, implicit)); - // Use implicit whitelist, so install pkg1 and pkg4 + // Use implicit allowlist, so install pkg1 and pkg4 implicit = true; assertTrue(UserSystemPackageInstaller.shouldInstallPackage( pkg1, pkgBitSetMap, userWhitelist, implicit)); @@ -302,12 +302,12 @@ public class UserSystemPackageInstallerTest { final long maskOfTypeA = 0b0001L; final long maskOfTypeC = 0b0100L; - final String packageName1 = "pkg1"; // whitelisted for user type A - final String packageName2 = "pkg2"; // blacklisted whenever whitelisted - final String packageName3 = "pkg3"; // whitelisted for user type C - final String packageName4 = "pkg4"; // whitelisted for user type A + final String packageName1 = "pkg1"; // allowlisted for user type A + final String packageName2 = "pkg2"; // denylisted whenever allowlisted + final String packageName3 = "pkg3"; // allowlisted for user type C + final String packageName4 = "pkg4"; // allowlisted for user type A - final ArrayMap<String, Long> pkgBitSetMap = new ArrayMap<>(); // Whitelist: bitset per pkg + final ArrayMap<String, Long> pkgBitSetMap = new ArrayMap<>(); // Allowlist: bitset per pkg pkgBitSetMap.put(packageName1, maskOfTypeA); pkgBitSetMap.put(packageName2, 0L); pkgBitSetMap.put(packageName3, maskOfTypeC); @@ -368,7 +368,7 @@ public class UserSystemPackageInstallerTest { } // Add auto-generated RRO package to expectedPackages since they are not (supposed to be) - // in the whitelist but they should be installed. + // in the allowlist but they should be installed. for (PackageInfo p : packageInfos) { if (p.isOverlayPackage() && UserSystemPackageInstaller.hasAutoGeneratedRROSuffix(p.packageName) @@ -396,7 +396,7 @@ public class UserSystemPackageInstallerTest { } /** - * Test that overlay package not in whitelist should be installed for all user at Explicit mode. + * Test that overlay package not in allowlist should be installed for all user at Explicit mode. */ @Test public void testInstallOverlayPackagesExplicitMode() { @@ -513,7 +513,7 @@ public class UserSystemPackageInstallerTest { assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode()); } - /** Sets the whitelist mode to the desired value via adb's setprop. */ + /** Sets the allowlist mode to the desired value via adb's setprop. */ private void setUserTypePackageWhitelistMode(int mode) { UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); try { @@ -529,7 +529,7 @@ public class UserSystemPackageInstallerTest { /** @see UserSystemPackageInstaller#mWhitelistedPackagesForUserTypes */ private ArrayMap<String, Long> getNewPackageToWhitelistedBitSetMap() { final ArrayMap<String, Long> pkgBitSetMap = new ArrayMap<>(); - // "android" is always treated as whitelisted for all types, regardless of the xml file. + // "android" is always treated as allowlisted for all types, regardless of the xml file. pkgBitSetMap.put("android", ~0L); return pkgBitSetMap; } 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 8398585ca74a..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(); @@ -836,7 +857,7 @@ public class DexManagerTests { @Test public void testOobPackageSelectionWhitelist() { - // Various whitelist of apps to run in OOB mode. + // Various allowlist of apps to run in OOB mode. final String kWhitelistApp0 = "com.priv.app0"; final String kWhitelistApp1 = "com.priv.app1"; final String kWhitelistApp2 = "com.priv.app2"; @@ -845,17 +866,17 @@ public class DexManagerTests { // Packages that shares the targeting process. final Collection<String> runningPackages = Arrays.asList("com.priv.app1", "com.priv.app2"); - // Feature is off, whitelist does not matter + // Feature is off, allowlist does not matter assertFalse(shouldPackageRunOob(false, kWhitelistApp0, runningPackages)); assertFalse(shouldPackageRunOob(false, kWhitelistApp1, runningPackages)); assertFalse(shouldPackageRunOob(false, "", runningPackages)); assertFalse(shouldPackageRunOob(false, "ALL", runningPackages)); - // Feature is on, app not in whitelist + // Feature is on, app not in allowlist assertFalse(shouldPackageRunOob(true, kWhitelistApp0, runningPackages)); assertFalse(shouldPackageRunOob(true, "", runningPackages)); - // Feature is on, app in whitelist + // Feature is on, app in allowlist assertTrue(shouldPackageRunOob(true, kWhitelistApp1, runningPackages)); assertTrue(shouldPackageRunOob(true, kWhitelistApp2, runningPackages)); assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, runningPackages)); 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/AndroidPackageInfoFlagBehaviorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt index 0a32e4a53284..946f27e09fdb 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt @@ -26,6 +26,7 @@ import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companio import com.android.server.pm.parsing.pkg.AndroidPackage import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -102,6 +103,7 @@ class AndroidPackageInfoFlagBehaviorTest : AndroidPackageParsingTestBase() { lateinit var param: Param<Any> @Test + @Ignore("b/155935153") fun fieldPresence() { oldPackages.asSequence().zip(newPackages.asSequence()) .forEach { (old, new) -> @@ -124,6 +126,7 @@ class AndroidPackageInfoFlagBehaviorTest : AndroidPackageParsingTestBase() { } @Test + @Ignore("b/155935153") fun fieldAbsence() { newPackages.forEach { val newWithoutFlag = param.newPkgFunction(it, 0) diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt index 74b4d122cbc0..9f9ec31f0c91 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt @@ -20,6 +20,7 @@ import android.content.pm.PackageManager import android.platform.test.annotations.Presubmit import androidx.test.filters.LargeTest import com.google.common.truth.Expect + import org.junit.Rule import org.junit.Test 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/src/com/android/server/policy/OWNERS b/services/tests/servicestests/src/com/android/server/policy/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/policy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/power/OWNERS b/services/tests/servicestests/src/com/android/server/power/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/power/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS b/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS new file mode 100644 index 000000000000..388003863c1d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/recoverysystem/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java index 035a2f11112c..9b8a2a82c6df 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; @@ -33,6 +34,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.IntentSender; +import android.content.pm.PackageManager; +import android.hardware.boot.V1_2.IBootControl; import android.os.Handler; import android.os.IPowerManager; import android.os.IRecoverySystemProgressListener; @@ -66,9 +69,13 @@ public class RecoverySystemServiceTest { private IThermalService mIThermalService; private FileWriter mUncryptUpdateFileWriter; private LockSettingsInternal mLockSettingsInternal; + private IBootControl mIBootControl; + + private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package"; + private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package"; @Before - public void setup() { + public void setup() throws Exception { mContext = mock(Context.class); mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties(); mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class); @@ -83,8 +90,13 @@ public class RecoverySystemServiceTest { PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager, mIThermalService, new Handler(looper)); + mIBootControl = mock(IBootControl.class); + when(mIBootControl.getCurrentSlot()).thenReturn(0); + when(mIBootControl.getActiveBootSlot()).thenReturn(1); + mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties, - powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal); + powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal, + mIBootControl); } @Test @@ -209,65 +221,99 @@ public class RecoverySystemServiceTest { @Test(expected = SecurityException.class) public void requestLskf_protected() { - doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.RECOVERY), any()); - mRecoverySystemService.requestLskf("test", null); - } - - - @Test - public void requestLskf_nullToken_failure() { - assertThat(mRecoverySystemService.requestLskf(null, null), is(false)); + when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( + PackageManager.PERMISSION_DENIED); + mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null); } @Test public void requestLskf_success() throws Exception { IntentSender intentSender = mock(IntentSender.class); - assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); } @Test - public void requestLskf_subsequentRequestClearsPrepared() throws Exception { + public void requestLskf_subsequentRequestNotClearPrepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); - assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); - assertThat(mRecoverySystemService.requestLskf("test2", null), is(true)); - assertThat(mRecoverySystemService.rebootWithLskf("test", null), is(false)); - assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(false)); - - mRecoverySystemService.onPreparedForReboot(true); - assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(true)); - verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true), + is(true)); verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean()); } - @Test public void requestLskf_requestedButNotPrepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); - assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any()); } + @Test + public void isLskfCaptured_requestedButNotPrepared() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); + assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(false)); + } + + @Test + public void isLskfCaptured_Prepared() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); + mRecoverySystemService.onPreparedForReboot(true); + verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(true)); + } + @Test(expected = SecurityException.class) public void clearLskf_protected() { - doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.RECOVERY), any()); - mRecoverySystemService.clearLskf(); + when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( + PackageManager.PERMISSION_DENIED); + mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME); } @Test public void clearLskf_requestedThenCleared() throws Exception { IntentSender intentSender = mock(IntentSender.class); - assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); - assertThat(mRecoverySystemService.clearLskf(), is(true)); + assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); + verify(mLockSettingsInternal).clearRebootEscrow(); + } + + @Test + public void clearLskf_callerNotRequested_Success() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); + assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); + verify(mLockSettingsInternal, never()).clearRebootEscrow(); + } + + @Test + public void clearLskf_multiClient_BothClientsClear() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, intentSender), + is(true)); + + assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); + verify(mLockSettingsInternal, never()).clearRebootEscrow(); + assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal).clearRebootEscrow(); } @@ -279,27 +325,93 @@ public class RecoverySystemServiceTest { @Test(expected = SecurityException.class) public void rebootWithLskf_protected() { - doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.RECOVERY), any()); - mRecoverySystemService.rebootWithLskf("test1", null); + when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( + PackageManager.PERMISSION_DENIED); + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true); } @Test public void rebootWithLskf_Success() throws Exception { - assertThat(mRecoverySystemService.requestLskf("test", null), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); - assertThat(mRecoverySystemService.rebootWithLskf("test", "ab-update"), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), + is(true)); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); } + + @Test + public void rebootWithLskf_slotMismatch_Failure() throws Exception { + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false), + is(false)); + } + @Test public void rebootWithLskf_withoutPrepare_Failure() throws Exception { - assertThat(mRecoverySystemService.rebootWithLskf("test1", null), is(false)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), + is(false)); + } + + @Test + public void rebootWithLskf_withNullCallerId_Failure() throws Exception { + assertThat(mRecoverySystemService.rebootWithLskf(null, null, true), is(false)); + verifyNoMoreInteractions(mIPowerManager); + } + + @Test + public void rebootWithLskf_multiClient_ClientASuccess() throws Exception { + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + + // Client B's clear won't affect client A's preparation. + assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), + is(true)); + verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); + } + + + @Test + public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception { + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); + + assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), + is(false)); + verifyNoMoreInteractions(mIPowerManager); + + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); + assertThat( + mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), + is(true)); + verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); } @Test - public void rebootWithLskf_withNullUpdateToken_Failure() throws Exception { - assertThat(mRecoverySystemService.rebootWithLskf(null, null), is(false)); + public void rebootWithLskf_multiClient_BothClientsClear_Failure() throws Exception { + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); + + // Client A clears + assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), + is(false)); + verifyNoMoreInteractions(mIPowerManager); + + // Client B clears + assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); + verify(mLockSettingsInternal).clearRebootEscrow(); + assertThat( + mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), + is(false)); verifyNoMoreInteractions(mIPowerManager); } + + // TODO(xunchang) add more multi client tests } diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java index 131e4f321a6c..0727e5adb9ca 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java @@ -17,6 +17,7 @@ package com.android.server.recoverysystem; import android.content.Context; +import android.hardware.boot.V1_2.IBootControl; import android.os.PowerManager; import com.android.internal.widget.LockSettingsInternal; @@ -30,16 +31,19 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { private final FileWriter mUncryptPackageFileWriter; private final UncryptSocket mUncryptSocket; private final LockSettingsInternal mLockSettingsInternal; + private final IBootControl mIBootControl; MockInjector(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, - UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) { + UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal, + IBootControl bootControl) { super(context); mSystemProperties = systemProperties; mPowerManager = powerManager; mUncryptPackageFileWriter = uncryptPackageFileWriter; mUncryptSocket = uncryptSocket; mLockSettingsInternal = lockSettingsInternal; + mIBootControl = bootControl; } @Override @@ -85,13 +89,19 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { public LockSettingsInternal getLockSettingsService() { return mLockSettingsInternal; } + + @Override + public IBootControl getBootControl() { + return mIBootControl; + } } RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, - UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) { + UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal, + IBootControl bootControl) { super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter, - uncryptSocket, lockSettingsInternal)); + uncryptSocket, lockSettingsInternal, bootControl)); } public static class FakeSystemProperties { @@ -102,6 +112,8 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { || RecoverySystemService.INIT_SERVICE_SETUP_BCB.equals(key) || RecoverySystemService.INIT_SERVICE_CLEAR_BCB.equals(key)) { return null; + } else if (RecoverySystemService.AB_UPDATE.equals(key)) { + return "true"; } else { throw new IllegalArgumentException("unexpected test key: " + key); } diff --git a/services/tests/servicestests/src/com/android/server/rollback/OWNERS b/services/tests/servicestests/src/com/android/server/rollback/OWNERS new file mode 100644 index 000000000000..d04a70619caa --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/rollback/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/rollback/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java index 102d5bb373c8..cc32d5c5a292 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java @@ -48,41 +48,25 @@ public class RollbackStoreTest { private static final String INSTALLER = "some.installer"; private static final Correspondence<VersionedPackage, VersionedPackage> VER_PKG_CORR = - new Correspondence<VersionedPackage, VersionedPackage>() { - @Override - public boolean compare(VersionedPackage a, VersionedPackage b) { - if (a == null || b == null) { - return a == b; - } - return a.equals(b); + Correspondence.from((VersionedPackage a, VersionedPackage b) -> { + if (a == null || b == null) { + return a == b; } - - @Override - public String toString() { - return "is the same as"; - } - }; + return a.equals(b); + }, "is the same as"); private static final Correspondence<PackageRollbackInfo.RestoreInfo, PackageRollbackInfo.RestoreInfo> RESTORE_INFO_CORR = - new Correspondence<PackageRollbackInfo.RestoreInfo, PackageRollbackInfo.RestoreInfo>() { - @Override - public boolean compare(PackageRollbackInfo.RestoreInfo a, - PackageRollbackInfo.RestoreInfo b) { - if (a == null || b == null) { - return a == b; - } - return a.userId == b.userId - && a.appId == b.appId - && Objects.equals(a.seInfo, b.seInfo); - } - - @Override - public String toString() { - return "is the same as"; + Correspondence.from((PackageRollbackInfo.RestoreInfo a, + PackageRollbackInfo.RestoreInfo b) -> { + if (a == null || b == null) { + return a == b; } - }; + return a.userId == b.userId + && a.appId == b.appId + && Objects.equals(a.seInfo, b.seInfo); + }, "is the same as"); private static final String JSON_ROLLBACK_NO_EXT = "{'info':{'rollbackId':123,'packages':" + "[{'versionRolledBackFrom':{'packageName':'blah','longVersionCode':55}," diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS new file mode 100644 index 000000000000..e21b66ecb394 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS @@ -0,0 +1 @@ +include /media/java/android/media/soundtrigger_middleware/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/stats/OWNERS b/services/tests/servicestests/src/com/android/server/stats/OWNERS new file mode 100644 index 000000000000..ee865b1e4ec8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/stats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/stats/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/storage/DiskStatsFileLoggerTest.java b/services/tests/servicestests/src/com/android/server/storage/DiskStatsFileLoggerTest.java index 13a3c2f23988..8fb2e6838412 100644 --- a/services/tests/servicestests/src/com/android/server/storage/DiskStatsFileLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/storage/DiskStatsFileLoggerTest.java @@ -123,7 +123,7 @@ public class DiskStatsFileLoggerTest extends AndroidTestCase { JSONArray cacheSizes = output.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); assertThat(cacheSizes.length()).isEqualTo(2); - // We need to do this crazy Set over this because the DiskStatsFileLogger provides no + // We need to do this unexpected Set over this because the DiskStatsFileLogger provides no // guarantee of the ordering of the apps in its output. By using a set, we avoid any order // problems. ArraySet<AppSizeGrouping> apps = new ArraySet<>(); @@ -132,7 +132,7 @@ public class DiskStatsFileLoggerTest extends AndroidTestCase { appSizes.getLong(i), cacheSizes.getLong(i)); apps.add(app); } - assertThat(apps).containsAllOf(new AppSizeGrouping("com.test.app", 1100, 20), + assertThat(apps).containsAtLeast(new AppSizeGrouping("com.test.app", 1100, 20), new AppSizeGrouping("com.test.app2", 11, 2)); } diff --git a/services/tests/servicestests/src/com/android/server/storage/OWNERS b/services/tests/servicestests/src/com/android/server/storage/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/storage/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java index 10981ab49513..17d99e652726 100644 --- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java @@ -184,7 +184,7 @@ public class SystemConfigTest { /** * Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_APP_CONFIGS} - * permission flag for the tag: whitelisted-staged-installer. + * permission flag for the tag: allowlisted-staged-installer. */ @Test public void readPermissions_allowAppConfigs_parsesStagedInstallerWhitelist() @@ -204,7 +204,7 @@ public class SystemConfigTest { /** * Tests that readPermissions works correctly without {@link SystemConfig#ALLOW_APP_CONFIGS} - * permission flag for the tag: whitelisted-staged-installer. + * permission flag for the tag: allowlisted-staged-installer. */ @Test public void readPermissions_notAllowAppConfigs_wontParseStagedInstallerWhitelist() diff --git a/services/tests/servicestests/src/com/android/server/textclassifier/IconsContentProviderTest.java b/services/tests/servicestests/src/com/android/server/textclassifier/IconsContentProviderTest.java index a787c321fc66..3b963f6697f9 100644 --- a/services/tests/servicestests/src/com/android/server/textclassifier/IconsContentProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/textclassifier/IconsContentProviderTest.java @@ -29,7 +29,7 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Sanity test for {@link IconsContentProvider}. + * Validity test for {@link IconsContentProvider}. */ @RunWith(AndroidJUnit4.class) public final class IconsContentProviderTest { diff --git a/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS new file mode 100644 index 000000000000..46b3cb8824a0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/textclassifier/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/textservices/OWNERS b/services/tests/servicestests/src/com/android/server/textservices/OWNERS new file mode 100644 index 000000000000..0471e29a25cd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/textservices/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 816455 + +include /services/core/java/com/android/server/textservices/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java index 2eeeb3ebaa2a..f0b1be594909 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -132,15 +133,14 @@ public class TimeDetectorServiceTest { doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion(); - mTimeDetectorService.suggestManualTime(manualTimeSuggestion); - mTestHandler.assertTotalMessagesEnqueued(1); + + assertTrue(mTimeDetectorService.suggestManualTime(manualTimeSuggestion)); + mStubbedTimeDetectorStrategy.verifySuggestManualTimeCalled(manualTimeSuggestion); verify(mMockContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString()); - mTestHandler.waitForMessagesToBeProcessed(); - mStubbedTimeDetectorStrategy.verifySuggestManualTimeCalled(manualTimeSuggestion); } @Test(expected = SecurityException.class) @@ -173,6 +173,36 @@ public class TimeDetectorServiceTest { mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion); } + @Test(expected = SecurityException.class) + public void testSuggestGnssTime_withoutPermission() { + doThrow(new SecurityException("Mock")) + .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion(); + + try { + mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion); + fail(); + } finally { + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME), anyString()); + } + } + + @Test + public void testSuggestGnssTime() throws Exception { + doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + + GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion(); + mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion); + mTestHandler.assertTotalMessagesEnqueued(1); + + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME), anyString()); + + mTestHandler.waitForMessagesToBeProcessed(); + mStubbedTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion); + } + @Test public void testDump() { when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)) @@ -217,27 +247,30 @@ public class TimeDetectorServiceTest { return new NetworkTimeSuggestion(timeValue); } + private static GnssTimeSuggestion createGnssTimeSuggestion() { + TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L); + return new GnssTimeSuggestion(timeValue); + } + private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy { // Call tracking. private TelephonyTimeSuggestion mLastTelephonySuggestion; private ManualTimeSuggestion mLastManualSuggestion; private NetworkTimeSuggestion mLastNetworkSuggestion; + private GnssTimeSuggestion mLastGnssSuggestion; private boolean mHandleAutoTimeDetectionChangedCalled; private boolean mDumpCalled; @Override - public void initialize(Callback ignored) { - } - - @Override public void suggestTelephonyTime(TelephonyTimeSuggestion timeSuggestion) { mLastTelephonySuggestion = timeSuggestion; } @Override - public void suggestManualTime(ManualTimeSuggestion timeSuggestion) { + public boolean suggestManualTime(ManualTimeSuggestion timeSuggestion) { mLastManualSuggestion = timeSuggestion; + return true; } @Override @@ -246,7 +279,12 @@ public class TimeDetectorServiceTest { } @Override - public void handleAutoTimeDetectionChanged() { + public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) { + mLastGnssSuggestion = timeSuggestion; + } + + @Override + public void handleAutoTimeConfigChanged() { mHandleAutoTimeDetectionChangedCalled = true; } @@ -259,6 +297,7 @@ public class TimeDetectorServiceTest { mLastTelephonySuggestion = null; mLastManualSuggestion = null; mLastNetworkSuggestion = null; + mLastGnssSuggestion = null; mHandleAutoTimeDetectionChangedCalled = false; mDumpCalled = false; } @@ -267,14 +306,18 @@ public class TimeDetectorServiceTest { assertEquals(expectedSuggestion, mLastTelephonySuggestion); } - public void verifySuggestManualTimeCalled(ManualTimeSuggestion expectedSuggestion) { + void verifySuggestManualTimeCalled(ManualTimeSuggestion expectedSuggestion) { assertEquals(expectedSuggestion, mLastManualSuggestion); } - public void verifySuggestNetworkTimeCalled(NetworkTimeSuggestion expectedSuggestion) { + void verifySuggestNetworkTimeCalled(NetworkTimeSuggestion expectedSuggestion) { assertEquals(expectedSuggestion, mLastNetworkSuggestion); } + void verifySuggestGnssTimeCalled(GnssTimeSuggestion expectedSuggestion) { + assertEquals(expectedSuggestion, mLastGnssSuggestion); + } + void verifyHandleAutoTimeDetectionChangedCalled() { assertTrue(mHandleAutoTimeDetectionChangedCalled); } diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java index 803b245889e7..b1adb0b4ce60 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java @@ -16,41 +16,53 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; -import android.icu.util.Calendar; -import android.icu.util.GregorianCalendar; -import android.icu.util.TimeZone; import android.os.TimestampedValue; import androidx.test.runner.AndroidJUnit4; +import com.android.server.timedetector.TimeDetectorStrategy.Origin; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; @RunWith(AndroidJUnit4.class) public class TimeDetectorStrategyImplTest { - private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO = + private static final Instant TIME_LOWER_BOUND = createUtcTime(2009, 1, 1, 12, 0, 0); + + private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO = new TimestampedValue<>( 123456789L /* realtimeClockMillis */, - createUtcTime(2008, 5, 23, 12, 0, 0)); + createUtcTime(2010, 5, 23, 12, 0, 0)); + + // This is the traditional ordering for time detection on Android. + private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK }; /** * An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO} * time. Can be used as the basis for time suggestions. */ - private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0); + private static final Instant ARBITRARY_TEST_TIME = createUtcTime(2018, 1, 1, 12, 0, 0); private static final int ARBITRARY_SLOT_INDEX = 123456; @@ -67,10 +79,10 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(true); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion timeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); mScript.simulateTimePassing() .simulateTelephonyTimeSuggestion(timeSuggestion); @@ -106,9 +118,9 @@ public class TimeDetectorStrategyImplTest { // Send the first time signal. It should be used. { TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS); + mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME); - // Increment the the device clocks to simulate the passage of time. + // Increment the device clocks to simulate the passage of time. mScript.simulateTimePassing(clockIncrementMillis); long expectedSystemClockMillis1 = @@ -157,13 +169,13 @@ public class TimeDetectorStrategyImplTest { // uses the lowest slotIndex when multiple telephony suggestions are available. int slotIndex1 = ARBITRARY_SLOT_INDEX; int slotIndex2 = ARBITRARY_SLOT_INDEX + 1; - long slotIndex1TimeMillis = ARBITRARY_TEST_TIME_MILLIS; - long slotIndex2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis(); + Instant slotIndex1Time = ARBITRARY_TEST_TIME; + Instant slotIndex2Time = ARBITRARY_TEST_TIME.plus(Duration.ofDays(1)); // Make a suggestion with slotIndex2. { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -180,7 +192,7 @@ public class TimeDetectorStrategyImplTest { // Now make a different suggestion with slotIndex1. { TelephonyTimeSuggestion slotIndex1TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -198,7 +210,7 @@ public class TimeDetectorStrategyImplTest { // slotIndex1 suggestion will still "win". { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion) @@ -213,7 +225,7 @@ public class TimeDetectorStrategyImplTest { // is in an older "bucket". { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -232,7 +244,7 @@ public class TimeDetectorStrategyImplTest { int slotIndex = ARBITRARY_SLOT_INDEX; TelephonyTimeSuggestion timeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS); + mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME); mScript.simulateTimePassing() .simulateTelephonyTimeSuggestion(timeSuggestion) .verifySystemClockWasNotSetAndResetCallTracking() @@ -246,11 +258,11 @@ public class TimeDetectorStrategyImplTest { .pokeThresholds(systemClockUpdateThreshold) .pokeAutoTimeDetectionEnabled(true); - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; int slotIndex = ARBITRARY_SLOT_INDEX; TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime(); // Initialize the strategy / device with a time set from a telephony suggestion. @@ -300,6 +312,23 @@ public class TimeDetectorStrategyImplTest { } @Test + public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + int slotIndex = ARBITRARY_SLOT_INDEX; + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + + TelephonyTimeSuggestion timeSuggestion = + mScript.generateTelephonyTimeSuggestion( + slotIndex, suggestedTime); + + mScript.simulateTelephonyTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestTelephonySuggestion(slotIndex, null); + } + + @Test public void testSuggestTelephonyTime_timeDetectionToggled() { final int clockIncrementMillis = 100; final int systemClockUpdateThreshold = 2000; @@ -308,9 +337,9 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(false); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime(); // Simulate time passing. @@ -366,9 +395,9 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(true); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion telephonySuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); mScript.simulateTimePassing(); @@ -397,13 +426,13 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(false); ManualTimeSuggestion timeSuggestion = - mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing(); long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime()); - mScript.simulateManualTimeSuggestion(timeSuggestion) + mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */) .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis); } @@ -416,9 +445,9 @@ public class TimeDetectorStrategyImplTest { int slotIndex = ARBITRARY_SLOT_INDEX; // Simulate a telephony suggestion. - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion telephonyTimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); // Simulate the passage of time. mScript.simulateTimePassing(); @@ -441,14 +470,14 @@ public class TimeDetectorStrategyImplTest { mScript.simulateTimePassing(); // Simulate a manual suggestion 1 day different from the auto suggestion. - long manualTimeMillis = testTimeMillis + Duration.ofDays(1).toMillis(); + Instant manualTime = testTime.plus(Duration.ofDays(1)); ManualTimeSuggestion manualTimeSuggestion = - mScript.generateManualTimeSuggestion(manualTimeMillis); + mScript.generateManualTimeSuggestion(manualTime); mScript.simulateTimePassing(); long expectedManualClockMillis = mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUtcTime()); - mScript.simulateManualTimeSuggestion(manualTimeSuggestion) + mScript.simulateManualTimeSuggestion(manualTimeSuggestion, true /* expectedResult */) .verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis) .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion); @@ -469,29 +498,40 @@ public class TimeDetectorStrategyImplTest { .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion); } - /** - * Manual suggestions should be ignored if auto time is enabled. - */ @Test - public void testSuggestManualTime_autoTimeEnabled() { + public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true); ManualTimeSuggestion timeSuggestion = - mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing() - .simulateManualTimeSuggestion(timeSuggestion) + .simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */) .verifySystemClockWasNotSetAndResetCallTracking(); } @Test + public void manualTimeSuggestion_ignoresTimeLowerBound() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(false); + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + + ManualTimeSuggestion timeSuggestion = + mScript.generateManualTimeSuggestion(suggestedTime); + + mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */) + .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli()); + } + + @Test public void testSuggestNetworkTime_autoTimeEnabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_NETWORK) .pokeAutoTimeDetectionEnabled(true); NetworkTimeSuggestion timeSuggestion = - mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing(); @@ -504,10 +544,11 @@ public class TimeDetectorStrategyImplTest { @Test public void testSuggestNetworkTime_autoTimeDisabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_NETWORK) .pokeAutoTimeDetectionEnabled(false); NetworkTimeSuggestion timeSuggestion = - mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing() .simulateNetworkTimeSuggestion(timeSuggestion) @@ -515,21 +556,83 @@ public class TimeDetectorStrategyImplTest { } @Test - public void testSuggestNetworkTime_telephonySuggestionsBeatNetworkSuggestions() { + public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_NETWORK) + .pokeAutoTimeDetectionEnabled(true); + + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + NetworkTimeSuggestion timeSuggestion = mScript + .generateNetworkTimeSuggestion(suggestedTime); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestNetworkSuggestion(null); + } + + @Test + public void testSuggestGnssTime_autoTimeEnabled() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) + .pokeAutoTimeDetectionEnabled(true); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateTimePassing(); + + long expectedSystemClockMillis = + mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime()); + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis); + } + + @Test + public void testSuggestGnssTime_autoTimeDisabled() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) + .pokeAutoTimeDetectionEnabled(false); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateTimePassing() + .simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void gnssTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) .pokeAutoTimeDetectionEnabled(true); + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + GnssTimeSuggestion timeSuggestion = mScript + .generateGnssTimeSuggestion(suggestedTime); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestGnssSuggestion(null); + } + + @Test + public void highPrioritySuggestionsBeatLowerPrioritySuggestions_telephonyNetworkOrigins() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK); + // Three obviously different times that could not be mistaken for each other. - long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS; - long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis(); - long telephonyTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis(); + Instant networkTime1 = ARBITRARY_TEST_TIME; + Instant networkTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); // A small increment used to simulate the passage of time, but not enough to interfere with // macro-level time changes associated with suggestion age. final long smallTimeIncrementMillis = 101; // A network suggestion is made. It should be used because there is no telephony suggestion. NetworkTimeSuggestion networkTimeSuggestion1 = - mScript.generateNetworkTimeSuggestion(networkTimeMillis1); + mScript.generateNetworkTimeSuggestion(networkTime1); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateNetworkTimeSuggestion(networkTimeSuggestion1) .verifySystemClockWasSetAndResetCallTracking( @@ -539,7 +642,7 @@ public class TimeDetectorStrategyImplTest { mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null) .assertLatestNetworkSuggestion(networkTimeSuggestion1); assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion()); - assertNull(mScript.peekBestTelephonySuggestion()); + assertNull("No telephony suggestions were made:", mScript.peekBestTelephonySuggestion()); // Simulate a little time passing. mScript.simulateTimePassing(smallTimeIncrementMillis) @@ -548,7 +651,7 @@ public class TimeDetectorStrategyImplTest { // Now a telephony suggestion is made. Telephony suggestions are prioritized over network // suggestions so it should "win". TelephonyTimeSuggestion telephonyTimeSuggestion = - mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeMillis); + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) .verifySystemClockWasSetAndResetCallTracking( @@ -568,7 +671,7 @@ public class TimeDetectorStrategyImplTest { // Now another network suggestion is made. Telephony suggestions are prioritized over // network suggestions so the latest telephony suggestion should still "win". NetworkTimeSuggestion networkTimeSuggestion2 = - mScript.generateNetworkTimeSuggestion(networkTimeMillis2); + mScript.generateNetworkTimeSuggestion(networkTime2); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateNetworkTimeSuggestion(networkTimeSuggestion2) .verifySystemClockWasNotSetAndResetCallTracking(); @@ -594,7 +697,9 @@ public class TimeDetectorStrategyImplTest { mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) .assertLatestNetworkSuggestion(networkTimeSuggestion2); assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion()); - assertNull(mScript.peekBestTelephonySuggestion()); + assertNull( + "Telephony suggestion should be expired:", + mScript.peekBestTelephonySuggestion()); // Toggle auto-time off and on to force the detection logic to run. mScript.simulateAutoTimeDetectionToggle() @@ -609,19 +714,262 @@ public class TimeDetectorStrategyImplTest { mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) .assertLatestNetworkSuggestion(networkTimeSuggestion2); assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion()); - assertNull(mScript.peekBestTelephonySuggestion()); + assertNull( + "Telephony suggestion should still be expired:", + mScript.peekBestTelephonySuggestion()); + } + + @Test + public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkGnssOrigins() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_GNSS); + + // Three obviously different times that could not be mistaken for each other. + Instant gnssTime1 = ARBITRARY_TEST_TIME; + Instant gnssTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant networkTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); + // A small increment used to simulate the passage of time, but not enough to interfere with + // macro-level time changes associated with suggestion age. + final long smallTimeIncrementMillis = 101; + + // A gnss suggestion is made. It should be used because there is no network suggestion. + GnssTimeSuggestion gnssTimeSuggestion1 = + mScript.generateGnssTimeSuggestion(gnssTime1); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateGnssTimeSuggestion(gnssTimeSuggestion1) + .verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(gnssTimeSuggestion1.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(null) + .assertLatestGnssSuggestion(gnssTimeSuggestion1); + assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion()); + assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion()); + + // Simulate a little time passing. + mScript.simulateTimePassing(smallTimeIncrementMillis) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Now a network suggestion is made. Network suggestions are prioritized over gnss + // suggestions so it should "win". + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion1); + assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion()); + assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion()); + + // Simulate some significant time passing: half the time allowed before a time signal + // becomes "too old to use". + mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Now another gnss suggestion is made. Network suggestions are prioritized over + // gnss suggestions so the latest network suggestion should still "win". + GnssTimeSuggestion gnssTimeSuggestion2 = + mScript.generateGnssTimeSuggestion(gnssTime2); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateGnssTimeSuggestion(gnssTimeSuggestion2) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion()); + + // Simulate some significant time passing: half the time allowed before a time signal + // becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to + // be used but networkTimeSuggestion2 is not. + mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2); + + // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last + // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle + // to re-run the detection logic. This may change in future but until then we rely on a + // steady stream of suggestions to re-evaluate. + mScript.verifySystemClockWasNotSetAndResetCallTracking(); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertNull( + "Network suggestion should be expired:", + mScript.peekLatestValidNetworkSuggestion()); + + // Toggle auto-time off and on to force the detection logic to run. + mScript.simulateAutoTimeDetectionToggle() + .simulateTimePassing(smallTimeIncrementMillis) + .simulateAutoTimeDetectionToggle(); + + // Verify the latest gnss time now wins. + mScript.verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertNull( + "Network suggestion should still be expired:", + mScript.peekLatestValidNetworkSuggestion()); + } + + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + GnssTimeSuggestion gnssTimeSuggestion = + mScript.generateGnssTimeSuggestion(gnssTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + + mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateGnssTimeSuggestion(gnssTimeSuggestion) + .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + GnssTimeSuggestion gnssTimeSuggestion = + mScript.generateGnssTimeSuggestion(gnssTime); + + mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateGnssTimeSuggestion(gnssTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK); + + NetworkTimeSuggestion timeSuggestion = + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); + } + + @Test + public void whenHigherPrioritySuggestionsAreNotAvailable_fallbacksToNext() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .assertLatestGnssSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); + } + + @Test + public void suggestionsFromTelephonyOriginNotInPriorityList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_NETWORK); + + int slotIndex = ARBITRARY_SLOT_INDEX; + Instant testTime = ARBITRARY_TEST_TIME; + TelephonyTimeSuggestion timeSuggestion = + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); + + mScript.simulateTelephonyTimeSuggestion(timeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY); + + NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion( + ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY); + + GnssTimeSuggestion timeSuggestion = mScript.generateGnssTimeSuggestion( + ARBITRARY_TEST_TIME); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .assertLatestGnssSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(false) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY); + + ManualTimeSuggestion timeSuggestion = + mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); } /** * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving * like the real thing should, it also asserts preconditions. */ - private static class FakeCallback implements TimeDetectorStrategy.Callback { + private static class FakeCallback implements TimeDetectorStrategyImpl.Callback { private boolean mAutoTimeDetectionEnabled; private boolean mWakeLockAcquired; private long mElapsedRealtimeMillis; private long mSystemClockMillis; private int mSystemClockUpdateThresholdMillis = 2000; + private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY; // Tracking operations. private boolean mSystemClockWasSet; @@ -637,6 +985,16 @@ public class TimeDetectorStrategyImplTest { } @Override + public Instant autoTimeLowerBound() { + return TIME_LOWER_BOUND; + } + + @Override + public int[] autoOriginPriorities() { + return mAutoOriginPriorities; + } + + @Override public void acquireWakeLock() { if (mWakeLockAcquired) { fail("Wake lock already acquired"); @@ -685,6 +1043,10 @@ public class TimeDetectorStrategyImplTest { mAutoTimeDetectionEnabled = enabled; } + void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) { + mAutoOriginPriorities = autoOriginPriorities; + } + long peekElapsedRealtimeMillis() { return mElapsedRealtimeMillis; } @@ -703,7 +1065,10 @@ public class TimeDetectorStrategyImplTest { } void verifySystemClockNotSet() { - assertFalse(mSystemClockWasSet); + assertFalse( + String.format("System clock was manipulated and set to %s(=%s)", + Instant.ofEpochMilli(mSystemClockMillis), mSystemClockMillis), + mSystemClockWasSet); } void verifySystemClockWasSet(long expectedSystemClockMillis) { @@ -731,9 +1096,7 @@ public class TimeDetectorStrategyImplTest { Script() { mFakeCallback = new FakeCallback(); - mTimeDetectorStrategy = new TimeDetectorStrategyImpl(); - mTimeDetectorStrategy.initialize(mFakeCallback); - + mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeCallback); } Script pokeAutoTimeDetectionEnabled(boolean enabled) { @@ -741,9 +1104,9 @@ public class TimeDetectorStrategyImplTest { return this; } - Script pokeFakeClocks(TimestampedValue<Long> timeInfo) { + Script pokeFakeClocks(TimestampedValue<Instant> timeInfo) { mFakeCallback.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis()); - mFakeCallback.pokeSystemClockMillis(timeInfo.getValue()); + mFakeCallback.pokeSystemClockMillis(timeInfo.getValue().toEpochMilli()); return this; } @@ -752,6 +1115,11 @@ public class TimeDetectorStrategyImplTest { return this; } + Script pokeAutoOriginPriorities(@Origin int... autoOriginPriorities) { + mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorities); + return this; + } + long peekElapsedRealtimeMillis() { return mFakeCallback.peekElapsedRealtimeMillis(); } @@ -765,8 +1133,15 @@ public class TimeDetectorStrategyImplTest { return this; } - Script simulateManualTimeSuggestion(ManualTimeSuggestion timeSuggestion) { - mTimeDetectorStrategy.suggestManualTime(timeSuggestion); + Script simulateManualTimeSuggestion( + ManualTimeSuggestion timeSuggestion, boolean expectedResult) { + String errorMessage = expectedResult + ? "Manual time suggestion was ignored, but expected to be accepted." + : "Manual time suggestion was accepted, but expected to be ignored."; + assertEquals( + errorMessage, + expectedResult, + mTimeDetectorStrategy.suggestManualTime(timeSuggestion)); return this; } @@ -775,9 +1150,14 @@ public class TimeDetectorStrategyImplTest { return this; } + Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) { + mTimeDetectorStrategy.suggestGnssTime(timeSuggestion); + return this; + } + Script simulateAutoTimeDetectionToggle() { mFakeCallback.simulateAutoTimeZoneDetectionToggle(); - mTimeDetectorStrategy.handleAutoTimeDetectionChanged(); + mTimeDetectorStrategy.handleAutoTimeConfigChanged(); return this; } @@ -809,7 +1189,10 @@ public class TimeDetectorStrategyImplTest { * White box test info: Asserts the latest suggestion for the slotIndex is as expected. */ Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) { - assertEquals(expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex)); + assertEquals( + "Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got " + + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex), + expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex)); return this; } @@ -822,6 +1205,14 @@ public class TimeDetectorStrategyImplTest { } /** + * White box test info: Asserts the latest gnss suggestion is as expected. + */ + Script assertLatestGnssSuggestion(GnssTimeSuggestion expected) { + assertEquals(expected, mTimeDetectorStrategy.getLatestGnssSuggestion()); + return this; + } + + /** * White box test info: Returns the telephony suggestion that would be used, if any, given * the current elapsed real time clock and regardless of origin prioritization. */ @@ -838,12 +1229,22 @@ public class TimeDetectorStrategyImplTest { } /** + * White box test info: Returns the gnss suggestion that would be used, if any, given the + * current elapsed real time clock and regardless of origin prioritization. + */ + GnssTimeSuggestion peekLatestValidGnssSuggestion() { + return mTimeDetectorStrategy.findLatestValidGnssSuggestionForTests(); + } + + /** * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the * reference time. */ - ManualTimeSuggestion generateManualTimeSuggestion(long timeMillis) { + ManualTimeSuggestion generateManualTimeSuggestion(Instant suggestedTime) { TimestampedValue<Long> utcTime = - new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis); + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); return new ManualTimeSuggestion(utcTime); } @@ -851,25 +1252,49 @@ public class TimeDetectorStrategyImplTest { * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for * the reference time. */ - TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, Long timeMillis) { - TimestampedValue<Long> time = null; - if (timeMillis != null) { - time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis); - } + TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, long timeMillis) { + TimestampedValue<Long> time = + new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis); return createTelephonyTimeSuggestion(slotIndex, time); } /** + * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for + * the reference time. + */ + TelephonyTimeSuggestion generateTelephonyTimeSuggestion( + int slotIndex, Instant suggestedTime) { + if (suggestedTime == null) { + return createTelephonyTimeSuggestion(slotIndex, null); + } + return generateTelephonyTimeSuggestion(slotIndex, suggestedTime.toEpochMilli()); + } + + /** * Generates a NetworkTimeSuggestion using the current elapsed realtime clock for the * reference time. */ - NetworkTimeSuggestion generateNetworkTimeSuggestion(long timeMillis) { + NetworkTimeSuggestion generateNetworkTimeSuggestion(Instant suggestedTime) { TimestampedValue<Long> utcTime = - new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis); + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); return new NetworkTimeSuggestion(utcTime); } /** + * Generates a GnssTimeSuggestion using the current elapsed realtime clock for the + * reference time. + */ + GnssTimeSuggestion generateGnssTimeSuggestion(Instant suggestedTime) { + TimestampedValue<Long> utcTime = + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); + return new GnssTimeSuggestion(utcTime); + } + + /** * Calculates what the supplied time would be when adjusted for the movement of the fake * elapsed realtime clock. */ @@ -885,11 +1310,9 @@ public class TimeDetectorStrategyImplTest { .build(); } - private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute, - int second) { - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC")); - cal.clear(); - cal.set(year, monthInYear - 1, day, hourOfDay, minute, second); - return cal.getTimeInMillis(); + private static Instant createUtcTime(int year, int monthInYear, int day, int hourOfDay, + int minute, int second) { + return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second) + .toInstant(ZoneOffset.UTC); } } diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java index 5c6fe0fc4cad..2c4c4d0ee91f 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java @@ -43,13 +43,13 @@ import android.app.timezone.RulesManager; import android.app.timezone.RulesState; import android.os.ParcelFileDescriptor; +import com.android.i18n.timezone.TzDataSetVersion; import com.android.timezone.distro.DistroVersion; import com.android.timezone.distro.StagedDistroOperation; import com.android.timezone.distro.TimeZoneDistro; import com.android.timezone.distro.installer.TimeZoneDistroInstaller; import libcore.io.IoUtils; -import libcore.timezone.TzDataSetVersion; import org.junit.Before; import org.junit.Test; diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java index da34e1b792c1..baec558f3ac6 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java @@ -96,15 +96,16 @@ public class TimeZoneDetectorServiceTest { doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); ManualTimeZoneSuggestion timeZoneSuggestion = createManualTimeZoneSuggestion(); - mTimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion); - mTestHandler.assertTotalMessagesEnqueued(1); + + boolean expectedResult = true; // The test strategy always returns true. + assertEquals(expectedResult, + mTimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion)); + + mStubbedTimeZoneDetectorStrategy.verifySuggestManualTimeZoneCalled(timeZoneSuggestion); verify(mMockContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString()); - - mTestHandler.waitForMessagesToBeProcessed(); - mStubbedTimeZoneDetectorStrategy.verifySuggestManualTimeZoneCalled(timeZoneSuggestion); } @Test(expected = SecurityException.class) @@ -187,8 +188,9 @@ public class TimeZoneDetectorServiceTest { private boolean mDumpCalled; @Override - public void suggestManualTimeZone(ManualTimeZoneSuggestion timeZoneSuggestion) { + public boolean suggestManualTimeZone(ManualTimeZoneSuggestion timeZoneSuggestion) { mLastManualSuggestion = timeZoneSuggestion; + return true; } @Override diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index 30bb12e3e616..1fbe781a67b7 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -98,7 +98,7 @@ public class TimeZoneDetectorStrategyImplTest { .initializeAutoTimeZoneDetection(true) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); - script.suggestTelephonyTimeZone(slotIndex1TimeZoneSuggestion) + script.simulateTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion) .verifyTimeZoneNotSet(); // Assert internal service state. @@ -111,7 +111,7 @@ public class TimeZoneDetectorStrategyImplTest { assertEquals(expectedSlotIndex1ScoredSuggestion, mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests()); - script.suggestTelephonyTimeZone(slotIndex2TimeZoneSuggestion) + script.simulateTelephonyTimeZoneSuggestion(slotIndex2TimeZoneSuggestion) .verifyTimeZoneNotSet(); // Assert internal service state. @@ -144,8 +144,7 @@ public class TimeZoneDetectorStrategyImplTest { { TelephonyTimeZoneSuggestion lowQualitySuggestion = testCase.createSuggestion(SLOT_INDEX1, "America/New_York"); - - script.suggestTelephonyTimeZone(lowQualitySuggestion) + script.simulateTelephonyTimeZoneSuggestion(lowQualitySuggestion) .verifyTimeZoneNotSet(); // Assert internal service state. @@ -162,7 +161,7 @@ public class TimeZoneDetectorStrategyImplTest { { TelephonyTimeZoneSuggestion goodQualitySuggestion = testCase2.createSuggestion(SLOT_INDEX1, "Europe/London"); - script.suggestTelephonyTimeZone(goodQualitySuggestion) + script.simulateTelephonyTimeZoneSuggestion(goodQualitySuggestion) .verifyTimeZoneSetAndReset(goodQualitySuggestion); // Assert internal service state. @@ -179,7 +178,7 @@ public class TimeZoneDetectorStrategyImplTest { { TelephonyTimeZoneSuggestion lowQualitySuggestion2 = testCase.createSuggestion(SLOT_INDEX1, "America/Los_Angeles"); - script.suggestTelephonyTimeZone(lowQualitySuggestion2) + script.simulateTelephonyTimeZoneSuggestion(lowQualitySuggestion2) .verifyTimeZoneNotSet(); // Assert internal service state. @@ -208,7 +207,7 @@ public class TimeZoneDetectorStrategyImplTest { TelephonyTimeZoneSuggestion suggestion = testCase.createSuggestion(SLOT_INDEX1, "Europe/London"); - script.suggestTelephonyTimeZone(suggestion); + script.simulateTelephonyTimeZoneSuggestion(suggestion); // When time zone detection is not enabled, the time zone suggestion will not be set // regardless of the score. @@ -288,7 +287,7 @@ public class TimeZoneDetectorStrategyImplTest { new QualifiedTelephonyTimeZoneSuggestion( zoneSlotIndex1Suggestion, testCase.expectedScore); - script.suggestTelephonyTimeZone(zoneSlotIndex1Suggestion); + script.simulateTelephonyTimeZoneSuggestion(zoneSlotIndex1Suggestion); if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) { script.verifyTimeZoneSetAndReset(zoneSlotIndex1Suggestion); } else { @@ -324,8 +323,8 @@ public class TimeZoneDetectorStrategyImplTest { .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID) // Initialize the latest suggestions as empty so we don't need to worry about nulls // below for the first loop. - .suggestTelephonyTimeZone(emptySlotIndex1Suggestion) - .suggestTelephonyTimeZone(emptySlotIndex2Suggestion) + .simulateTelephonyTimeZoneSuggestion(emptySlotIndex1Suggestion) + .simulateTelephonyTimeZoneSuggestion(emptySlotIndex2Suggestion) .resetState(); for (SuggestionTestCase testCase : TEST_CASES) { @@ -341,7 +340,7 @@ public class TimeZoneDetectorStrategyImplTest { testCase.expectedScore); // Start the test by making a suggestion for slotIndex1. - script.suggestTelephonyTimeZone(zoneSlotIndex1Suggestion); + script.simulateTelephonyTimeZoneSuggestion(zoneSlotIndex1Suggestion); if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) { script.verifyTimeZoneSetAndReset(zoneSlotIndex1Suggestion); } else { @@ -358,7 +357,7 @@ public class TimeZoneDetectorStrategyImplTest { // SlotIndex2 then makes an alternative suggestion with an identical score. SlotIndex1's // suggestion should still "win" if it is above the required threshold. - script.suggestTelephonyTimeZone(zoneSlotIndex2Suggestion); + script.simulateTelephonyTimeZoneSuggestion(zoneSlotIndex2Suggestion); script.verifyTimeZoneNotSet(); // Assert internal service state. @@ -373,7 +372,7 @@ public class TimeZoneDetectorStrategyImplTest { // Withdrawing slotIndex1's suggestion should leave slotIndex2 as the new winner. Since // the zoneId is different, the time zone setting should be updated if the score is high // enough. - script.suggestTelephonyTimeZone(emptySlotIndex1Suggestion); + script.simulateTelephonyTimeZoneSuggestion(emptySlotIndex1Suggestion); if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) { script.verifyTimeZoneSetAndReset(zoneSlotIndex2Suggestion); } else { @@ -389,7 +388,7 @@ public class TimeZoneDetectorStrategyImplTest { mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests()); // Reset the state for the next loop. - script.suggestTelephonyTimeZone(emptySlotIndex2Suggestion) + script.simulateTelephonyTimeZoneSuggestion(emptySlotIndex2Suggestion) .verifyTimeZoneNotSet(); assertEquals(expectedEmptySlotIndex1ScoredSuggestion, mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1)); @@ -417,10 +416,10 @@ public class TimeZoneDetectorStrategyImplTest { testCase.createSuggestion(SLOT_INDEX1, "America/New_York"); // Initialization. - script.suggestTelephonyTimeZone(losAngelesSuggestion) + script.simulateTelephonyTimeZoneSuggestion(losAngelesSuggestion) .verifyTimeZoneSetAndReset(losAngelesSuggestion); // Suggest it again - it should not be set because it is already set. - script.suggestTelephonyTimeZone(losAngelesSuggestion) + script.simulateTelephonyTimeZoneSuggestion(losAngelesSuggestion) .verifyTimeZoneNotSet(); // Toggling time zone detection should set the device time zone only if the current setting @@ -433,7 +432,7 @@ public class TimeZoneDetectorStrategyImplTest { // Simulate a user turning auto detection off, a new suggestion being made while auto // detection is off, and the user turning it on again. script.autoTimeZoneDetectionEnabled(false) - .suggestTelephonyTimeZone(newYorkSuggestion) + .simulateTelephonyTimeZoneSuggestion(newYorkSuggestion) .verifyTimeZoneNotSet(); // Latest suggestion should be used. script.autoTimeZoneDetectionEnabled(true) @@ -447,7 +446,8 @@ public class TimeZoneDetectorStrategyImplTest { .initializeAutoTimeZoneDetection(true); // Auto time zone detection is enabled so the manual suggestion should be ignored. - script.suggestManualTimeZone(createManualSuggestion("Europe/Paris")) + script.simulateManualTimeZoneSuggestion( + createManualSuggestion("Europe/Paris"), false /* expectedResult */) .verifyTimeZoneNotSet(); } @@ -460,7 +460,7 @@ public class TimeZoneDetectorStrategyImplTest { // Auto time zone detection is disabled so the manual suggestion should be used. ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris"); - script.suggestManualTimeZone(manualSuggestion) + script.simulateManualTimeZoneSuggestion(manualSuggestion, true /* expectedResult */) .verifyTimeZoneSetAndReset(manualSuggestion); } @@ -603,14 +603,16 @@ public class TimeZoneDetectorStrategyImplTest { /** * Simulates the time zone detection strategy receiving a telephony-originated suggestion. */ - Script suggestTelephonyTimeZone(TelephonyTimeZoneSuggestion timeZoneSuggestion) { + Script simulateTelephonyTimeZoneSuggestion(TelephonyTimeZoneSuggestion timeZoneSuggestion) { mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion); return this; } /** Simulates the time zone detection strategy receiving a user-originated suggestion. */ - Script suggestManualTimeZone(ManualTimeZoneSuggestion manualTimeZoneSuggestion) { - mTimeZoneDetectorStrategy.suggestManualTimeZone(manualTimeZoneSuggestion); + Script simulateManualTimeZoneSuggestion( + ManualTimeZoneSuggestion manualTimeZoneSuggestion, boolean expectedResult) { + assertEquals(expectedResult, + mTimeZoneDetectorStrategy.suggestManualTimeZone(manualTimeZoneSuggestion)); return this; } diff --git a/services/tests/servicestests/src/com/android/server/tv/OWNERS b/services/tests/servicestests/src/com/android/server/tv/OWNERS new file mode 100644 index 000000000000..305027ce077f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/tv/OWNERS @@ -0,0 +1 @@ +include /media/java/android/media/tv/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java index f9343236662b..1055069c746b 100644 --- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java @@ -74,16 +74,14 @@ public class TunerResourceManagerServiceTest { mReclaimed = true; } - public boolean isRelaimed() { + public boolean isReclaimed() { return mReclaimed; } } // A correspondence to compare a FrontendResource and a TunerFrontendInfo. private static final Correspondence<FrontendResource, TunerFrontendInfo> FR_TFI_COMPARE = - new Correspondence<FrontendResource, TunerFrontendInfo>() { - @Override - public boolean compare(FrontendResource actual, TunerFrontendInfo expected) { + Correspondence.from((FrontendResource actual, TunerFrontendInfo expected) -> { if (actual == null || expected == null) { return (actual == null) && (expected == null); } @@ -91,13 +89,7 @@ public class TunerResourceManagerServiceTest { return actual.getId() == expected.getId() && actual.getType() == expected.getFrontendType() && actual.getExclusiveGroupId() == expected.getExclusiveGroupId(); - } - - @Override - public String toString() { - return "is correctly configured from "; - } - }; + }, "is correctly configured from "); @Before public void setUp() throws Exception { @@ -387,13 +379,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); request = new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); } @Test @@ -452,7 +444,7 @@ public class TunerResourceManagerServiceTest { .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -486,7 +478,7 @@ public class TunerResourceManagerServiceTest { // Release frontend mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService - .getFrontendResource(frontendId)); + .getFrontendResource(frontendId), clientId[0]); assertThat(mTunerResourceManagerService .getFrontendResource(frontendId).isInUse()).isFalse(); assertThat(mTunerResourceManagerService @@ -548,7 +540,7 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService.getCasResource(1) .getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId1[0]))); assertThat(mTunerResourceManagerService.getCasResource(1).isFullyUsed()).isFalse(); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -633,7 +625,7 @@ public class TunerResourceManagerServiceTest { .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getLnbResource(lnbIds[0]) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) .getInUseLnbIds().size()).isEqualTo(0); } @@ -761,4 +753,293 @@ public class TunerResourceManagerServiceTest { backgroundRecordProfile)).isEqualTo( (backgroundPlaybackPriority > backgroundRecordPriority)); } + + @Test + public void shareFrontendTest_FrontendWithExclusiveGroupReadyToShare() { + /**** Register Clients and Set Priority ****/ + + // Int array to save the returned client ids + int[] ownerClientId0 = new int[1]; + int[] ownerClientId1 = new int[1]; + int[] shareClientId0 = new int[1]; + int[] shareClientId1 = new int[1]; + + // Predefined client profiles + ResourceClientProfile[] ownerProfiles = new ResourceClientProfile[2]; + ResourceClientProfile[] shareProfiles = new ResourceClientProfile[2]; + ownerProfiles[0] = new ResourceClientProfile( + "0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + ownerProfiles[1] = new ResourceClientProfile( + "1" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + shareProfiles[0] = new ResourceClientProfile( + "2" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + shareProfiles[1] = new ResourceClientProfile( + "3" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + + // Predefined client reclaim listeners + TestResourcesReclaimListener ownerListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener ownerListener1 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener1 = new TestResourcesReclaimListener(); + // Register clients and validate the returned client ids + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[0], ownerListener0, ownerClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[0], shareListener0, shareClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[1], ownerListener1, ownerClientId1); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[1], shareListener1, shareClientId1); + assertThat(ownerClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(ownerClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId0[0], + 100/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId0[0], + 200/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId1[0], + 300/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId1[0], + 400/*priority*/, + 0/*niceValue*/); + + /**** Init Frontend Resources ****/ + + // Predefined frontend info + TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; + infos[0] = new TunerFrontendInfo( + 0 /*id*/, + FrontendSettings.TYPE_DVBT, + 1 /*exclusiveGroupId*/); + infos[1] = new TunerFrontendInfo( + 1 /*id*/, + FrontendSettings.TYPE_DVBS, + 1 /*exclusiveGroupId*/); + + /**** Init Lnb Resources ****/ + int[] lnbIds = {1}; + mTunerResourceManagerService.setLnbInfoListInternal(lnbIds); + + // Update frontend list in TRM + mTunerResourceManagerService.setFrontendInfoListInternal(infos); + + /**** Request Frontend ****/ + + // Predefined frontend request and array to save returned frontend handle + int[] frontendHandle = new int[1]; + TunerFrontendRequest request = new TunerFrontendRequest( + ownerClientId0[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Request call and validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Share Frontend ****/ + + // Share frontend call and validate the internal mapping + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId1[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + // Verify fe in use status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isTrue(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isTrue(); + // Verify fe owner status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + // Verify share fe client status in the primary owner client + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + shareClientId0[0], + shareClientId1[0]))); + // Verify in use frontend list in all the primary owner and share owner clients + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Remove Frontend Share Owner ****/ + + // Unregister the second share fe client + mTunerResourceManagerService.unregisterClientProfileInternal(shareClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + shareClientId0[0]))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Request Shared Frontend with Higher Priority Client ****/ + + // Predefined second frontend request + request = new TunerFrontendRequest( + ownerClientId1[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Second request call + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + + // Validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + assertThat(ownerListener0.isReclaimed()).isTrue(); + assertThat(shareListener0.isReclaimed()).isTrue(); + + /**** Release Frontend Resource From Primary Owner ****/ + + // Reshare the frontend + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Release the frontend resource from the primary owner + mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService + .getFrontendResource(infos[0].getId()), ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + + /**** Unregister Primary Owner when the Share owner owns an Lnb ****/ + + // Predefined Lnb request and handle array + TunerLnbRequest requestLnb = new TunerLnbRequest(shareClientId0[0]); + int[] lnbHandle = new int[1]; + + // Request for an Lnb + assertThat(mTunerResourceManagerService + .requestLnbInternal(requestLnb, lnbHandle)) + .isTrue(); + + // Request and share the frontend resource again + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Unregister the primary owner of the shared frontend + mTunerResourceManagerService.unregisterClientProfileInternal(ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseLnbIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + lnbIds[0]))); + } } diff --git a/services/tests/servicestests/src/com/android/server/uri/OWNERS b/services/tests/servicestests/src/com/android/server/uri/OWNERS new file mode 100644 index 000000000000..ca5d5f9803e3 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/uri/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/uri/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/usage/OWNERS b/services/tests/servicestests/src/com/android/server/usage/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/usage/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/vibrator/OWNERS b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS new file mode 100644 index 000000000000..cc63ceb2c7ad --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/vibrator/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS 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/JobTestApp/OWNERS b/services/tests/servicestests/test-apps/JobTestApp/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/servicestests/test-apps/JobTestApp/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS 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/PackageParserApp/OWNERS b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS 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/servicestests/utils/com/android/server/testutils/TestUtils.java b/services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java index b200293ee916..fa14b24823d0 100644 --- a/services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java +++ b/services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java @@ -52,7 +52,7 @@ public class TestUtils { * EasyMock-style "strict" mock that throws immediately on any interaction that was not * explicitly allowed. * - * You can allow certain method calls on a whitelist basis by stubbing them e.g. with + * You can allow certain method calls on a allowlist basis by stubbing them e.g. with * {@link Mockito#doAnswer}, {@link Mockito#doNothing}, etc. */ public static <T> T strictMock(Class<T> c) { 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/shortcutmanagerutils/OWNERS b/services/tests/shortcutmanagerutils/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/shortcutmanagerutils/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp index 4439f998a527..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", @@ -57,6 +66,6 @@ android_test { "libui", "libunwindstack", "libutils", - "netd_aidl_interface-cpp", + "netd_aidl_interface-V5-cpp", ], } diff --git a/services/tests/uiservicestests/src/com/android/server/OWNERS b/services/tests/uiservicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..05944c03c638 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/OWNERS @@ -0,0 +1 @@ +per-file UiModeManagerServiceTest.java = file:/packages/SystemUI/OWNERS diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java index 453830004ac3..dfde931798ac 100644 --- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java @@ -41,6 +41,7 @@ import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; import com.android.server.wm.WindowManagerInternal; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -168,6 +169,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { LocalServices.addService(clazz, service); } + @Ignore // b/152719290 - Fails on stage-aosp-master @Test public void setNightMoveActivated_overridesFunctionCorrectly() throws RemoteException { // set up @@ -208,6 +210,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class), any()); } + @Ignore // b/152719290 - Fails on stage-aosp-master @Test public void setAutoMode_screenOffUnRegistered() throws RemoteException { try { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 2e0f1992478d..ca2ef9531fd1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -1186,7 +1186,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { NotificationRecord r = getLightsNotification(); mService.buzzBeepBlinkLocked(r); verifyNeverLights(); - assertFalse(r.isInterruptive()); + assertTrue(r.isInterruptive()); assertEquals(-1, r.getLastAudiblyAlertedMs()); } @@ -1347,6 +1347,22 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { } @Test + public void testLightsCheckCurrentUser() { + final Notification n = new Builder(getContext(), "test") + .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); + int userId = mUser.getIdentifier() + 10; + StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, + mPid, n, UserHandle.of(userId), null, System.currentTimeMillis()); + NotificationRecord r = new NotificationRecord(getContext(), sbn, + new NotificationChannel("test", "test", IMPORTANCE_HIGH)); + + mService.buzzBeepBlinkLocked(r); + verifyNeverLights(); + assertFalse(r.isInterruptive()); + assertEquals(-1, r.getLastAudiblyAlertedMs()); + } + + @Test public void testListenerHintCall() throws Exception { NotificationChannel ringtoneChannel = new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 7f0b4dbabc3a..4259831c15f8 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -411,7 +411,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { MockitoAnnotations.initMocks(this); DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class); - when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L); + when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L); ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class); LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java index 00061931b18d..fcff228fb591 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java @@ -215,20 +215,14 @@ public class NotificationShellCmdTest extends UiServiceTestCase { "Charlotte" }; static final String[] MESSAGES = { - "Shall I compare thee to a summer's day?", - "Thou art more lovely and more temperate:", - "Rough winds do shake the darling buds of May,", - "And summer's lease hath all too short a date;", - "Sometime too hot the eye of heaven shines,", - "And often is his gold complexion dimm'd;", - "And every fair from fair sometime declines,", - "By chance or nature's changing course untrimm'd;", - "But thy eternal summer shall not fade,", - "Nor lose possession of that fair thou ow'st;", - "Nor shall death brag thou wander'st in his shade,", - "When in eternal lines to time thou grow'st:", - " So long as men can breathe or eyes can see,", - " So long lives this, and this gives life to thee.", + "Who has seen the wind?", + "Neither I nor you.", + "But when the leaves hang trembling,", + "The wind is passing through.", + "Who has seen the wind?", + "Neither you nor I.", + "But when the trees bow down their heads,", + "The wind is passing by." }; @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/OWNERS b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS new file mode 100644 index 000000000000..396fd1213aca --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 6aeb40dae20b..dd6104ef9fe3 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -28,8 +28,8 @@ import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MAX; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; +import static android.util.StatsLog.ANNOTATION_ID_IS_UID; -import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER; @@ -56,6 +56,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -70,6 +71,7 @@ import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.ContentProvider; +import android.content.ContentResolver; import android.content.Context; import android.content.IContentProvider; import android.content.pm.ApplicationInfo; @@ -80,13 +82,16 @@ import android.content.res.Resources; import android.graphics.Color; import android.media.AudioAttributes; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; +import android.os.Bundle; +import android.os.RemoteCallback; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.service.notification.ConversationChannelWrapper; -import android.test.mock.MockIContentProvider; import android.test.suitebuilder.annotation.SmallTest; import android.testing.TestableContentResolver; import android.util.ArrayMap; @@ -109,7 +114,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.Spy; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; @@ -147,7 +151,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Mock NotificationUsageStats mUsageStats; @Mock RankingHandler mHandler; @Mock PackageManager mPm; - @Spy IContentProvider mTestIContentProvider = new MockIContentProvider(); + IContentProvider mTestIContentProvider; @Mock Context mContext; @Mock ZenModeHelper mMockZenModeHelper; @Mock AppOpsManager mAppOpsManager; @@ -194,6 +198,39 @@ public class PreferencesHelperTest extends UiServiceTestCase { Global.putInt(contentResolver, Global.NOTIFICATION_BUBBLES, 1); ContentProvider testContentProvider = mock(ContentProvider.class); + mTestIContentProvider = mock(IContentProvider.class, invocation -> { + throw new UnsupportedOperationException("unimplemented mock method"); + }); + doAnswer(invocation -> { + String callingPkg = invocation.getArgument(0); + String featureId = invocation.getArgument(1); + Uri uri = invocation.getArgument(2); + RemoteCallback cb = invocation.getArgument(3); + IContentProvider mock = (IContentProvider) (invocation.getMock()); + AsyncTask.SERIAL_EXECUTOR.execute(() -> { + final Bundle bundle = new Bundle(); + try { + bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, + mock.canonicalize(callingPkg, featureId, uri)); + } catch (RemoteException e) { /* consume */ } + cb.sendResult(bundle); + }); + return null; + }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any(), any()); + doAnswer(invocation -> { + Uri uri = invocation.getArgument(0); + RemoteCallback cb = invocation.getArgument(1); + IContentProvider mock = (IContentProvider) (invocation.getMock()); + AsyncTask.SERIAL_EXECUTOR.execute(() -> { + final Bundle bundle = new Bundle(); + try { + bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, mock.getType(uri)); + } catch (RemoteException e) { /* consume */ } + cb.sendResult(bundle); + }); + return null; + }).when(mTestIContentProvider).getTypeAsync(any(), any()); + when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); contentResolver.addProvider(TEST_AUTHORITY, testContentProvider); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java index eca71b69ec0b..e5ae2d3f63ab 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java @@ -305,6 +305,7 @@ public class ShortcutHelperTest extends UiServiceTestCase { //when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), // anyString(), anyInt(), any())).thenReturn(true); - assertThat(mShortcutHelper.getValidShortcutInfo("a", "p", UserHandle.SYSTEM)).isSameAs(si); + assertThat(mShortcutHelper.getValidShortcutInfo("a", "p", UserHandle.SYSTEM)) + .isSameInstanceAs(si); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index 3c7206fee9d1..69e4190a02ae 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -33,8 +33,8 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCRE import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +import static android.util.StatsLog.ANNOTATION_ID_IS_UID; -import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE; import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER; diff --git a/services/tests/uiservicestests/src/com/android/server/slice/OWNERS b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS new file mode 100644 index 000000000000..3d0859f6f701 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/slice/OWNERS 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/tests/wmtests/OWNERS b/services/tests/wmtests/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/services/tests/wmtests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java index 56cb447e65b0..f53894ad9ec5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java @@ -102,7 +102,7 @@ public class HighRefreshRateBlacklistTest { final FakeDeviceConfig config = new FakeDeviceConfig(); mBlacklist = new HighRefreshRateBlacklist(r, config); - // First check that the default blacklist is in effect + // First check that the default denylist is in effect assertTrue(mBlacklist.isBlacklisted(APP1)); assertFalse(mBlacklist.isBlacklisted(APP2)); assertFalse(mBlacklist.isBlacklisted(APP3)); @@ -130,7 +130,7 @@ public class HighRefreshRateBlacklistTest { assertTrue(mBlacklist.isBlacklisted(APP2)); assertTrue(mBlacklist.isBlacklisted(APP3)); - // Change an unrelated flag in our namespace and verify that the blacklist is intact + // Change an unrelated flag in our namespace and verify that the denylist is intact config.putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, "someKey", "someValue"); assertFalse(mBlacklist.isBlacklisted(APP1)); assertTrue(mBlacklist.isBlacklisted(APP2)); |