summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java2
-rw-r--r--tests/FlickerTests/ActivityEmbedding/Android.bp123
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt2
-rw-r--r--tests/FlickerTests/AppClose/Android.bp31
-rw-r--r--tests/FlickerTests/AppLaunch/Android.bp123
-rw-r--r--tests/FlickerTests/AppLaunch/OWNERS2
-rw-r--r--tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt12
-rw-r--r--tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt1
-rw-r--r--tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt2
-rw-r--r--tests/FlickerTests/IME/Android.bp146
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt4
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt20
-rw-r--r--tests/FlickerTests/Notification/Android.bp54
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt10
-rw-r--r--tests/FlickerTests/QuickSwitch/Android.bp38
-rw-r--r--tests/FlickerTests/Rotation/Android.bp38
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt20
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt52
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml14
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java79
-rw-r--r--tests/Input/Android.bp1
-rw-r--r--tests/Input/AndroidTest.xml6
-rw-r--r--tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt202
-rw-r--r--tests/Input/src/com/android/server/input/InputManagerServiceTests.kt1
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt96
-rw-r--r--tests/Input/src/com/android/test/input/AnrTest.kt4
-rw-r--r--tests/Input/src/com/android/test/input/InputEventAssignerTest.kt186
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java8
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java2
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java2
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java2
-rw-r--r--tests/Internal/Android.bp2
-rw-r--r--tests/Internal/AndroidTest.xml8
-rw-r--r--tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java5
-rw-r--r--tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java7
-rw-r--r--tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java41
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java207
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogServiceTest.java283
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java4
-rw-r--r--tests/Internal/src/com/android/internal/util/ParcellingTests.java5
-rw-r--r--tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java324
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java18
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java1
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java1
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java1
-rw-r--r--tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java31
-rw-r--r--tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java21
-rw-r--r--tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java20
-rw-r--r--tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java17
-rw-r--r--tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java17
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp1
51 files changed, 2128 insertions, 169 deletions
diff --git a/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
index 08430f2f2744..4143f595f9a0 100644
--- a/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
+++ b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
@@ -159,7 +159,7 @@ public class BatteryUsageStatsPerfTest {
private static BatteryUsageStats buildBatteryUsageStats() {
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, false, 0)
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, false, false, false, 0)
.setBatteryCapacity(4000)
.setDischargePercentage(20)
.setDischargedPowerRange(1000, 2000)
diff --git a/tests/FlickerTests/ActivityEmbedding/Android.bp b/tests/FlickerTests/ActivityEmbedding/Android.bp
index e09fbf6adc02..c681ce96a269 100644
--- a/tests/FlickerTests/ActivityEmbedding/Android.bp
+++ b/tests/FlickerTests/ActivityEmbedding/Android.bp
@@ -24,6 +24,9 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+////////////////////////////////////////////////////////////////////////////////
+// Begin to cleanup after CL merges
+
filegroup {
name: "FlickerTestsOtherCommon-src",
srcs: ["src/**/ActivityEmbeddingTestBase.kt"],
@@ -82,3 +85,123 @@ android_test {
":FlickerTestsOtherCommon-src",
],
}
+
+// End to cleanup after CL merges
+////////////////////////////////////////////////////////////////////////////////
+
+android_test {
+ name: "FlickerTestsActivityEmbedding",
+ defaults: ["FlickerTestsDefault"],
+ manifest: "AndroidManifest.xml",
+ package_name: "com.android.server.wm.flicker",
+ instrumentation_target_package: "com.android.server.wm.flicker",
+ test_config_template: "AndroidTestTemplate.xml",
+ srcs: ["src/**/*"],
+ static_libs: [
+ "FlickerTestsBase",
+ "FlickerTestsOtherCommon",
+ ],
+ data: ["trace_config/*"],
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsActivityEmbedding module
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-CatchAll",
+ base: "FlickerTestsActivityEmbedding",
+ exclude_filters: [
+ "com.android.server.wm.flicker.activityembedding.close.CloseSecondaryActivityInSplitTest",
+ "com.android.server.wm.flicker.activityembedding.layoutchange.HorizontalSplitChangeRatioTest",
+ "com.android.server.wm.flicker.activityembedding.open.MainActivityStartsSecondaryWithAlwaysExpandTest",
+ "com.android.server.wm.flicker.activityembedding.open.OpenActivityEmbeddingPlaceholderSplitTest",
+ "com.android.server.wm.flicker.activityembedding.open.OpenActivityEmbeddingSecondaryToSplitTest",
+ "com.android.server.wm.flicker.activityembedding.open.OpenThirdActivityOverSplitTest",
+ "com.android.server.wm.flicker.activityembedding.open.OpenTrampolineActivityTest",
+ "com.android.server.wm.flicker.activityembedding.pip.SecondaryActivityEnterPipTest",
+ "com.android.server.wm.flicker.activityembedding.rotation.RotateSplitNoChangeTest",
+ "com.android.server.wm.flicker.activityembedding.rtl.RTLStartSecondaryWithPlaceholderTest",
+ "com.android.server.wm.flicker.activityembedding.splitscreen.EnterSystemSplitTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Close-CloseSecondaryActivityInSplitTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.close.CloseSecondaryActivityInSplitTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-LayoutChange-HorizontalSplitChangeRatioTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.layoutchange.HorizontalSplitChangeRatioTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Open-MainActivityStartsSecondaryWithAlwaysExpandTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.open.MainActivityStartsSecondaryWithAlwaysExpandTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Open-OpenActivityEmbeddingPlaceholderSplitTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.open.OpenActivityEmbeddingPlaceholderSplitTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Open-OpenActivityEmbeddingSecondaryToSplitTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.open.OpenActivityEmbeddingSecondaryToSplitTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Open-OpenThirdActivityOverSplitTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.open.OpenThirdActivityOverSplitTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Open-OpenTrampolineActivityTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.open.OpenTrampolineActivityTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Pip-SecondaryActivityEnterPipTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.pip.SecondaryActivityEnterPipTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Rotation-RotateSplitNoChangeTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.rotation.RotateSplitNoChangeTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-Rtl-RTLStartSecondaryWithPlaceholderTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.rtl.RTLStartSecondaryWithPlaceholderTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsActivityEmbedding-SplitScreen-EnterSystemSplitTest",
+ base: "FlickerTestsActivityEmbedding",
+ include_filters: ["com.android.server.wm.flicker.activityembedding.splitscreen.EnterSystemSplitTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsActivityEmbedding module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
index ee2c05e82d51..06326f8cc8d2 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
@@ -36,7 +36,7 @@ abstract class RotationTransition(flicker: LegacyFlickerTest) : ActivityEmbeddin
teardown { testApp.exit(wmHelper) }
transitions {
this.setRotation(flicker.scenario.endRotation)
- if (!flicker.scenario.isTablet) {
+ if (!usesTaskbar) {
wmHelper.StateSyncBuilder()
.add(navBarInPosition(flicker.scenario.isGesturalNavigation))
.waitForAndVerify()
diff --git a/tests/FlickerTests/AppClose/Android.bp b/tests/FlickerTests/AppClose/Android.bp
index d14a178fe316..8b45740aad7b 100644
--- a/tests/FlickerTests/AppClose/Android.bp
+++ b/tests/FlickerTests/AppClose/Android.bp
@@ -33,3 +33,34 @@ android_test {
static_libs: ["FlickerTestsBase"],
data: ["trace_config/*"],
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsAppClose module
+
+test_module_config {
+ name: "FlickerTestsAppClose-CatchAll",
+ base: "FlickerTestsAppClose",
+ exclude_filters: [
+ "com.android.server.wm.flicker.close.CloseAppBackButtonTest",
+ "com.android.server.wm.flicker.close.CloseAppHomeButtonTest",
+ "com.android.server.wm.flicker.close.",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppClose-CloseAppBackButtonTest",
+ base: "FlickerTestsAppClose",
+ include_filters: ["com.android.server.wm.flicker.close.CloseAppBackButtonTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppClose-CloseAppHomeButtonTest",
+ base: "FlickerTestsAppClose",
+ include_filters: ["com.android.server.wm.flicker.close.CloseAppHomeButtonTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsAppClose module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/AppLaunch/Android.bp b/tests/FlickerTests/AppLaunch/Android.bp
index 72a90650927f..b61739f100ab 100644
--- a/tests/FlickerTests/AppLaunch/Android.bp
+++ b/tests/FlickerTests/AppLaunch/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_windowing_animations_transitions",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
@@ -23,6 +24,9 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+////////////////////////////////////////////////////////////////////////////////
+// Begin to cleanup after CL merges
+
filegroup {
name: "FlickerTestsAppLaunchCommon-src",
srcs: ["src/**/common/*"],
@@ -69,3 +73,122 @@ android_test {
],
data: ["trace_config/*"],
}
+
+// End to cleanup after CL merges
+////////////////////////////////////////////////////////////////////////////////
+
+android_test {
+ name: "FlickerTestsAppLaunch",
+ defaults: ["FlickerTestsDefault"],
+ manifest: "AndroidManifest.xml",
+ test_config_template: "AndroidTestTemplate.xml",
+ srcs: ["src/**/*"],
+ static_libs: [
+ "FlickerTestsBase",
+ "FlickerTestsAppLaunchCommon",
+ ],
+ data: ["trace_config/*"],
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsAppLaunch module
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-CatchAll",
+ base: "FlickerTestsAppLaunch",
+ exclude_filters: [
+ "com.android.server.wm.flicker.launch.TaskTransitionTest",
+ "com.android.server.wm.flicker.launch.ActivityTransitionTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromIconColdTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromIntentColdAfterCameraTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromIntentColdTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromIntentWarmTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromLockscreenViaIntentTest",
+ "com.android.server.wm.flicker.launch.OpenAppFromOverviewTest",
+ "com.android.server.wm.flicker.launch.OpenCameraFromHomeOnDoubleClickPowerButtonTest",
+ "com.android.server.wm.flicker.launch.OpenTransferSplashscreenAppFromLauncherTransition",
+ "com.android.server.wm.flicker.launch.OverrideTaskTransitionTest",
+ "com.android.server.wm.flicker.launch.TaskTransitionTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-ActivityTransitionTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.ActivityTransitionTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromIconColdTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromIconColdTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromIntentColdAfterCameraTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromIntentColdAfterCameraTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromIntentColdTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromIntentColdTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromIntentWarmTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromIntentWarmTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromLockscreenViaIntentTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromLockscreenViaIntentTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenAppFromOverviewTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenAppFromOverviewTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenCameraFromHomeOnDoubleClickPowerButtonTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenCameraFromHomeOnDoubleClickPowerButtonTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OpenTransferSplashscreenAppFromLauncherTransition",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OpenTransferSplashscreenAppFromLauncherTransition"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-OverrideTaskTransitionTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.OverrideTaskTransitionTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppLaunch-TaskTransitionTest",
+ base: "FlickerTestsAppLaunch",
+ include_filters: ["com.android.server.wm.flicker.launch.TaskTransitionTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsAppLaunch module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/AppLaunch/OWNERS b/tests/FlickerTests/AppLaunch/OWNERS
index 2c414a27cacb..d16b57dcb84c 100644
--- a/tests/FlickerTests/AppLaunch/OWNERS
+++ b/tests/FlickerTests/AppLaunch/OWNERS
@@ -1,4 +1,2 @@
-# System UI > ... > Overview (recent apps) > UI
-# Bug template url: https://b.corp.google.com/issues/new?component=807991&template=1390280 = per-file *Overview*
# window manager > animations/transitions
# Bug template url: https://b.corp.google.com/issues/new?component=316275&template=1018192
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt
index 44ae27c2ee4b..adeba72c9c96 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt
@@ -75,7 +75,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@FlakyTest(bugId = 288341660)
@Test
fun navBarLayerVisibilityChanges() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.assertLayers {
this.isInvisible(ComponentNameMatcher.NAV_BAR)
.then()
@@ -97,7 +97,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@FlakyTest(bugId = 293581770)
@Test
fun navBarWindowsVisibilityChanges() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.assertWm {
this.isNonAppWindowInvisible(ComponentNameMatcher.NAV_BAR)
.then()
@@ -112,7 +112,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
fun taskBarLayerIsVisibleAtEnd() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
}
@@ -170,7 +170,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
fun navBarLayerIsVisibleAtEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.NAV_BAR) }
}
@@ -184,7 +184,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
override fun appLayerBecomesVisible() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
super.appLayerBecomesVisible()
}
@@ -192,7 +192,7 @@ open class OpenAppFromLockscreenViaIntentTest(flicker: LegacyFlickerTest) :
@FlakyTest(bugId = 227143265)
@Test
fun appLayerBecomesVisibleTablet() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
super.appLayerBecomesVisible()
}
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt
index 8a3304b0343d..b497e3048759 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt
@@ -28,6 +28,7 @@ abstract class OpenAppFromIconTransition(flicker: LegacyFlickerTest) :
get() = {
super.transition(this)
setup {
+ // By default, launcher doesn't rotate on phones, but rotates on tablets
if (flicker.scenario.isTablet) {
tapl.setExpectedRotation(flicker.scenario.startRotation.value)
} else {
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt
index f8fd35860f6f..a6e31d49a0e8 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt
@@ -103,7 +103,7 @@ abstract class OpenAppFromLockscreenTransition(flicker: LegacyFlickerTest) :
@Presubmit
@Test
open fun navBarLayerPositionAtEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerPositionAtEnd()
}
diff --git a/tests/FlickerTests/IME/Android.bp b/tests/FlickerTests/IME/Android.bp
index 78d93e1cb32a..f80e6b4b2f5e 100644
--- a/tests/FlickerTests/IME/Android.bp
+++ b/tests/FlickerTests/IME/Android.bp
@@ -24,6 +24,9 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+////////////////////////////////////////////////////////////////////////////////
+// Begin to cleanup after CL merges
+
filegroup {
name: "FlickerTestsImeCommon-src",
srcs: ["src/**/common/*"],
@@ -39,6 +42,9 @@ filegroup {
srcs: ["src/**/ShowImeOnAppStart*"],
}
+// End to cleanup after CL merges
+////////////////////////////////////////////////////////////////////////////////
+
android_test {
name: "FlickerTestsIme",
defaults: ["FlickerTestsDefault"],
@@ -53,6 +59,9 @@ android_test {
data: ["trace_config/*"],
}
+////////////////////////////////////////////////////////////////////////////////
+// Begin to cleanup after CL merges
+
java_library {
name: "FlickerTestsImeCommon",
defaults: ["FlickerTestsDefault"],
@@ -107,3 +116,140 @@ android_test {
],
data: ["trace_config/*"],
}
+
+// End to cleanup after CL merges
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsIme module
+
+test_module_config {
+ name: "FlickerTestsIme-CatchAll",
+ base: "FlickerTestsIme",
+ exclude_filters: [
+ "com.android.server.wm.flicker.ime.CloseImeOnDismissPopupDialogTest",
+ "com.android.server.wm.flicker.ime.CloseImeOnGoHomeTest",
+ "com.android.server.wm.flicker.ime.CloseImeShownOnAppStartOnGoHomeTest",
+ "com.android.server.wm.flicker.ime.CloseImeShownOnAppStartToAppOnPressBackTest",
+ "com.android.server.wm.flicker.ime.CloseImeToAppOnPressBackTest",
+ "com.android.server.wm.flicker.ime.CloseImeToHomeOnFinishActivityTest",
+ "com.android.server.wm.flicker.ime.OpenImeWindowToFixedPortraitAppTest",
+ "com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest",
+ "com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromOverviewTest",
+ "com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest",
+ "com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppTest",
+ "com.android.server.wm.flicker.ime.ShowImeOnUnlockScreenTest",
+ "com.android.server.wm.flicker.ime.ShowImeWhenFocusingOnInputFieldTest",
+ "com.android.server.wm.flicker.ime.ShowImeWhileDismissingThemedPopupDialogTest",
+ "com.android.server.wm.flicker.ime.ShowImeWhileEnteringOverviewTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeOnDismissPopupDialogTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeOnDismissPopupDialogTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeOnGoHomeTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeOnGoHomeTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeShownOnAppStartOnGoHomeTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeShownOnAppStartOnGoHomeTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeShownOnAppStartToAppOnPressBackTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeShownOnAppStartToAppOnPressBackTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeToAppOnPressBackTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeToAppOnPressBackTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-CloseImeToHomeOnFinishActivityTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.CloseImeToHomeOnFinishActivityTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-OpenImeWindowToFixedPortraitAppTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.OpenImeWindowToFixedPortraitAppTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeOnAppStartWhenLaunchingAppFromOverviewTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromOverviewTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeOnAppStartWhenLaunchingAppTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeOnAppStartWhenLaunchingAppTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeOnUnlockScreenTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeOnUnlockScreenTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeWhenFocusingOnInputFieldTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeWhenFocusingOnInputFieldTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeWhileDismissingThemedPopupDialogTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeWhileDismissingThemedPopupDialogTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsIme-ShowImeWhileEnteringOverviewTest",
+ base: "FlickerTestsIme",
+ include_filters: ["com.android.server.wm.flicker.ime.ShowImeWhileEnteringOverviewTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsIme module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index dc2bd1bc9996..522c68bba0d1 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -72,7 +72,7 @@ class CloseImeToAppOnPressBackTest(flicker: LegacyFlickerTest) : BaseTest(flicke
@Presubmit
@Test
override fun navBarLayerPositionAtStartAndEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
Assume.assumeFalse(flicker.scenario.isLandscapeOrSeascapeAtStart)
flicker.navBarLayerPositionAtStartAndEnd()
}
@@ -80,7 +80,7 @@ class CloseImeToAppOnPressBackTest(flicker: LegacyFlickerTest) : BaseTest(flicke
@Presubmit
@Test
fun navBarLayerPositionAtStartAndEndLandscapeOrSeascapeAtStart() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart)
flicker.navBarLayerPositionAtStartAndEnd()
}
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index c96c760e2d7b..eb63e4985a9f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -28,6 +28,7 @@ import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd
+import com.android.server.wm.flicker.taskBarLayerIsVisibleAtStartAndEnd
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -93,7 +94,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
@Presubmit
@Test
fun navBarLayerIsVisibleAtStartAndEnd3Button() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
flicker.navBarLayerIsVisibleAtStartAndEnd()
}
@@ -105,7 +106,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
@Presubmit
@Test
fun navBarLayerIsInvisibleInLandscapeGestural() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart)
Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.NAV_BAR) }
@@ -114,7 +115,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
/**
* In the legacy transitions, the nav bar is not marked as invisible. In the new transitions
- * this is fixed and the nav bar shows as invisible
+ * this is fixed and the status bar shows as invisible
*/
@Presubmit
@Test
@@ -128,7 +129,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
/**
* In the legacy transitions, the nav bar is not marked as invisible. In the new transitions
- * this is fixed and the nav bar shows as invisible
+ * this is fixed and the status bar shows as invisible
*/
@Presubmit
@Test
@@ -149,6 +150,10 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
@Ignore("Visibility changes depending on orientation and navigation mode")
override fun navBarLayerPositionAtStartAndEnd() {}
+ @Test
+ @Ignore("Visibility changes depending on orientation and navigation mode")
+ override fun taskBarLayerIsVisibleAtStartAndEnd() {}
+
/** {@inheritDoc} */
@Test
@Ignore("Visibility changes depending on orientation and navigation mode")
@@ -161,7 +166,10 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
@Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
+ fun taskBarLayerIsVisibleAtStartAndEndForTablets() {
+ Assume.assumeTrue(flicker.scenario.isTablet)
+ flicker.taskBarLayerIsVisibleAtStartAndEnd()
+ }
@Presubmit
@Test
@@ -174,7 +182,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
@Test
fun statusBarLayerIsInvisibleInLandscape() {
Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart)
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
flicker.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) }
}
diff --git a/tests/FlickerTests/Notification/Android.bp b/tests/FlickerTests/Notification/Android.bp
index 4648383b2771..06daaafacbd8 100644
--- a/tests/FlickerTests/Notification/Android.bp
+++ b/tests/FlickerTests/Notification/Android.bp
@@ -32,3 +32,57 @@ android_test {
static_libs: ["FlickerTestsBase"],
data: ["trace_config/*"],
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsNotification module
+
+test_module_config {
+ name: "FlickerTestsNotification-CatchAll",
+ base: "FlickerTestsNotification",
+ exclude_filters: [
+ "com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest",
+ "com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationWarmTest",
+ "com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationWithOverlayAppTest",
+ "com.android.server.wm.flicker.notification.OpenAppFromNotificationColdTest",
+ "com.android.server.wm.flicker.notification.OpenAppFromNotificationWarmTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsNotification-OpenAppFromLockscreenNotificationColdTest",
+ base: "FlickerTestsNotification",
+ include_filters: ["com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsNotification-OpenAppFromLockscreenNotificationWarmTest",
+ base: "FlickerTestsNotification",
+ include_filters: ["com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationWarmTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsNotification-OpenAppFromLockscreenNotificationWithOverlayAppTest",
+ base: "FlickerTestsNotification",
+ include_filters: ["com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationWithOverlayAppTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsNotification-OpenAppFromNotificationColdTest",
+ base: "FlickerTestsNotification",
+ include_filters: ["com.android.server.wm.flicker.notification.OpenAppFromNotificationColdTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsNotification-OpenAppFromNotificationWarmTest",
+ base: "FlickerTestsNotification",
+ include_filters: ["com.android.server.wm.flicker.notification.OpenAppFromNotificationWarmTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsNotification module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
index 07fc2300286a..ad70757a9a4d 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
@@ -151,7 +151,7 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
open fun taskBarWindowIsVisibleAtEnd() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
flicker.taskBarWindowIsVisibleAtEnd()
}
@@ -163,7 +163,7 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
open fun taskBarLayerIsVisibleAtEnd() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
flicker.taskBarLayerIsVisibleAtEnd()
}
@@ -171,7 +171,7 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
open fun navBarLayerPositionAtEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerPositionAtEnd()
}
@@ -179,14 +179,14 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
@Presubmit
@Test
open fun navBarLayerIsVisibleAtEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerIsVisibleAtEnd()
}
@Presubmit
@Test
open fun navBarWindowIsVisibleAtEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarWindowIsVisibleAtEnd()
}
diff --git a/tests/FlickerTests/QuickSwitch/Android.bp b/tests/FlickerTests/QuickSwitch/Android.bp
index 8755d0e3b304..4d5dba3d9221 100644
--- a/tests/FlickerTests/QuickSwitch/Android.bp
+++ b/tests/FlickerTests/QuickSwitch/Android.bp
@@ -32,3 +32,41 @@ android_test {
static_libs: ["FlickerTestsBase"],
data: ["trace_config/*"],
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsQuickswitch module
+
+test_module_config {
+ name: "FlickerTestsQuickswitch-CatchAll",
+ base: "FlickerTestsQuickswitch",
+ exclude_filters: [
+ "com.android.server.wm.flicker.quickswitch.QuickSwitchBetweenTwoAppsBackTest",
+ "com.android.server.wm.flicker.quickswitch.QuickSwitchBetweenTwoAppsForwardTest",
+ "com.android.server.wm.flicker.quickswitch.QuickSwitchFromLauncherTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsQuickswitch-QuickSwitchBetweenTwoAppsBackTest",
+ base: "FlickerTestsQuickswitch",
+ include_filters: ["com.android.server.wm.flicker.quickswitch.QuickSwitchBetweenTwoAppsBackTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsQuickswitch-QuickSwitchBetweenTwoAppsForwardTest",
+ base: "FlickerTestsQuickswitch",
+ include_filters: ["com.android.server.wm.flicker.quickswitch.QuickSwitchBetweenTwoAppsForwardTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsQuickswitch-QuickSwitchFromLauncherTest",
+ base: "FlickerTestsQuickswitch",
+ include_filters: ["com.android.server.wm.flicker.quickswitch.QuickSwitchFromLauncherTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsQuickswitch module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/Rotation/Android.bp b/tests/FlickerTests/Rotation/Android.bp
index aceb8bad256f..0884ef9734b0 100644
--- a/tests/FlickerTests/Rotation/Android.bp
+++ b/tests/FlickerTests/Rotation/Android.bp
@@ -37,3 +37,41 @@ android_test {
static_libs: ["FlickerTestsBase"],
data: ["trace_config/*"],
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Begin breakdowns for FlickerTestsRotation module
+
+test_module_config {
+ name: "FlickerTestsAppRotation-CatchAll",
+ base: "FlickerTestsRotation",
+ exclude_filters: [
+ "com.android.server.wm.flicker.rotation.ChangeAppRotationTest",
+ "com.android.server.wm.flicker.rotation.OpenShowWhenLockedSeamlessAppRotationTest",
+ "com.android.server.wm.flicker.rotation.SeamlessAppRotationTest",
+ ],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppRotation-ChangeAppRotationTest",
+ base: "FlickerTestsRotation",
+ include_filters: ["com.android.server.wm.flicker.rotation.ChangeAppRotationTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppRotation-OpenShowWhenLockedSeamlessAppRotationTest",
+ base: "FlickerTestsRotation",
+ include_filters: ["com.android.server.wm.flicker.rotation.OpenShowWhenLockedSeamlessAppRotationTest"],
+ test_suites: ["device-tests"],
+}
+
+test_module_config {
+ name: "FlickerTestsAppRotation-SeamlessAppRotationTest",
+ base: "FlickerTestsRotation",
+ include_filters: ["com.android.server.wm.flicker.rotation.SeamlessAppRotationTest"],
+ test_suites: ["device-tests"],
+}
+
+// End breakdowns for FlickerTestsRotation module
+////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 060015bcc4b2..851ce022bd81 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -26,6 +26,7 @@ import android.tools.traces.component.ComponentNameMatcher
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.wm.shell.Flags
import org.junit.Assume
import org.junit.AssumptionViolatedException
import org.junit.Test
@@ -48,6 +49,9 @@ constructor(
private val logTag = this::class.java.simpleName
+ protected val usesTaskbar: Boolean
+ get() = flicker.scenario.isTablet || Flags.enableTaskbarOnPhones()
+
/** Specification of the test transition to execute */
abstract val transition: FlickerBuilder.() -> Unit
@@ -87,7 +91,7 @@ constructor(
@Presubmit
@Test
open fun navBarLayerIsVisibleAtStartAndEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerIsVisibleAtStartAndEnd()
}
@@ -100,7 +104,7 @@ constructor(
@Presubmit
@Test
open fun navBarLayerPositionAtStartAndEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerPositionAtStartAndEnd()
}
@@ -112,7 +116,7 @@ constructor(
@Presubmit
@Test
open fun navBarWindowIsAlwaysVisible() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
Assume.assumeFalse(flicker.scenario.isLandscapeOrSeascapeAtStart)
flicker.navBarWindowIsAlwaysVisible()
}
@@ -126,32 +130,28 @@ constructor(
@Presubmit
@Test
open fun navBarWindowIsVisibleAtStartAndEnd() {
- Assume.assumeFalse(flicker.scenario.isTablet)
+ Assume.assumeFalse(usesTaskbar)
flicker.navBarWindowIsVisibleAtStartAndEnd()
}
/**
* Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of the
* transition
- *
- * Note: Large screen only
*/
@Presubmit
@Test
open fun taskBarLayerIsVisibleAtStartAndEnd() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
flicker.taskBarLayerIsVisibleAtStartAndEnd()
}
/**
* Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole transition
- *
- * Note: Large screen only
*/
@Presubmit
@Test
open fun taskBarWindowIsAlwaysVisible() {
- Assume.assumeTrue(flicker.scenario.isTablet)
+ Assume.assumeTrue(usesTaskbar)
flicker.taskBarWindowIsAlwaysVisible()
}
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
index 5121f6677cea..8811e00f9661 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -17,6 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.graphics.Rect
+import android.platform.uiautomator_helpers.DeviceHelpers
import android.tools.device.apphelpers.IStandardAppHelper
import android.tools.helpers.SYSTEMUI_PACKAGE
import android.tools.traces.parsers.WindowManagerStateHelper
@@ -26,6 +27,7 @@ import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
+import java.time.Duration
/**
* Wrapper class around App helper classes. This class adds functionality to the apps that the
@@ -41,16 +43,6 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
RIGHT_BOTTOM
}
- private val TIMEOUT_MS = 3_000L
- private val CAPTION = "desktop_mode_caption"
- private val CAPTION_HANDLE = "caption_handle"
- private val MAXIMIZE_BUTTON = "maximize_window"
- private val MAXIMIZE_BUTTON_VIEW = "maximize_button_view"
- private val CLOSE_BUTTON = "close_window"
-
- private val caption: BySelector
- get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
-
/** Wait for an app moved to desktop to finish its transition. */
private fun waitForAppToMoveToDesktop(wmHelper: WindowManagerStateHelper) {
wmHelper
@@ -123,7 +115,7 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
)
error("expected a freeform window with caption but window is not in freeform mode")
val captions =
- device.wait(Until.findObjects(caption), TIMEOUT_MS)
+ device.wait(Until.findObjects(caption), TIMEOUT.toMillis())
?: error("Unable to find view $caption\n")
return captions.find {
@@ -200,6 +192,33 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
device.drag(startX, startY, endX, endY, 100)
}
+ fun enterDesktopModeFromAppHandleMenu(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice) {
+ val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+ val startX = windowRect.centerX()
+ // Click a little under the top to prevent opening the notification shade.
+ val startY = 10
+
+ // Click on the app handle coordinates.
+ device.click(startX, startY)
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+
+ val pill = getAppHandlePillForWindow()
+ val desktopModeButton =
+ pill
+ ?.children
+ ?.find { it.resourceName.endsWith(DESKTOP_MODE_BUTTON) }
+
+ desktopModeButton?.click()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+ }
+
+ private fun getAppHandlePillForWindow(): UiObject2? {
+ val pillContainer: BySelector = By.res(SYSTEMUI_PACKAGE, PILL_CONTAINER)
+ return DeviceHelpers.waitForObj(pillContainer, TIMEOUT)
+ }
+
/** Wait for transition to full screen to finish. */
private fun waitForTransitionToFullscreen(wmHelper: WindowManagerStateHelper) {
wmHelper
@@ -208,4 +227,15 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
.withAppTransitionIdle()
.waitForAndVerify()
}
+
+ private companion object {
+ val TIMEOUT = Duration.ofSeconds(3)
+ val CAPTION = "desktop_mode_caption"
+ val MAXIMIZE_BUTTON_VIEW = "maximize_button_view"
+ val CLOSE_BUTTON = "close_window"
+ val PILL_CONTAINER = "windowing_pill"
+ val DESKTOP_MODE_BUTTON = "desktop_button"
+ val caption: BySelector
+ get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
+ }
}
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
index 36cbf1a8fe84..365a0ea017f6 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -27,15 +27,6 @@
where things are arranged differently and to circle back up to the top once we reach the
bottom. -->
- <!-- View used for testing sourceRectHint. -->
- <View
- android:id="@+id/source_rect"
- android:layout_width="320dp"
- android:layout_height="180dp"
- android:visibility="gone"
- android:background="@android:color/holo_green_light"
- />
-
<Button
android:id="@+id/enter_pip"
android:layout_width="wrap_content"
@@ -122,12 +113,11 @@
android:onClick="onRatioSelected"/>
</RadioGroup>
- <Button
+ <CheckBox
android:id="@+id/set_source_rect_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Set SourceRectHint"
- android:onClick="setSourceRectHint"/>
+ android:text="Set SourceRectHint"/>
<TextView
android:layout_width="wrap_content"
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
index 27eb5a06451a..13d7f7f0d521 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
@@ -43,10 +43,10 @@ import android.media.MediaMetadata;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Bundle;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Rational;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
@@ -70,7 +70,7 @@ public class PipActivity extends Activity {
*/
private static final String TITLE_STATE_PAUSED = "TestApp media is paused";
- private static final Rational RATIO_DEFAULT = null;
+ private static final Rational RATIO_DEFAULT = new Rational(16, 9);
private static final Rational RATIO_SQUARE = new Rational(1, 1);
private static final Rational RATIO_WIDE = new Rational(2, 1);
private static final Rational RATIO_TALL = new Rational(1, 2);
@@ -88,8 +88,7 @@ public class PipActivity extends Activity {
"com.android.wm.shell.flicker.testapp.ASPECT_RATIO";
private final PictureInPictureParams.Builder mPipParamsBuilder =
- new PictureInPictureParams.Builder()
- .setAspectRatio(RATIO_DEFAULT);
+ new PictureInPictureParams.Builder();
private MediaSession mMediaSession;
private final PlaybackState.Builder mPlaybackStateBuilder = new PlaybackState.Builder()
.setActions(ACTION_PLAY | ACTION_PAUSE | ACTION_STOP)
@@ -139,6 +138,9 @@ public class PipActivity extends Activity {
}
};
+ private Rational mAspectRatio = RATIO_DEFAULT;
+ private boolean mEnableSourceRectHint;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -156,6 +158,14 @@ public class PipActivity extends Activity {
findViewById(R.id.media_session_stop)
.setOnClickListener(v -> updateMediaSessionState(STATE_STOPPED));
+ final CheckBox setSourceRectHintCheckBox = findViewById(R.id.set_source_rect_hint);
+ setSourceRectHintCheckBox.setOnCheckedChangeListener((v, isChecked) -> {
+ if (mEnableSourceRectHint != isChecked) {
+ mEnableSourceRectHint = isChecked;
+ updateSourceRectHint();
+ }
+ });
+
mMediaSession = new MediaSession(this, "WMShell_TestApp");
mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());
mMediaSession.setCallback(new MediaSession.Callback() {
@@ -250,47 +260,64 @@ public class PipActivity extends Activity {
}
}
+ private void updateSourceRectHint() {
+ if (!mEnableSourceRectHint) return;
+ // Similar to PipUtils#getEnterPipWithOverlaySrcRectHint, crop the display bounds
+ // as source rect hint based on the current aspect ratio.
+ final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+ final Rect displayBounds = new Rect(0, 0,
+ displayMetrics.widthPixels, displayMetrics.heightPixels);
+ final Rect sourceRectHint = getEnterPipWithOverlaySrcRectHint(
+ displayBounds, mAspectRatio.floatValue());
+ mPipParamsBuilder
+ .setAspectRatio(mAspectRatio)
+ .setSourceRectHint(sourceRectHint);
+ setPictureInPictureParams(mPipParamsBuilder.build());
+ }
+
/**
- * Adds a temporary view used for testing sourceRectHint.
- *
+ * Crop a Rect matches the aspect ratio and pivots at the center point.
+ * This is a counterpart of {@link PipUtils#getEnterPipWithOverlaySrcRectHint}
*/
- public void setSourceRectHint(View v) {
- View rectView = findViewById(R.id.source_rect);
- if (rectView != null) {
- rectView.setVisibility(View.VISIBLE);
- rectView.getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- Rect boundingRect = new Rect();
- rectView.getGlobalVisibleRect(boundingRect);
- mPipParamsBuilder.setSourceRectHint(boundingRect);
- setPictureInPictureParams(mPipParamsBuilder.build());
- rectView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- }
- });
- rectView.invalidate(); // changing the visibility, invalidating to redraw the view
+ private Rect getEnterPipWithOverlaySrcRectHint(Rect appBounds, float aspectRatio) {
+ final float appBoundsAspectRatio = appBounds.width() / (float) appBounds.height();
+ final int width, height;
+ int left = appBounds.left;
+ int top = appBounds.top;
+ if (appBoundsAspectRatio < aspectRatio) {
+ width = appBounds.width();
+ height = (int) (width / aspectRatio);
+ top = appBounds.top + (appBounds.height() - height) / 2;
+ } else {
+ height = appBounds.height();
+ width = (int) (height * aspectRatio);
+ left = appBounds.left + (appBounds.width() - width) / 2;
}
+ return new Rect(left, top, left + width, top + height);
}
public void onRatioSelected(View v) {
switch (v.getId()) {
case R.id.ratio_default:
- mPipParamsBuilder.setAspectRatio(RATIO_DEFAULT);
+ mAspectRatio = RATIO_DEFAULT;
break;
case R.id.ratio_square:
- mPipParamsBuilder.setAspectRatio(RATIO_SQUARE);
+ mAspectRatio = RATIO_SQUARE;
break;
case R.id.ratio_wide:
- mPipParamsBuilder.setAspectRatio(RATIO_WIDE);
+ mAspectRatio = RATIO_WIDE;
break;
case R.id.ratio_tall:
- mPipParamsBuilder.setAspectRatio(RATIO_TALL);
+ mAspectRatio = RATIO_TALL;
break;
}
+ setPictureInPictureParams(mPipParamsBuilder.setAspectRatio(mAspectRatio).build());
+ if (mEnableSourceRectHint) {
+ updateSourceRectHint();
+ }
}
private void updateMediaSessionState(int newState) {
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index f367c38b06e9..06c2651b604d 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -48,6 +48,7 @@ android_test {
"testables",
"testng",
"truth",
+ "ui-trace-collector",
],
libs: [
"android.test.mock",
diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml
index 4a99bd4f1801..bc9322fbd3dc 100644
--- a/tests/Input/AndroidTest.xml
+++ b/tests/Input/AndroidTest.xml
@@ -22,6 +22,10 @@
<option name="shell-timeout" value="660s" />
<option name="test-timeout" value="600s" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="device-listeners" value="android.tools.collectors.DefaultUITraceListener"/>
+ <!-- DefaultUITraceListener args -->
+ <option name="instrumentation-arg" key="skip_test_success_metrics" value="true"/>
+ <option name="instrumentation-arg" key="per_class" value="true"/>
</test>
<object class="com.android.tradefed.testtype.suite.module.TestFailureModuleController"
type="module_controller">
@@ -32,6 +36,8 @@
<option name="pull-pattern-keys" value="input_.*" />
<!-- Pull files created by tests, like the output of screenshot tests -->
<option name="directory-keys" value="/sdcard/Download/InputTests" />
+ <!-- Pull perfetto traces from DefaultUITraceListener -->
+ <option name="pull-pattern-keys" value="perfetto_file_path*" />
<option name="collect-on-run-ended-only" value="false" />
</metrics_collector>
</configuration>
diff --git a/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt
new file mode 100644
index 000000000000..14aac6637d4f
--- /dev/null
+++ b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.os.Handler
+import android.os.HandlerExecutor
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.platform.test.flag.junit.SetFlagsRule
+import android.view.KeyEvent
+import androidx.test.core.app.ApplicationProvider
+import com.android.server.testutils.any
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnitRunner
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.fail
+
+/**
+ * Tests for [InputManager.KeyGestureEventListener].
+ *
+ * Build/Install/Run:
+ * atest InputTests:KeyGestureEventListenerTest
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner::class)
+class KeyGestureEventListenerTest {
+
+ companion object {
+ const val DEVICE_ID = 1
+ val HOME_GESTURE_EVENT = KeyGestureEvent(
+ DEVICE_ID,
+ intArrayOf(KeyEvent.KEYCODE_H),
+ KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME
+ )
+ }
+
+ @get:Rule
+ val rule = SetFlagsRule()
+
+ private val testLooper = TestLooper()
+ private val executor = HandlerExecutor(Handler(testLooper.looper))
+ private var registeredListener: IKeyGestureEventListener? = null
+ private lateinit var context: Context
+ private lateinit var inputManager: InputManager
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
+
+ @Mock
+ private lateinit var iInputManagerMock: IInputManager
+
+ @Before
+ fun setUp() {
+ context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManagerMock)
+ inputManager = InputManager(context)
+ `when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
+ .thenReturn(inputManager)
+
+ // Handle key gesture event listener registration.
+ doAnswer {
+ val listener = it.getArgument(0) as IKeyGestureEventListener
+ if (registeredListener != null &&
+ registeredListener!!.asBinder() != listener.asBinder()) {
+ // There can only be one registered key gesture event listener per process.
+ fail("Trying to register a new listener when one already exists")
+ }
+ registeredListener = listener
+ null
+ }.`when`(iInputManagerMock).registerKeyGestureEventListener(any())
+
+ // Handle key gesture event listener being unregistered.
+ doAnswer {
+ val listener = it.getArgument(0) as IKeyGestureEventListener
+ if (registeredListener == null ||
+ registeredListener!!.asBinder() != listener.asBinder()) {
+ fail("Trying to unregister a listener that is not registered")
+ }
+ registeredListener = null
+ null
+ }.`when`(iInputManagerMock).unregisterKeyGestureEventListener(any())
+ }
+
+ @After
+ fun tearDown() {
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
+ }
+
+ private fun notifyKeyGestureEvent(event: KeyGestureEvent) {
+ registeredListener!!.onKeyGestureEvent(
+ event.deviceId,
+ event.keycodes,
+ event.modifierState,
+ event.keyGestureType
+ )
+ }
+
+ @Test
+ fun testListenerHasCorrectGestureNotified() {
+ var callbackCount = 0
+
+ // Add a key gesture event listener
+ inputManager.registerKeyGestureEventListener(executor) {
+ event: KeyGestureEvent ->
+ assertEquals(HOME_GESTURE_EVENT, event)
+ callbackCount++
+ }
+
+ // Notifying key gesture event will notify the listener.
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
+ testLooper.dispatchNext()
+ assertEquals(1, callbackCount)
+ }
+
+ @Test
+ fun testAddingListenersRegistersInternalCallbackListener() {
+ // Set up two callbacks.
+ val callback1 = InputManager.KeyGestureEventListener { _ -> }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> }
+
+ assertNull(registeredListener)
+
+ // Adding the listener should register the callback with InputManagerService.
+ inputManager.registerKeyGestureEventListener(executor, callback1)
+ assertNotNull(registeredListener)
+
+ // Adding another listener should not register new internal listener.
+ val currListener = registeredListener
+ inputManager.registerKeyGestureEventListener(executor, callback2)
+ assertEquals(currListener, registeredListener)
+ }
+
+ @Test
+ fun testRemovingListenersUnregistersInternalCallbackListener() {
+ // Set up two callbacks.
+ val callback1 = InputManager.KeyGestureEventListener { _ -> }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> }
+
+ inputManager.registerKeyGestureEventListener(executor, callback1)
+ inputManager.registerKeyGestureEventListener(executor, callback2)
+
+ // Only removing all listeners should remove the internal callback
+ inputManager.unregisterKeyGestureEventListener(callback1)
+ assertNotNull(registeredListener)
+ inputManager.unregisterKeyGestureEventListener(callback2)
+ assertNull(registeredListener)
+ }
+
+ @Test
+ fun testMultipleListeners() {
+ // Set up two callbacks.
+ var callbackCount1 = 0
+ var callbackCount2 = 0
+ val callback1 = InputManager.KeyGestureEventListener { _ -> callbackCount1++ }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> callbackCount2++ }
+
+ // Add both key gesture event listeners
+ inputManager.registerKeyGestureEventListener(executor, callback1)
+ inputManager.registerKeyGestureEventListener(executor, callback2)
+
+ // Notifying key gesture event, should notify both the callbacks.
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
+ testLooper.dispatchAll()
+ assertEquals(1, callbackCount1)
+ assertEquals(1, callbackCount2)
+
+ inputManager.unregisterKeyGestureEventListener(callback2)
+ // Notifying key gesture event, should still trigger callback1 but not
+ // callback2.
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
+ testLooper.dispatchAll()
+ assertEquals(2, callbackCount1)
+ assertEquals(1, callbackCount2)
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index 3c72498082e4..8829f74f5092 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -151,6 +151,7 @@ class InputManagerServiceTests {
verify(native).setTouchpadNaturalScrollingEnabled(anyBoolean())
verify(native).setTouchpadTapToClickEnabled(anyBoolean())
verify(native).setTouchpadTapDraggingEnabled(anyBoolean())
+ verify(native).setShouldNotifyTouchpadHardwareState(anyBoolean())
verify(native).setTouchpadRightClickZoneEnabled(anyBoolean())
verify(native).setShowTouches(anyBoolean())
verify(native).setMotionClassifierEnabled(anyBoolean())
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
new file mode 100644
index 000000000000..3f611e0ead53
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.hardware.input.IKeyGestureEventListener
+import android.hardware.input.KeyGestureEvent
+import android.platform.test.annotations.Presubmit
+import android.view.KeyEvent
+import androidx.test.core.app.ApplicationProvider
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+
+/**
+ * Tests for {@link KeyGestureController}.
+ *
+ * Build/Install/Run:
+ * atest InputTests:KeyGestureControllerTests
+ */
+@Presubmit
+class KeyGestureControllerTests {
+
+ companion object {
+ val DEVICE_ID = 1
+ val HOME_GESTURE_EVENT = KeyGestureEvent(
+ DEVICE_ID,
+ intArrayOf(KeyEvent.KEYCODE_H),
+ KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME
+ )
+ }
+
+ @get:Rule
+ val rule = MockitoJUnit.rule()!!
+
+ private lateinit var keyGestureController: KeyGestureController
+ private lateinit var context: Context
+ private var lastEvent: KeyGestureEvent? = null
+
+ @Before
+ fun setup() {
+ context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ keyGestureController = KeyGestureController()
+ }
+
+ @Test
+ fun testKeyGestureEvent_registerUnregisterListener() {
+ val listener = KeyGestureEventListener()
+
+ // Register key gesture event listener
+ keyGestureController.registerKeyGestureEventListener(listener, 0)
+ keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT)
+ assertEquals(
+ "Listener should get callback on key gesture event",
+ HOME_GESTURE_EVENT,
+ lastEvent!!
+ )
+
+ // Unregister listener
+ lastEvent = null
+ keyGestureController.unregisterKeyGestureEventListener(listener, 0)
+ keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT)
+ assertNull("Listener should not get callback after being unregistered", lastEvent)
+ }
+
+ inner class KeyGestureEventListener : IKeyGestureEventListener.Stub() {
+ override fun onKeyGestureEvent(
+ deviceId: Int,
+ keycodes: IntArray,
+ modifierState: Int,
+ gestureType: Int
+ ) {
+ lastEvent = KeyGestureEvent(deviceId, keycodes, modifierState, gestureType)
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 8d1fc508ffe7..d32cedb24a36 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -40,7 +40,7 @@ import androidx.test.uiautomator.Until
import com.android.cts.input.DebugInputRule
import com.android.cts.input.UinputTouchScreen
-import java.util.concurrent.TimeUnit
+import java.time.Duration
import org.junit.After
import org.junit.Assert.assertEquals
@@ -193,6 +193,6 @@ class AnrTest {
val flags = " -W -n "
val startCmd = "am start $flags $PACKAGE_NAME/.UnresponsiveGestureMonitorActivity"
instrumentation.uiAutomation.executeShellCommand(startCmd)
- waitForStableWindowGeometry(5L, TimeUnit.SECONDS)
+ waitForStableWindowGeometry(Duration.ofSeconds(5))
}
}
diff --git a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
index c1a86b3a2dac..015e188fc98e 100644
--- a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
+++ b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt
@@ -18,12 +18,20 @@ package com.android.test.input
import android.view.InputDevice.SOURCE_MOUSE
import android.view.InputDevice.SOURCE_TOUCHSCREEN
+import android.view.InputDevice.SOURCE_STYLUS
+import android.view.InputDevice.SOURCE_TOUCHPAD
+
import android.view.InputEventAssigner
import android.view.KeyEvent
import android.view.MotionEvent
import org.junit.Assert.assertEquals
import org.junit.Test
+sealed class StreamEvent
+private data object Vsync : StreamEvent()
+data class MotionEventData(val action: Int, val source: Int, val id: Int, val expectedId: Int) :
+ StreamEvent()
+
/**
* Create a MotionEvent with the provided action, eventTime, and source
*/
@@ -49,64 +57,164 @@ private fun createKeyEvent(action: Int, eventTime: Long): KeyEvent {
return KeyEvent(eventTime, eventTime, action, code, repeat)
}
+/**
+ * Check that the correct eventIds are assigned in a stream. The stream consists of motion
+ * events or vsync (processed frame)
+ * Each streamEvent should have unique ids when writing tests
+ * The test passes even if two events get assigned the same eventId, since the mapping is
+ * streamEventId -> motionEventId and streamEvents have unique ids
+ */
+private fun checkEventStream(vararg streamEvents: StreamEvent) {
+ val assigner = InputEventAssigner()
+ var eventTime = 10L
+ // Maps MotionEventData.id to MotionEvent.id
+ // We can't control the event id of the generated motion events but for testing it's easier
+ // to label the events with a custom id for readability
+ val eventIdMap: HashMap<Int, Int> = HashMap()
+ for (streamEvent in streamEvents) {
+ when (streamEvent) {
+ is MotionEventData -> {
+ val event = createMotionEvent(streamEvent.action, eventTime, streamEvent.source)
+ eventIdMap[streamEvent.id] = event.id
+ val eventId = assigner.processEvent(event)
+ assertEquals(eventIdMap[streamEvent.expectedId], eventId)
+ }
+ is Vsync -> assigner.notifyFrameProcessed()
+ }
+ eventTime += 1
+ }
+}
+
class InputEventAssignerTest {
companion object {
private const val TAG = "InputEventAssignerTest"
}
/**
- * A single MOVE event should be assigned to the next available frame.
+ * A single event should be assigned to the next available frame.
*/
@Test
- fun testTouchGesture() {
- val assigner = InputEventAssigner()
- val event = createMotionEvent(MotionEvent.ACTION_MOVE, 10, SOURCE_TOUCHSCREEN)
- val eventId = assigner.processEvent(event)
- assertEquals(event.id, eventId)
+ fun testTouchMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testMouseMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_MOUSE, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testMouseScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testStylusMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testStylusHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_HOVER_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
+ }
+
+ @Test
+ fun testTouchpadMove() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1)
+ )
}
/**
- * DOWN event should be used until a vsync comes in. After vsync, the latest event should be
- * produced.
+ * Test that before a VSYNC the event id generated by input event assigner for move events is
+ * the id of the down event. Move events coming after a VSYNC should be assigned their own event
+ * id
*/
+ private fun testDownAndMove(source: Int) {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, source, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_MOVE, source, id = 2, expectedId = 1),
+ Vsync,
+ MotionEventData(MotionEvent.ACTION_MOVE, source, id = 4, expectedId = 4)
+ )
+ }
+
@Test
- fun testTouchDownWithMove() {
- val assigner = InputEventAssigner()
- val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_TOUCHSCREEN)
- val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_TOUCHSCREEN)
- val move2 = createMotionEvent(MotionEvent.ACTION_MOVE, 13, SOURCE_TOUCHSCREEN)
- val move3 = createMotionEvent(MotionEvent.ACTION_MOVE, 14, SOURCE_TOUCHSCREEN)
- val move4 = createMotionEvent(MotionEvent.ACTION_MOVE, 15, SOURCE_TOUCHSCREEN)
- var eventId = assigner.processEvent(down)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move1)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move2)
- // Even though we already had 2 move events, there was no choreographer callback yet.
- // Therefore, we should still get the id of the down event
- assertEquals(down.id, eventId)
+ fun testTouchDownAndMove() {
+ testDownAndMove(SOURCE_TOUCHSCREEN)
+ }
- // Now send CALLBACK_INPUT to the assigner. It should provide the latest motion event
- assigner.notifyFrameProcessed()
- eventId = assigner.processEvent(move3)
- assertEquals(move3.id, eventId)
- eventId = assigner.processEvent(move4)
- assertEquals(move4.id, eventId)
+ @Test
+ fun testMouseDownAndMove() {
+ testDownAndMove(SOURCE_MOUSE)
+ }
+
+ @Test
+ fun testStylusDownAndMove() {
+ testDownAndMove(SOURCE_STYLUS)
+ }
+
+ @Test
+ fun testTouchpadDownAndMove() {
+ testDownAndMove(SOURCE_TOUCHPAD)
}
/**
- * Similar to the above test, but with SOURCE_MOUSE. Since we don't have down latency
- * concept for non-touchscreens, the latest input event will be used.
+ * After an up event, motion events should be assigned their own event id
*/
@Test
- fun testMouseDownWithMove() {
- val assigner = InputEventAssigner()
- val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_MOUSE)
- val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_MOUSE)
- var eventId = assigner.processEvent(down)
- assertEquals(down.id, eventId)
- eventId = assigner.processEvent(move1)
- assertEquals(move1.id, eventId)
+ fun testMouseDownUpAndScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_UP, SOURCE_MOUSE, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After an up event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testStylusDownUpAndHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_UP, SOURCE_STYLUS, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After a cancel event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testMouseDownCancelAndScroll() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_MOUSE, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3)
+ )
+ }
+
+ /**
+ * After a cancel event, motion events should be assigned their own event id
+ */
+ @Test
+ fun testStylusDownCancelAndHover() {
+ checkEventStream(
+ MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1),
+ MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_STYLUS, id = 2, expectedId = 2),
+ MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3)
+ )
}
/**
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
index e60d8efdbfa4..a2c3572eca9b 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
@@ -37,14 +37,14 @@ import android.content.res.Configuration;
import android.os.SystemClock;
import android.platform.test.annotations.RootPermissionTest;
import android.platform.test.rule.UnlockScreenRule;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
import android.view.WindowManager;
import android.widget.EditText;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java
index 2ac25f2696d3..b994bfb00007 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java
@@ -33,10 +33,10 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.content.Intent;
import android.platform.test.annotations.RootPermissionTest;
import android.platform.test.rule.UnlockScreenRule;
-import android.support.test.uiautomator.UiDevice;
import android.widget.EditText;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
index 5368025ff898..2128cbf90542 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
@@ -48,12 +48,12 @@ import android.os.Build;
import android.os.SystemClock;
import android.platform.test.annotations.RootPermissionTest;
import android.platform.test.rule.UnlockScreenRule;
-import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import android.view.WindowManager;
import android.widget.EditText;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java
index c7463218b646..1249a4564e8e 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java
@@ -18,10 +18,10 @@ package com.android.inputmethod.stresstest;
import android.app.Instrumentation;
import android.os.RemoteException;
-import android.support.test.uiautomator.UiDevice;
import androidx.annotation.NonNull;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index 827ff4fbd989..ad98e47fa8f0 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -24,6 +24,7 @@ android_test {
"flickerlib-parsers",
"perfetto_trace_java_protos",
"flickerlib-trace_processor_shell",
+ "ravenwood-junit",
],
java_resource_dirs: ["res"],
certificate: "platform",
@@ -39,6 +40,7 @@ android_ravenwood_test {
"platform-test-annotations",
],
srcs: [
+ "src/com/android/internal/graphics/ColorUtilsTest.java",
"src/com/android/internal/util/ParcellingTests.java",
],
auto_gen_config: true,
diff --git a/tests/Internal/AndroidTest.xml b/tests/Internal/AndroidTest.xml
index 7b67e9ebcced..2d6c650eb2dc 100644
--- a/tests/Internal/AndroidTest.xml
+++ b/tests/Internal/AndroidTest.xml
@@ -26,4 +26,12 @@
<option name="package" value="com.android.internal.tests" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
</test>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="pull-pattern-keys" value="perfetto_file_path"/>
+ <option name="directory-keys"
+ value="/data/user/0/com.android.internal.tests/files"/>
+ <option name="collect-on-run-ended-only" value="true"/>
+ <option name="clean-up" value="true"/>
+ </metrics_collector>
</configuration> \ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java b/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
index d0bb8e3745bc..38a22f2fc2f3 100644
--- a/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
+++ b/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
@@ -19,14 +19,19 @@ package com.android.internal.graphics;
import static org.junit.Assert.assertTrue;
import android.graphics.Color;
+import android.platform.test.ravenwood.RavenwoodRule;
import androidx.test.filters.SmallTest;
+import org.junit.Rule;
import org.junit.Test;
@SmallTest
public class ColorUtilsTest {
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
@Test
public void calculateMinimumBackgroundAlpha_satisfiestContrast() {
diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
index 5a48327e7576..9657225588b7 100644
--- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
@@ -214,6 +214,13 @@ public class LegacyProtoLogImplTest {
verify(mReader, never()).getViewerString(anyLong());
}
+ @Test
+ public void loadViewerConfigOnLogcatGroupRegistration() {
+ TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
+ mProtoLog.registerGroups(TestProtoLogGroup.TEST_GROUP);
+ verify(mReader).loadViewerConfig(any(), any());
+ }
+
private static class ProtoLogData {
Long mMessageHash = null;
Long mElapsedTime = null;
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index b6672a0e2f4b..4b745b289d33 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -29,7 +29,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static java.io.File.createTempFile;
-import static java.nio.file.Files.createTempDirectory;
import android.content.Context;
import android.os.SystemClock;
@@ -45,6 +44,7 @@ import android.tracing.perfetto.DataSource;
import android.util.proto.ProtoInputStream;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogDataType;
@@ -67,7 +67,6 @@ import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Random;
-import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -78,7 +77,8 @@ import java.util.concurrent.atomic.AtomicInteger;
@Presubmit
@RunWith(JUnit4.class)
public class PerfettoProtoLogImplTest {
- private final File mTracingDirectory = createTempDirectory("temp").toFile();
+ private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext().getFilesDir();
private final ResultWriter mWriter = new ResultWriter()
.forScenario(new ScenarioBuilder()
@@ -126,30 +126,35 @@ public class PerfettoProtoLogImplTest {
.setMessage("My Test Debug Log Message %b")
.setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_DEBUG)
.setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:123")
).addMessages(
Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
.setMessageId(2)
.setMessage("My Test Verbose Log Message %b")
.setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_VERBOSE)
.setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:342")
).addMessages(
Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
.setMessageId(3)
.setMessage("My Test Warn Log Message %b")
.setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_WARN)
.setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:563")
).addMessages(
Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
.setMessageId(4)
.setMessage("My Test Error Log Message %b")
.setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_ERROR)
.setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:156")
).addMessages(
Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
.setMessageId(5)
.setMessage("My Test WTF Log Message %b")
.setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_WTF)
.setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:192")
);
ViewerConfigInputStreamProvider viewerConfigInputStreamProvider = Mockito.mock(
@@ -379,7 +384,7 @@ public class PerfettoProtoLogImplTest {
new Object[]{5});
verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
- LogLevel.INFO), eq("UNKNOWN MESSAGE#1234 (5)"));
+ LogLevel.INFO), eq("UNKNOWN MESSAGE args = (5)"));
verify(mReader).getViewerString(eq(1234L));
}
@@ -446,8 +451,8 @@ public class PerfettoProtoLogImplTest {
before = SystemClock.elapsedRealtimeNanos();
mProtoLog.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP,
- "My test message :: %s, %d, %o, %x, %f, %b",
- "test", 1, 2, 3, 0.4, true);
+ "My test message :: %s, %d, %x, %f, %b",
+ "test", 1, 3, 0.4, true);
after = SystemClock.elapsedRealtimeNanos();
} finally {
traceMonitor.stop(mWriter);
@@ -462,7 +467,27 @@ public class PerfettoProtoLogImplTest {
Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos())
.isAtMost(after);
Truth.assertThat(protolog.messages.getFirst().getMessage())
- .isEqualTo("My test message :: test, 2, 4, 6, 0.400000, true");
+ .isEqualTo("My test message :: test, 2, 6, 0.400000, true");
+ }
+
+ @Test
+ public void supportsLocationInformation() throws IOException {
+ PerfettoTraceMonitor traceMonitor =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(true).build();
+ try {
+ traceMonitor.start();
+ mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ LogDataType.BOOLEAN, new Object[]{true});
+ } finally {
+ traceMonitor.stop(mWriter);
+ }
+
+ final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig);
+ final ProtoLogTrace protolog = reader.readProtoLogTrace();
+
+ Truth.assertThat(protolog.messages).hasSize(1);
+ Truth.assertThat(protolog.messages.get(0).getLocation())
+ .isEqualTo("com/test/MyTestClass.java:123");
}
private long addMessageToConfig(ProtologCommon.ProtoLogLevel logLevel, String message) {
@@ -698,7 +723,7 @@ public class PerfettoProtoLogImplTest {
traceMonitor.start();
mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
- "My test null string: %s", null);
+ "My test null string: %s", (Object) null);
} finally {
traceMonitor.stop(mWriter);
}
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java
new file mode 100644
index 000000000000..e3ec62d5b5a6
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.contains;
+import static org.mockito.ArgumentMatchers.endsWith;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.times;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Test class for {@link ProtoLogImpl}.
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class ProtoLogCommandHandlerTest {
+
+ @Mock
+ ProtoLogService mProtoLogService;
+ @Mock
+ PrintWriter mPrintWriter;
+
+ @Test
+ public void printsHelpForAllAvailableCommands() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.onHelp();
+ validateOnHelpPrinted();
+ }
+
+ @Test
+ public void printsHelpIfCommandIsNull() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.onCommand(null);
+ validateOnHelpPrinted();
+ }
+
+ @Test
+ public void handlesGroupListCommand() {
+ Mockito.when(mProtoLogService.getGroups())
+ .thenReturn(new String[] {"MY_TEST_GROUP", "MY_OTHER_GROUP"});
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "groups", "list" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("MY_TEST_GROUP"));
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("MY_OTHER_GROUP"));
+ }
+
+ @Test
+ public void handlesIncompleteGroupsCommand() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "groups" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("Incomplete command"));
+ }
+
+ @Test
+ public void handlesGroupStatusCommand() {
+ Mockito.when(mProtoLogService.getGroups()).thenReturn(new String[] {"MY_GROUP"});
+ Mockito.when(mProtoLogService.isLoggingToLogcat("MY_GROUP")).thenReturn(true);
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "groups", "status", "MY_GROUP" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("MY_GROUP"));
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("LOG_TO_LOGCAT = true"));
+ }
+
+ @Test
+ public void handlesGroupStatusCommandOfUnregisteredGroups() {
+ Mockito.when(mProtoLogService.getGroups()).thenReturn(new String[] {});
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "groups", "status", "MY_GROUP" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("MY_GROUP"));
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("UNREGISTERED"));
+ }
+
+ @Test
+ public void handlesGroupStatusCommandWithNoGroups() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "groups", "status" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("Incomplete command"));
+ }
+
+ @Test
+ public void handlesIncompleteLogcatCommand() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat" });
+
+ Mockito.verify(mPrintWriter, times(1))
+ .println(contains("Incomplete command"));
+ }
+
+ @Test
+ public void handlesLogcatEnableCommand() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "enable", "MY_GROUP" });
+ Mockito.verify(mProtoLogService).enableProtoLogToLogcat("MY_GROUP");
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "enable", "MY_GROUP", "MY_OTHER_GROUP" });
+ Mockito.verify(mProtoLogService)
+ .enableProtoLogToLogcat("MY_GROUP", "MY_OTHER_GROUP");
+ }
+
+ @Test
+ public void handlesLogcatDisableCommand() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "disable", "MY_GROUP" });
+ Mockito.verify(mProtoLogService).disableProtoLogToLogcat("MY_GROUP");
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "disable", "MY_GROUP", "MY_OTHER_GROUP" });
+ Mockito.verify(mProtoLogService)
+ .disableProtoLogToLogcat("MY_GROUP", "MY_OTHER_GROUP");
+ }
+
+ @Test
+ public void handlesLogcatEnableCommandWithNoGroups() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "enable" });
+ Mockito.verify(mPrintWriter).println(contains("Incomplete command"));
+ }
+
+ @Test
+ public void handlesLogcatDisableCommandWithNoGroups() {
+ final ProtoLogCommandHandler cmdHandler =
+ new ProtoLogCommandHandler(mProtoLogService, mPrintWriter);
+
+ cmdHandler.exec(mProtoLogService, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ new String[] { "logcat", "disable" });
+ Mockito.verify(mPrintWriter).println(contains("Incomplete command"));
+ }
+
+ private void validateOnHelpPrinted() {
+ Mockito.verify(mPrintWriter, times(1)).println(endsWith("help"));
+ Mockito.verify(mPrintWriter, times(1))
+ .println(endsWith("groups (list | status)"));
+ Mockito.verify(mPrintWriter, times(1))
+ .println(endsWith("logcat (enable | disable) <group>"));
+ Mockito.verify(mPrintWriter, atLeast(0)).println(anyString());
+ }
+}
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogServiceTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogServiceTest.java
new file mode 100644
index 000000000000..feac59c702ea
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogServiceTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+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.Mockito.never;
+
+import static java.io.File.createTempFile;
+import static java.nio.file.Files.createTempDirectory;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.tools.ScenarioBuilder;
+import android.tools.Tag;
+import android.tools.io.ResultArtifactDescriptor;
+import android.tools.io.TraceType;
+import android.tools.traces.TraceConfig;
+import android.tools.traces.TraceConfigs;
+import android.tools.traces.io.ResultReader;
+import android.tools.traces.io.ResultWriter;
+import android.tools.traces.monitors.PerfettoTraceMonitor;
+
+import com.google.common.truth.Truth;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import perfetto.protos.Protolog.ProtoLogViewerConfig;
+import perfetto.protos.ProtologCommon;
+import perfetto.protos.TraceOuterClass.Trace;
+import perfetto.protos.TracePacketOuterClass.TracePacket;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Test class for {@link ProtoLogImpl}.
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class ProtoLogServiceTest {
+
+ private static final String TEST_GROUP = "MY_TEST_GROUP";
+ private static final String OTHER_TEST_GROUP = "MY_OTHER_TEST_GROUP";
+
+ private static final ProtoLogViewerConfig VIEWER_CONFIG =
+ ProtoLogViewerConfig.newBuilder()
+ .addGroups(
+ ProtoLogViewerConfig.Group.newBuilder()
+ .setId(1)
+ .setName(TEST_GROUP)
+ .setTag(TEST_GROUP)
+ ).addMessages(
+ ProtoLogViewerConfig.MessageData.newBuilder()
+ .setMessageId(1)
+ .setMessage("My Test Debug Log Message %b")
+ .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_DEBUG)
+ .setGroupId(1)
+ ).addMessages(
+ ProtoLogViewerConfig.MessageData.newBuilder()
+ .setMessageId(2)
+ .setMessage("My Test Verbose Log Message %b")
+ .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_VERBOSE)
+ .setGroupId(1)
+ ).build();
+
+ @Mock
+ IProtoLogClient mMockClient;
+
+ @Mock
+ IProtoLogClient mSecondMockClient;
+
+ @Mock
+ IBinder mMockClientBinder;
+
+ @Mock
+ IBinder mSecondMockClientBinder;
+
+ private final File mTracingDirectory = createTempDirectory("temp").toFile();
+
+ private final ResultWriter mWriter = new ResultWriter()
+ .forScenario(new ScenarioBuilder()
+ .forClass(createTempFile("temp", "").getName()).build())
+ .withOutputDir(mTracingDirectory)
+ .setRunComplete();
+
+ private final TraceConfigs mTraceConfig = new TraceConfigs(
+ new TraceConfig(false, true, false),
+ new TraceConfig(false, true, false),
+ new TraceConfig(false, true, false),
+ new TraceConfig(false, true, false)
+ );
+
+ @Captor
+ ArgumentCaptor<IBinder.DeathRecipient> mDeathRecipientArgumentCaptor;
+
+ @Captor
+ ArgumentCaptor<IBinder.DeathRecipient> mSecondDeathRecipientArgumentCaptor;
+
+ private File mViewerConfigFile;
+
+ public ProtoLogServiceTest() throws IOException {
+ }
+
+ @Before
+ public void setUp() {
+ Mockito.when(mMockClient.asBinder()).thenReturn(mMockClientBinder);
+ Mockito.when(mSecondMockClient.asBinder()).thenReturn(mSecondMockClientBinder);
+
+ try {
+ mViewerConfigFile = File.createTempFile("viewer-config", ".pb");
+ try (var fos = new FileOutputStream(mViewerConfigFile);
+ BufferedOutputStream bos = new BufferedOutputStream(fos)) {
+
+ bos.write(VIEWER_CONFIG.toByteArray());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void canRegisterClientWithGroupsOnly() throws RemoteException {
+ final ProtoLogService service = new ProtoLogService();
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, true));
+ service.registerClient(mMockClient, args);
+
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
+ Truth.assertThat(service.getGroups()).asList().containsExactly(TEST_GROUP);
+ }
+
+ @Test
+ public void willDumpViewerConfigOnlyOnceOnTraceStop()
+ throws RemoteException, InvalidProtocolBufferException {
+ final ProtoLogService service = new ProtoLogService();
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, true))
+ .setViewerConfigFile(mViewerConfigFile.getAbsolutePath());
+ service.registerClient(mMockClient, args);
+ service.registerClient(mSecondMockClient, args);
+
+ PerfettoTraceMonitor traceMonitor =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+
+ traceMonitor.start();
+ traceMonitor.stop(mWriter);
+ final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig);
+ final byte[] traceData = reader.getArtifact()
+ .readBytes(new ResultArtifactDescriptor(TraceType.PERFETTO, Tag.ALL));
+
+ final Trace trace = Trace.parseFrom(traceData);
+
+ final List<TracePacket> configPackets = trace.getPacketList().stream()
+ .filter(it -> it.hasProtologViewerConfig())
+ // Exclude viewer configs from regular system tracing
+ .filter(it ->
+ it.getProtologViewerConfig().getGroups(0).getName().equals(TEST_GROUP))
+ .toList();
+ Truth.assertThat(configPackets).hasSize(1);
+ Truth.assertThat(configPackets.get(0).getProtologViewerConfig().toString())
+ .isEqualTo(VIEWER_CONFIG.toString());
+ }
+
+ @Test
+ public void willDumpViewerConfigOnLastClientDisconnected()
+ throws RemoteException, FileNotFoundException {
+ final ProtoLogService.ViewerConfigFileTracer tracer =
+ Mockito.mock(ProtoLogService.ViewerConfigFileTracer.class);
+ final ProtoLogService service = new ProtoLogService(tracer);
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(
+ TEST_GROUP, true))
+ .setViewerConfigFile(mViewerConfigFile.getAbsolutePath());
+ service.registerClient(mMockClient, args);
+ service.registerClient(mSecondMockClient, args);
+
+ Mockito.verify(mMockClientBinder)
+ .linkToDeath(mDeathRecipientArgumentCaptor.capture(), anyInt());
+ Mockito.verify(mSecondMockClientBinder)
+ .linkToDeath(mSecondDeathRecipientArgumentCaptor.capture(), anyInt());
+
+ mDeathRecipientArgumentCaptor.getValue().binderDied();
+ Mockito.verify(tracer, never()).trace(any(), any());
+ mSecondDeathRecipientArgumentCaptor.getValue().binderDied();
+ Mockito.verify(tracer).trace(any(), eq(mViewerConfigFile.getAbsolutePath()));
+ }
+
+ @Test
+ public void sendEnableLoggingToLogcatToClient() throws RemoteException {
+ final var service = new ProtoLogService();
+
+ final var args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, false));
+ service.registerClient(mMockClient, args);
+
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
+ service.enableProtoLogToLogcat(TEST_GROUP);
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
+
+ Mockito.verify(mMockClient).toggleLogcat(eq(true),
+ Mockito.argThat(it -> it.length == 1 && it[0].equals(TEST_GROUP)));
+ }
+
+ @Test
+ public void sendDisableLoggingToLogcatToClient() throws RemoteException {
+ final ProtoLogService service = new ProtoLogService();
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, true));
+ service.registerClient(mMockClient, args);
+
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
+ service.disableProtoLogToLogcat(TEST_GROUP);
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
+
+ Mockito.verify(mMockClient).toggleLogcat(eq(false),
+ Mockito.argThat(it -> it.length == 1 && it[0].equals(TEST_GROUP)));
+ }
+
+ @Test
+ public void doNotSendLoggingToLogcatToClientWithoutRegisteredGroup() throws RemoteException {
+ final ProtoLogService service = new ProtoLogService();
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, false));
+ service.registerClient(mMockClient, args);
+
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
+ service.enableProtoLogToLogcat(OTHER_TEST_GROUP);
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
+
+ Mockito.verify(mMockClient, never()).toggleLogcat(anyBoolean(), any());
+ }
+
+ @Test
+ public void handlesToggleToLogcatBeforeClientIsRegistered() throws RemoteException {
+ final ProtoLogService service = new ProtoLogService();
+
+ Truth.assertThat(service.getGroups()).asList().doesNotContain(TEST_GROUP);
+ service.enableProtoLogToLogcat(TEST_GROUP);
+ Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
+
+ final ProtoLogService.RegisterClientArgs args = new ProtoLogService.RegisterClientArgs()
+ .setGroups(new ProtoLogService.RegisterClientArgs.GroupConfig(TEST_GROUP, false));
+ service.registerClient(mMockClient, args);
+
+ Mockito.verify(mMockClient).toggleLogcat(eq(true),
+ Mockito.argThat(it -> it.length == 1 && it[0].equals(TEST_GROUP)));
+ }
+}
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java b/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java
index be9fb1b309f6..9a062e3b2f80 100644
--- a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java
@@ -67,7 +67,7 @@ public class ProtologDataSourceTest {
@Test
public void allEnabledTraceMode() {
- final ProtoLogDataSource ds = new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {});
+ final ProtoLogDataSource ds = new ProtoLogDataSource((idx, c) -> {}, () -> {}, (idx, c) -> {});
final ProtoLogDataSource.TlsState tlsState = createTlsState(
DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig(
@@ -154,7 +154,7 @@ public class ProtologDataSourceTest {
private ProtoLogDataSource.TlsState createTlsState(
DataSourceConfigOuterClass.DataSourceConfig config) {
final ProtoLogDataSource ds =
- Mockito.spy(new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {}));
+ Mockito.spy(new ProtoLogDataSource((idx, c) -> {}, () -> {}, (idx, c) -> {}));
ProtoInputStream configStream = new ProtoInputStream(config.toByteArray());
final ProtoLogDataSource.Instance dsInstance = Mockito.spy(
diff --git a/tests/Internal/src/com/android/internal/util/ParcellingTests.java b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
index 65a3436a4c5e..fb63422cdf9f 100644
--- a/tests/Internal/src/com/android/internal/util/ParcellingTests.java
+++ b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
@@ -18,6 +18,7 @@ package com.android.internal.util;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -26,6 +27,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.util.Parcelling.BuiltIn.ForInstant;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -38,6 +40,9 @@ import java.time.Instant;
@RunWith(JUnit4.class)
public class ParcellingTests {
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
private Parcel mParcel = Parcel.obtain();
@Test
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 3722fefb12ad..c0e90f9232d6 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
@@ -77,6 +78,7 @@ import org.mockito.stubbing.Answer;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -413,6 +415,311 @@ public class CrashRecoveryTest {
verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
}
+ @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopWithRescuePartyAndRollbackObserver() throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE);
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: SCOPED_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: ALL_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset()
+ throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE);
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserver() throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ String systemUi = "com.android.systemui";
+ VersionedPackage versionedPackageUi = new VersionedPackage(
+ systemUi, VERSION_CODE);
+ RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW,
+ ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi));
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: SCOPED_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: ALL_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_UNTRUSTED_DEFAULTS
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 5);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_UNTRUSTED_CHANGES
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 5);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 6);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_TRUSTED_DEFAULTS
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 6);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 7);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops.
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 7);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 8);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset()
+ throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ String systemUi = "com.android.systemui";
+ VersionedPackage versionedPackageUi = new VersionedPackage(
+ systemUi, VERSION_CODE);
+ RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW,
+ ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi));
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops.
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) {
RollbackPackageHealthObserver rollbackObserver =
spy(new RollbackPackageHealthObserver(mSpyContext, mApexManager));
@@ -424,7 +731,6 @@ public class CrashRecoveryTest {
watchdog.registerHealthObserver(rollbackObserver);
return rollbackObserver;
}
-
RescuePartyObserver setUpRescuePartyObserver(PackageWatchdog watchdog) {
setCrashRecoveryPropRescueBootCount(0);
RescuePartyObserver rescuePartyObserver = spy(RescuePartyObserver.getInstance(mSpyContext));
@@ -686,4 +992,20 @@ public class CrashRecoveryTest {
mTestLooper.moveTimeForward(milliSeconds);
mTestLooper.dispatchAll();
}
+
+ private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
+ List<VersionedPackage> packages, int failureReason) {
+ long triggerFailureCount = watchdog.getTriggerFailureCount();
+ if (failureReason == PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK
+ || failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
+ triggerFailureCount = 1;
+ }
+ for (int i = 0; i < triggerFailureCount; i++) {
+ watchdog.onPackageFailure(packages, failureReason);
+ }
+ mTestLooper.dispatchAll();
+ if (Flags.recoverabilityDetection()) {
+ moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
+ }
+ }
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index a8b383cd4274..ab406ef4632e 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -23,9 +23,12 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -33,6 +36,7 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
@@ -116,6 +120,7 @@ public class PackageWatchdogTest {
private ConnectivityModuleConnector mConnectivityModuleConnector;
@Mock
private PackageManager mMockPackageManager;
+ @Mock Intent mMockIntent;
// Mock only sysprop apis
private PackageWatchdog.BootThreshold mSpyBootThreshold;
@Captor
@@ -1669,6 +1674,19 @@ public class PackageWatchdogTest {
PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS);
}
+ /**
+ * Tests device config changes are propagated correctly.
+ */
+ @Test
+ public void testRegisterShutdownBroadcastReceiver() {
+ PackageWatchdog watchdog = createWatchdog();
+ doReturn(mMockIntent).when(mSpyContext)
+ .registerReceiverForAllUsers(any(), any(), any(), any());
+
+ watchdog.registerShutdownBroadcastReceiver();
+ verify(mSpyContext).registerReceiverForAllUsers(any(), any(), eq(null), eq(null));
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
index 359eb35384c7..5012c235a2a5 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
@@ -84,6 +84,7 @@ public class SurfaceControlViewHostSyncTest extends Activity implements SurfaceH
content.addView(enableSyncButton,
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM));
+ content.setFitsSystemWindows(true);
setContentView(content);
mSv.setZOrderOnTop(false);
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
index 73e01634709e..4119ea2c73c3 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
@@ -37,6 +37,7 @@ public class SurfaceControlViewHostTest extends Activity implements SurfaceHolde
protected void onCreate(Bundle savedInstanceState) {
FrameLayout content = new FrameLayout(this);
+ content.setFitsSystemWindows(true);
super.onCreate(savedInstanceState);
mView = new SurfaceView(this);
content.addView(mView, new FrameLayout.LayoutParams(
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
index ac7dc9e2f31f..528706860b31 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
@@ -88,6 +88,7 @@ public class SurfaceInputTestActivity extends Activity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout content = new LinearLayout(this);
+ content.setFitsSystemWindows(true);
mLocalSurfaceView = new SurfaceView(this);
content.addView(mLocalSurfaceView, new LinearLayout.LayoutParams(
500, 500, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
index 09236ffebdf4..459db8a0a1ac 100644
--- a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
@@ -74,6 +74,9 @@ public class BitmapUploadActivity extends AppCompatActivity {
}
}
+ private ObjectAnimator mColorValueAnimator;
+ private ObjectAnimator mYAnimator;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -81,16 +84,28 @@ public class BitmapUploadActivity extends AppCompatActivity {
// animate color to force bitmap uploads
UploadView uploadView = findViewById(R.id.upload_view);
- ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255);
- colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
- colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
- colorValueAnimator.start();
+ mColorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255);
+ mColorValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
+ mColorValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ mColorValueAnimator.start();
// animate scene root to guarantee there's a minimum amount of GPU rendering work
View uploadRoot = findViewById(R.id.upload_root);
- ObjectAnimator yAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100);
- yAnimator.setRepeatMode(ValueAnimator.REVERSE);
- yAnimator.setRepeatCount(ValueAnimator.INFINITE);
- yAnimator.start();
+ mYAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100);
+ mYAnimator.setRepeatMode(ValueAnimator.REVERSE);
+ mYAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ mYAnimator.start();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mColorValueAnimator != null) {
+ mColorValueAnimator.cancel();
+ }
+
+ if (mYAnimator != null) {
+ mYAnimator.cancel();
+ }
}
}
diff --git a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
index 882163bd6b0e..9d10f76198c3 100644
--- a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java
@@ -66,18 +66,29 @@ public class FullscreenOverdrawActivity extends AppCompatActivity {
return PixelFormat.OPAQUE;
}
}
+
+ private ObjectAnimator mObjectAnimator;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OverdrawDrawable overdraw = new OverdrawDrawable();
getWindow().setBackgroundDrawable(overdraw);
-
setContentView(new View(this));
- ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdraw, "colorValue", 0, 255);
- objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
- objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
- objectAnimator.start();
+ mObjectAnimator = ObjectAnimator.ofInt(overdraw, "colorValue", 0, 255);
+ mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
+ mObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
+
+ mObjectAnimator.start();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mObjectAnimator != null) {
+ mObjectAnimator.cancel();
+ }
}
}
diff --git a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java
index b26a660981da..1b28dc29d6aa 100644
--- a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java
@@ -33,6 +33,7 @@ import com.android.test.uibench.opengl.ImageFlipRenderThread;
public class GlTextureViewActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {
private ImageFlipRenderThread mRenderThread;
private TextureView mTextureView;
+ private ObjectAnimator mAnimator;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -54,17 +55,17 @@ public class GlTextureViewActivity extends AppCompatActivity implements TextureV
int distance = Math.max(mTextureView.getWidth(), mTextureView.getHeight());
mTextureView.setCameraDistance(distance * metrics.density);
- ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
- animator.setRepeatMode(ObjectAnimator.REVERSE);
- animator.setRepeatCount(ObjectAnimator.INFINITE);
- animator.setDuration(4000);
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ mAnimator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
+ mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+ mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+ mAnimator.setDuration(4000);
+ mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTextureView.invalidate();
}
});
- animator.start();
+ mAnimator.start();
}
@Override
@@ -86,4 +87,11 @@ public class GlTextureViewActivity extends AppCompatActivity implements TextureV
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ }
} \ No newline at end of file
diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java
index 76ed1ae4e445..f1e96c80c85a 100644
--- a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java
@@ -51,6 +51,7 @@ public class InvalidateActivity extends AppCompatActivity {
}
private ColorView[][] mColorViews;
+ private ObjectAnimator mAnimator;
@SuppressWarnings("unused")
public void setColorValue(int colorValue) {
@@ -80,9 +81,17 @@ public class InvalidateActivity extends AppCompatActivity {
}
}
- ObjectAnimator animator = ObjectAnimator.ofInt(this, "colorValue", 0, 255);
- animator.setRepeatMode(ValueAnimator.REVERSE);
- animator.setRepeatCount(ValueAnimator.INFINITE);
- animator.start();
+ mAnimator = ObjectAnimator.ofInt(this, "colorValue", 0, 255);
+ mAnimator.setRepeatMode(ValueAnimator.REVERSE);
+ mAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ mAnimator.start();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
}
}
diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java
index 804ced14d522..95635720d4f9 100644
--- a/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java
@@ -33,6 +33,7 @@ public class InvalidateTreeActivity extends AppCompatActivity {
private final ArrayList<LinearLayout> mLayouts = new ArrayList<>();
private int mColorToggle = 0;
+ private ObjectAnimator mAnimator;
private void createQuadTree(LinearLayout parent, int remainingDepth) {
mLayouts.add(parent);
@@ -71,9 +72,17 @@ public class InvalidateTreeActivity extends AppCompatActivity {
createQuadTree(root, 8);
setContentView(root);
- ObjectAnimator animator = ObjectAnimator.ofInt(this, "ignoredValue", 0, 1000);
- animator.setRepeatMode(ValueAnimator.REVERSE);
- animator.setRepeatCount(ValueAnimator.INFINITE);
- animator.start();
+ mAnimator = ObjectAnimator.ofInt(this, "ignoredValue", 0, 1000);
+ mAnimator.setRepeatMode(ValueAnimator.REVERSE);
+ mAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ mAnimator.start();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
}
}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
index 4c531b8f9ee0..a4085e5315a4 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
@@ -23,6 +23,7 @@ android_test {
resource_dirs: ["res"],
libs: ["android.test.runner"],
static_libs: [
+ "androidx.core_core",
"androidx.test.ext.junit",
"androidx.test.rules",
"compatibility-device-util-axt",