summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--[-rwxr-xr-x]tests/AccessoryDisplay/sink/res/drawable-hdpi/ic_app.pngbin3608 -> 3608 bytes
-rw-r--r--[-rwxr-xr-x]tests/AccessoryDisplay/source/res/drawable-hdpi/ic_app.pngbin3608 -> 3608 bytes
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java3
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java1
-rw-r--r--tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java11
-rw-r--r--[-rwxr-xr-x]tests/AttestationVerificationTest/AndroidManifest.xml0
-rw-r--r--tests/AttestationVerificationTest/src/com/android/server/security/AttestationVerificationPeerDeviceVerifierTest.kt131
-rw-r--r--tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml2
-rw-r--r--tests/ChoreographerTests/Android.bp1
-rw-r--r--tests/CompanionDeviceMultiDeviceTests/client/Android.bp3
-rw-r--r--tests/CompanionDeviceMultiDeviceTests/host/Android.bp3
-rw-r--r--tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml4
-rw-r--r--tests/CtsSurfaceControlTestsStaging/Android.bp1
-rw-r--r--tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java2
-rw-r--r--[-rwxr-xr-x]tests/DozeTest/res/drawable-hdpi/ic_app.pngbin3608 -> 3608 bytes
-rw-r--r--tests/FlickerTests/ActivityEmbedding/Android.bp56
-rw-r--r--tests/FlickerTests/ActivityEmbedding/AndroidManifest.xml4
-rw-r--r--tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt4
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt25
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt4
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt5
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt4
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt23
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt35
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt16
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt46
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt53
-rw-r--r--tests/FlickerTests/Android.bp13
-rw-r--r--tests/FlickerTests/AppClose/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/AppLaunch/Android.bp2
-rw-r--r--tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt9
-rw-r--r--tests/FlickerTests/FlickerService/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt2
-rw-r--r--tests/FlickerTests/IME/AndroidTestTemplate.xml5
-rw-r--r--tests/FlickerTests/IME/OWNERS2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt10
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt4
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt4
-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/CloseImeToHomeOnFinishActivityTest.kt2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt4
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt10
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt8
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt4
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt107
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt5
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt6
-rw-r--r--tests/FlickerTests/Notification/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt2
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt2
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt7
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt2
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt9
-rw-r--r--tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt4
-rw-r--r--tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt4
-rw-r--r--tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt4
-rw-r--r--tests/FlickerTests/README.md75
-rw-r--r--tests/FlickerTests/Rotation/AndroidTestTemplate.xml3
-rw-r--r--tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/OpenShowWhenLockedSeamlessAppRotationTest.kt125
-rw-r--r--tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt2
-rw-r--r--tests/FlickerTests/libs/window-extensions-release.aarbin21364 -> 0 bytes
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt5
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/OWNERS2
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt168
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt8
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt8
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt27
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml14
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml107
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml22
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java27
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java4
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java11
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java11
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java6
-rw-r--r--tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java9
-rw-r--r--tests/HugeBackup/AndroidManifest.xml2
-rw-r--r--tests/Input/Android.bp9
-rw-r--r--tests/Input/AndroidManifest.xml2
-rw-r--r--tests/Input/AndroidTest.xml6
-rw-r--r--tests/Input/assets/testPointerFillStyle.pngbin0 -> 569 bytes
-rw-r--r--tests/Input/assets/testPointerScale.pngbin0 -> 949 bytes
-rw-r--r--tests/Input/src/com/android/server/input/InputManagerServiceTests.kt396
-rw-r--r--tests/Input/src/com/android/server/input/InputShellCommandTest.java8
-rw-r--r--tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt1073
-rw-r--r--tests/Input/src/com/android/test/input/AnrTest.kt39
-rw-r--r--tests/Input/src/com/android/test/input/InputDeviceTest.java5
-rw-r--r--tests/Input/src/com/android/test/input/PointerIconLoadingTest.kt136
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java1
-rw-r--r--tests/InputScreenshotTest/assets/phone/light_landscape_layout-preview.pngbin77171 -> 88200 bytes
-rw-r--r--tests/InputScreenshotTest/assets/phone/light_portrait_layout-preview.pngbin70807 -> 80959 bytes
-rw-r--r--tests/InputScreenshotTest/assets/tablet/dark_portrait_layout-preview.pngbin45677 -> 48907 bytes
-rw-r--r--tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenPathManager.kt (renamed from tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenImagePathManager.kt)35
-rw-r--r--tests/InputScreenshotTest/src/android/input/screenshot/InputScreenshotTestRule.kt2
-rw-r--r--tests/Internal/TEST_MAPPING7
-rw-r--r--tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java7
-rw-r--r--tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java152
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java5
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java (renamed from tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java)6
-rw-r--r--tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt81
-rw-r--r--[-rwxr-xr-x]tests/OdmApps/app/AndroidManifest.xml0
-rw-r--r--[-rwxr-xr-x]tests/OdmApps/priv-app/AndroidManifest.xml0
-rw-r--r--[-rwxr-xr-x]tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.pngbin3608 -> 3608 bytes
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/EmbeddedWindowService.java2
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java4
-rw-r--r--tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java39
-rw-r--r--tests/TouchLatency/Android.bp1
-rw-r--r--tests/TouchLatency/app/src/main/res/values/styles.xml1
-rw-r--r--tests/UsbManagerTests/Android.bp3
-rw-r--r--tests/UsbManagerTests/src/android/hardware/usb/DeviceFilterTest.java248
-rw-r--r--tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java165
-rw-r--r--tests/UsbTests/Android.bp2
-rw-r--r--tests/UsbTests/TEST_MAPPING7
-rw-r--r--tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java178
-rw-r--r--tests/WindowInsetsTests/AndroidManifest.xml7
-rw-r--r--tests/WindowInsetsTests/res/layout/controller_activity.xml184
-rw-r--r--tests/WindowInsetsTests/res/layout/main_activity.xml38
-rw-r--r--tests/WindowInsetsTests/res/values-night/styles.xml43
-rw-r--r--tests/WindowInsetsTests/res/values/strings.xml10
-rw-r--r--tests/WindowInsetsTests/res/values/styles.xml13
-rw-r--r--tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java73
-rw-r--r--tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java18
-rw-r--r--tests/graphics/SilkFX/AndroidManifest.xml5
-rw-r--r--tests/graphics/SilkFX/res/values/style.xml5
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp14
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml11
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml23
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml27
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java90
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java97
-rw-r--r--tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java29
-rw-r--r--tests/testables/src/android/testing/TestableResources.java11
-rw-r--r--tests/testables/src/android/testing/ViewUtils.java15
-rw-r--r--tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java1
141 files changed, 3091 insertions, 1580 deletions
diff --git a/tests/AccessoryDisplay/sink/res/drawable-hdpi/ic_app.png b/tests/AccessoryDisplay/sink/res/drawable-hdpi/ic_app.png
index 66a198496cfb..66a198496cfb 100755..100644
--- a/tests/AccessoryDisplay/sink/res/drawable-hdpi/ic_app.png
+++ b/tests/AccessoryDisplay/sink/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/AccessoryDisplay/source/res/drawable-hdpi/ic_app.png b/tests/AccessoryDisplay/source/res/drawable-hdpi/ic_app.png
index 66a198496cfb..66a198496cfb 100755..100644
--- a/tests/AccessoryDisplay/source/res/drawable-hdpi/ic_app.png
+++ b/tests/AccessoryDisplay/source/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
index 5d6a4a3541c1..1c78e5bcb536 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
@@ -90,6 +90,9 @@ public final class OomAdjPerfTest extends BasePerfTest {
TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE1_NAME);
TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE2_NAME);
TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE3_NAME);
+
+ Utils.wakeUp();
+ Utils.runShellCommand("wm dismiss-keyguard");
}
@After
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
index d7f4d9de6735..705fe296ae17 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
@@ -175,6 +175,7 @@ public class TargetPackageUtils {
context.startService(intent);
Assert.assertTrue("Timeout when waiting for starting package " + pkgName,
pair.second.await(AWAIT_SERVICE_CONNECT_MS, TimeUnit.MILLISECONDS));
+ Utils.runShellCommand("am unfreeze --sticky " + pkgName);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
index 9bd94f2a9a1e..421ae57deae3 100644
--- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
@@ -66,4 +66,15 @@ public class Utils {
ResultReceiver resultReceiver = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER);
resultReceiver.send(0, null);
}
+
+ /**
+ * Wake up the device.
+ */
+ public static void wakeUp() {
+ try {
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).wakeUp();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/tests/AttestationVerificationTest/AndroidManifest.xml b/tests/AttestationVerificationTest/AndroidManifest.xml
index 37321ad80b0f..37321ad80b0f 100755..100644
--- a/tests/AttestationVerificationTest/AndroidManifest.xml
+++ b/tests/AttestationVerificationTest/AndroidManifest.xml
diff --git a/tests/AttestationVerificationTest/src/com/android/server/security/AttestationVerificationPeerDeviceVerifierTest.kt b/tests/AttestationVerificationTest/src/com/android/server/security/AttestationVerificationPeerDeviceVerifierTest.kt
index dfbbda6c6f5e..afb3593e3e98 100644
--- a/tests/AttestationVerificationTest/src/com/android/server/security/AttestationVerificationPeerDeviceVerifierTest.kt
+++ b/tests/AttestationVerificationTest/src/com/android/server/security/AttestationVerificationPeerDeviceVerifierTest.kt
@@ -9,21 +9,28 @@ import android.security.attestationverification.AttestationVerificationManager.R
import android.security.attestationverification.AttestationVerificationManager.RESULT_SUCCESS
import android.security.attestationverification.AttestationVerificationManager.TYPE_CHALLENGE
import android.security.attestationverification.AttestationVerificationManager.TYPE_PUBLIC_KEY
+import android.util.IndentingPrintWriter
+import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.security.AttestationVerificationManagerService.DumpLogger
import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
import java.io.ByteArrayOutputStream
+import java.io.PrintWriter
+import java.io.StringWriter
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.security.cert.TrustAnchor
import java.security.cert.X509Certificate
import java.time.LocalDate
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
/** Test for Peer Device attestation verifier. */
@SmallTest
@@ -31,6 +38,7 @@ import java.time.LocalDate
class AttestationVerificationPeerDeviceVerifierTest {
private val certificateFactory = CertificateFactory.getInstance("X.509")
@Mock private lateinit var context: Context
+ private val dumpLogger = DumpLogger()
private lateinit var trustAnchors: HashSet<TrustAnchor>
@Before
@@ -44,37 +52,50 @@ class AttestationVerificationPeerDeviceVerifierTest {
}
}
+ @After
+ fun dumpAndLog() {
+ val dump = dumpLogger.getDump()
+ Log.d(TAG, "$dump")
+ }
+
@Test
fun verifyAttestation_returnsSuccessTypeChallenge() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 2, 1),
- LocalDate.of(2021, 8, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 2, 1),
+ LocalDate.of(2021, 8, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_SUCCESS)
}
@Test
fun verifyAttestation_returnsSuccessLocalPatchOlderThanOneYear() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 2, 1),
- LocalDate.of(2021, 1, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 2, 1),
+ LocalDate.of(2021, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_SUCCESS)
}
@Test
fun verifyAttestation_returnsSuccessTypePublicKey() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 2, 1),
- LocalDate.of(2021, 8, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 2, 1),
+ LocalDate.of(2021, 8, 1)
+ )
val leafCert =
(TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToCerts() as List)[0]
@@ -84,61 +105,75 @@ class AttestationVerificationPeerDeviceVerifierTest {
val result = verifier.verifyAttestation(
TYPE_PUBLIC_KEY, pkRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_SUCCESS)
}
@Test
fun verifyAttestation_returnsSuccessOwnedBySystem() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 2, 1),
- LocalDate.of(2021, 1, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 2, 1),
+ LocalDate.of(2021, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "activeUnlockValid".encodeToByteArray())
challengeRequirements.putBoolean("android.key_owned_by_system", true)
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_OWNED_BY_SYSTEM_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_OWNED_BY_SYSTEM_FILENAME.fromPEMFileToByteArray()
+ )
+
assertThat(result).isEqualTo(RESULT_SUCCESS)
}
@Test
fun verifyAttestation_returnsFailureOwnedBySystem() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 2, 1),
- LocalDate.of(2021, 1, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 2, 1),
+ LocalDate.of(2021, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
challengeRequirements.putBoolean("android.key_owned_by_system", true)
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_FAILURE)
}
@Test
fun verifyAttestation_returnsFailurePatchDateNotWithinOneYearLocalPatch() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2023, 3, 1),
- LocalDate.of(2023, 2, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2023, 3, 1),
+ LocalDate.of(2023, 2, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_FAILURE)
}
@Test
fun verifyAttestation_returnsFailureTrustedAnchorEmpty() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, HashSet(), false, LocalDate.of(2022, 1, 1),
- LocalDate.of(2022, 1, 1))
+ context, dumpLogger, HashSet(), false, LocalDate.of(2022, 1, 1),
+ LocalDate.of(2022, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_FAILURE)
}
@@ -151,32 +186,39 @@ class AttestationVerificationPeerDeviceVerifierTest {
}
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, badTrustAnchors, false, LocalDate.of(2022, 1, 1),
- LocalDate.of(2022, 1, 1))
+ context, dumpLogger, badTrustAnchors, false, LocalDate.of(2022, 1, 1),
+ LocalDate.of(2022, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_FAILURE)
}
fun verifyAttestation_returnsFailureChallenge() {
val verifier = AttestationVerificationPeerDeviceVerifier(
- context, trustAnchors, false, LocalDate.of(2022, 1, 1),
- LocalDate.of(2022, 1, 1))
+ context, dumpLogger, trustAnchors, false, LocalDate.of(2022, 1, 1),
+ LocalDate.of(2022, 1, 1)
+ )
val challengeRequirements = Bundle()
challengeRequirements.putByteArray(PARAM_CHALLENGE, "wrong".encodeToByteArray())
- val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
- TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
+ val result = verifier.verifyAttestation(
+ TYPE_CHALLENGE, challengeRequirements,
+ TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray()
+ )
assertThat(result).isEqualTo(RESULT_FAILURE)
}
private fun String.fromPEMFileToCerts(): Collection<Certificate> {
return certificateFactory.generateCertificates(
InstrumentationRegistry.getInstrumentation().getContext().getResources().getAssets()
- .open(this))
+ .open(this)
+ )
}
private fun String.fromPEMFileToByteArray(): ByteArray {
@@ -188,6 +230,12 @@ class AttestationVerificationPeerDeviceVerifierTest {
return bos.toByteArray()
}
+ private fun DumpLogger.getDump(): String {
+ val sw = StringWriter()
+ this.dumpTo(IndentingPrintWriter(PrintWriter(sw), " "))
+ return sw.toString()
+ }
+
class TestActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -195,6 +243,7 @@ class AttestationVerificationPeerDeviceVerifierTest {
}
companion object {
+ private const val TAG = "AVFTest"
private const val TEST_ROOT_CERT_FILENAME = "test_root_certs.pem"
private const val TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME =
"test_attestation_with_root_certs.pem"
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml
index 27a8b2a0611b..3363af477dcb 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml
@@ -18,7 +18,7 @@
android:versionCode="1"
android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="17" />
+ <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17" />
<instrumentation
android:name="android.test.InstrumentationTestRunner"
diff --git a/tests/ChoreographerTests/Android.bp b/tests/ChoreographerTests/Android.bp
index 5d49120ee702..3f48d70d659f 100644
--- a/tests/ChoreographerTests/Android.bp
+++ b/tests/ChoreographerTests/Android.bp
@@ -19,6 +19,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_android_core_graphics_stack",
}
android_test {
diff --git a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
index 1e68c9dd459f..9994826d061a 100644
--- a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
+++ b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
@@ -19,10 +19,11 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_framework_cdm",
}
android_test {
- name: "cdm_snippet",
+ name: "cdm_snippet_legacy",
srcs: ["src/**/*.kt"],
manifest: "AndroidManifest.xml",
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/Android.bp b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
index 03335c7cd576..37cb8500fbab 100644
--- a/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
+++ b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
@@ -19,6 +19,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_framework_cdm",
}
python_test_host {
@@ -36,7 +37,7 @@ python_test_host {
tags: ["mobly"],
},
data: [
- ":cdm_snippet",
+ ":cdm_snippet_legacy",
],
version: {
py2: {
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
index 9d1813ff79bc..7c7ef6345a41 100644
--- a/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
+++ b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
@@ -24,12 +24,12 @@
<device name="device1">
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="test-file-name" value="cdm_snippet.apk" />
+ <option name="test-file-name" value="cdm_snippet_legacy.apk" />
</target_preparer>
</device>
<device name="device2">
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="test-file-name" value="cdm_snippet.apk" />
+ <option name="test-file-name" value="cdm_snippet_legacy.apk" />
</target_preparer>
</device>
diff --git a/tests/CtsSurfaceControlTestsStaging/Android.bp b/tests/CtsSurfaceControlTestsStaging/Android.bp
index 96e4a9ea4300..1038c9e93931 100644
--- a/tests/CtsSurfaceControlTestsStaging/Android.bp
+++ b/tests/CtsSurfaceControlTestsStaging/Android.bp
@@ -19,6 +19,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_android_core_graphics_stack",
}
android_test {
diff --git a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
index caaee634c57a..4d4827676c74 100644
--- a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
+++ b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
@@ -30,10 +30,12 @@ import com.android.compatibility.common.util.DisplayUtil;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Ignore // b/330376055: Write tests for functionality for both dVRR and MRR devices.
@RunWith(AndroidJUnit4.class)
public class SurfaceControlTest {
private static final String TAG = "SurfaceControlTest";
diff --git a/tests/DozeTest/res/drawable-hdpi/ic_app.png b/tests/DozeTest/res/drawable-hdpi/ic_app.png
index 66a198496cfb..66a198496cfb 100755..100644
--- a/tests/DozeTest/res/drawable-hdpi/ic_app.png
+++ b/tests/DozeTest/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/FlickerTests/ActivityEmbedding/Android.bp b/tests/FlickerTests/ActivityEmbedding/Android.bp
index 2cdf54248ebc..e09fbf6adc02 100644
--- a/tests/FlickerTests/ActivityEmbedding/Android.bp
+++ b/tests/FlickerTests/ActivityEmbedding/Android.bp
@@ -20,17 +20,65 @@ package {
// all of the 'license_kinds' from "frameworks_base_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
+ default_team: "trendy_team_windowing_sdk",
default_applicable_licenses: ["frameworks_base_license"],
}
-android_test {
- name: "FlickerTestsOther",
+filegroup {
+ name: "FlickerTestsOtherCommon-src",
+ srcs: ["src/**/ActivityEmbeddingTestBase.kt"],
+}
+
+filegroup {
+ name: "FlickerTestsOtherOpen-src",
+ srcs: ["src/**/open/*"],
+}
+
+filegroup {
+ name: "FlickerTestsOtherRotation-src",
+ srcs: ["src/**/rotation/*"],
+}
+
+java_library {
+ name: "FlickerTestsOtherCommon",
+ defaults: ["FlickerTestsDefault"],
+ srcs: [":FlickerTestsOtherCommon-src"],
+ static_libs: ["FlickerTestsBase"],
+}
+
+java_defaults {
+ name: "FlickerTestsOtherDefaults",
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"],
+ static_libs: [
+ "FlickerTestsBase",
+ "FlickerTestsOtherCommon",
+ ],
data: ["trace_config/*"],
}
+
+android_test {
+ name: "FlickerTestsOtherOpen",
+ defaults: ["FlickerTestsOtherDefaults"],
+ srcs: [":FlickerTestsOtherOpen-src"],
+}
+
+android_test {
+ name: "FlickerTestsOtherRotation",
+ defaults: ["FlickerTestsOtherDefaults"],
+ srcs: [":FlickerTestsOtherRotation-src"],
+}
+
+android_test {
+ name: "FlickerTestsOther",
+ defaults: ["FlickerTestsOtherDefaults"],
+ srcs: ["src/**/*"],
+ exclude_srcs: [
+ ":FlickerTestsOtherOpen-src",
+ ":FlickerTestsOtherRotation-src",
+ ":FlickerTestsOtherCommon-src",
+ ],
+}
diff --git a/tests/FlickerTests/ActivityEmbedding/AndroidManifest.xml b/tests/FlickerTests/ActivityEmbedding/AndroidManifest.xml
index 6f8f008cf85b..955b43a32827 100644
--- a/tests/FlickerTests/ActivityEmbedding/AndroidManifest.xml
+++ b/tests/FlickerTests/ActivityEmbedding/AndroidManifest.xml
@@ -19,7 +19,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.server.wm.flicker">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="35"/>
<!-- Read and write traces from external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -46,6 +46,8 @@
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<!-- Allow the test to connect to perfetto trace processor -->
<uses-permission android:name="android.permission.INTERNET"/>
+ <!-- Allow to query for the Launcher TestInfo on SDK 30+ -->
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<!-- Allow the test to write directly to /sdcard/ and connect to trace processor -->
<application android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config"
diff --git a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
index 439cf136c220..82de070921f0 100644
--- a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
index 46ad77e1eff9..519b4296d93a 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.close
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -122,7 +122,7 @@ class CloseSecondaryActivityInSplitTest(flicker: LegacyFlickerTest) :
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
*
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
index af4f7a721464..4cd6d15b2983 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.layoutchange
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -114,11 +114,11 @@ class HorizontalSplitChangeRatioTest(flicker: LegacyFlickerTest) :
// Compare dimensions of two splits, given we're using default split attributes,
// both activities take up the same visible size on the display.
check { "height" }
- .that(topLayerRegion.region.height)
- .isEqual(bottomLayerRegion.region.height)
+ .that(topLayerRegion.region.bounds.height())
+ .isEqual(bottomLayerRegion.region.bounds.height())
check { "width" }
- .that(topLayerRegion.region.width)
- .isEqual(bottomLayerRegion.region.width)
+ .that(topLayerRegion.region.bounds.width())
+ .isEqual(bottomLayerRegion.region.bounds.width())
topLayerRegion.notOverlaps(bottomLayerRegion.region)
// Layers of two activities sum to be fullscreen size on display.
topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
@@ -132,14 +132,17 @@ class HorizontalSplitChangeRatioTest(flicker: LegacyFlickerTest) :
// Compare dimensions of two splits, given we're using default split attributes,
// both activities take up the same visible size on the display.
check { "height" }
- .that(topLayerRegion.region.height)
- .isLower(bottomLayerRegion.region.height)
+ .that(topLayerRegion.region.bounds.height())
+ .isLower(bottomLayerRegion.region.bounds.height())
check { "height" }
- .that(topLayerRegion.region.height / 0.3f - bottomLayerRegion.region.height / 0.7f)
+ .that(
+ topLayerRegion.region.bounds.height() / 0.3f -
+ bottomLayerRegion.region.bounds.height() / 0.7f
+ )
.isLower(0.1f)
check { "width" }
- .that(topLayerRegion.region.width)
- .isEqual(bottomLayerRegion.region.width)
+ .that(topLayerRegion.region.bounds.width())
+ .isEqual(bottomLayerRegion.region.bounds.width())
topLayerRegion.notOverlaps(bottomLayerRegion.region)
// Layers of two activities sum to be fullscreen size on display.
topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
@@ -148,7 +151,7 @@ class HorizontalSplitChangeRatioTest(flicker: LegacyFlickerTest) :
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
index e511b727d57f..5df8b57294f0 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.open
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -132,7 +132,7 @@ class MainActivityStartsSecondaryWithAlwaysExpandTest(flicker: LegacyFlickerTest
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt
index 000b457026be..6327d92ed570 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -90,7 +90,10 @@ class OpenActivityEmbeddingSecondaryToSplitTest(flicker: LegacyFlickerTest) :
flicker.assertWm {
notContains(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
.then()
- .isAppWindowInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .isAppWindowInvisible(
+ ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT,
+ isOptional = true
+ )
.then()
.isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
}
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
index 4352177a8984..78004ccc3f97 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.open
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -143,7 +143,7 @@ class OpenThirdActivityOverSplitTest(flicker: LegacyFlickerTest) :
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
*
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
index 62cf6cd528e9..67825d2df361 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.open
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -43,6 +43,7 @@ import org.junit.runners.Parameterized
*
* To run this test: `atest FlickerTestsOther:OpenTrampolineActivityTest`
*/
+@FlakyTest(bugId = 341209752)
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -156,11 +157,11 @@ class OpenTrampolineActivityTest(flicker: LegacyFlickerTest) : ActivityEmbedding
it.timestamp
)
check { "height" }
- .that(mainActivityRegion.region.height)
- .isEqual(secondaryActivityRegion.region.height)
+ .that(mainActivityRegion.region.bounds.height())
+ .isEqual(secondaryActivityRegion.region.bounds.height())
check { "width" }
- .that(mainActivityRegion.region.width)
- .isEqual(secondaryActivityRegion.region.width)
+ .that(mainActivityRegion.region.bounds.width())
+ .isEqual(secondaryActivityRegion.region.bounds.width())
mainActivityRegion
.plus(secondaryActivityRegion.region)
.coversExactly(startDisplayBounds)
@@ -168,7 +169,6 @@ class OpenTrampolineActivityTest(flicker: LegacyFlickerTest) : ActivityEmbedding
}
}
- @FlakyTest(bugId = 290736037)
/** Main activity should go from fullscreen to being a split with secondary activity. */
@Test
fun mainActivityLayerGoesFromFullscreenToSplit() {
@@ -192,18 +192,17 @@ class OpenTrampolineActivityTest(flicker: LegacyFlickerTest) : ActivityEmbedding
// Compare dimensions of two splits, given we're using default split attributes,
// both activities take up the same visible size on the display.
check { "height" }
- .that(leftLayerRegion.region.height)
- .isEqual(rightLayerRegion.region.height)
+ .that(leftLayerRegion.region.bounds.height())
+ .isEqual(rightLayerRegion.region.bounds.height())
check { "width" }
- .that(leftLayerRegion.region.width)
- .isEqual(rightLayerRegion.region.width)
+ .that(leftLayerRegion.region.bounds.width())
+ .isEqual(rightLayerRegion.region.bounds.width())
leftLayerRegion.notOverlaps(rightLayerRegion.region)
// Layers of two activities sum to be fullscreen size on display.
leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds)
}
}
- @FlakyTest(bugId = 288591571)
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
super.visibleLayersShownMoreThanOneConsecutiveEntry()
@@ -211,7 +210,7 @@ class OpenTrampolineActivityTest(flicker: LegacyFlickerTest) : ActivityEmbedding
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
index aa8b4cebe91d..eed9225d3da0 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding.pip
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -79,11 +79,11 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
// Compare dimensions of two splits, given we're using default split attributes,
// both activities take up the same visible size on the display.
check { "height" }
- .that(leftLayerRegion.region.height)
- .isEqual(rightLayerRegion.region.height)
+ .that(leftLayerRegion.region.bounds.height())
+ .isEqual(rightLayerRegion.region.bounds.height())
check { "width" }
- .that(leftLayerRegion.region.width)
- .isEqual(rightLayerRegion.region.width)
+ .that(leftLayerRegion.region.bounds.width())
+ .isEqual(rightLayerRegion.region.bounds.width())
leftLayerRegion.notOverlaps(rightLayerRegion.region)
leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds)
}
@@ -136,9 +136,11 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
val pipWindowRegion =
visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
check { "height" }
- .that(pipWindowRegion.region.height)
- .isLower(startDisplayBounds.height / 2)
- check { "width" }.that(pipWindowRegion.region.width).isLower(startDisplayBounds.width)
+ .that(pipWindowRegion.region.bounds.height())
+ .isLower(startDisplayBounds.height() / 2)
+ check { "width" }
+ .that(pipWindowRegion.region.bounds.width())
+ .isLower(startDisplayBounds.width())
}
}
@@ -151,7 +153,7 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
ComponentNameMatcher.PIP_CONTENT_OVERLAY.layerMatchesAnyOf(it) && it.isVisible
}
pipLayerList.zipWithNext { previous, current ->
- if (startDisplayBounds.width > startDisplayBounds.height) {
+ if (startDisplayBounds.width() > startDisplayBounds.height()) {
// Only verify when the display is landscape, because otherwise the final pip
// window can be to the left of the original secondary activity.
current.screenBounds.isToTheRightBottom(previous.screenBounds.region, 3)
@@ -162,8 +164,12 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
}
flicker.assertLayersEnd {
val pipRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
- check { "height" }.that(pipRegion.region.height).isLower(startDisplayBounds.height / 2)
- check { "width" }.that(pipRegion.region.width).isLower(startDisplayBounds.width)
+ check { "height" }
+ .that(pipRegion.region.bounds.height())
+ .isLower(startDisplayBounds.height() / 2)
+ check { "width" }
+ .that(pipRegion.region.bounds.width())
+ .isLower(startDisplayBounds.width())
}
}
@@ -175,7 +181,7 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
invoke("secondaryLayerNotJumpToLeft") {
val secondaryVisibleRegion =
it.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
- if (secondaryVisibleRegion.region.isNotEmpty) {
+ if (!secondaryVisibleRegion.region.isEmpty) {
check { "left" }.that(secondaryVisibleRegion.region.bounds.left).isGreater(0)
}
}
@@ -199,7 +205,8 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
it.visibleRegion(ComponentNameMatcher.PIP_CONTENT_OVERLAY)
val secondaryVisibleRegion =
it.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
- overlayVisibleRegion.coversExactly(secondaryVisibleRegion.region)
+ // TODO(b/340992001): replace coverAtLeast with coverExactly
+ overlayVisibleRegion.coversAtLeast(secondaryVisibleRegion.region)
}
.then()
.isInvisible(ComponentNameMatcher.PIP_CONTENT_OVERLAY)
@@ -222,7 +229,7 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) :
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
*
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
index 3d834c16163f..f5e6c7854eba 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
@@ -85,11 +85,11 @@ open class RotateSplitNoChangeTest(flicker: LegacyFlickerTest) : RotationTransit
// Compare dimensions of two splits, given we're using default split attributes,
// both activities take up the same visible size on the display.
check { "height" }
- .that(leftLayerRegion.region.height)
- .isEqual(rightLayerRegion.region.height)
+ .that(leftLayerRegion.region.bounds.height())
+ .isEqual(rightLayerRegion.region.bounds.height())
check { "width" }
- .that(leftLayerRegion.region.width)
- .isEqual(rightLayerRegion.region.width)
+ .that(leftLayerRegion.region.bounds.width())
+ .isEqual(rightLayerRegion.region.bounds.width())
leftLayerRegion.notOverlaps(rightLayerRegion.region)
// Layers of two activities sum to be fullscreen size on display.
leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
@@ -108,11 +108,11 @@ open class RotateSplitNoChangeTest(flicker: LegacyFlickerTest) : RotationTransit
val rightLayerRegion =
this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
check { "height" }
- .that(leftLayerRegion.region.height)
- .isEqual(rightLayerRegion.region.height)
+ .that(leftLayerRegion.region.bounds.height())
+ .isEqual(rightLayerRegion.region.bounds.height())
check { "width" }
- .that(leftLayerRegion.region.width)
- .isEqual(rightLayerRegion.region.width)
+ .that(leftLayerRegion.region.bounds.width())
+ .isEqual(rightLayerRegion.region.bounds.width())
leftLayerRegion.notOverlaps(rightLayerRegion.region)
leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
}
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 511c94849681..ee2c05e82d51 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
@@ -16,9 +16,13 @@
package com.android.server.wm.flicker.activityembedding.rotation
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
+import android.tools.Position
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.Condition
+import android.tools.traces.DeviceStateDump
import android.tools.traces.component.ComponentNameMatcher
import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
import com.android.server.wm.flicker.helpers.setRotation
@@ -30,7 +34,14 @@ abstract class RotationTransition(flicker: LegacyFlickerTest) : ActivityEmbeddin
override val transition: FlickerBuilder.() -> Unit = {
setup { this.setRotation(flicker.scenario.startRotation) }
teardown { testApp.exit(wmHelper) }
- transitions { this.setRotation(flicker.scenario.endRotation) }
+ transitions {
+ this.setRotation(flicker.scenario.endRotation)
+ if (!flicker.scenario.isTablet) {
+ wmHelper.StateSyncBuilder()
+ .add(navBarInPosition(flicker.scenario.isGesturalNavigation))
+ .waitForAndVerify()
+ }
+ }
}
/** {@inheritDoc} */
@@ -76,4 +87,37 @@ abstract class RotationTransition(flicker: LegacyFlickerTest) : ActivityEmbeddin
appLayerRotates_StartingPos()
appLayerRotates_EndingPos()
}
+
+ private fun navBarInPosition(isGesturalNavigation: Boolean): Condition<DeviceStateDump> {
+ return Condition("navBarPosition") { dump ->
+ val display =
+ dump.layerState.displays.filterNot { it.isOff }.minByOrNull { it.id }
+ ?: error("There is no display!")
+ val displayArea = display.layerStackSpace
+ val navBarPosition = display.navBarPosition(isGesturalNavigation)
+ val navBarRegion = dump.layerState
+ .getLayerWithBuffer(ComponentNameMatcher.NAV_BAR)
+ ?.visibleRegion?.bounds ?: Rect()
+
+ when (navBarPosition) {
+ Position.TOP ->
+ navBarRegion.top == displayArea.top &&
+ navBarRegion.left == displayArea.left &&
+ navBarRegion.right == displayArea.right
+ Position.BOTTOM ->
+ navBarRegion.bottom == displayArea.bottom &&
+ navBarRegion.left == displayArea.left &&
+ navBarRegion.right == displayArea.right
+ Position.LEFT ->
+ navBarRegion.left == displayArea.left &&
+ navBarRegion.top == displayArea.top &&
+ navBarRegion.bottom == displayArea.bottom
+ Position.RIGHT ->
+ navBarRegion.right == displayArea.right &&
+ navBarRegion.top == displayArea.top &&
+ navBarRegion.bottom == displayArea.bottom
+ else -> error("Unknown position $navBarPosition")
+ }
+ }
+ }
}
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
index 7298e5f71b05..379b45cdf08e 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
@@ -16,9 +16,9 @@
package com.android.server.wm.flicker.activityembedding.splitscreen
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -32,6 +32,7 @@ import com.android.wm.shell.flicker.utils.SplitScreenUtils
import com.android.wm.shell.flicker.utils.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.utils.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.utils.splitScreenDividerBecomesVisible
+import kotlin.math.abs
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -59,14 +60,16 @@ class EnterSystemSplitTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBa
testApp.launchViaIntent(wmHelper)
testApp.launchSecondaryActivity(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
- tapl.goHome()
- wmHelper
- .StateSyncBuilder()
- .withAppTransitionIdle()
- .withHomeActivityVisible()
- .waitForAndVerify()
startDisplayBounds =
wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found")
+
+ // Record the displayBounds before `goHome()` in case the launcher is fixed-portrait.
+ tapl.goHome()
+ wmHelper
+ .StateSyncBuilder()
+ .withAppTransitionIdle()
+ .withHomeActivityVisible()
+ .waitForAndVerify()
}
transitions {
SplitScreenUtils.enterSplit(
@@ -135,19 +138,13 @@ class EnterSystemSplitTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBa
.plus(systemDivider.region)
.coversExactly(startDisplayBounds)
check { "ActivityEmbeddingSplitHeight" }
- .that(leftAELayerRegion.region.height)
- .isEqual(rightAELayerRegion.region.height)
- check { "SystemSplitHeight" }
- .that(rightAELayerRegion.region.height)
- .isEqual(secondaryAppLayerRegion.region.height)
- // TODO(b/292283182): Remove this special case handling.
+ .that(leftAELayerRegion.region.bounds.height())
+ .isEqual(rightAELayerRegion.region.bounds.height())
check { "ActivityEmbeddingSplitWidth" }
- .that(Math.abs(leftAELayerRegion.region.width - rightAELayerRegion.region.width))
- .isLower(2)
- check { "SystemSplitWidth" }
.that(
- Math.abs(
- secondaryAppLayerRegion.region.width - 2 * rightAELayerRegion.region.width
+ abs(
+ leftAELayerRegion.region.bounds.width() -
+ rightAELayerRegion.region.bounds.width()
)
)
.isLower(2)
@@ -163,22 +160,14 @@ class EnterSystemSplitTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBa
visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
val rightAEWindowRegion =
visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
- // There's no window for the divider bar.
- val secondaryAppLayerRegion =
- visibleRegion(ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent())
check { "ActivityEmbeddingSplitHeight" }
- .that(leftAEWindowRegion.region.height)
- .isEqual(rightAEWindowRegion.region.height)
- check { "SystemSplitHeight" }
- .that(rightAEWindowRegion.region.height)
- .isEqual(secondaryAppLayerRegion.region.height)
+ .that(leftAEWindowRegion.region.bounds.height())
+ .isEqual(rightAEWindowRegion.region.bounds.height())
check { "ActivityEmbeddingSplitWidth" }
- .that(Math.abs(leftAEWindowRegion.region.width - rightAEWindowRegion.region.width))
- .isLower(2)
- check { "SystemSplitWidth" }
.that(
- Math.abs(
- secondaryAppLayerRegion.region.width - 2 * rightAEWindowRegion.region.width
+ abs(
+ leftAEWindowRegion.region.bounds.width() -
+ rightAEWindowRegion.region.bounds.width()
)
)
.isLower(2)
@@ -190,7 +179,7 @@ class EnterSystemSplitTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBa
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
/**
* Creates the test configurations.
*
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 1d71f95ef64f..d658d5991a57 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -63,17 +63,20 @@ java_library {
],
}
-android_library_import {
- name: "wm-flicker-window-extensions_nodeps",
- aars: ["libs/window-extensions-release.aar"],
+java_library {
+ name: "wm-flicker-window-extensions",
sdk_version: "current",
+ static_libs: [
+ "androidx.window.extensions_extensions-nodeps",
+ ],
+ installable: false,
}
java_library {
- name: "wm-flicker-window-extensions",
+ name: "wm-flicker-window-extensions-core",
sdk_version: "current",
static_libs: [
- "wm-flicker-window-extensions_nodeps",
+ "androidx.window.extensions.core_core-nodeps",
],
installable: false,
}
diff --git a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
index 4b6224efaf60..4ffb11ab92ae 100644
--- a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/AppLaunch/Android.bp b/tests/FlickerTests/AppLaunch/Android.bp
index f5e962124b37..72a90650927f 100644
--- a/tests/FlickerTests/AppLaunch/Android.bp
+++ b/tests/FlickerTests/AppLaunch/Android.bp
@@ -30,7 +30,7 @@ filegroup {
filegroup {
name: "FlickerTestsAppLaunch1-src",
- srcs: ["src/**/OpenApp*"],
+ srcs: ["src/**/OpenAppFrom*"],
}
java_library {
diff --git a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
index 583bcb74ffc2..0fa4d07b2eca 100644
--- a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index b1d78cbc034e..a71599d25632 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -19,8 +19,9 @@ package com.android.server.wm.flicker.launch
import android.app.Instrumentation
import android.app.WallpaperManager
import android.content.res.Resources
+import android.graphics.Rect
+import android.graphics.Region
import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Region
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -213,6 +214,12 @@ class TaskTransitionTest(flicker: LegacyFlickerTest) : BaseTest(flicker) {
private fun LayersTraceSubject.visibleRegionCovers(
component: IComponentMatcher,
+ expectedArea: Rect,
+ isOptional: Boolean = true
+ ): LayersTraceSubject = visibleRegionCovers(component, Region(expectedArea), isOptional)
+
+ private fun LayersTraceSubject.visibleRegionCovers(
+ component: IComponentMatcher,
expectedArea: Region,
isOptional: Boolean = true
): LayersTraceSubject =
diff --git a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
index d6ae2b3a5d94..4d9fefbc7d88 100644
--- a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt
index 8a241de32a2b..209a14b3657d 100644
--- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt
+++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt
@@ -17,6 +17,7 @@
package com.android.server.wm.flicker.service
import android.app.Instrumentation
+import android.platform.test.rule.DisableNotificationCooldownSettingRule
import android.platform.test.rule.NavigationModeRule
import android.platform.test.rule.PressHomeRule
import android.platform.test.rule.UnlockScreenRule
@@ -48,6 +49,7 @@ object Utils {
clearCacheAfterParsing = false
)
)
+ .around(DisableNotificationCooldownSettingRule())
.around(PressHomeRule())
}
}
diff --git a/tests/FlickerTests/IME/AndroidTestTemplate.xml b/tests/FlickerTests/IME/AndroidTestTemplate.xml
index 988f76f4175c..b879c54dcab3 100644
--- a/tests/FlickerTests/IME/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/IME/AndroidTestTemplate.xml
@@ -8,8 +8,12 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
+ <!-- enable AOD -->
+ <option name="set-secure-setting" key="doze_always_on" value="1" />
<!-- prevents the phone from restarting -->
<option name="force-skip-system-props" value="true"/>
<!-- set WM tracing verbose level to all -->
@@ -78,6 +82,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/IME/OWNERS b/tests/FlickerTests/IME/OWNERS
index ae1098d496df..e3a2e674ae7a 100644
--- a/tests/FlickerTests/IME/OWNERS
+++ b/tests/FlickerTests/IME/OWNERS
@@ -1,3 +1,3 @@
# ime
# Bug component: 34867
-include /services/core/java/com/android/server/inputmethod/OWNERS
+file:/services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 7e486abbd30f..2b6ddcb43f18 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -32,6 +32,9 @@ import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
+/**
+ * To run this test: `atest FlickerTestsIme1:CloseImeOnDismissPopupDialogTest`
+ */
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -83,11 +86,12 @@ class CloseImeOnDismissPopupDialogTest(flicker: LegacyFlickerTest) : BaseTest(fl
}
if (imeSnapshotLayers.isNotEmpty()) {
val visibleAreas =
- imeSnapshotLayers
- .mapNotNull { imeSnapshotLayer -> imeSnapshotLayer.layer.visibleRegion }
+ imeSnapshotLayers.mapNotNull { imeSnapshotLayer ->
+ imeSnapshotLayer.layer.visibleRegion
+ }
val imeVisibleRegion = RegionSubject(visibleAreas, timestamp)
val appVisibleRegion = it.visibleRegion(imeTestApp)
- if (imeVisibleRegion.region.isNotEmpty) {
+ if (!imeVisibleRegion.region.isEmpty) {
imeVisibleRegion.coversAtMost(appVisibleRegion.region)
}
}
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 2f3ec6301215..0344197c1425 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -33,8 +33,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window closing to home transitions. To run this test: `atest
- * FlickerTests:CloseImeWindowToHomeTest`
+ * Test IME window closing to home transitions.
+ * To run this test: `atest FlickerTestsIme1:CloseImeOnGoHomeTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index 8821b69cdb3e..fde1373b032b 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -42,7 +42,7 @@ import org.junit.runners.Parameterized
*
* More details on b/190352379
*
- * To run this test: `atest FlickerTests:CloseImeAutoOpenWindowToHomeTest`
+ * To run this test: `atest FlickerTestsIme1:CloseImeShownOnAppStartOnGoHomeTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index d75eba68c7cc..ed6e8df3e293 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -23,6 +23,7 @@ import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.legacy.LegacyFlickerTestFactory
import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
import org.junit.FixMethodOrder
@@ -42,7 +43,7 @@ import org.junit.runners.Parameterized
*
* More details on b/190352379
*
- * To run this test: `atest FlickerTests:CloseImeAutoOpenWindowToAppTest`
+ * To run this test: `atest FlickerTestsIme1:CloseImeShownOnAppStartToAppOnPressBackTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -77,6 +78,7 @@ class CloseImeShownOnAppStartToAppOnPressBackTest(flicker: LegacyFlickerTest) :
@Presubmit @Test fun imeLayerBecomesInvisible() = flicker.imeLayerBecomesInvisible()
+ @FlakyTest(bugId = 330486656)
@Presubmit
@Test
fun imeAppLayerIsAlwaysVisible() {
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 41d9e30a17ee..dc2bd1bc9996 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
@@ -34,8 +34,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window closing back to app window transitions. To run this test: `atest
- * FlickerTests:CloseImeWindowToAppTest`
+ * Test IME window closing back to app window transitions.
+ * To run this test: `atest FlickerTestsIme1:CloseImeToAppOnPressBackTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
index 0e7fb7975df8..05771e88fc83 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
@@ -40,7 +40,7 @@ import org.junit.runners.Parameterized
* Unlike {@link OpenImeWindowTest} testing IME window opening transitions, this test also verify
* there is no flickering when back to the simple activity without requesting IME to show.
*
- * To run this test: `atest FlickerTests:OpenImeWindowAndCloseTest`
+ * To run this test: `atest FlickerTestsIme1:CloseImeToHomeOnFinishActivityTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
index 47a7e1b65b2d..336fe6f991ca 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -36,8 +36,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window shown on the app with fixing portrait orientation. To run this test: `atest
- * FlickerTests:OpenImeWindowToFixedPortraitAppTest`
+ * Test IME window shown on the app with fixing portrait orientation.
+ * To run this test: `atest FlickerTestsIme2:OpenImeWindowToFixedPortraitAppTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
index e8249bca4c2d..b8f11dcf8970 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
@@ -38,8 +38,9 @@ import org.junit.runners.Parameterized
/**
* Test IME window layer will become visible when switching from the fixed orientation activity
- * (e.g. Launcher activity). To run this test: `atest
- * FlickerTests:ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest`
+ * (e.g. Launcher activity).
+ * To run this test:
+ * `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -115,7 +116,10 @@ class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker: LegacyF
.isEqual(true)
imeLayerSubjects.forEach { imeLayerSubject ->
- imeLayerSubject.check { "alpha" }.that(imeLayerSubject.layer.color.a).isEqual(1.0f)
+ imeLayerSubject
+ .check { "alpha" }
+ .that(imeLayerSubject.layer.color.alpha())
+ .isEqual(1.0f)
}
}
}
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 617237d37368..34a708578396 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -33,7 +33,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window opening transitions. To run this test: `atest FlickerTests:ReOpenImeWindowTest`
+ * Test IME window opening transitions.
+ * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppFromOverviewTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -50,7 +51,10 @@ class ShowImeOnAppStartWhenLaunchingAppFromOverviewTest(flicker: LegacyFlickerTe
testApp.launchViaIntent(wmHelper)
testApp.openIME(wmHelper)
this.setRotation(flicker.scenario.startRotation)
- device.pressRecentApps()
+ if (flicker.scenario.isTablet && tapl.isTransientTaskbar()) {
+ tapl.launchedAppState.swipeUpToUnstashTaskbar()
+ }
+ tapl.launchedAppState.switchToOverview()
wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
}
transitions {
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 7b62c8967628..7c72c3187a7f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -35,8 +35,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME windows switching with 2-Buttons or gestural navigation. To run this test: `atest
- * FlickerTests:SwitchImeWindowsFromGestureNavTest`
+ * Test IME windows switching with 2-Buttons or gestural navigation.
+ * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index 53bfb4ecf66f..fe5320cd1a46 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -36,7 +36,7 @@ import org.junit.runners.Parameterized
/**
* Launch an app that automatically displays the IME
*
- * To run this test: `atest FlickerTests:LaunchAppShowImeOnStartTest`
+ * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppTest`
*
* Actions:
* ```
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
new file mode 100644
index 000000000000..92b6b934874f
--- /dev/null
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
@@ -0,0 +1,107 @@
+/*
+ * 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.server.wm.flicker.ime
+
+import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.UnlockScreenRule
+import android.tools.Rotation
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test IME window closing on lock and opening on screen unlock.
+ * To run this test: `atest FlickerTestsIme2:ShowImeOnUnlockScreenTest`
+ */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ShowImeOnUnlockScreenTest(flicker: LegacyFlickerTest) : BaseTest(flicker) {
+ private val testApp = ImeAppHelper(instrumentation)
+ private val imeOrSnapshot = ComponentNameMatcher.IME.or(ComponentNameMatcher.IME_SNAPSHOT)
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit = {
+ setup {
+ tapl.expectedRotationCheckEnabled = false
+ testApp.launchViaIntent(wmHelper)
+ testApp.openIME(wmHelper)
+ }
+ transitions {
+ device.sleep()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+ UnlockScreenRule.unlockScreen(device)
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
+ }
+ teardown { testApp.exit(wmHelper) }
+ }
+
+ @Presubmit
+ @Test
+ fun imeAndAppAnimateTogetherWhenLockingAndUnlocking() {
+ flicker.assertLayers {
+ this.isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ .then()
+ .isInvisible(testApp)
+ .isInvisible(imeOrSnapshot)
+ .then()
+ .isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun navBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun statusBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun taskBarWindowIsAlwaysVisible() {}
+
+ @FlakyTest(bugId = 338178020)
+ @Test
+ override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+ super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ LegacyFlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(Rotation.ROTATION_0)
+ )
+ }
+}
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
index 12290af8fd46..9eaf998ed63f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
@@ -31,7 +31,10 @@ import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-/** Test IME window opening transitions. To run this test: `atest FlickerTests:OpenImeWindowTest` */
+/**
+ * Test IME window opening transitions.
+ * To run this test: `atest FlickerTestsIme2:ShowImeWhenFocusingOnInputFieldTest`
+ */
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 0948351ac65b..7186a2c48c4c 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -41,7 +41,7 @@ import org.junit.runners.Parameterized
/**
* Test IME snapshot mechanism won't apply when transitioning from non-IME focused dialog activity.
- * To run this test: `atest FlickerTests:LaunchAppShowImeAndDialogThemeAppTest`
+ * To run this test: `atest FlickerTestsIme2:ShowImeWhileDismissingThemedPopupDialogTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
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 a14dc62b0023..c96c760e2d7b 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
@@ -37,8 +37,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window layer will be associated with the app task when going to the overview screen. To
- * run this test: `atest FlickerTests:OpenImeWindowToOverViewTest`
+ * Test IME window layer will be associated with the app task when going to the overview screen.
+ * To run this test: `atest FlickerTestsIme2:ShowImeWhileEnteringOverviewTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -191,7 +191,7 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl
this.invoke("imeLayerIsVisibleAndAlignAppWidow") {
val imeVisibleRegion = it.visibleRegion(ComponentNameMatcher.IME)
val appVisibleRegion = it.visibleRegion(imeTestApp)
- if (imeVisibleRegion.region.isNotEmpty) {
+ if (!imeVisibleRegion.region.isEmpty) {
it.isVisible(ComponentNameMatcher.IME)
imeVisibleRegion.coversAtMost(appVisibleRegion.region)
}
diff --git a/tests/FlickerTests/Notification/AndroidTestTemplate.xml b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
index 403685831be7..04b312a896b9 100644
--- a/tests/FlickerTests/Notification/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
index ffaeeadb1042..8c9ab9aadb8e 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
@@ -40,7 +40,7 @@ import org.junit.runners.Parameterized
*
* This test assumes the device doesn't have AOD enabled
*
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationCold`
+ * To run this test: `atest FlickerTestsNotification:OpenAppFromLockscreenNotificationColdTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
index 6e67e193ed8c..e595100a2cbe 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
@@ -40,7 +40,7 @@ import org.junit.runners.Parameterized
*
* This test assumes the device doesn't have AOD enabled
*
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWarm`
+ * To run this test: `atest FlickerTestsNotification:OpenAppFromLockscreenNotificationWarmTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
index 8e210d455591..fbe1d34272c9 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
@@ -40,7 +40,8 @@ import org.junit.runners.Parameterized
*
* This test assumes the device doesn't have AOD enabled
*
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWithLockOverlayApp`
+ * To run this test:
+ * `atest FlickerTestsNotification:OpenAppFromLockscreenNotificationWithOverlayAppTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -123,7 +124,9 @@ class OpenAppFromLockscreenNotificationWithOverlayAppTest(flicker: LegacyFlicker
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
- @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+ @FlakyTest(bugId = 227143265)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
@FlakyTest(bugId = 278227468)
@Test
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
index b6d09d0bf3bb..c8ca644dde90 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
@@ -36,7 +36,7 @@ import org.junit.runners.Parameterized
/**
* Test cold launching an app from a notification.
*
- * To run this test: `atest FlickerTests:OpenAppFromNotificationCold`
+ * To run this test: `atest FlickerTestsNotification:OpenAppFromNotificationColdTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
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 1e607bfb2f49..07fc2300286a 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
@@ -18,6 +18,7 @@ package com.android.server.wm.flicker.notification
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.DisableNotificationCooldownSettingRule
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.FlickerTestData
@@ -37,6 +38,7 @@ import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
import org.junit.Assume
+import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -47,7 +49,7 @@ import org.junit.runners.Parameterized
/**
* Test cold launching an app from a notification.
*
- * To run this test: `atest FlickerTests:OpenAppFromNotificationWarm`
+ * To run this test: `atest FlickerTestsNotification:OpenAppFromNotificationWarmTest`
*/
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -208,5 +210,10 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
+
+ /** Ensures that posted notifications will alert and HUN even just after boot. */
+ @ClassRule
+ @JvmField
+ val disablenotificationCooldown = DisableNotificationCooldownSettingRule()
}
}
diff --git a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
index 797ca4eacd5f..8acdabc2337d 100644
--- a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 8b09b590e790..9bb62e1e1794 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -16,9 +16,9 @@
package com.android.server.wm.flicker.quickswitch
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
import android.tools.NavBar
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -237,7 +237,7 @@ class QuickSwitchBetweenTwoAppsBackTest(flicker: LegacyFlickerTest) : BaseTest(f
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
companion object {
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index c54ddcf793f6..491b9945d12d 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.quickswitch
+import android.graphics.Rect
import android.tools.NavBar
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -285,7 +285,7 @@ class QuickSwitchBetweenTwoAppsForwardTest(flicker: LegacyFlickerTest) : BaseTes
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
companion object {
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index 69a84a0cbcb0..de54c95da361 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -16,10 +16,10 @@
package com.android.server.wm.flicker.quickswitch
+import android.graphics.Rect
import android.platform.test.annotations.Presubmit
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.datatypes.Rect
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -266,7 +266,7 @@ class QuickSwitchFromLauncherTest(flicker: LegacyFlickerTest) : BaseTest(flicker
companion object {
/** {@inheritDoc} */
- private var startDisplayBounds = Rect.EMPTY
+ private var startDisplayBounds = Rect()
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tests/FlickerTests/README.md b/tests/FlickerTests/README.md
index 6b28fdf8a8ef..7429250f5cc0 100644
--- a/tests/FlickerTests/README.md
+++ b/tests/FlickerTests/README.md
@@ -7,82 +7,17 @@ The tests are organized in packages according to the transitions they test (e.g.
## Adding a Test
-By default tests should inherit from `RotationTestBase` or `NonRotationTestBase` and must override the variable `transitionToRun` (Kotlin) or the function `getTransitionToRun()` (Java).
-Only tests that are not supported by these classes should inherit directly from the `FlickerTestBase` class.
+By default, tests should inherit from `TestBase` and override the variable `transition` (Kotlin) or the function `getTransition()` (Java).
-### Rotation animations and transitions
+Inheriting from this class ensures the common assertions will be executed, namely:
-Tests that rotate the device should inherit from `RotationTestBase`.
-Tests that inherit from the class automatically receive start and end rotation values.
-Moreover, these tests inherit the following checks:
* all regions on the screen are covered
* status bar is always visible
-* status bar rotates
+* status bar is at the correct position at the start and end of the transition
* nav bar is always visible
-* nav bar is rotates
+* nav bar is at the correct position at the start and end of the transition
The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
-### Non-Rotation animations and transitions
+For more examples of how a test looks like check `ChangeAppRotationTest` within the `Rotation` subdirectory.
-`NonRotationTestBase` was created to make it easier to write tests that do not involve rotation (e.g., `Pip`, `split screen` or `IME`).
-Tests that inherit from the class are automatically executed twice: once in portrait and once in landscape mode and the assertions are checked independently.
-Moreover, these tests inherit the following checks:
-* all regions on the screen are covered
-* status bar is always visible
-* nav bar is always visible
-
-The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
-
-### Exceptional cases
-
-Tests that rotate the device should inherit from `RotationTestBase`.
-This class allows the test to be freely configured and does not provide any assertions.
-
-
-### Example
-
-Start by defining common or error prone transitions using `TransitionRunner`.
-```kotlin
-@LargeTest
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class MyTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- mTestApp = MyAppHelper(InstrumentationRegistry.getInstrumentation())
- }
-
- override val transitionToRun: TransitionRunner
- get() = TransitionRunner.newBuilder()
- .withTag("myTest")
- .recordAllRuns()
- .runBefore { device.pressHome() }
- .runBefore { device.waitForIdle() }
- .run { testApp.open() }
- .runAfter{ testApp.exit() }
- .repeat(2)
- .includeJankyRuns()
- .build()
-
- @Test
- fun myWMTest() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindow(MyTestApp)
- .forAllEntries()
- }
- }
-
- @Test
- fun mySFTest() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(MyTestApp)
- .forAllEntries()
- }
- }
-}
-```
diff --git a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
index b5ea7390e9ba..91ece214aad5 100644
--- a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
@@ -78,6 +80,7 @@
value="trace_config.textproto"
/>
<option name="instrumentation-arg" key="per_run" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/>
</test>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/OpenShowWhenLockedSeamlessAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/OpenShowWhenLockedSeamlessAppRotationTest.kt
new file mode 100644
index 000000000000..bf569bc23df6
--- /dev/null
+++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/OpenShowWhenLockedSeamlessAppRotationTest.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.server.wm.flicker.rotation
+
+import android.platform.test.annotations.Presubmit
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.flicker.assertions.FlickerTest
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
+import android.tools.traces.component.ComponentNameMatcher
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test opening an app over lockscreen with rotation change using seamless rotations.
+ */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenShowWhenLockedSeamlessAppRotationTest(flicker: LegacyFlickerTest) : BaseTest(flicker) {
+ val testApp = SeamlessRotationAppHelper(instrumentation)
+
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ setup {
+ device.sleep()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+ device.wakeUp()
+ val originalRotation = device.displayRotation
+ ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_90)
+ Assume.assumeTrue("Assume that lockscreen uses fixed orientation",
+ originalRotation == device.displayRotation)
+ }
+ transitions {
+ // The activity is show-when-locked, so the requested orientation will be changed
+ // from NOSENSOR(keyguard) to UNSPECIFIED(activity). Then the fixed-user-rotation
+ // (by setRotation) will take effect to rotate the display.
+ testApp.launchViaIntent(wmHelper)
+ }
+ teardown { testApp.exit(wmHelper) }
+ }
+
+ @Presubmit
+ @Test
+ fun notContainsRotationAnimation() {
+ flicker.assertLayers {
+ // Verifies that com.android.wm.shell.transition.ScreenRotationAnimation is not used.
+ notContains(ComponentNameMatcher("", "Animation leash of screenshot rotation"))
+ }
+ }
+
+ // Ignore the assertions which are included in SeamlessAppRotationTest.
+ @Test
+ @Ignore("Uninterested")
+ override fun statusBarLayerPositionAtStartAndEnd() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun statusBarLayerIsVisibleAtStartAndEnd() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun statusBarWindowIsAlwaysVisible() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun navBarLayerPositionAtStartAndEnd() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun navBarLayerIsVisibleAtStartAndEnd() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun navBarWindowIsVisibleAtStartAndEnd() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun navBarWindowIsAlwaysVisible() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun visibleLayersShownMoreThanOneConsecutiveEntry() {}
+
+ @Test
+ @Ignore("Uninterested")
+ override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {}
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ // The rotation will be controlled by the setup of test.
+ return LegacyFlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(Rotation.ROTATION_0),
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
+ )
+ }
+ }
+}
diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index c7da778b752b..c49b509a9db3 100644
--- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -21,6 +21,7 @@ import android.tools.device.apphelpers.StandardAppHelper
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.subject.layers.LayerTraceEntrySubject
+import android.tools.flicker.subject.layers.LayersTraceSubject
import android.tools.traces.component.ComponentNameMatcher
import android.tools.traces.component.IComponentMatcher
import android.tools.traces.surfaceflinger.Display
@@ -46,6 +47,7 @@ abstract class RotationTransition(flicker: LegacyFlickerTest) : BaseTest(flicker
flicker.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
ignoreLayers =
+ LayersTraceSubject.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS +
listOf(
ComponentNameMatcher.SPLASH_SCREEN,
ComponentNameMatcher.SNAPSHOT,
diff --git a/tests/FlickerTests/libs/window-extensions-release.aar b/tests/FlickerTests/libs/window-extensions-release.aar
deleted file mode 100644
index 918e514f4c89..000000000000
--- a/tests/FlickerTests/libs/window-extensions-release.aar
+++ /dev/null
Binary files differ
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 17f91ebad771..060015bcc4b2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -40,9 +40,10 @@ abstract class BaseTest
constructor(
protected val flicker: LegacyFlickerTest,
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation(),
+ protected val tapl: LauncherInstrumentation = LauncherInstrumentation()
) {
- protected val tapl: LauncherInstrumentation by lazy {
- LauncherInstrumentation().also { it.expectedRotationCheckEnabled = true }
+ init {
+ tapl.setExpectedRotationCheckEnabled(true)
}
private val logTag = this::class.java.simpleName
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index 8853c1db856f..348d0af5a2d3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -279,12 +279,11 @@ fun LegacyFlickerTest.snapshotStartingWindowLayerCoversExactlyOnApp(
subject.isVisible
}
val visibleAreas =
- snapshotLayers
- .mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
+ snapshotLayers.mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
val snapshotRegion = RegionSubject(visibleAreas, it.timestamp)
val appVisibleRegion = it.visibleRegion(component)
// Verify the size of snapshotRegion covers appVisibleRegion exactly in animation.
- if (snapshotRegion.region.isNotEmpty && appVisibleRegion.region.isNotEmpty) {
+ if (!snapshotRegion.region.isEmpty && !appVisibleRegion.region.isEmpty) {
snapshotRegion.coversExactly(appVisibleRegion.region)
}
}
diff --git a/tests/FlickerTests/test-apps/app-helpers/OWNERS b/tests/FlickerTests/test-apps/app-helpers/OWNERS
new file mode 100644
index 000000000000..ab6253200f73
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/OWNERS
@@ -0,0 +1,2 @@
+uysalorhan@google.com
+pragyabajoria@google.com \ No newline at end of file
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
new file mode 100644
index 000000000000..9a5e88becf1e
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -0,0 +1,168 @@
+/*
+ * 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.server.wm.flicker.helpers
+
+import android.graphics.Rect
+import android.tools.device.apphelpers.IStandardAppHelper
+import android.tools.helpers.SYSTEMUI_PACKAGE
+import android.tools.traces.parsers.WindowManagerStateHelper
+import android.tools.traces.wm.WindowingMode
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+
+/**
+ * Wrapper class around App helper classes. This class adds functionality to the apps that the
+ * desktop apps would have.
+ */
+open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
+ IStandardAppHelper by innerHelper {
+
+ enum class Corners {
+ LEFT_TOP,
+ RIGHT_TOP,
+ LEFT_BOTTOM,
+ 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
+ .StateSyncBuilder()
+ .withWindowSurfaceAppeared(innerHelper)
+ .withFreeformApp(innerHelper)
+ .withAppTransitionIdle()
+ .waitForAndVerify()
+ }
+
+ /** Move an app to Desktop by dragging the app handle at the top. */
+ fun enterDesktopWithDrag(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice,
+ ) {
+ innerHelper.launchViaIntent(wmHelper)
+ dragToDesktop(wmHelper, device)
+ waitForAppToMoveToDesktop(wmHelper)
+ }
+
+ private fun dragToDesktop(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+ val startX = windowRect.centerX()
+
+ // Start dragging a little under the top to prevent dragging the notification shade.
+ val startY = 10
+
+ val displayRect =
+ wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
+ ?: throw IllegalStateException("Default display is null")
+
+ // The position we want to drag to
+ val endY = displayRect.centerY() / 2
+
+ // drag the window to move to desktop
+ device.drag(startX, startY, startX, endY, 100)
+ }
+
+ /** Click maximise button on the app header for the given app. */
+ fun maximiseDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val caption = getCaptionForTheApp(wmHelper, device)
+ val maximizeButton =
+ caption
+ ?.children
+ ?.find { it.resourceName.endsWith(MAXIMIZE_BUTTON_VIEW) }
+ ?.children
+ ?.get(0)
+ maximizeButton?.click()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+ }
+ /** Click close button on the app header for the given app. */
+ fun closeDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val caption = getCaptionForTheApp(wmHelper, device)
+ val closeButton = caption?.children?.find { it.resourceName.endsWith(CLOSE_BUTTON) }
+ closeButton?.click()
+ wmHelper
+ .StateSyncBuilder()
+ .withAppTransitionIdle()
+ .withWindowSurfaceDisappeared(innerHelper)
+ .waitForAndVerify()
+ }
+
+ private fun getCaptionForTheApp(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice
+ ): UiObject2? {
+ if (
+ wmHelper.getWindow(innerHelper)?.windowingMode !=
+ WindowingMode.WINDOWING_MODE_FREEFORM.value
+ )
+ error("expected a freeform window with caption but window is not in freeform mode")
+ val captions =
+ device.wait(Until.findObjects(caption), TIMEOUT_MS)
+ ?: error("Unable to find view $caption\n")
+
+ return captions.find {
+ wmHelper.getWindowRegion(innerHelper).bounds.contains(it.visibleBounds)
+ }
+ }
+
+ /** Resize a desktop app from its corners. */
+ fun cornerResize(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice,
+ corner: Corners,
+ horizontalChange: Int,
+ verticalChange: Int
+ ) {
+ val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+ val (startX, startY) = getStartCoordinatesForCornerResize(windowRect, corner)
+
+ // The position we want to drag to
+ val endY = startY + verticalChange
+ val endX = startX + horizontalChange
+
+ // drag the specified corner of the window to the end coordinate.
+ device.drag(startX, startY, endX, endY, 100)
+ wmHelper
+ .StateSyncBuilder()
+ .withAppTransitionIdle()
+ .waitForAndVerify()
+ }
+
+ private fun getStartCoordinatesForCornerResize(
+ windowRect: Rect,
+ corner: Corners
+ ): Pair<Int, Int> {
+ return when (corner) {
+ Corners.LEFT_TOP -> Pair(windowRect.left, windowRect.top)
+ Corners.RIGHT_TOP -> Pair(windowRect.right, windowRect.top)
+ Corners.LEFT_BOTTOM -> Pair(windowRect.left, windowRect.bottom)
+ Corners.RIGHT_BOTTOM -> Pair(windowRect.right, windowRect.bottom)
+ }
+ }
+}
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index 0c60f284a35b..ef8d84fb915a 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -45,13 +45,7 @@ constructor(
require(gameView != null) { "Mock game app view not found." }
val bound = gameView.getVisibleBounds()
- return uiDevice.swipe(
- bound.centerX(),
- bound.top,
- bound.centerX(),
- bound.centerY(),
- SWIPE_STEPS
- )
+ return uiDevice.swipe(bound.centerX(), 0, bound.centerX(), bound.centerY(), SWIPE_STEPS)
}
/**
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
index b09e53b6400d..634b6eedd7e6 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -17,8 +17,8 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.datatypes.Rect
-import android.tools.datatypes.Region
+import android.graphics.Rect
+import android.graphics.Region
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.helpers.FIND_TIMEOUT
import android.tools.helpers.SYSTEMUI_PACKAGE
@@ -86,7 +86,7 @@ constructor(
.add("letterboxAppRepositioned") {
val letterboxAppWindow = getWindowRegion(wmHelper)
val appRegionBounds = letterboxAppWindow.bounds
- val appWidth = appRegionBounds.width
+ val appWidth = appRegionBounds.width()
return@add if (right)
appRegionBounds.left == displayBounds.right - appWidth &&
appRegionBounds.right == displayBounds.right
@@ -108,7 +108,7 @@ constructor(
.add("letterboxAppRepositioned") {
val letterboxAppWindow = getWindowRegion(wmHelper)
val appRegionBounds = letterboxAppWindow.bounds
- val appHeight = appRegionBounds.height
+ val appHeight = appRegionBounds.height()
return@add if (bottom)
appRegionBounds.bottom == displayBounds.bottom &&
appRegionBounds.top == (displayBounds.bottom - appHeight + navBarHeight)
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index db933b30a822..43fd57bf39aa 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -18,10 +18,11 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.content.Intent
+import android.graphics.Rect
+import android.graphics.Region
import android.media.session.MediaController
import android.media.session.MediaSessionManager
-import android.tools.datatypes.Rect
-import android.tools.datatypes.Region
+import android.tools.datatypes.coversMoreThan
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.helpers.FIND_TIMEOUT
import android.tools.helpers.SYSTEMUI_PACKAGE
@@ -62,7 +63,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
/** Drags the PIP window to the provided final coordinates without releasing the pointer. */
fun dragPipWindowAwayFromEdgeWithoutRelease(wmHelper: WindowManagerStateHelper, steps: Int) {
- val initWindowRect = getWindowRect(wmHelper).clone()
+ val initWindowRect = Rect(getWindowRect(wmHelper))
// initial pointer at the center of the window
val initialCoord =
@@ -101,7 +102,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
* @throws IllegalStateException if default display bounds are not available
*/
fun dragPipWindowAwayFromEdge(wmHelper: WindowManagerStateHelper, steps: Int) {
- val initWindowRect = getWindowRect(wmHelper).clone()
+ val initWindowRect = Rect(getWindowRect(wmHelper))
// initial pointer at the center of the window
val startX = initWindowRect.centerX()
@@ -153,12 +154,12 @@ open class PipAppHelper(instrumentation: Instrumentation) :
val windowRect = getWindowRect(wmHelper)
// first pointer's initial x coordinate is halfway between the left edge and the center
- val initLeftX = (windowRect.centerX() - windowRect.width / 4).toFloat()
+ val initLeftX = (windowRect.centerX() - windowRect.width() / 4).toFloat()
// second pointer's initial x coordinate is halfway between the right edge and the center
- val initRightX = (windowRect.centerX() + windowRect.width / 4).toFloat()
+ val initRightX = (windowRect.centerX() + windowRect.width() / 4).toFloat()
// horizontal distance the window should increase by
- val distIncrease = windowRect.width * percent
+ val distIncrease = windowRect.width() * percent
// final x-coordinates
val finalLeftX = initLeftX - (distIncrease / 2)
@@ -183,7 +184,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
adjustedSteps
)
- waitForPipWindowToExpandFrom(wmHelper, Region.from(windowRect))
+ waitForPipWindowToExpandFrom(wmHelper, Region(windowRect))
}
/**
@@ -201,12 +202,12 @@ open class PipAppHelper(instrumentation: Instrumentation) :
val windowRect = getWindowRect(wmHelper)
// first pointer's initial x coordinate is halfway between the left edge and the center
- val initLeftX = (windowRect.centerX() - windowRect.width / 4).toFloat()
+ val initLeftX = (windowRect.centerX() - windowRect.width() / 4).toFloat()
// second pointer's initial x coordinate is halfway between the right edge and the center
- val initRightX = (windowRect.centerX() + windowRect.width / 4).toFloat()
+ val initRightX = (windowRect.centerX() + windowRect.width() / 4).toFloat()
// decrease by the distance specified through the percentage
- val distDecrease = windowRect.width * percent
+ val distDecrease = windowRect.width() * percent
// get the final x-coordinates and make sure they are not passing the center of the window
val finalLeftX = Math.min(initLeftX + (distDecrease / 2), windowRect.centerX().toFloat())
@@ -231,7 +232,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
adjustedSteps
)
- waitForPipWindowToMinimizeFrom(wmHelper, Region.from(windowRect))
+ waitForPipWindowToMinimizeFrom(wmHelper, Region(windowRect))
}
/**
@@ -375,7 +376,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
uiDevice.click(windowRect.centerX(), windowRect.centerY())
Log.d(TAG, "Wait for app transition to end")
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
- waitForPipWindowToExpandFrom(wmHelper, Region.from(windowRect))
+ waitForPipWindowToExpandFrom(wmHelper, Region(windowRect))
}
private fun waitForPipWindowToExpandFrom(
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 9198ae184b18..45260bddd355 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -18,7 +18,10 @@
package="com.android.server.wm.flicker.testapp">
<uses-sdk android:minSdkVersion="29"
- android:targetSdkVersion="29"/>
+ android:targetSdkVersion="35"/>
+
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+
<application android:allowBackup="false"
android:supportsRtl="true">
<uses-library android:name="androidx.window.extensions" android:required="false"/>
@@ -71,6 +74,7 @@
android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
+ android:showWhenLocked="true"
android:label="SeamlessActivity"
android:exported="true">
<intent-filter>
@@ -107,7 +111,7 @@
android:immersive="true"
android:resizeableActivity="true"
android:screenOrientation="portrait"
- android:theme="@android:style/Theme.NoTitleBar"
+ android:theme="@style/OptOutEdgeToEdge.NoTitleBar"
android:configChanges="screenSize"
android:label="PortraitImmersiveActivity"
android:exported="true">
@@ -119,7 +123,7 @@
<activity android:name=".LaunchTransparentActivity"
android:resizeableActivity="false"
android:screenOrientation="portrait"
- android:theme="@android:style/Theme"
+ android:theme="@style/OptOutEdgeToEdge"
android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchTransparentActivity"
android:label="LaunchTransparentActivity"
android:exported="true">
@@ -273,7 +277,7 @@
android:exported="true"
android:label="MailActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.MailActivity"
- android:theme="@style/Theme.AppCompat.Light">
+ android:theme="@style/OptOutEdgeToEdge.AppCompatTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -282,7 +286,7 @@
<activity android:name=".GameActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity"
android:immersive="true"
- android:theme="@android:style/Theme.NoTitleBar"
+ android:theme="@style/OptOutEdgeToEdge.NoTitleBar"
android:configChanges="screenSize"
android:label="GameActivity"
android:exported="true">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
index 86c21906163f..917aec1e809d 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
@@ -14,66 +14,71 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
+<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
android:background="@android:color/holo_orange_light">
- <Button
- android:id="@+id/launch_secondary_activity_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchSecondaryActivity"
- android:tag="LEFT_TO_RIGHT"
- android:text="Launch Secondary Activity" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <Button
- android:id="@+id/launch_secondary_activity_rtl_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchSecondaryActivity"
- android:tag="RIGHT_TO_LEFT"
- android:text="Launch Secondary Activity in RTL" />
+ <Button
+ android:id="@+id/launch_secondary_activity_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchSecondaryActivity"
+ android:tag="LEFT_TO_RIGHT"
+ android:text="Launch Secondary Activity" />
- <Button
- android:id="@+id/launch_secondary_activity_horizontally_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchSecondaryActivity"
- android:tag="BOTTOM_TO_TOP"
- android:text="Launch Secondary Activity Horizontally" />
+ <Button
+ android:id="@+id/launch_secondary_activity_rtl_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchSecondaryActivity"
+ android:tag="RIGHT_TO_LEFT"
+ android:text="Launch Secondary Activity in RTL" />
- <Button
- android:id="@+id/launch_placeholder_split_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchPlaceholderSplit"
- android:tag="LEFT_TO_RIGHT"
- android:text="Launch Placeholder Split" />
+ <Button
+ android:id="@+id/launch_secondary_activity_horizontally_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchSecondaryActivity"
+ android:tag="BOTTOM_TO_TOP"
+ android:text="Launch Secondary Activity Horizontally" />
- <Button
- android:id="@+id/launch_always_expand_activity_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchAlwaysExpandActivity"
- android:text="Launch Always Expand Activity" />
+ <Button
+ android:id="@+id/launch_placeholder_split_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchPlaceholderSplit"
+ android:tag="LEFT_TO_RIGHT"
+ android:text="Launch Placeholder Split" />
- <Button
- android:id="@+id/launch_placeholder_split_rtl_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchPlaceholderSplit"
- android:tag="RIGHT_TO_LEFT"
- android:text="Launch Placeholder Split in RTL" />
+ <Button
+ android:id="@+id/launch_always_expand_activity_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchAlwaysExpandActivity"
+ android:text="Launch Always Expand Activity" />
- <Button
- android:id="@+id/launch_trampoline_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:onClick="launchTrampolineActivity"
- android:tag="LEFT_TO_RIGHT"
- android:text="Launch Trampoline Activity" />
+ <Button
+ android:id="@+id/launch_placeholder_split_rtl_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchPlaceholderSplit"
+ android:tag="RIGHT_TO_LEFT"
+ android:text="Launch Placeholder Split in RTL" />
-</LinearLayout>
+ <Button
+ android:id="@+id/launch_trampoline_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:onClick="launchTrampolineActivity"
+ android:tag="LEFT_TO_RIGHT"
+ android:text="Launch Trampoline Activity" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
index 9b742d96e35b..47d113717ae0 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
@@ -16,7 +16,19 @@
-->
<resources>
- <style name="DefaultTheme" parent="@android:style/Theme.DeviceDefault">
+ <style name="OptOutEdgeToEdge" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ </style>
+
+ <style name="OptOutEdgeToEdge.NoTitleBar" parent="@android:style/Theme.NoTitleBar">
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ </style>
+
+ <style name="OptOutEdgeToEdge.AppCompatTheme" parent="@style/Theme.AppCompat.Light">
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ </style>
+
+ <style name="DefaultTheme" parent="@style/OptOutEdgeToEdge">
<item name="android:windowBackground">@android:color/darker_gray</item>
</style>
@@ -32,7 +44,7 @@
<item name="android:windowLayoutInDisplayCutoutMode">never</item>
</style>
- <style name="DialogTheme" parent="@android:style/Theme.DeviceDefault">
+ <style name="DialogTheme" parent="@style/OptOutEdgeToEdge">
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@null</item>
@@ -43,18 +55,18 @@
<item name="android:windowSoftInputMode">stateUnchanged</item>
</style>
- <style name="TransparentTheme" parent="@android:style/Theme.DeviceDefault">
+ <style name="TransparentTheme" parent="@style/OptOutEdgeToEdge">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
- <style name="no_starting_window" parent="@android:style/Theme.DeviceDefault">
+ <style name="no_starting_window" parent="@style/OptOutEdgeToEdge">
<item name="android:windowDisablePreview">true</item>
</style>
- <style name="SplashscreenAppTheme" parent="@android:style/Theme.DeviceDefault">
+ <style name="SplashscreenAppTheme" parent="@style/OptOutEdgeToEdge">
<!-- Splashscreen Attributes -->
<item name="android:windowSplashScreenAnimatedIcon">@drawable/avd_anim</item>
<!-- Here we want to match the duration of our AVD -->
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
index 23fa91c37728..2df3da63436b 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.testapp;
-import androidx.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -103,18 +102,13 @@ public class ActivityEmbeddingMainActivity extends Activity {
}
private static SplitPairRule createSplitPairRules(@NonNull String layoutDirection) {
- final Set<SplitPairFilter> pairFilters = new HashSet<>();
- final SplitPairFilter activitiesPair = new SplitPairFilter(
- ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
- ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT,
- null /* secondaryActivityIntentAction */);
- pairFilters.add(activitiesPair);
+ final Set<SplitPairFilter> pairFilters = getSplitPairFilters();
final SplitAttributes splitAttributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.SPLIT_TYPE_EQUAL)
.setLayoutDirection(parseLayoutDirection(layoutDirection))
.build();
// Setting thresholds to ALWAYS_ALLOW values to make it easy for running on all devices.
- final SplitPairRule rule = new SplitPairRule.Builder(pairFilters)
+ return new SplitPairRule.Builder(pairFilters)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
.setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
@@ -122,7 +116,22 @@ public class ActivityEmbeddingMainActivity extends Activity {
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
.setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
.build();
- return rule;
+ }
+
+ @NonNull
+ private static Set<SplitPairFilter> getSplitPairFilters() {
+ final Set<SplitPairFilter> pairFilters = new HashSet<>();
+ final SplitPairFilter mainAndSecondaryActivitiesPair = new SplitPairFilter(
+ ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
+ ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT,
+ null /* secondaryActivityIntentAction */);
+ pairFilters.add(mainAndSecondaryActivitiesPair);
+ final SplitPairFilter mainAndTrampolineActivitiesPair = new SplitPairFilter(
+ ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
+ ActivityOptions.ActivityEmbedding.TrampolineActivity.COMPONENT,
+ null /* secondaryActivityIntentAction */);
+ pairFilters.add(mainAndTrampolineActivitiesPair);
+ return pairFilters;
}
private static SplitPlaceholderRule createSplitPlaceholderRules(
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java
index c92b82b896f2..a86ba5f76374 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java
@@ -125,7 +125,7 @@ public class BubbleHelper {
.setContentTitle("BubbleChat")
.setContentIntent(PendingIntent.getActivity(mContext, 0,
new Intent(mContext, LaunchBubbleActivity.class),
- PendingIntent.FLAG_UPDATE_CURRENT))
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE))
.setStyle(new Notification.MessagingStyle(chatBot)
.setConversationTitle("BubbleChat")
.addMessage("BubbleChat",
@@ -140,7 +140,7 @@ public class BubbleHelper {
Intent target = new Intent(mContext, BubbleActivity.class);
target.putExtra(EXTRA_BUBBLE_NOTIF_ID, info.id);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, info.id, target,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
return new Notification.BubbleMetadata.Builder()
.setIntent(bubbleIntent)
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java
index dea34442464d..37332c9712f5 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java
@@ -17,6 +17,9 @@
package com.android.server.wm.flicker.testapp;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import android.app.Activity;
import android.app.Person;
import android.content.Context;
@@ -24,6 +27,7 @@ import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
+import android.os.Build;
import android.os.Bundle;
import android.view.View;
@@ -36,6 +40,13 @@ public class LaunchBubbleActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+ && checkSelfPermission(POST_NOTIFICATIONS) != PERMISSION_GRANTED) {
+ // POST_NOTIFICATIONS permission required for notification post sdk 33.
+ requestPermissions(new String[] { POST_NOTIFICATIONS }, 0);
+ }
+
addInboxShortcut(getApplicationContext());
mBubbleHelper = BubbleHelper.getInstance(this);
setContentView(R.layout.activity_main);
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
index a4dd5753539d..d6427abcc65a 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
@@ -16,6 +16,9 @@
package com.android.server.wm.flicker.testapp;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -23,6 +26,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.Button;
@@ -34,6 +38,13 @@ public class NotificationActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+ && checkSelfPermission(POST_NOTIFICATIONS) != PERMISSION_GRANTED) {
+ // POST_NOTIFICATIONS permission required for notification post sdk 33.
+ requestPermissions(new String[] { POST_NOTIFICATIONS }, 0);
+ }
+
WindowManager.LayoutParams p = getWindow().getAttributes();
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
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 1ab8ddbe20e2..27eb5a06451a 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
@@ -198,7 +198,7 @@ public class PipActivity extends Activity {
filter.addAction(ACTION_SET_REQUESTED_ORIENTATION);
filter.addAction(ACTION_ENTER_PIP);
filter.addAction(ACTION_ASPECT_RATIO);
- registerReceiver(mBroadcastReceiver, filter);
+ registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED);
handleIntentExtra(getIntent());
}
@@ -222,8 +222,8 @@ public class PipActivity extends Activity {
private RemoteAction buildRemoteAction(Icon icon, String label, String action) {
final Intent intent = new Intent(action);
- final PendingIntent pendingIntent =
- PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
return new RemoteAction(icon, label, label, pendingIntent);
}
diff --git a/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
index 2ed4fec4a93c..c52be7c2b0c6 100644
--- a/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
+++ b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
@@ -27,6 +27,9 @@ import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.Rule;
import org.junit.Test;
import java.io.FileOutputStream;
@@ -46,6 +49,12 @@ public class Helper {
private static final long BLOCK_SIZE = 4096;
+ @Rule
+ public final AdoptShellPermissionsRule mAdoptShellPermissionsRule =
+ new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ android.Manifest.permission.SETUP_FSVERITY);
+
@Test
public void prepareTest() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
diff --git a/tests/HugeBackup/AndroidManifest.xml b/tests/HugeBackup/AndroidManifest.xml
index 92445dddef5a..945e59bd36ed 100644
--- a/tests/HugeBackup/AndroidManifest.xml
+++ b/tests/HugeBackup/AndroidManifest.xml
@@ -25,7 +25,7 @@
android:versionName="1.0">
<!-- The backup/restore mechanism was introduced in API version 8 -->
- <uses-sdk android:minSdkVersion="21"
+ <uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="8"/>
<application android:label="Huge Backup"
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index d17cd1fa2c3b..f367c38b06e9 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -18,26 +18,33 @@ android_test {
"src/**/*.java",
"src/**/*.kt",
],
+ asset_dirs: ["assets"],
kotlincflags: [
"-Werror",
],
platform_apis: true,
certificate: "platform",
static_libs: [
+ "android.view.flags-aconfig-java",
"androidx.test.core",
"androidx.test.ext.junit",
"androidx.test.ext.truth",
"androidx.test.rules",
"androidx.test.runner",
"androidx.test.uiautomator_uiautomator",
- "servicestests-utils",
+ "collector-device-lib",
+ "compatibility-device-util-axt",
+ "cts-input-lib",
+ "cts-wm-util",
"flag-junit",
"frameworks-base-testutils",
"hamcrest-library",
"kotlin-test",
"mockito-target-minus-junit4",
"platform-test-annotations",
+ "platform-screenshot-diff-core",
"services.core.unboosted",
+ "servicestests-utils",
"testables",
"testng",
"truth",
diff --git a/tests/Input/AndroidManifest.xml b/tests/Input/AndroidManifest.xml
index 3b723ddf811f..a05d08ccceba 100644
--- a/tests/Input/AndroidManifest.xml
+++ b/tests/Input/AndroidManifest.xml
@@ -22,6 +22,8 @@
<uses-permission android:name="android.permission.MONITOR_INPUT"/>
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<application android:label="InputTest" android:debuggable="true">
diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml
index f602c5124e77..8db37058af2b 100644
--- a/tests/Input/AndroidTest.xml
+++ b/tests/Input/AndroidTest.xml
@@ -28,4 +28,10 @@
<!-- Take screenshot upon test failure -->
<option name="screenshot-on-failure" value="true" />
</object>
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="pull-pattern-keys" value="input_.*" />
+ <!-- Pull files created by tests, like the output of screenshot tests -->
+ <option name="directory-keys" value="/storage/emulated/0/InputTests" />
+ <option name="collect-on-run-ended-only" value="false" />
+ </metrics_collector>
</configuration>
diff --git a/tests/Input/assets/testPointerFillStyle.png b/tests/Input/assets/testPointerFillStyle.png
new file mode 100644
index 000000000000..b2354f8f4799
--- /dev/null
+++ b/tests/Input/assets/testPointerFillStyle.png
Binary files differ
diff --git a/tests/Input/assets/testPointerScale.png b/tests/Input/assets/testPointerScale.png
new file mode 100644
index 000000000000..54d37c24afc6
--- /dev/null
+++ b/tests/Input/assets/testPointerScale.png
Binary files differ
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index f6f766a6a5b0..3c72498082e4 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -19,22 +19,28 @@ package com.android.server.input
import android.content.Context
import android.content.ContextWrapper
+import android.hardware.display.DisplayManager
import android.hardware.display.DisplayViewport
+import android.hardware.display.VirtualDisplay
import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
+import android.os.InputEventInjectionSync
+import android.os.SystemClock
import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit
-import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.provider.Settings
+import android.view.View.OnKeyListener
+import android.view.InputDevice
+import android.view.KeyEvent
+import android.view.SurfaceHolder
+import android.view.SurfaceView
import android.test.mock.MockContentResolver
-import android.view.Display
-import android.view.PointerIcon
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.util.test.FakeSettingsProvider
import com.google.common.truth.Truth.assertThat
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import org.junit.After
-import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
@@ -43,21 +49,16 @@ import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.junit.MockitoJUnit
import org.mockito.stubbing.OngoingStubbing
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
/**
* Tests for {@link InputManagerService}.
@@ -141,7 +142,9 @@ class InputManagerServiceTests {
fun testInputSettingsUpdatedOnSystemRunning() {
verifyZeroInteractions(native)
- service.systemRunning()
+ runWithShellPermissionIdentity {
+ service.systemRunning()
+ }
verify(native).setPointerSpeed(anyInt())
verify(native).setTouchpadPointerSpeed(anyInt())
@@ -166,203 +169,6 @@ class InputManagerServiceTests {
localService.setDisplayViewports(viewports)
verify(native).setDisplayViewports(any(Array<DisplayViewport>::class.java))
verify(native).setPointerDisplayId(displayId)
-
- val x = 42f
- val y = 314f
- service.onPointerDisplayIdChanged(displayId, x, y)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(displayId, x, y)
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun testSetVirtualMousePointerDisplayId() {
- // Set the virtual mouse pointer displayId, and ensure that the calling thread is blocked
- // until the native callback happens.
- var countDownLatch = CountDownLatch(1)
- val overrideDisplayId = 123
- Thread {
- assertTrue("Setting virtual pointer display should succeed",
- localService.setVirtualMousePointerDisplayId(overrideDisplayId))
- countDownLatch.countDown()
- }.start()
- assertFalse("Setting virtual pointer display should block",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
-
- val x = 42f
- val y = 314f
- service.onPointerDisplayIdChanged(overrideDisplayId, x, y)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(overrideDisplayId, x, y)
- assertTrue("Native callback unblocks calling thread",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
- verify(native).setPointerDisplayId(overrideDisplayId)
-
- // Ensure that setting the same override again succeeds immediately.
- assertTrue("Setting the same virtual mouse pointer displayId again should succeed",
- localService.setVirtualMousePointerDisplayId(overrideDisplayId))
-
- // Ensure that we did not query WM for the pointerDisplayId when setting the override
- verify(wmCallbacks, never()).pointerDisplayId
-
- // Unset the virtual mouse pointer displayId, and ensure that we query WM for the new
- // pointer displayId and the calling thread is blocked until the native callback happens.
- countDownLatch = CountDownLatch(1)
- val pointerDisplayId = 42
- `when`(wmCallbacks.pointerDisplayId).thenReturn(pointerDisplayId)
- Thread {
- assertTrue("Unsetting virtual mouse pointer displayId should succeed",
- localService.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY))
- countDownLatch.countDown()
- }.start()
- assertFalse("Unsetting virtual mouse pointer displayId should block",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
-
- service.onPointerDisplayIdChanged(pointerDisplayId, x, y)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(pointerDisplayId, x, y)
- assertTrue("Native callback unblocks calling thread",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
- verify(native).setPointerDisplayId(pointerDisplayId)
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun testSetVirtualMousePointerDisplayId_unsuccessfulUpdate() {
- // Set the virtual mouse pointer displayId, and ensure that the calling thread is blocked
- // until the native callback happens.
- val countDownLatch = CountDownLatch(1)
- val overrideDisplayId = 123
- Thread {
- assertFalse("Setting virtual pointer display should be unsuccessful",
- localService.setVirtualMousePointerDisplayId(overrideDisplayId))
- countDownLatch.countDown()
- }.start()
- assertFalse("Setting virtual pointer display should block",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
-
- val x = 42f
- val y = 314f
- // Assume the native callback updates the pointerDisplayId to the incorrect value.
- service.onPointerDisplayIdChanged(Display.INVALID_DISPLAY, x, y)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(Display.INVALID_DISPLAY, x, y)
- assertTrue("Native callback unblocks calling thread",
- countDownLatch.await(100, TimeUnit.MILLISECONDS))
- verify(native).setPointerDisplayId(overrideDisplayId)
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun testSetVirtualMousePointerDisplayId_competingRequests() {
- val firstRequestSyncLatch = CountDownLatch(1)
- doAnswer {
- firstRequestSyncLatch.countDown()
- }.`when`(native).setPointerDisplayId(anyInt())
-
- val firstRequestLatch = CountDownLatch(1)
- val firstOverride = 123
- Thread {
- assertFalse("Setting virtual pointer display from thread 1 should be unsuccessful",
- localService.setVirtualMousePointerDisplayId(firstOverride))
- firstRequestLatch.countDown()
- }.start()
- assertFalse("Setting virtual pointer display should block",
- firstRequestLatch.await(100, TimeUnit.MILLISECONDS))
-
- assertTrue("Wait for first thread's request should succeed",
- firstRequestSyncLatch.await(100, TimeUnit.MILLISECONDS))
-
- val secondRequestLatch = CountDownLatch(1)
- val secondOverride = 42
- Thread {
- assertTrue("Setting virtual mouse pointer from thread 2 should be successful",
- localService.setVirtualMousePointerDisplayId(secondOverride))
- secondRequestLatch.countDown()
- }.start()
- assertFalse("Setting virtual mouse pointer should block",
- secondRequestLatch.await(100, TimeUnit.MILLISECONDS))
-
- val x = 42f
- val y = 314f
- // Assume the native callback updates directly to the second request.
- service.onPointerDisplayIdChanged(secondOverride, x, y)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(secondOverride, x, y)
- assertTrue("Native callback unblocks first thread",
- firstRequestLatch.await(100, TimeUnit.MILLISECONDS))
- assertTrue("Native callback unblocks second thread",
- secondRequestLatch.await(100, TimeUnit.MILLISECONDS))
- verify(native, times(2)).setPointerDisplayId(anyInt())
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun onDisplayRemoved_resetAllAdditionalInputProperties() {
- setVirtualMousePointerDisplayIdAndVerify(10)
-
- localService.setPointerIconVisible(false, 10)
- verify(native).setPointerIconVisibility(10, false)
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
- localService.setMousePointerAccelerationEnabled(false, 10)
- verify(native).setMousePointerAccelerationEnabled(10, false)
-
- service.onDisplayRemoved(10)
- verify(native).setPointerIconVisibility(10, true)
- verify(native).displayRemoved(eq(10))
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED))
- verify(native).setMousePointerAccelerationEnabled(10, true)
- verifyNoMoreInteractions(native)
-
- // This call should not block because the virtual mouse pointer override was never removed.
- localService.setVirtualMousePointerDisplayId(10)
-
- verify(native).setPointerDisplayId(eq(10))
- verifyNoMoreInteractions(native)
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun updateAdditionalInputPropertiesForOverrideDisplay() {
- setVirtualMousePointerDisplayIdAndVerify(10)
-
- localService.setPointerIconVisible(false, 10)
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
- verify(native).setPointerIconVisibility(10, false)
- localService.setMousePointerAccelerationEnabled(false, 10)
- verify(native).setMousePointerAccelerationEnabled(10, false)
-
- localService.setPointerIconVisible(true, 10)
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED))
- verify(native).setPointerIconVisibility(10, true)
- localService.setMousePointerAccelerationEnabled(true, 10)
- verify(native).setMousePointerAccelerationEnabled(10, true)
-
- localService.setPointerIconVisible(false, 20)
- verify(native).setPointerIconVisibility(20, false)
- localService.setMousePointerAccelerationEnabled(false, 20)
- verify(native).setMousePointerAccelerationEnabled(20, false)
- verifyNoMoreInteractions(native)
-
- clearInvocations(native)
- setVirtualMousePointerDisplayIdAndVerify(20)
-
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
- }
-
- @RequiresFlagsDisabled(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER)
- @Test
- fun setAdditionalInputPropertiesBeforeOverride() {
- localService.setPointerIconVisible(false, 10)
- localService.setMousePointerAccelerationEnabled(false, 10)
-
- verify(native).setPointerIconVisibility(10, false)
- verify(native).setMousePointerAccelerationEnabled(10, false)
- verifyNoMoreInteractions(native)
-
- setVirtualMousePointerDisplayIdAndVerify(10)
-
- verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
}
@Test
@@ -399,18 +205,172 @@ class InputManagerServiceTests {
verify(native, times(2)).changeKeyboardLayoutAssociation()
}
- private fun setVirtualMousePointerDisplayIdAndVerify(overrideDisplayId: Int) {
- val thread = Thread { localService.setVirtualMousePointerDisplayId(overrideDisplayId) }
- thread.start()
+ private fun createVirtualDisplays(count: Int): List<VirtualDisplay> {
+ val displayManager: DisplayManager = context.getSystemService(
+ DisplayManager::class.java
+ ) as DisplayManager
+ val virtualDisplays = mutableListOf<VirtualDisplay>()
+ for (i in 0 until count) {
+ virtualDisplays.add(displayManager.createVirtualDisplay(
+ /* displayName= */ "testVirtualDisplay$i",
+ /* width= */ 100,
+ /* height= */ 100,
+ /* densityDpi= */ 100,
+ /* surface= */ null,
+ /* flags= */ 0
+ ))
+ }
+ return virtualDisplays
+ }
+
+ // Helper function that creates a KeyEvent with Keycode A with the given action
+ private fun createKeycodeAEvent(inputDevice: InputDevice, action: Int): KeyEvent {
+ val eventTime = SystemClock.uptimeMillis()
+ return KeyEvent(
+ /* downTime= */ eventTime,
+ /* eventTime= */ eventTime,
+ /* action= */ action,
+ /* code= */ KeyEvent.KEYCODE_A,
+ /* repeat= */ 0,
+ /* metaState= */ 0,
+ /* deviceId= */ inputDevice.id,
+ /* scanCode= */ 0,
+ /* flags= */ KeyEvent.FLAG_FROM_SYSTEM,
+ /* source= */ InputDevice.SOURCE_KEYBOARD
+ )
+ }
+
+ private fun createInputDevice(): InputDevice {
+ return InputDevice.Builder()
+ .setId(123)
+ .setName("abc")
+ .setDescriptor("def")
+ .setSources(InputDevice.SOURCE_KEYBOARD)
+ .build()
+ }
- // Allow some time for the set override call to park while waiting for the native callback.
- Thread.sleep(100 /*millis*/)
- verify(native).setPointerDisplayId(overrideDisplayId)
+ @Test
+ fun addUniqueIdAssociationByDescriptor_verifyAssociations() {
+ // Overall goal is to have 2 displays and verify that events from the InputDevice are
+ // sent only to the view that is on the associated display.
+ // So, associate the InputDevice with display 1, then send and verify KeyEvents.
+ // Then remove associations, then associate the InputDevice with display 2, then send
+ // and verify commands.
+
+ // Make 2 virtual displays with some mock SurfaceViews
+ val mockSurfaceView1 = mock(SurfaceView::class.java)
+ val mockSurfaceView2 = mock(SurfaceView::class.java)
+ val mockSurfaceHolder1 = mock(SurfaceHolder::class.java)
+ `when`(mockSurfaceView1.holder).thenReturn(mockSurfaceHolder1)
+ val mockSurfaceHolder2 = mock(SurfaceHolder::class.java)
+ `when`(mockSurfaceView2.holder).thenReturn(mockSurfaceHolder2)
+
+ val virtualDisplays = createVirtualDisplays(2)
+
+ // Simulate an InputDevice
+ val inputDevice = createInputDevice()
+
+ // Associate input device with display
+ service.addUniqueIdAssociationByDescriptor(
+ inputDevice.descriptor,
+ virtualDisplays[0].display.displayId.toString()
+ )
+
+ // Simulate 2 different KeyEvents
+ val downEvent = createKeycodeAEvent(inputDevice, KeyEvent.ACTION_DOWN)
+ val upEvent = createKeycodeAEvent(inputDevice, KeyEvent.ACTION_UP)
+
+ // Create a mock OnKeyListener object
+ val mockOnKeyListener = mock(OnKeyListener::class.java)
+
+ // Verify that the event went to Display 1 not Display 2
+ service.injectInputEvent(downEvent, InputEventInjectionSync.NONE)
+
+ // Call the onKey method on the mock OnKeyListener object
+ mockOnKeyListener.onKey(mockSurfaceView1, /* keyCode= */ KeyEvent.KEYCODE_A, downEvent)
+ mockOnKeyListener.onKey(mockSurfaceView2, /* keyCode= */ KeyEvent.KEYCODE_A, upEvent)
+
+ // Verify that the onKey method was called with the expected arguments
+ verify(mockOnKeyListener).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, downEvent)
+ verify(mockOnKeyListener, never()).onKey(mockSurfaceView2, KeyEvent.KEYCODE_A, downEvent)
+
+ // Remove association
+ service.removeUniqueIdAssociationByDescriptor(inputDevice.descriptor)
+
+ // Associate with Display 2
+ service.addUniqueIdAssociationByDescriptor(
+ inputDevice.descriptor,
+ virtualDisplays[1].display.displayId.toString()
+ )
+
+ // Simulate a KeyEvent
+ service.injectInputEvent(upEvent, InputEventInjectionSync.NONE)
+
+ // Verify that the event went to Display 2 not Display 1
+ verify(mockOnKeyListener).onKey(mockSurfaceView2, KeyEvent.KEYCODE_A, upEvent)
+ verify(mockOnKeyListener, never()).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, upEvent)
+ }
- service.onPointerDisplayIdChanged(overrideDisplayId, 0f, 0f)
- testLooper.dispatchNext()
- verify(wmCallbacks).notifyPointerDisplayIdChanged(overrideDisplayId, 0f, 0f)
- thread.join(100 /*millis*/)
+ @Test
+ fun addUniqueIdAssociationByPort_verifyAssociations() {
+ // Overall goal is to have 2 displays and verify that events from the InputDevice are
+ // sent only to the view that is on the associated display.
+ // So, associate the InputDevice with display 1, then send and verify KeyEvents.
+ // Then remove associations, then associate the InputDevice with display 2, then send
+ // and verify commands.
+
+ // Make 2 virtual displays with some mock SurfaceViews
+ val mockSurfaceView1 = mock(SurfaceView::class.java)
+ val mockSurfaceView2 = mock(SurfaceView::class.java)
+ val mockSurfaceHolder1 = mock(SurfaceHolder::class.java)
+ `when`(mockSurfaceView1.holder).thenReturn(mockSurfaceHolder1)
+ val mockSurfaceHolder2 = mock(SurfaceHolder::class.java)
+ `when`(mockSurfaceView2.holder).thenReturn(mockSurfaceHolder2)
+
+ val virtualDisplays = createVirtualDisplays(2)
+
+ // Simulate an InputDevice
+ val inputDevice = createInputDevice()
+
+ // Associate input device with display
+ service.addUniqueIdAssociationByPort(
+ inputDevice.name,
+ virtualDisplays[0].display.displayId.toString()
+ )
+
+ // Simulate 2 different KeyEvents
+ val downEvent = createKeycodeAEvent(inputDevice, KeyEvent.ACTION_DOWN)
+ val upEvent = createKeycodeAEvent(inputDevice, KeyEvent.ACTION_UP)
+
+ // Create a mock OnKeyListener object
+ val mockOnKeyListener = mock(OnKeyListener::class.java)
+
+ // Verify that the event went to Display 1 not Display 2
+ service.injectInputEvent(downEvent, InputEventInjectionSync.NONE)
+
+ // Call the onKey method on the mock OnKeyListener object
+ mockOnKeyListener.onKey(mockSurfaceView1, /* keyCode= */ KeyEvent.KEYCODE_A, downEvent)
+ mockOnKeyListener.onKey(mockSurfaceView2, /* keyCode= */ KeyEvent.KEYCODE_A, upEvent)
+
+ // Verify that the onKey method was called with the expected arguments
+ verify(mockOnKeyListener).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, downEvent)
+ verify(mockOnKeyListener, never()).onKey(mockSurfaceView2, KeyEvent.KEYCODE_A, downEvent)
+
+ // Remove association
+ service.removeUniqueIdAssociationByPort(inputDevice.name)
+
+ // Associate with Display 2
+ service.addUniqueIdAssociationByPort(
+ inputDevice.name,
+ virtualDisplays[1].display.displayId.toString()
+ )
+
+ // Simulate a KeyEvent
+ service.injectInputEvent(upEvent, InputEventInjectionSync.NONE)
+
+ // Verify that the event went to Display 2 not Display 1
+ verify(mockOnKeyListener).onKey(mockSurfaceView2, KeyEvent.KEYCODE_A, upEvent)
+ verify(mockOnKeyListener, never()).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, upEvent)
}
}
diff --git a/tests/Input/src/com/android/server/input/InputShellCommandTest.java b/tests/Input/src/com/android/server/input/InputShellCommandTest.java
index f4845a518b20..11f46335f017 100644
--- a/tests/Input/src/com/android/server/input/InputShellCommandTest.java
+++ b/tests/Input/src/com/android/server/input/InputShellCommandTest.java
@@ -125,6 +125,14 @@ public class InputShellCommandTest {
assertThat(mInputEventInjector.mInjectedEvents).isEmpty();
}
+ @Test
+ public void testInvalidKeyEventCommandArgsCombination() {
+ // --duration and --longpress must not be sent together
+ runCommand("keyevent --duration 1000 --longpress KEYCODE_A");
+
+ assertThat(mInputEventInjector.mInjectedEvents).isEmpty();
+ }
+
private InputEvent getSingleInjectedInputEvent() {
assertThat(mInputEventInjector.mInjectedEvents).hasSize(1);
return mInputEventInjector.mInjectedEvents.get(0);
diff --git a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index e60764f137af..93f97cb4a7ee 100644
--- a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -33,7 +33,6 @@ import android.icu.util.ULocale
import android.os.Bundle
import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit
-import android.provider.Settings
import android.util.proto.ProtoOutputStream
import android.view.InputDevice
import android.view.inputmethod.InputMethodInfo
@@ -47,9 +46,7 @@ import com.android.test.input.R
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
-import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -234,631 +231,332 @@ class KeyboardLayoutManagerTests {
}
@Test
- fun testDefaultUi_getKeyboardLayouts() {
- NewSettingsApiFlag(false).use {
- val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
- assertNotEquals(
- "Default UI: Keyboard layout API should not return empty array",
- 0,
- keyboardLayouts.size
- )
- assertTrue(
- "Default UI: Keyboard layout API should provide English(US) layout",
- hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
- }
+ fun testGetKeyboardLayouts() {
+ val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+ assertNotEquals(
+ "Keyboard layout API should not return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue(
+ "Keyboard layout API should provide English(US) layout",
+ hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
}
@Test
- fun testNewUi_getKeyboardLayouts() {
- NewSettingsApiFlag(true).use {
- val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
- assertNotEquals(
- "New UI: Keyboard layout API should not return empty array",
- 0,
- keyboardLayouts.size
- )
- assertTrue(
- "New UI: Keyboard layout API should provide English(US) layout",
- hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
- }
+ fun testGetKeyboardLayout() {
+ val keyboardLayout =
+ keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
+ assertEquals("getKeyboardLayout API should return correct Layout from " +
+ "available layouts",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayout!!.descriptor
+ )
}
@Test
- fun testDefaultUi_getKeyboardLayoutsForInputDevice() {
- NewSettingsApiFlag(false).use {
- val keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
- assertNotEquals(
- "Default UI: getKeyboardLayoutsForInputDevice API should not return empty array",
- 0,
- keyboardLayouts.size
- )
- assertTrue(
- "Default UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
- "layout",
- hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
+ fun testGetSetKeyboardLayoutForInputDevice_withImeInfo() {
+ val imeSubtype = createImeSubtype()
- val vendorSpecificKeyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutsForInputDevice(
- vendorSpecificKeyboardDevice.identifier
- )
- assertEquals(
- "Default UI: getKeyboardLayoutsForInputDevice API should return only vendor " +
- "specific layout",
- 1,
- vendorSpecificKeyboardLayouts.size
- )
- assertEquals(
- "Default UI: getKeyboardLayoutsForInputDevice API should return vendor specific " +
- "layout",
- VENDOR_SPECIFIC_LAYOUT_DESCRIPTOR,
- vendorSpecificKeyboardLayouts[0].descriptor
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ var result =
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
)
- }
- }
+ assertEquals(
+ "getKeyboardLayoutForInputDevice API should return the set layout",
+ ENGLISH_UK_LAYOUT_DESCRIPTOR,
+ result.layoutDescriptor
+ )
- @Test
- fun testNewUi_getKeyboardLayoutsForInputDevice() {
- NewSettingsApiFlag(true).use {
- val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
- assertNotEquals(
- "New UI: getKeyboardLayoutsForInputDevice API should not return empty array",
- 0,
- keyboardLayouts.size
- )
- assertTrue(
- "New UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
- "layout",
- hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ // This should replace previously set layout
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ result =
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
)
- }
+ assertEquals(
+ "getKeyboardLayoutForInputDevice API should return the last set layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ result.layoutDescriptor
+ )
}
@Test
- fun testDefaultUi_getSetCurrentKeyboardLayoutForInputDevice() {
- NewSettingsApiFlag(false).use {
- assertNull(
- "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null if " +
- "nothing was set",
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
-
- keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier,
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- val keyboardLayout =
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- assertEquals(
- "Default UI: getCurrentKeyboardLayoutForInputDevice API should return the set " +
- "layout",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayout
+ fun testGetKeyboardLayoutListForInputDevice() {
+ // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
+ var keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("hi-Latn")
+ )
+ assertNotEquals(
+ "getKeyboardLayoutListForInputDevice API should return the list of " +
+ "supported layouts with matching script code",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+ "containing English(US) layout for hi-Latn",
+ containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+ "containing English(No script code) layout for hi-Latn",
+ containsLayout(
+ keyboardLayouts,
+ createLayoutDescriptor("keyboard_layout_english_without_script_code")
)
- }
- }
+ )
- @Test
- fun testNewUi_getSetCurrentKeyboardLayoutForInputDevice() {
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier,
- ENGLISH_US_LAYOUT_DESCRIPTOR
+ // Check Layouts for "hi" which by default uses 'Deva' script.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("hi")
)
- assertNull(
- "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null " +
- "even after setCurrentKeyboardLayoutForInputDevice",
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
- }
- }
+ assertEquals("getKeyboardLayoutListForInputDevice API should return empty " +
+ "list if no supported layouts available",
+ 0,
+ keyboardLayouts.size
+ )
- @Test
- fun testDefaultUi_getEnabledKeyboardLayoutsForInputDevice() {
- NewSettingsApiFlag(false).use {
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ // If user manually selected some layout, always provide it in the layout list
+ val imeSubtype = createImeSubtypeForLanguageTag("hi")
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ imeSubtype
)
-
- val keyboardLayouts =
- keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
- keyboardDevice.identifier
- )
- assertEquals(
- "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return added " +
- "layout",
+ assertEquals("getKeyboardLayoutListForInputDevice API should return user " +
+ "selected layout even if the script is incompatible with IME",
1,
- keyboardLayouts.size
- )
- assertEquals(
- "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return " +
- "English(US) layout",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayouts[0]
- )
- assertEquals(
- "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
- "English(US) layout (Auto select the first enabled layout)",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
-
- keyboardLayoutManager.removeKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- assertEquals(
- "Default UI: getKeyboardLayoutsForInputDevice API should return 0 layouts",
- 0,
- keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
- keyboardDevice.identifier
- ).size
- )
- assertNull(
- "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null after " +
- "the enabled layout is removed",
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
- }
- }
-
- @Test
- fun testNewUi_getEnabledKeyboardLayoutsForInputDevice() {
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
- )
-
- assertEquals(
- "New UI: getEnabledKeyboardLayoutsForInputDevice API should return always return " +
- "an empty array",
- 0,
- keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
- keyboardDevice.identifier
- ).size
- )
- assertNull(
- "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null",
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
- }
- }
-
- @Test
- fun testDefaultUi_switchKeyboardLayout() {
- NewSettingsApiFlag(false).use {
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
- assertEquals(
- "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
- "English(US) layout",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
-
- keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
-
- // Throws null pointer because trying to show toast using TestLooper
- assertThrows(NullPointerException::class.java) { testLooper.dispatchAll() }
- assertEquals("Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
- "English(UK) layout",
- ENGLISH_UK_LAYOUT_DESCRIPTOR,
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
- }
- }
-
- @Test
- fun testNewUi_switchKeyboardLayout() {
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- keyboardLayoutManager.addKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
-
- keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
- testLooper.dispatchAll()
-
- assertNull("New UI: getCurrentKeyboardLayoutForInputDevice API should always return " +
- "null",
- keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
- keyboardDevice.identifier
- )
- )
- }
- }
-
- @Test
- fun testDefaultUi_getKeyboardLayout() {
- NewSettingsApiFlag(false).use {
- val keyboardLayout =
- keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
- assertEquals("Default UI: getKeyboardLayout API should return correct Layout from " +
- "available layouts",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayout!!.descriptor
- )
- }
- }
-
- @Test
- fun testNewUi_getKeyboardLayout() {
- NewSettingsApiFlag(true).use {
- val keyboardLayout =
- keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
- assertEquals("New UI: getKeyboardLayout API should return correct Layout from " +
- "available layouts",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- keyboardLayout!!.descriptor
- )
- }
- }
-
- @Test
- fun testDefaultUi_getSetKeyboardLayoutForInputDevice_WithImeInfo() {
- NewSettingsApiFlag(false).use {
- val imeSubtype = createImeSubtype()
- keyboardLayoutManager.setKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
- ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
- assertEquals(
- "Default UI: getKeyboardLayoutForInputDevice API should always return " +
- "KeyboardLayoutSelectionResult.FAILED",
- KeyboardLayoutSelectionResult.FAILED,
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
- )
- )
- }
- }
-
- @Test
- fun testNewUi_getSetKeyboardLayoutForInputDevice_withImeInfo() {
- NewSettingsApiFlag(true).use {
- val imeSubtype = createImeSubtype()
-
- keyboardLayoutManager.setKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
- ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
- var result =
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
- )
- assertEquals(
- "New UI: getKeyboardLayoutForInputDevice API should return the set layout",
- ENGLISH_UK_LAYOUT_DESCRIPTOR,
- result.layoutDescriptor
- )
-
- // This should replace previously set layout
- keyboardLayoutManager.setKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- result =
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
- )
- assertEquals(
- "New UI: getKeyboardLayoutForInputDevice API should return the last set layout",
- ENGLISH_US_LAYOUT_DESCRIPTOR,
- result.layoutDescriptor
- )
- }
- }
-
- @Test
- fun testDefaultUi_getKeyboardLayoutListForInputDevice() {
- NewSettingsApiFlag(false).use {
- val keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtype()
- )
- assertEquals("Default UI: getKeyboardLayoutListForInputDevice API should always " +
- "return empty array",
- 0,
- keyboardLayouts.size
- )
- }
- }
+ keyboardLayouts.size
+ )
- @Test
- fun testNewUi_getKeyboardLayoutListForInputDevice() {
- NewSettingsApiFlag(true).use {
- // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
- var keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ // Special case Japanese: UScript ignores provided script code for certain language tags
+ // Should manually match provided script codes and then rely on Uscript to derive
+ // script from language tags and match those.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("hi-Latn")
- )
- assertNotEquals(
- "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
- "supported layouts with matching script code",
- 0,
- keyboardLayouts.size
+ createImeSubtypeForLanguageTag("ja-Latn-JP")
)
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
- "containing English(US) layout for hi-Latn",
- containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
- "containing English(No script code) layout for hi-Latn",
- containsLayout(
- keyboardLayouts,
- createLayoutDescriptor("keyboard_layout_english_without_script_code")
- )
+ assertNotEquals(
+ "getKeyboardLayoutListForInputDevice API should return the list of " +
+ "supported layouts with matching script code for ja-Latn-JP",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+ "containing English(US) layout for ja-Latn-JP",
+ containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+ "containing English(No script code) layout for ja-Latn-JP",
+ containsLayout(
+ keyboardLayouts,
+ createLayoutDescriptor("keyboard_layout_english_without_script_code")
)
+ )
- // Check Layouts for "hi" which by default uses 'Deva' script.
- keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ // If script code not explicitly provided for Japanese should rely on Uscript to find
+ // derived script code and hence no suitable layout will be found.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("hi")
- )
- assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return empty " +
- "list if no supported layouts available",
- 0,
- keyboardLayouts.size
+ createImeSubtypeForLanguageTag("ja-JP")
)
+ assertEquals(
+ "getKeyboardLayoutListForInputDevice API should return empty list of " +
+ "supported layouts with matching script code for ja-JP",
+ 0,
+ keyboardLayouts.size
+ )
- // If user manually selected some layout, always provide it in the layout list
- val imeSubtype = createImeSubtypeForLanguageTag("hi")
- keyboardLayoutManager.setKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- imeSubtype
- )
- assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return user " +
- "selected layout even if the script is incompatible with IME",
- 1,
- keyboardLayouts.size
- )
-
- // Special case Japanese: UScript ignores provided script code for certain language tags
- // Should manually match provided script codes and then rely on Uscript to derive
- // script from language tags and match those.
- keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("ja-Latn-JP")
- )
- assertNotEquals(
- "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
- "supported layouts with matching script code for ja-Latn-JP",
- 0,
- keyboardLayouts.size
- )
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
- "containing English(US) layout for ja-Latn-JP",
- containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
- "containing English(No script code) layout for ja-Latn-JP",
- containsLayout(
- keyboardLayouts,
- createLayoutDescriptor("keyboard_layout_english_without_script_code")
- )
- )
-
- // If script code not explicitly provided for Japanese should rely on Uscript to find
- // derived script code and hence no suitable layout will be found.
- keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("ja-JP")
- )
- assertEquals(
- "New UI: getKeyboardLayoutListForInputDevice API should return empty list of " +
- "supported layouts with matching script code for ja-JP",
- 0,
- keyboardLayouts.size
- )
-
- // If IME doesn't have a corresponding language tag, then should show all available
- // layouts no matter the script code.
- keyboardLayouts =
- keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo, null
- )
- assertNotEquals(
- "New UI: getKeyboardLayoutListForInputDevice API should return all layouts if" +
- "language tag or subtype not provided",
- 0,
- keyboardLayouts.size
- )
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Latin " +
- "layouts if language tag or subtype not provided",
- containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
- )
- assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
- "layouts if language tag or subtype not provided",
- containsLayout(
- keyboardLayouts,
- createLayoutDescriptor("keyboard_layout_russian")
- )
- )
- }
- }
-
- @Test
- fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
- NewSettingsApiFlag(true).use {
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTag("en-US"),
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTag("en-GB"),
- ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTag("de"),
- GERMAN_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTag("fr-FR"),
- createLayoutDescriptor("keyboard_layout_french")
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTag("ru"),
+ // If IME doesn't have a corresponding language tag, then should show all available
+ // layouts no matter the script code.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, null
+ )
+ assertNotEquals(
+ "getKeyboardLayoutListForInputDevice API should return all layouts if" +
+ "language tag or subtype not provided",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should contain Latin " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ assertTrue("getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(
+ keyboardLayouts,
createLayoutDescriptor("keyboard_layout_russian")
)
- assertEquals(
- "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
- "KeyboardLayoutSelectionResult.FAILED when no layout available",
- KeyboardLayoutSelectionResult.FAILED,
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("it")
- )
- )
- assertEquals(
- "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
- "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
- "available",
- KeyboardLayoutSelectionResult.FAILED,
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTag("en-Deva")
- )
- )
- }
+ )
}
@Test
- fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
- NewSettingsApiFlag(true).use {
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
- createLayoutDescriptor("keyboard_layout_english_us_dvorak")
- )
- // Try to match layout type even if country doesn't match
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
- createLayoutDescriptor("keyboard_layout_english_us_dvorak")
- )
- // Choose layout based on layout type priority, if layout type is not provided by IME
- // (Qwerty > Dvorak > Extended)
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
- ENGLISH_US_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
- ENGLISH_UK_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
- GERMAN_LAYOUT_DESCRIPTOR
- )
- // Wrong layout type should match with language if provided layout type not available
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
- GERMAN_LAYOUT_DESCRIPTOR
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
- createLayoutDescriptor("keyboard_layout_french")
- )
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
- createLayoutDescriptor("keyboard_layout_russian_qwerty")
- )
- // If layout type is empty then prioritize KCM with empty layout type
- assertCorrectLayout(
- keyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
- createLayoutDescriptor("keyboard_layout_russian")
+ fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("en-US"),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("en-GB"),
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("de"),
+ GERMAN_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("fr-FR"),
+ createLayoutDescriptor("keyboard_layout_french")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("ru"),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ assertEquals(
+ "getDefaultKeyboardLayoutForInputDevice should return " +
+ "KeyboardLayoutSelectionResult.FAILED when no layout available",
+ KeyboardLayoutSelectionResult.FAILED,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("it")
)
- assertEquals("New UI: getDefaultKeyboardLayoutForInputDevice should return " +
+ )
+ assertEquals(
+ "getDefaultKeyboardLayoutForInputDevice should return " +
"KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
"available",
- KeyboardLayoutSelectionResult.FAILED,
- keyboardLayoutManager.getKeyboardLayoutForInputDevice(
- keyboardDevice.identifier, USER_ID, imeInfo,
- createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
- )
+ KeyboardLayoutSelectionResult.FAILED,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("en-Deva")
)
- }
+ )
}
@Test
- fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
- NewSettingsApiFlag(true).use {
- val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
- // Should return English dvorak even if IME current layout is French, since HW says the
- // keyboard is a Dvorak keyboard
- assertCorrectLayout(
- englishDvorakKeyboardDevice,
- frenchSubtype,
- createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
+ // Try to match layout type even if country doesn't match
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
+ // Choose layout based on layout type priority, if layout type is not provided by IME
+ // (Qwerty > Dvorak > Extended)
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
+ GERMAN_LAYOUT_DESCRIPTOR
+ )
+ // Wrong layout type should match with language if provided layout type not available
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
+ GERMAN_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
+ createLayoutDescriptor("keyboard_layout_french")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
+ createLayoutDescriptor("keyboard_layout_russian_qwerty")
+ )
+ // If layout type is empty then prioritize KCM with empty layout type
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ assertEquals("getDefaultKeyboardLayoutForInputDevice should return " +
+ "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
+ "available",
+ KeyboardLayoutSelectionResult.FAILED,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
)
+ )
+ // If prefer layout with empty country over mismatched country
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-AU", "qwerty"),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ }
- // Back to back changing HW keyboards with same product and vendor ID but different
- // language and layout type should configure the layouts correctly.
- assertCorrectLayout(
- englishQwertyKeyboardDevice,
- frenchSubtype,
- createLayoutDescriptor("keyboard_layout_english_us")
- )
+ @Test
+ fun testGetDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
+ val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
+ // Should return English dvorak even if IME current layout is French, since HW says the
+ // keyboard is a Dvorak keyboard
+ assertCorrectLayout(
+ englishDvorakKeyboardDevice,
+ frenchSubtype,
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
- // Fallback to IME information if the HW provided layout script is incompatible with the
- // provided IME subtype
- assertCorrectLayout(
- englishDvorakKeyboardDevice,
- createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
- createLayoutDescriptor("keyboard_layout_russian")
- )
- }
+ // Back to back changing HW keyboards with same product and vendor ID but different
+ // language and layout type should configure the layouts correctly.
+ assertCorrectLayout(
+ englishQwertyKeyboardDevice,
+ frenchSubtype,
+ createLayoutDescriptor("keyboard_layout_english_us")
+ )
+
+ // Fallback to IME information if the HW provided layout script is incompatible with the
+ // provided IME subtype
+ assertCorrectLayout(
+ englishDvorakKeyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
}
@Test
@@ -867,27 +565,25 @@ class KeyboardLayoutManagerTests {
KeyboardLayoutManager.ImeInfo(0, imeInfo,
createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
- ExtendedMockito.verify {
- FrameworkStatsLog.write(
- ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.eq(keyboardDevice.vendorId),
- ArgumentMatchers.eq(keyboardDevice.productId),
- ArgumentMatchers.eq(
- createByteArray(
- KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
- LAYOUT_TYPE_DEFAULT,
- GERMAN_LAYOUT_NAME,
- KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
- "de-Latn",
- LAYOUT_TYPE_QWERTZ
- ),
+ keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(
+ ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+ ArgumentMatchers.anyBoolean(),
+ ArgumentMatchers.eq(keyboardDevice.vendorId),
+ ArgumentMatchers.eq(keyboardDevice.productId),
+ ArgumentMatchers.eq(
+ createByteArray(
+ KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+ LAYOUT_TYPE_DEFAULT,
+ GERMAN_LAYOUT_NAME,
+ KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
+ "de-Latn",
+ LAYOUT_TYPE_QWERTZ
),
- ArgumentMatchers.eq(keyboardDevice.deviceBus),
- )
- }
+ ),
+ ArgumentMatchers.eq(keyboardDevice.deviceBus),
+ )
}
}
@@ -897,27 +593,25 @@ class KeyboardLayoutManagerTests {
KeyboardLayoutManager.ImeInfo(0, imeInfo,
createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
- ExtendedMockito.verify {
- FrameworkStatsLog.write(
- ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
- ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
- ArgumentMatchers.eq(
- createByteArray(
- "en",
- LAYOUT_TYPE_QWERTY,
- ENGLISH_US_LAYOUT_NAME,
- KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
- "de-Latn",
- LAYOUT_TYPE_QWERTZ
- )
- ),
- ArgumentMatchers.eq(keyboardDevice.deviceBus),
- )
- }
+ keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(
+ ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+ ArgumentMatchers.anyBoolean(),
+ ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
+ ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
+ ArgumentMatchers.eq(
+ createByteArray(
+ "en",
+ LAYOUT_TYPE_QWERTY,
+ ENGLISH_US_LAYOUT_NAME,
+ KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
+ "de-Latn",
+ LAYOUT_TYPE_QWERTZ
+ )
+ ),
+ ArgumentMatchers.eq(keyboardDevice.deviceBus),
+ )
}
}
@@ -925,27 +619,25 @@ class KeyboardLayoutManagerTests {
fun testConfigurationLogged_onInputDeviceAdded_DefaultSelection() {
val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
- ExtendedMockito.verify {
- FrameworkStatsLog.write(
- ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.eq(keyboardDevice.vendorId),
- ArgumentMatchers.eq(keyboardDevice.productId),
- ArgumentMatchers.eq(
- createByteArray(
- KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
- LAYOUT_TYPE_DEFAULT,
- "Default",
- KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
- KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
- LAYOUT_TYPE_DEFAULT
- ),
+ keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(
+ ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+ ArgumentMatchers.anyBoolean(),
+ ArgumentMatchers.eq(keyboardDevice.vendorId),
+ ArgumentMatchers.eq(keyboardDevice.productId),
+ ArgumentMatchers.eq(
+ createByteArray(
+ KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+ LAYOUT_TYPE_DEFAULT,
+ "Default",
+ KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
+ KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+ LAYOUT_TYPE_DEFAULT
),
- ArgumentMatchers.eq(keyboardDevice.deviceBus),
- )
- }
+ ),
+ ArgumentMatchers.eq(keyboardDevice.deviceBus),
+ )
}
}
@@ -953,19 +645,17 @@ class KeyboardLayoutManagerTests {
fun testConfigurationNotLogged_onInputDeviceChanged() {
val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
- ExtendedMockito.verify({
- FrameworkStatsLog.write(
- ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any(ByteArray::class.java),
- ArgumentMatchers.anyInt(),
- )
- }, Mockito.times(0))
- }
+ keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+ ExtendedMockito.verify({
+ FrameworkStatsLog.write(
+ ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+ ArgumentMatchers.anyBoolean(),
+ ArgumentMatchers.anyInt(),
+ ArgumentMatchers.anyInt(),
+ ArgumentMatchers.any(ByteArray::class.java),
+ ArgumentMatchers.anyInt(),
+ )
+ }, Mockito.times(0))
}
@Test
@@ -975,18 +665,16 @@ class KeyboardLayoutManagerTests {
Mockito.doReturn(false).`when`(keyboardLayoutManager).isVirtualDevice(
ArgumentMatchers.eq(keyboardDevice.id)
)
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
- ExtendedMockito.verify(
- notificationManager,
- Mockito.times(1)
- ).notifyAsUser(
- ArgumentMatchers.isNull(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any(),
- ArgumentMatchers.any()
- )
- }
+ keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+ ExtendedMockito.verify(
+ notificationManager,
+ Mockito.times(1)
+ ).notifyAsUser(
+ ArgumentMatchers.isNull(),
+ ArgumentMatchers.anyInt(),
+ ArgumentMatchers.any(),
+ ArgumentMatchers.any()
+ )
}
@Test
@@ -996,18 +684,16 @@ class KeyboardLayoutManagerTests {
Mockito.doReturn(true).`when`(keyboardLayoutManager).isVirtualDevice(
ArgumentMatchers.eq(keyboardDevice.id)
)
- NewSettingsApiFlag(true).use {
- keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
- ExtendedMockito.verify(
- notificationManager,
- Mockito.never()
- ).notifyAsUser(
- ArgumentMatchers.isNull(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any(),
- ArgumentMatchers.any()
- )
- }
+ keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+ ExtendedMockito.verify(
+ notificationManager,
+ Mockito.never()
+ ).notifyAsUser(
+ ArgumentMatchers.isNull(),
+ ArgumentMatchers.anyInt(),
+ ArgumentMatchers.any(),
+ ArgumentMatchers.any()
+ )
}
private fun assertCorrectLayout(
@@ -1019,7 +705,7 @@ class KeyboardLayoutManagerTests {
device.identifier, USER_ID, imeInfo, imeSubtype
)
assertEquals(
- "New UI: getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
+ "getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
expectedLayout,
result.layoutDescriptor
)
@@ -1123,21 +809,4 @@ class KeyboardLayoutManagerTests {
info.serviceInfo.name = RECEIVER_NAME
return info
}
-
- private inner class NewSettingsApiFlag constructor(enabled: Boolean) : AutoCloseable {
- init {
- Settings.Global.putString(
- context.contentResolver,
- "settings_new_keyboard_ui", enabled.toString()
- )
- }
-
- override fun close() {
- Settings.Global.putString(
- context.contentResolver,
- "settings_new_keyboard_ui",
- ""
- )
- }
- }
}
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 4893d14ad79b..d32cedb24a36 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -21,26 +21,33 @@ import androidx.test.filters.MediumTest
import android.app.ActivityManager
import android.app.ApplicationExitInfo
+import android.content.Context
import android.graphics.Rect
+import android.hardware.display.DisplayManager
import android.os.Build
import android.os.IInputConstants.UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS
import android.os.SystemClock
import android.provider.Settings
import android.provider.Settings.Global.HIDE_ERROR_DIALOGS
+import android.server.wm.CtsWindowInfoUtils.waitForStableWindowGeometry
import android.testing.PollingCheck
-import android.view.InputDevice
-import android.view.MotionEvent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
+import com.android.cts.input.DebugInputRule
+import com.android.cts.input.UinputTouchScreen
+
+import java.time.Duration
+
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -69,6 +76,9 @@ class AnrTest {
private val DISPATCHING_TIMEOUT = (UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
Build.HW_TIMEOUT_MULTIPLIER)
+ @get:Rule
+ val debugInputRule = DebugInputRule()
+
@Before
fun setUp() {
val contentResolver = instrumentation.targetContext.contentResolver
@@ -84,12 +94,14 @@ class AnrTest {
}
@Test
+ @DebugInputRule.DebugInput(bug = 339924248)
fun testGestureMonitorAnr_Close() {
triggerAnr()
clickCloseAppOnAnrDialog()
}
@Test
+ @DebugInputRule.DebugInput(bug = 339924248)
fun testGestureMonitorAnr_Wait() {
triggerAnr()
clickWaitOnAnrDialog()
@@ -105,7 +117,7 @@ class AnrTest {
val closeAppButton: UiObject2? =
uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000)
if (closeAppButton == null) {
- fail("Could not find anr dialog")
+ fail("Could not find anr dialog/close button")
return
}
closeAppButton.click()
@@ -150,6 +162,18 @@ class AnrTest {
assertEquals(ApplicationExitInfo.REASON_ANR, reasons[0].reason)
}
+ private fun clickOnObject(obj: UiObject2) {
+ val displayManager =
+ instrumentation.context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+ val display = displayManager.getDisplay(obj.getDisplayId())
+ val touchScreen = UinputTouchScreen(instrumentation, display)
+
+ val rect: Rect = obj.visibleBounds
+ val pointer = touchScreen.touchDown(rect.centerX(), rect.centerY())
+ pointer.lift()
+ touchScreen.close()
+ }
+
private fun triggerAnr() {
startUnresponsiveActivity()
val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
@@ -160,13 +184,7 @@ class AnrTest {
return
}
- val rect: Rect = obj.visibleBounds
- val downTime = SystemClock.uptimeMillis()
- val downEvent = MotionEvent.obtain(downTime, downTime,
- MotionEvent.ACTION_DOWN, rect.left.toFloat(), rect.top.toFloat(), 0 /* metaState */)
- downEvent.source = InputDevice.SOURCE_TOUCHSCREEN
-
- instrumentation.uiAutomation.injectInputEvent(downEvent, false /* sync*/)
+ clickOnObject(obj)
SystemClock.sleep(DISPATCHING_TIMEOUT.toLong()) // default ANR timeout for gesture monitors
}
@@ -175,5 +193,6 @@ class AnrTest {
val flags = " -W -n "
val startCmd = "am start $flags $PACKAGE_NAME/.UnresponsiveGestureMonitorActivity"
instrumentation.uiAutomation.executeShellCommand(startCmd)
+ waitForStableWindowGeometry(Duration.ofSeconds(5))
}
}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index 5f1bc8748db8..87a0de63120e 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -61,6 +61,7 @@ public class InputDeviceTest {
assertEquals(device.getMotionRanges().size(), outDevice.getMotionRanges().size());
assertEquals(device.getHostUsiVersion(), outDevice.getHostUsiVersion());
assertEquals(device.getAssociatedDisplayId(), outDevice.getAssociatedDisplayId());
+ assertEquals(device.isEnabled(), outDevice.isEnabled());
KeyCharacterMap keyCharacterMap = device.getKeyCharacterMap();
KeyCharacterMap outKeyCharacterMap = outDevice.getKeyCharacterMap();
@@ -100,7 +101,9 @@ public class InputDeviceTest {
.setKeyboardLanguageTag("en-US")
.setKeyboardLayoutType("qwerty")
.setUsiVersion(new HostUsiVersion(2, 0))
- .setShouldSmoothScroll(true);
+ .setShouldSmoothScroll(true)
+ .setAssociatedDisplayId(Display.DEFAULT_DISPLAY)
+ .setEnabled(false);
for (int i = 0; i < 30; i++) {
deviceBuilder.addMotionRange(
diff --git a/tests/Input/src/com/android/test/input/PointerIconLoadingTest.kt b/tests/Input/src/com/android/test/input/PointerIconLoadingTest.kt
new file mode 100644
index 000000000000..d196b85a7466
--- /dev/null
+++ b/tests/Input/src/com/android/test/input/PointerIconLoadingTest.kt
@@ -0,0 +1,136 @@
+/*
+ * 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.test.input
+
+import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.os.Environment
+import android.view.ContextThemeWrapper
+import android.view.PointerIcon
+import android.view.flags.Flags.enableVectorCursorA11ySettings
+import android.view.flags.Flags.enableVectorCursors
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+import platform.test.screenshot.GoldenPathManager
+import platform.test.screenshot.PathConfig
+import platform.test.screenshot.ScreenshotTestRule
+import platform.test.screenshot.assertAgainstGolden
+import platform.test.screenshot.matchers.BitmapMatcher
+import platform.test.screenshot.matchers.PixelPerfectMatcher
+
+/**
+ * Unit tests for PointerIcon.
+ *
+ * Run with:
+ * atest InputTests:com.android.test.input.PointerIconLoadingTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class PointerIconLoadingTest {
+ private lateinit var context: Context
+ private lateinit var exactScreenshotMatcher: BitmapMatcher
+
+ @get:Rule
+ val testName = TestName()
+
+ @get:Rule
+ val screenshotRule = ScreenshotTestRule(GoldenPathManager(
+ InstrumentationRegistry.getInstrumentation().getContext(),
+ ASSETS_PATH,
+ TEST_OUTPUT_PATH,
+ PathConfig()
+ ), disableIconPool = false)
+
+ @Before
+ fun setUp() {
+ context = InstrumentationRegistry.getInstrumentation().targetContext
+ val config =
+ Configuration(context.resources.configuration).apply {
+ densityDpi = DENSITY_DPI
+ screenWidthDp = SCREEN_WIDTH_DP
+ screenHeightDp = SCREEN_HEIGHT_DP
+ smallestScreenWidthDp = SCREEN_WIDTH_DP
+ }
+ context = context.createConfigurationContext(config)
+
+ exactScreenshotMatcher = PixelPerfectMatcher()
+ }
+
+ @Test
+ fun testPointerFillStyle() {
+ assumeTrue(enableVectorCursors())
+ assumeTrue(enableVectorCursorA11ySettings())
+
+ val theme: Resources.Theme = context.getResources().newTheme()
+ theme.setTo(context.getTheme())
+ theme.applyStyle(
+ PointerIcon.vectorFillStyleToResource(PointerIcon.POINTER_ICON_VECTOR_STYLE_FILL_GREEN),
+ /* force= */ true)
+
+ val pointerIcon =
+ PointerIcon.getLoadedSystemIcon(
+ ContextThemeWrapper(context, theme),
+ PointerIcon.TYPE_ARROW,
+ /* useLargeIcons= */ false,
+ /* pointerScale= */ 1f)
+
+ pointerIcon.getBitmap().assertAgainstGolden(
+ screenshotRule,
+ testName.methodName,
+ exactScreenshotMatcher
+ )
+ }
+
+ @Test
+ fun testPointerScale() {
+ assumeTrue(enableVectorCursors())
+ assumeTrue(enableVectorCursorA11ySettings())
+
+ val pointerScale = 2f
+
+ val pointerIcon =
+ PointerIcon.getLoadedSystemIcon(
+ context,
+ PointerIcon.TYPE_ARROW,
+ /* useLargeIcons= */ false,
+ pointerScale)
+
+ pointerIcon.getBitmap().assertAgainstGolden(
+ screenshotRule,
+ testName.methodName,
+ exactScreenshotMatcher
+ )
+ }
+
+ companion object {
+ const val DENSITY_DPI = 160
+ const val SCREEN_WIDTH_DP = 480
+ const val SCREEN_HEIGHT_DP = 800
+ const val ASSETS_PATH = "tests/input/assets"
+ val TEST_OUTPUT_PATH = Environment.getExternalStorageDirectory().absolutePath +
+ "/InputTests/" +
+ PointerIconLoadingTest::class.java.simpleName
+ }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
index c0c60eff0f9f..d03338909bb7 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
@@ -393,6 +393,7 @@ public final class ImeStressTestUtil {
mEditText.setFocusableInTouchMode(false);
}
rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ rootView.setFitsSystemWindows(true);
setContentView(rootView);
if (requestFocus) {
diff --git a/tests/InputScreenshotTest/assets/phone/light_landscape_layout-preview.png b/tests/InputScreenshotTest/assets/phone/light_landscape_layout-preview.png
index 443de8edc2d3..7cdab94534b0 100644
--- a/tests/InputScreenshotTest/assets/phone/light_landscape_layout-preview.png
+++ b/tests/InputScreenshotTest/assets/phone/light_landscape_layout-preview.png
Binary files differ
diff --git a/tests/InputScreenshotTest/assets/phone/light_portrait_layout-preview.png b/tests/InputScreenshotTest/assets/phone/light_portrait_layout-preview.png
index c51da052f4bf..377288d4aa2d 100644
--- a/tests/InputScreenshotTest/assets/phone/light_portrait_layout-preview.png
+++ b/tests/InputScreenshotTest/assets/phone/light_portrait_layout-preview.png
Binary files differ
diff --git a/tests/InputScreenshotTest/assets/tablet/dark_portrait_layout-preview.png b/tests/InputScreenshotTest/assets/tablet/dark_portrait_layout-preview.png
index ab23401bf629..68b147338a1d 100644
--- a/tests/InputScreenshotTest/assets/tablet/dark_portrait_layout-preview.png
+++ b/tests/InputScreenshotTest/assets/tablet/dark_portrait_layout-preview.png
Binary files differ
diff --git a/tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenImagePathManager.kt b/tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenPathManager.kt
index 8faf22440828..9f14b136861f 100644
--- a/tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenImagePathManager.kt
+++ b/tests/InputScreenshotTest/src/android/input/screenshot/InputGoldenPathManager.kt
@@ -17,28 +17,25 @@
package com.android.input.screenshot
import androidx.test.platform.app.InstrumentationRegistry
-import platform.test.screenshot.GoldenImagePathManager
+import platform.test.screenshot.GoldenPathManager
import platform.test.screenshot.PathConfig
-/** A [GoldenImagePathManager] that should be used for all Input screenshot tests. */
-class InputGoldenImagePathManager(
- pathConfig: PathConfig,
- assetsPathRelativeToBuildRoot: String
-) :
- GoldenImagePathManager(
- appContext = InstrumentationRegistry.getInstrumentation().context,
- assetsPathRelativeToBuildRoot = assetsPathRelativeToBuildRoot,
- deviceLocalPath =
- InstrumentationRegistry.getInstrumentation()
- .targetContext
- .filesDir
- .absolutePath
- .toString() + "/input_screenshots",
- pathConfig = pathConfig,
- ) {
+/** A [GoldenPathManager] that should be used for all Input screenshot tests. */
+class InputGoldenPathManager(pathConfig: PathConfig, assetsPathRelativeToBuildRoot: String) :
+ GoldenPathManager(
+ appContext = InstrumentationRegistry.getInstrumentation().context,
+ assetsPathRelativeToBuildRoot = assetsPathRelativeToBuildRoot,
+ deviceLocalPath =
+ InstrumentationRegistry.getInstrumentation()
+ .targetContext
+ .filesDir
+ .absolutePath
+ .toString() + "/input_screenshots",
+ pathConfig = pathConfig,
+ ) {
override fun toString(): String {
// This string is appended to all actual/expected screenshots on the device, so make sure
// it is a static value.
- return "InputGoldenImagePathManager"
+ return "InputGoldenPathManager"
}
-} \ No newline at end of file
+}
diff --git a/tests/InputScreenshotTest/src/android/input/screenshot/InputScreenshotTestRule.kt b/tests/InputScreenshotTest/src/android/input/screenshot/InputScreenshotTestRule.kt
index 75dab41d3609..2f408964fd8c 100644
--- a/tests/InputScreenshotTest/src/android/input/screenshot/InputScreenshotTestRule.kt
+++ b/tests/InputScreenshotTest/src/android/input/screenshot/InputScreenshotTestRule.kt
@@ -44,7 +44,7 @@ class InputScreenshotTestRule(
private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
private val screenshotRule =
ScreenshotTestRule(
- InputGoldenImagePathManager(
+ InputGoldenPathManager(
getEmulatedDevicePathConfig(emulationSpec),
assetsPathRelativeToBuildRoot
)
diff --git a/tests/Internal/TEST_MAPPING b/tests/Internal/TEST_MAPPING
new file mode 100644
index 000000000000..20af0287da5a
--- /dev/null
+++ b/tests/Internal/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "InternalTests"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
index d9a4c261ee15..5a27593c7a36 100644
--- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
@@ -90,7 +90,7 @@ public class LegacyProtoLogImplTest {
//noinspection ResultOfMethodCallIgnored
mFile.delete();
mProtoLog = new LegacyProtoLogImpl(mFile, mViewerConfigFilename,
- 1024 * 1024, mReader, 1024, new TreeMap<>());
+ 1024 * 1024, mReader, 1024, new TreeMap<>(), () -> {});
}
@After
@@ -393,5 +393,10 @@ public class LegacyProtoLogImplTest {
this.mLogToLogcat = logToLogcat;
}
+ @Override
+ public int getId() {
+ return ordinal();
+ }
+
}
}
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 548adeff07b2..1d7b6b348e10 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -65,6 +65,7 @@ import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
import perfetto.protos.Protolog;
import perfetto.protos.ProtologCommon;
@@ -95,6 +96,7 @@ public class PerfettoProtoLogImplTest {
private PerfettoProtoLogImpl mProtoLog;
private Protolog.ProtoLogViewerConfig.Builder mViewerConfigBuilder;
private File mFile;
+ private Runnable mCacheUpdater;
private ProtoLogViewerConfigReader mReader;
@@ -152,9 +154,11 @@ public class PerfettoProtoLogImplTest {
Mockito.when(viewerConfigInputStreamProvider.getInputStream())
.thenAnswer(it -> new ProtoInputStream(mViewerConfigBuilder.build().toByteArray()));
+ mCacheUpdater = () -> {};
mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
- mProtoLog =
- new PerfettoProtoLogImpl(viewerConfigInputStreamProvider, mReader, new TreeMap<>());
+ mProtoLog = new PerfettoProtoLogImpl(
+ viewerConfigInputStreamProvider, mReader, new TreeMap<>(),
+ () -> mCacheUpdater.run());
}
@After
@@ -500,7 +504,8 @@ public class PerfettoProtoLogImplTest {
PerfettoTraceMonitor traceMonitor =
PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
- TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true)))
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+ true)))
.build();
try {
traceMonitor.start();
@@ -526,6 +531,142 @@ public class PerfettoProtoLogImplTest {
Truth.assertThat(stacktrace).contains("stackTraceTrimmed");
}
+ @Test
+ public void cacheIsUpdatedWhenTracesStartAndStop() {
+ final AtomicInteger cacheUpdateCallCount = new AtomicInteger(0);
+ mCacheUpdater = cacheUpdateCallCount::incrementAndGet;
+
+ PerfettoTraceMonitor traceMonitor1 =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
+ false)))
+ .build();
+
+ PerfettoTraceMonitor traceMonitor2 =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+ false)))
+ .build();
+
+ Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(0);
+
+ try {
+ traceMonitor1.start();
+
+ Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(1);
+
+ try {
+ traceMonitor2.start();
+
+ Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(2);
+ } finally {
+ traceMonitor2.stop(mWriter);
+ }
+
+ Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(3);
+
+ } finally {
+ traceMonitor1.stop(mWriter);
+ }
+
+ Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(4);
+ }
+
+ @Test
+ public void isEnabledUpdatesBasedOnRunningTraces() {
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isTrue();
+
+ PerfettoTraceMonitor traceMonitor1 =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
+ false)))
+ .build();
+
+ PerfettoTraceMonitor traceMonitor2 =
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+ false)))
+ .build();
+
+ try {
+ traceMonitor1.start();
+
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ .isTrue();
+
+ try {
+ traceMonitor2.start();
+
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
+ LogLevel.VERBOSE)).isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ .isTrue();
+ } finally {
+ traceMonitor2.stop(mWriter);
+ }
+
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ .isTrue();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ .isTrue();
+ } finally {
+ traceMonitor1.stop(mWriter);
+ }
+
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ .isFalse();
+ Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ .isTrue();
+ }
+
private enum TestProtoLogGroup implements IProtoLogGroup {
TEST_GROUP(true, true, false, "TEST_TAG");
@@ -584,5 +725,10 @@ public class PerfettoProtoLogImplTest {
this.mLogToLogcat = logToLogcat;
}
+ @Override
+ public int getId() {
+ return ordinal();
+ }
+
}
}
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
index 4267c2c127ae..60456f9ea10f 100644
--- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
@@ -174,5 +174,10 @@ public class ProtoLogImplTest {
this.mLogToLogcat = logToLogcat;
}
+ @Override
+ public int getId() {
+ return ordinal();
+ }
+
}
}
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java b/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java
index a96389046d6a..be9fb1b309f6 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java
@@ -34,7 +34,7 @@ import perfetto.protos.DataSourceConfigOuterClass;
import perfetto.protos.ProtologCommon;
import perfetto.protos.ProtologConfig;
-public class PerfettoDataSourceTest {
+public class ProtologDataSourceTest {
@Before
public void before() {
assumeTrue(android.tracing.Flags.perfettoProtologTracing());
@@ -67,7 +67,7 @@ public class PerfettoDataSourceTest {
@Test
public void allEnabledTraceMode() {
- final ProtoLogDataSource ds = new ProtoLogDataSource(() -> {}, () -> {}, () -> {});
+ final ProtoLogDataSource ds = new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {});
final ProtoLogDataSource.TlsState tlsState = createTlsState(
DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig(
@@ -154,7 +154,7 @@ public class PerfettoDataSourceTest {
private ProtoLogDataSource.TlsState createTlsState(
DataSourceConfigOuterClass.DataSourceConfig config) {
final ProtoLogDataSource ds =
- Mockito.spy(new ProtoLogDataSource(() -> {}, () -> {}, () -> {}));
+ Mockito.spy(new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {}));
ProtoInputStream configStream = new ProtoInputStream(config.toByteArray());
final ProtoLogDataSource.Instance dsInstance = Mockito.spy(
diff --git a/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt b/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
index b5bd9ca746aa..8bc2f9716512 100644
--- a/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
+++ b/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
@@ -21,8 +21,13 @@ import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
+import android.view.InputDevice
+import android.view.InputDevice.SOURCE_MOUSE
import android.view.InputDevice.SOURCE_STYLUS
+import android.view.InputDevice.SOURCE_TOUCHSCREEN
+import android.view.InputDevice.SOURCE_TOUCHPAD
import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_CANCEL
import android.view.MotionEvent.ACTION_DOWN
import android.view.MotionEvent.ACTION_HOVER_EXIT
import android.view.MotionEvent.ACTION_UP
@@ -56,8 +61,8 @@ private fun drawLine(canvas: Canvas, from: MotionEvent, to: MotionEvent, paint:
}
private fun drawCircle(canvas: Canvas, event: MotionEvent, paint: Paint, radius: Float) {
- val x = event.getX()
- val y = event.getY()
+ val x = event.x
+ val y = event.y
canvas.drawCircle(x, y, radius, paint)
}
@@ -110,44 +115,72 @@ class DrawingView : View {
private val scaleGestureDetector = ScaleGestureDetector(context, scaleGestureListener, null)
private var touchPaint = Paint()
+ private var touchpadPaint = Paint()
private var stylusPaint = Paint()
+ private var mousePaint = Paint()
+ private var drawingTabletPaint = Paint()
private fun init() {
touchPaint.color = Color.RED
- touchPaint.setStrokeWidth(5f)
+ touchPaint.strokeWidth = 5f
+ touchpadPaint.color = Color.BLACK
+ touchpadPaint.strokeWidth = 5f
stylusPaint.color = Color.YELLOW
- stylusPaint.setStrokeWidth(5f)
-
+ stylusPaint.strokeWidth = 5f
+ mousePaint.color = Color.BLUE
+ mousePaint.strokeWidth = 5f
+ drawingTabletPaint.color = Color.GREEN
+ drawingTabletPaint.strokeWidth = 5f
setOnHoverListener { _, event -> processHoverEvent(event); true }
}
+ private fun resolvePaint(event: MotionEvent): Paint? {
+ val inputDevice = InputDevice.getDevice(event.deviceId)
+ val isTouchpadDevice = inputDevice != null && inputDevice.supportsSource(SOURCE_TOUCHPAD)
+ return if (event.isFromSource(SOURCE_STYLUS or SOURCE_MOUSE)) {
+ // External stylus / drawing tablet
+ drawingTabletPaint
+ } else if (event.isFromSource(SOURCE_TOUCHSCREEN) && !event.isFromSource(SOURCE_STYLUS)) {
+ // Touchscreen event
+ touchPaint
+ } else if (event.isFromSource(SOURCE_MOUSE) &&
+ (event.isFromSource(SOURCE_TOUCHPAD) || isTouchpadDevice)) {
+ // Touchpad event
+ touchpadPaint
+ } else if (event.isFromSource(SOURCE_MOUSE)) {
+ // Mouse event
+ mousePaint
+ } else if (event.isFromSource(SOURCE_STYLUS)) {
+ // Stylus event
+ stylusPaint
+ } else {
+ // Drop the event
+ null
+ }
+ }
+
private fun processTouchEvent(event: MotionEvent) {
scaleGestureDetector.onTouchEvent(event)
if (event.actionMasked == ACTION_DOWN) {
touchEvents.remove(event.deviceId)
myState?.state = PointerState.DOWN
- } else if (event.actionMasked == ACTION_UP) {
+ } else if (event.actionMasked == ACTION_UP || event.actionMasked == ACTION_CANCEL) {
myState?.state = PointerState.NONE
}
- var vec = touchEvents.getOrPut(event.deviceId) { Vector<Pair<MotionEvent, Paint>>() }
-
- val paint = if (event.isFromSource(SOURCE_STYLUS)) {
- val size = myState?.lineSize ?: 5f
- stylusPaint.setStrokeWidth(size)
- Paint(stylusPaint)
- } else {
+ val paint = resolvePaint(event)
+ if (paint != null) {
+ val vec = touchEvents.getOrPut(event.deviceId) { Vector<Pair<MotionEvent, Paint>>() }
val size = myState?.lineSize ?: 5f
- touchPaint.setStrokeWidth(size)
- Paint(touchPaint)
+ paint.strokeWidth = size
+ vec.add(Pair(MotionEvent.obtain(event), Paint(paint)))
+ invalidate()
}
- vec.add(Pair(MotionEvent.obtain(event), paint))
- invalidate()
}
private fun processHoverEvent(event: MotionEvent) {
hoverEvents.remove(event.deviceId)
- if (event.getActionMasked() != ACTION_HOVER_EXIT) {
- hoverEvents.put(event.deviceId, MotionEvent.obtain(event))
+ if (event.actionMasked != ACTION_HOVER_EXIT) {
+ hoverEvents[event.deviceId] = MotionEvent.obtain(event)
myState?.state = PointerState.HOVER
} else {
myState?.state = PointerState.NONE
@@ -155,7 +188,7 @@ class DrawingView : View {
invalidate()
}
- public override fun onTouchEvent(event: MotionEvent): Boolean {
+ override fun onTouchEvent(event: MotionEvent): Boolean {
processTouchEvent(event)
return true
}
@@ -171,12 +204,10 @@ class DrawingView : View {
}
// Draw hovers
for ((_, event) in hoverEvents ) {
- if (event.isFromSource(SOURCE_STYLUS)) {
- val size = myState?.circleSize ?: 20f
- drawCircle(canvas, event, stylusPaint, size)
- } else {
+ val paint = resolvePaint(event)
+ if (paint != null) {
val size = myState?.circleSize ?: 20f
- drawCircle(canvas, event, touchPaint, size)
+ drawCircle(canvas, event, paint, size)
}
}
}
diff --git a/tests/OdmApps/app/AndroidManifest.xml b/tests/OdmApps/app/AndroidManifest.xml
index 84a9ea84b522..84a9ea84b522 100755..100644
--- a/tests/OdmApps/app/AndroidManifest.xml
+++ b/tests/OdmApps/app/AndroidManifest.xml
diff --git a/tests/OdmApps/priv-app/AndroidManifest.xml b/tests/OdmApps/priv-app/AndroidManifest.xml
index 031cf64ea7b1..031cf64ea7b1 100755..100644
--- a/tests/OdmApps/priv-app/AndroidManifest.xml
+++ b/tests/OdmApps/priv-app/AndroidManifest.xml
diff --git a/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png b/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png
index 66a198496cfb..66a198496cfb 100755..100644
--- a/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png
+++ b/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/EmbeddedWindowService.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/EmbeddedWindowService.java
index 0fb4f90f354f..56fb30ccca9c 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/EmbeddedWindowService.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/EmbeddedWindowService.java
@@ -135,7 +135,7 @@ public class EmbeddedWindowService extends Service {
c.drawText("Remote", 250, 250, paint);
surface.unlockCanvasAndPost(c);
WindowManager wm = getSystemService(WindowManager.class);
- wm.registerBatchedSurfaceControlInputReceiver(displayId, inputTransferToken,
+ wm.registerBatchedSurfaceControlInputReceiver(inputTransferToken,
mSurfaceControl,
Choreographer.getInstance(), event -> {
Log.d(TAG, "onInputEvent-remote " + event);
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
index e700bc2f3d21..ac7dc9e2f31f 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
@@ -138,7 +138,7 @@ public class SurfaceInputTestActivity extends Activity {
c.drawText("Local SC", 0, 0, paint);
surface.unlockCanvasAndPost(c);
WindowManager wm = getSystemService(WindowManager.class);
- wm.registerBatchedSurfaceControlInputReceiver(getDisplayId(),
+ wm.registerBatchedSurfaceControlInputReceiver(
attachedSurfaceControl.getInputTransferToken(), mLocalSurfaceControl,
Choreographer.getInstance(), event -> {
Log.d(TAG, "onInputEvent-sc " + event);
@@ -159,7 +159,7 @@ public class SurfaceInputTestActivity extends Activity {
holder.unlockCanvasAndPost(c);
WindowManager wm = getSystemService(WindowManager.class);
- wm.registerBatchedSurfaceControlInputReceiver(getDisplayId(),
+ wm.registerBatchedSurfaceControlInputReceiver(
mLocalSurfaceView.getRootSurfaceControl().getInputTransferToken(),
mLocalSurfaceView.getSurfaceControl(),
Choreographer.getInstance(), event -> {
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
index a62103e0030b..f88d82bf29a8 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
@@ -16,10 +16,16 @@
package com.android.internal.telephony.tests;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -72,6 +78,37 @@ public class TelephonyUtilsTest {
// getSubscriptionUserHandle should be called if subID is active.
verify(mSubscriptionManager, times(1)).getSubscriptionUserHandle(eq(activeSubId));
}
+
+ @Test
+ public void testIsValidPlmn() {
+ assertTrue(TelephonyUtils.isValidPlmn("310260"));
+ assertTrue(TelephonyUtils.isValidPlmn("45006"));
+ assertFalse(TelephonyUtils.isValidPlmn("1234567"));
+ assertFalse(TelephonyUtils.isValidPlmn("1234"));
+ assertFalse(TelephonyUtils.isValidPlmn(""));
+ assertFalse(TelephonyUtils.isValidPlmn(null));
+ }
+
+ @Test
+ public void testIsValidService() {
+ assertTrue(TelephonyUtils.isValidService(FIRST_SERVICE_TYPE));
+ assertTrue(TelephonyUtils.isValidService(LAST_SERVICE_TYPE));
+ assertFalse(TelephonyUtils.isValidService(FIRST_SERVICE_TYPE - 1));
+ assertFalse(TelephonyUtils.isValidService(LAST_SERVICE_TYPE + 1));
+ }
+
+ @Test
+ public void testIsValidCountryCode() {
+ assertTrue(TelephonyUtils.isValidCountryCode("US"));
+ assertTrue(TelephonyUtils.isValidCountryCode("cn"));
+ assertFalse(TelephonyUtils.isValidCountryCode("11"));
+ assertFalse(TelephonyUtils.isValidCountryCode("USA"));
+ assertFalse(TelephonyUtils.isValidCountryCode("chn"));
+ assertFalse(TelephonyUtils.isValidCountryCode("U"));
+ assertFalse(TelephonyUtils.isValidCountryCode("G7"));
+ assertFalse(TelephonyUtils.isValidCountryCode(""));
+ assertFalse(TelephonyUtils.isValidCountryCode(null));
+ }
}
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
index 4ef1ead7d9c9..7990732d924d 100644
--- a/tests/TouchLatency/Android.bp
+++ b/tests/TouchLatency/Android.bp
@@ -5,6 +5,7 @@ package {
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_android_core_graphics_stack",
}
android_test {
diff --git a/tests/TouchLatency/app/src/main/res/values/styles.xml b/tests/TouchLatency/app/src/main/res/values/styles.xml
index b23a87e57754..5058331187e8 100644
--- a/tests/TouchLatency/app/src/main/res/values/styles.xml
+++ b/tests/TouchLatency/app/src/main/res/values/styles.xml
@@ -18,6 +18,7 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. -->
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
</resources>
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index f0bea3f3c28a..2909e66b53be 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -43,6 +43,9 @@ android_test {
"libmultiplejvmtiagentsinterferenceagent",
"libstaticjvmtiagent",
],
+ libs: [
+ "android.test.mock",
+ ],
certificate: "platform",
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/tests/UsbManagerTests/src/android/hardware/usb/DeviceFilterTest.java b/tests/UsbManagerTests/src/android/hardware/usb/DeviceFilterTest.java
new file mode 100644
index 000000000000..d6f3148e64f1
--- /dev/null
+++ b/tests/UsbManagerTests/src/android/hardware/usb/DeviceFilterTest.java
@@ -0,0 +1,248 @@
+/*
+ * 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 android.hardware.usb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.usb.flags.Flags;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.XmlUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.StringReader;
+
+/**
+ * Unit tests for {@link android.hardware.usb.DeviceFilter}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceFilterTest {
+
+ private static final int VID = 10;
+ private static final int PID = 11;
+ private static final int CLASS = 12;
+ private static final int SUBCLASS = 13;
+ private static final int PROTOCOL = 14;
+ private static final String MANUFACTURER = "Google";
+ private static final String PRODUCT = "Test";
+ private static final String SERIAL_NO = "4AL23";
+ private static final String INTERFACE_NAME = "MTP";
+
+ private MockitoSession mStaticMockSession;
+
+ @Before
+ public void setUp() throws Exception {
+ mStaticMockSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class)
+ .strictness(Strictness.WARN)
+ .startMocking();
+
+ when(Flags.enableInterfaceNameDeviceFilter()).thenReturn(true);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mStaticMockSession.finishMocking();
+ }
+
+ @Test
+ public void testConstructorFromValues_interfaceNameIsInitialized() {
+ DeviceFilter deviceFilter = new DeviceFilter(
+ VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER,
+ PRODUCT, SERIAL_NO, INTERFACE_NAME
+ );
+
+ verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter);
+ assertThat(deviceFilter.mInterfaceName).isEqualTo(INTERFACE_NAME);
+ }
+
+ @Test
+ public void testConstructorFromUsbDevice_interfaceNameIsNull() {
+ UsbDevice usbDevice = Mockito.mock(UsbDevice.class);
+ when(usbDevice.getVendorId()).thenReturn(VID);
+ when(usbDevice.getProductId()).thenReturn(PID);
+ when(usbDevice.getDeviceClass()).thenReturn(CLASS);
+ when(usbDevice.getDeviceSubclass()).thenReturn(SUBCLASS);
+ when(usbDevice.getDeviceProtocol()).thenReturn(PROTOCOL);
+ when(usbDevice.getManufacturerName()).thenReturn(MANUFACTURER);
+ when(usbDevice.getProductName()).thenReturn(PRODUCT);
+ when(usbDevice.getSerialNumber()).thenReturn(SERIAL_NO);
+
+ DeviceFilter deviceFilter = new DeviceFilter(usbDevice);
+
+ verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter);
+ assertThat(deviceFilter.mInterfaceName).isEqualTo(null);
+ }
+
+ @Test
+ public void testConstructorFromDeviceFilter_interfaceNameIsInitialized() {
+ DeviceFilter originalDeviceFilter = new DeviceFilter(
+ VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER,
+ PRODUCT, SERIAL_NO, INTERFACE_NAME
+ );
+
+ DeviceFilter deviceFilter = new DeviceFilter(originalDeviceFilter);
+
+ verifyDeviceFilterConfigurationExceptInterfaceName(deviceFilter);
+ assertThat(deviceFilter.mInterfaceName).isEqualTo(INTERFACE_NAME);
+ }
+
+
+ @Test
+ public void testReadFromXml_interfaceNamePresent_propertyIsInitialized() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device interface-name=\"MTP\"/>");
+
+ assertThat(deviceFilter.mInterfaceName).isEqualTo("MTP");
+ }
+
+ @Test
+ public void testReadFromXml_interfaceNameAbsent_propertyIsNull() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device vendor-id=\"1\" />");
+
+ assertThat(deviceFilter.mInterfaceName).isEqualTo(null);
+ }
+
+ @Test
+ public void testWrite_withInterfaceName() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device interface-name=\"MTP\"/>");
+ XmlSerializer serializer = Mockito.mock(XmlSerializer.class);
+
+ deviceFilter.write(serializer);
+
+ verify(serializer).attribute(null, "interface-name", "MTP");
+ }
+
+ @Test
+ public void testWrite_withoutInterfaceName() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml("<usb-device vendor-id=\"1\" />");
+ XmlSerializer serializer = Mockito.mock(XmlSerializer.class);
+
+ deviceFilter.write(serializer);
+
+ verify(serializer, times(0)).attribute(eq(null), eq("interface-name"), any());
+ }
+
+ @Test
+ public void testToString() {
+ DeviceFilter deviceFilter = new DeviceFilter(
+ VID, PID, CLASS, SUBCLASS, PROTOCOL, MANUFACTURER,
+ PRODUCT, SERIAL_NO, INTERFACE_NAME
+ );
+
+ assertThat(deviceFilter.toString()).isEqualTo(
+ "DeviceFilter[mVendorId=10,mProductId=11,mClass=12,mSubclass=13,mProtocol=14,"
+ + "mManufacturerName=Google,mProductName=Test,mSerialNumber=4AL23,"
+ + "mInterfaceName=MTP]");
+ }
+
+ @Test
+ public void testMatch_interfaceNameMatches_returnTrue() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml(
+ "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" "
+ + "interface-name=\"MTP\"/>");
+ UsbDevice usbDevice = Mockito.mock(UsbDevice.class);
+ when(usbDevice.getInterfaceCount()).thenReturn(1);
+ when(usbDevice.getInterface(0)).thenReturn(new UsbInterface(
+ /* id= */ 0,
+ /* alternateSetting= */ 0,
+ /* name= */ "MTP",
+ /* class= */ 255,
+ /* subClass= */ 255,
+ /* protocol= */ 0));
+
+ assertTrue(deviceFilter.matches(usbDevice));
+ }
+
+ @Test
+ public void testMatch_interfaceNameMismatch_returnFalse() throws Exception {
+ DeviceFilter deviceFilter = getDeviceFilterFromXml(
+ "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" "
+ + "interface-name=\"MTP\"/>");
+ UsbDevice usbDevice = Mockito.mock(UsbDevice.class);
+ when(usbDevice.getInterfaceCount()).thenReturn(1);
+ when(usbDevice.getInterface(0)).thenReturn(new UsbInterface(
+ /* id= */ 0,
+ /* alternateSetting= */ 0,
+ /* name= */ "UVC",
+ /* class= */ 255,
+ /* subClass= */ 255,
+ /* protocol= */ 0));
+
+ assertFalse(deviceFilter.matches(usbDevice));
+ }
+
+ @Test
+ public void testMatch_interfaceNameMismatchFlagDisabled_returnTrue() throws Exception {
+ when(Flags.enableInterfaceNameDeviceFilter()).thenReturn(false);
+ DeviceFilter deviceFilter = getDeviceFilterFromXml(
+ "<usb-device class=\"255\" subclass=\"255\" protocol=\"0\" "
+ + "interface-name=\"MTP\"/>");
+ UsbDevice usbDevice = Mockito.mock(UsbDevice.class);
+ when(usbDevice.getInterfaceCount()).thenReturn(1);
+ when(usbDevice.getInterface(0)).thenReturn(new UsbInterface(
+ /* id= */ 0,
+ /* alternateSetting= */ 0,
+ /* name= */ "UVC",
+ /* class= */ 255,
+ /* subClass= */ 255,
+ /* protocol= */ 0));
+
+ assertTrue(deviceFilter.matches(usbDevice));
+ }
+
+ private void verifyDeviceFilterConfigurationExceptInterfaceName(DeviceFilter deviceFilter) {
+ assertThat(deviceFilter.mVendorId).isEqualTo(VID);
+ assertThat(deviceFilter.mProductId).isEqualTo(PID);
+ assertThat(deviceFilter.mClass).isEqualTo(CLASS);
+ assertThat(deviceFilter.mSubclass).isEqualTo(SUBCLASS);
+ assertThat(deviceFilter.mProtocol).isEqualTo(PROTOCOL);
+ assertThat(deviceFilter.mManufacturerName).isEqualTo(MANUFACTURER);
+ assertThat(deviceFilter.mProductName).isEqualTo(PRODUCT);
+ assertThat(deviceFilter.mSerialNumber).isEqualTo(SERIAL_NO);
+ }
+
+ private DeviceFilter getDeviceFilterFromXml(String xml) throws Exception {
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(new StringReader(xml));
+ XmlUtils.nextElement(parser);
+
+ return DeviceFilter.read(parser);
+ }
+
+}
diff --git a/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
index 4780d8a610e8..87b26a63acc7 100644
--- a/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
+++ b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
@@ -16,6 +16,8 @@
package com.android.server.usbtest;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
+
import static com.android.server.usb.UsbProfileGroupSettingsManager.PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES;
import static org.mockito.ArgumentMatchers.any;
@@ -32,16 +34,20 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.Property;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.hardware.usb.UsbDevice;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.usb.UsbHandlerManager;
import com.android.server.usb.UsbProfileGroupSettingsManager;
import com.android.server.usb.UsbSettingsManager;
@@ -69,6 +75,7 @@ import java.util.List;
public class UsbProfileGroupSettingsManagerTest {
private static final String TEST_PACKAGE_NAME = "testPkg";
+
@Mock
private Context mContext;
@Mock
@@ -85,43 +92,78 @@ public class UsbProfileGroupSettingsManagerTest {
private UserManager mUserManager;
@Mock
private UsbUserSettingsManager mUsbUserSettingsManager;
- @Mock private Property mProperty;
- private ActivityManager.RunningAppProcessInfo mRunningAppProcessInfo;
- private PackageInfo mPackageInfo;
- private UsbProfileGroupSettingsManager mUsbProfileGroupSettingsManager;
+ @Mock
+ private Property mRestrictUsbOverlayActivitiesProperty;
+ @Mock
+ private UsbDevice mUsbDevice;
+
+ private MockContentResolver mContentResolver;
private MockitoSession mStaticMockSession;
+ private UsbProfileGroupSettingsManager mUsbProfileGroupSettingsManager;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mStaticMockSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class)
+ .strictness(Strictness.WARN)
+ .startMocking();
- mRunningAppProcessInfo = new ActivityManager.RunningAppProcessInfo();
- mRunningAppProcessInfo.pkgList = new String[]{TEST_PACKAGE_NAME};
- mPackageInfo = new PackageInfo();
- mPackageInfo.packageName = TEST_PACKAGE_NAME;
- mPackageInfo.applicationInfo = Mockito.mock(ApplicationInfo.class);
+ when(mUsbSettingsManager.getSettingsForUser(anyInt())).thenReturn(mUsbUserSettingsManager);
+ when(mUserManager.getEnabledProfiles(anyInt()))
+ .thenReturn(List.of(Mockito.mock(UserInfo.class)));
+
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
when(mContext.getResources()).thenReturn(Mockito.mock(Resources.class));
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
when(mContext.createPackageContextAsUser(anyString(), anyInt(), any(UserHandle.class)))
.thenReturn(mContext);
- when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
- mUsbProfileGroupSettingsManager = new UsbProfileGroupSettingsManager(mContext, mUserHandle,
- mUsbSettingsManager, mUsbHandlerManager);
+ mUsbProfileGroupSettingsManager = new UsbProfileGroupSettingsManager(
+ mContext, mUserHandle, mUsbSettingsManager, mUsbHandlerManager);
- mStaticMockSession = ExtendedMockito.mockitoSession()
- .mockStatic(Flags.class)
- .strictness(Strictness.WARN)
- .startMocking();
+ setupDefaultConfiguration();
+ }
+ /**
+ * Setups the following configuration
+ *
+ * <ul>
+ * <li>Flag is enabled
+ * <li>Device setup has completed
+ * <li>There is a foreground activity with MANAGE_USB permission
+ * <li>The foreground activity has PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES enabled
+ * </ul>
+ */
+ private void setupDefaultConfiguration() throws NameNotFoundException {
+ when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
+
+ Settings.Secure.putInt(mContentResolver, USER_SETUP_COMPLETE, 1);
+
+ ActivityManager.RunningAppProcessInfo mRunningAppProcessInfo =
+ new ActivityManager.RunningAppProcessInfo();
+ mRunningAppProcessInfo.pkgList = new String[] { TEST_PACKAGE_NAME };
+ when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
+
+ PackageInfo mPackageInfo = new PackageInfo();
+ mPackageInfo.packageName = TEST_PACKAGE_NAME;
+ mPackageInfo.applicationInfo = Mockito.mock(ApplicationInfo.class);
when(mPackageManager.getPackageInfo(TEST_PACKAGE_NAME, 0)).thenReturn(mPackageInfo);
- when(mPackageManager.getProperty(eq(PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES),
- eq(TEST_PACKAGE_NAME))).thenReturn(mProperty);
- when(mUserManager.getEnabledProfiles(anyInt()))
- .thenReturn(List.of(Mockito.mock(UserInfo.class)));
- when(mUsbSettingsManager.getSettingsForUser(anyInt())).thenReturn(mUsbUserSettingsManager);
+ when(mPackageManager.getPackagesHoldingPermissions(
+ new String[] { android.Manifest.permission.MANAGE_USB },
+ PackageManager.MATCH_SYSTEM_ONLY))
+ .thenReturn(List.of(mPackageInfo));
+
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(true);
+ when(mPackageManager.getProperty(
+ eq(PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(mRestrictUsbOverlayActivitiesProperty);
}
@After
@@ -130,66 +172,59 @@ public class UsbProfileGroupSettingsManagerTest {
}
@Test
- public void testDeviceAttached_flagTrueWithoutForegroundActivity_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
+ public void testDeviceAttached_foregroundActivityWithManifestField_resolveActivityNotCalled() {
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
+ verify(mUsbUserSettingsManager, times(0)).queryIntentActivities(any(Intent.class));
+ }
+
+ @Test
+ public void testDeviceAttached_noForegroundActivity_resolveActivityCalled() {
when(mActivityManager.getRunningAppProcesses()).thenReturn(new ArrayList<>());
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
public void testDeviceAttached_noForegroundActivityWithUsbPermission_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(new ArrayList<>());
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+ new String[] { android.Manifest.permission.MANAGE_USB },
+ PackageManager.MATCH_SYSTEM_ONLY))
+ .thenReturn(new ArrayList<>());
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
- public void testDeviceAttached_foregroundActivityWithManifestField_resolveActivityNotCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mProperty.getBoolean()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
- verify(mUsbUserSettingsManager, times(0))
- .queryIntentActivities(any(Intent.class));
- }
+ public void testDeviceAttached_restricUsbOverlayPropertyDisabled_resolveActivityCalled() {
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(false);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
- @Test
- public void testDeviceAttached_foregroundActivityWithoutManifestField_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mProperty.getBoolean()).thenReturn(false);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
- public void testDeviceAttached_flagFalseForegroundActivity_resolveActivityCalled() {
+ public void testDeviceAttached_flagFalse_resolveActivityCalled() {
when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(false);
- when(mProperty.getBoolean()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
+
+ @Test
+ public void
+ testDeviceAttached_setupNotCompleteAndNoBlockingActivities_resolveActivityNotCalled() {
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(false);
+ Settings.Secure.putInt(mContentResolver, USER_SETUP_COMPLETE, 0);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
+ verify(mUsbUserSettingsManager, times(0)).queryIntentActivities(any(Intent.class));
+ }
}
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index c4ebdecae735..c012cce494e2 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -37,6 +37,8 @@ android_test {
"services.usb",
"truth",
"UsbManagerTestLib",
+ "android.hardware.usb.flags-aconfig-java",
+ "flag-junit",
],
jni_libs: [
// Required for ExtendedMockito
diff --git a/tests/UsbTests/TEST_MAPPING b/tests/UsbTests/TEST_MAPPING
new file mode 100644
index 000000000000..70134b818722
--- /dev/null
+++ b/tests/UsbTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "UsbTests"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java
new file mode 100644
index 000000000000..56845aeb6a2c
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.server.usb;
+
+import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.usb.IUsbOperationInternal;
+import android.hardware.usb.flags.Flags;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.usb.UsbService}
+ */
+@RunWith(AndroidJUnit4.class)
+public class UsbServiceTest {
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private UsbPortManager mUsbPortManager;
+ @Mock
+ private UsbAlsaManager mUsbAlsaManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private UsbSettingsManager mUsbSettingsManager;
+ @Mock
+ private IUsbOperationInternal mCallback;
+
+ private static final String TEST_PORT_ID = "123";
+
+ private static final int TEST_TRANSACTION_ID = 1;
+
+ private static final int TEST_FIRST_CALLER_ID = 1000;
+
+ private static final int TEST_SECOND_CALLER_ID = 2000;
+
+ private UsbService mUsbService;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Before
+ public void setUp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING);
+ MockitoAnnotations.initMocks(this);
+
+ when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), eq(TEST_TRANSACTION_ID),
+ eq(mCallback), any())).thenReturn(true);
+
+ mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager,
+ mUserManager, mUsbSettingsManager);
+ }
+
+ private void assertToggleUsbSuccessfully(int uid, boolean enable) {
+ assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
+ TEST_TRANSACTION_ID, mCallback, uid));
+
+ verify(mUsbPortManager).enableUsbData(TEST_PORT_ID,
+ enable, TEST_TRANSACTION_ID, mCallback, null);
+ verifyZeroInteractions(mCallback);
+
+ clearInvocations(mUsbPortManager);
+ clearInvocations(mCallback);
+ }
+
+ private void assertToggleUsbFailed(int uid, boolean enable) throws Exception {
+ assertFalse(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
+ TEST_TRANSACTION_ID, mCallback, uid));
+
+ verifyZeroInteractions(mUsbPortManager);
+ verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+
+ clearInvocations(mUsbPortManager);
+ clearInvocations(mCallback);
+ }
+
+ /**
+ * Verify enableUsbData successfully disables USB port without error
+ */
+ @Test
+ public void disableUsb_successfullyDisable() {
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
+ }
+
+ /**
+ * Verify enableUsbData successfully enables USB port without error given no other stakers
+ */
+ @Test
+ public void enableUsbWhenNoOtherStakers_successfullyEnable() {
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true);
+ }
+
+ /**
+ * Verify enableUsbData does not enable USB port if other stakers are present
+ */
+ @Test
+ public void enableUsbPortWithOtherStakers_failsToEnable() throws Exception {
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
+
+ assertToggleUsbFailed(TEST_SECOND_CALLER_ID, true);
+ }
+
+ /**
+ * Verify enableUsbData successfully enables USB port when the last staker is removed
+ */
+ @Test
+ public void enableUsbByTheOnlyStaker_successfullyEnable() {
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
+
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true);
+ }
+
+ /**
+ * Verify enableUsbDataWhileDockedInternal does not enable USB port if other stakers are present
+ */
+ @Test
+ public void enableUsbWhileDockedWhenThereAreOtherStakers_failsToEnable()
+ throws RemoteException {
+ assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
+
+ mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
+ mCallback, TEST_SECOND_CALLER_ID);
+
+ verifyZeroInteractions(mUsbPortManager);
+ verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ }
+
+ /**
+ * Verify enableUsbDataWhileDockedInternal does enable USB port if other stakers are
+ * not present
+ */
+ @Test
+ public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnable() {
+ mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
+ mCallback, TEST_SECOND_CALLER_ID);
+
+ verify(mUsbPortManager).enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID,
+ mCallback, null);
+ verifyZeroInteractions(mCallback);
+ }
+}
diff --git a/tests/WindowInsetsTests/AndroidManifest.xml b/tests/WindowInsetsTests/AndroidManifest.xml
index 61dd9d4cd021..dbe9d363e285 100644
--- a/tests/WindowInsetsTests/AndroidManifest.xml
+++ b/tests/WindowInsetsTests/AndroidManifest.xml
@@ -18,7 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.test.windowinsetstests">
- <application android:label="@string/application_title">
+ <application android:label="@string/application_title"
+ android:theme="@style/base">
<activity android:name=".WindowInsetsTestsMainActivity"
android:exported="true">
<intent-filter>
@@ -29,11 +30,9 @@
<activity android:name=".ChatActivity"
android:label="@string/chat_activity_title"
- android:theme="@style/chat"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".ControllerActivity"
- android:label="@string/controller_activity_title"
- android:theme="@style/controller" />
+ android:label="@string/controller_activity_title" />
</application>
</manifest>
diff --git a/tests/WindowInsetsTests/res/layout/controller_activity.xml b/tests/WindowInsetsTests/res/layout/controller_activity.xml
index 5550eab61a33..7013059e1334 100644
--- a/tests/WindowInsetsTests/res/layout/controller_activity.xml
+++ b/tests/WindowInsetsTests/res/layout/controller_activity.xml
@@ -15,92 +15,110 @@
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ />
- <LinearLayout
- android:id="@+id/content"
+ <ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
-
- <Spinner
- android:id="@+id/spinnerBehavior"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="20dp" />
-
- <ToggleButton
- android:id="@+id/toggleButtonStatus"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:checked="true"
- android:text="Status Bars Toggle Button"
- android:textOff="Status Bars Invisible"
- android:textOn="Status Bars Visible" />
-
- <SeekBar
- android:id="@+id/seekBarStatus"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="20dp"
- android:max="10000"
- android:progress="10000" />
-
- <ToggleButton
- android:id="@+id/toggleButtonNavigation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:checked="true"
- android:text="Navigation Bars Toggle Button"
- android:textOff="Navigation Bars Invisible"
- android:textOn="Navigation Bars Visible" />
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp">
- <SeekBar
- android:id="@+id/seekBarNavigation"
+ <LinearLayout
+ android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="20dp"
- android:max="10000"
- android:progress="10000" />
-
- <ToggleButton
- android:id="@+id/toggleButtonIme"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:checked="true"
- android:text="IME Toggle Button"
- android:textOff="IME Invisible"
- android:textOn="IME Visible" />
-
- <SeekBar
- android:id="@+id/seekBarIme"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="20dp"
- android:max="10000"
- android:progress="0" />
-
- <TextView
- android:id="@+id/textViewControllableInsets"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="5dp" />
-
- <EditText
- android:id="@+id/editText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ems="10"
- android:hint="For testing IME..."
- android:inputType="text"
- android:text="" />
-
- </LinearLayout>
-
-</ScrollView> \ No newline at end of file
+ android:orientation="vertical">
+
+ <Spinner
+ android:id="@+id/spinnerBehavior"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="20dp" />
+
+ <ToggleButton
+ android:id="@+id/toggleButtonStatus"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/status_bars_toggle_button"
+ android:textOff="@string/status_bars_invisible"
+ android:textOn="@string/status_bars_visible" />
+
+ <SeekBar
+ android:id="@+id/seekBarStatus"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="20dp"
+ android:max="10000"
+ android:progress="10000" />
+
+ <ToggleButton
+ android:id="@+id/toggleButtonNavigation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/navigation_bars_toggle_button"
+ android:textOff="@string/navigation_bars_invisible"
+ android:textOn="@string/navigation_bars_visible" />
+
+ <SeekBar
+ android:id="@+id/seekBarNavigation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="20dp"
+ android:max="10000"
+ android:progress="10000" />
+
+ <ToggleButton
+ android:id="@+id/toggleButtonIme"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/ime_toggle_button"
+ android:textOff="@string/ime_invisible"
+ android:textOn="@string/ime_visible" />
+
+ <SeekBar
+ android:id="@+id/seekBarIme"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="20dp"
+ android:max="10000"
+ android:progress="0" />
+
+ <TextView
+ android:id="@+id/textViewControllableInsets"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dp" />
+
+ <EditText
+ android:id="@+id/editText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:autofillHints="@string/for_testing_ime"
+ android:hint="@string/for_testing_ime"
+ android:inputType="text"
+ android:text="" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/tests/WindowInsetsTests/res/layout/main_activity.xml b/tests/WindowInsetsTests/res/layout/main_activity.xml
index 621ed89204d1..d6d4ff9ca0a9 100644
--- a/tests/WindowInsetsTests/res/layout/main_activity.xml
+++ b/tests/WindowInsetsTests/res/layout/main_activity.xml
@@ -16,22 +16,38 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
- <Button
- android:id="@+id/chat_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/chat_activity_title"
- android:textAllCaps="false"/>
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ />
- <Button
- android:id="@+id/controller_button"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/controller_activity_title"
- android:textAllCaps="false"/>
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp">
+
+ <Button
+ android:id="@+id/chat_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chat_activity_title"
+ android:textAllCaps="false"/>
+
+ <Button
+ android:id="@+id/controller_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controller_activity_title"
+ android:textAllCaps="false"/>
+
+ </LinearLayout>
</LinearLayout>
diff --git a/tests/WindowInsetsTests/res/values-night/styles.xml b/tests/WindowInsetsTests/res/values-night/styles.xml
new file mode 100644
index 000000000000..323c5fd9698e
--- /dev/null
+++ b/tests/WindowInsetsTests/res/values-night/styles.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources>
+
+ <style name="base" parent="@style/Theme.MaterialComponents">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
+
+ <item name="colorPrimary">@color/primaryColor</item>
+ <item name="colorPrimaryDark">@color/primaryDarkColor</item>
+ <item name="colorSecondary">?attr/colorPrimary</item>
+ <item name="colorOnSecondary">@color/primaryTextColor</item>
+
+ <!-- Window decor -->
+ <item name="android:windowLightStatusBar">false</item>
+ <item name="android:windowLightNavigationBar">false</item>
+
+ </style>
+
+ <color name="primaryColor">#639ff9</color>
+ <color name="primaryLightColor">#6f6bff</color>
+ <color name="primaryDarkColor">#0016bb</color>
+ <color name="primaryTextColor">#ffffff</color>
+
+ <color name="bubble">#333333</color>
+ <color name="bubble_self">#185abc</color>
+
+</resources>
diff --git a/tests/WindowInsetsTests/res/values/strings.xml b/tests/WindowInsetsTests/res/values/strings.xml
index 516d4584426e..7b70852e6082 100644
--- a/tests/WindowInsetsTests/res/values/strings.xml
+++ b/tests/WindowInsetsTests/res/values/strings.xml
@@ -19,6 +19,16 @@
<string name="application_title">Window Insets Tests</string>
<string name="chat_activity_title">New Insets Chat</string>
<string name="controller_activity_title">Window Insets Controller</string>
+ <string name="status_bars_toggle_button">Status Bars Toggle Button</string>
+ <string name="status_bars_invisible">Status Bars Invisible</string>
+ <string name="status_bars_visible">Status Bars Visible</string>
+ <string name="navigation_bars_toggle_button">Navigation Bars Toggle Button</string>
+ <string name="navigation_bars_invisible">Navigation Bars Invisible</string>
+ <string name="navigation_bars_visible">Navigation Bars Visible</string>
+ <string name="ime_toggle_button">IME Bars Toggle Button</string>
+ <string name="ime_invisible">IME Bars Invisible</string>
+ <string name="ime_visible">IME Bars Visible</string>
+ <string name="for_testing_ime">For testing IME&#8230;</string>
<!-- The item positions should match the flag values respectively. -->
<string-array name="behaviors">
diff --git a/tests/WindowInsetsTests/res/values/styles.xml b/tests/WindowInsetsTests/res/values/styles.xml
index a84ffbed600d..4ce6323d8189 100644
--- a/tests/WindowInsetsTests/res/values/styles.xml
+++ b/tests/WindowInsetsTests/res/values/styles.xml
@@ -17,7 +17,7 @@
<resources>
- <style name="chat" parent="@style/Theme.MaterialComponents.Light">
+ <style name="base" parent="@style/Theme.MaterialComponents.Light">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
@@ -27,10 +27,8 @@
<item name="colorOnSecondary">@color/primaryTextColor</item>
<!-- Window decor -->
- <item name="android:statusBarColor">#ffffff</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowLightNavigationBar">true</item>
- <item name="android:navigationBarColor">#ffffff</item>
</style>
@@ -63,11 +61,4 @@
<dimen name="bubble_padding">8dp</dimen>
<dimen name="bubble_padding_side">16dp</dimen>
- <style name="controller" parent="android:Theme.Material">
- <item name="android:colorPrimaryDark">#111111</item>
- <item name="android:navigationBarColor">#111111</item>
- <item name="android:colorPrimary">#222222</item>
- <item name="android:colorAccent">#33ccff</item>
- </style>
-
-</resources> \ No newline at end of file
+</resources>
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
index 167d560633ab..1dd87dfd3977 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
@@ -16,12 +16,18 @@
package com.google.android.test.windowinsetstests;
-import android.app.Activity;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsets.Type.systemGestures;
+
import android.graphics.Insets;
import android.os.Bundle;
import android.view.View;
import android.view.WindowInsets;
-import android.view.WindowInsets.Type;
+import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;
import android.widget.AdapterView;
@@ -32,7 +38,9 @@ import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ToggleButton;
-public class ControllerActivity extends Activity implements View.OnApplyWindowInsetsListener {
+import androidx.appcompat.app.AppCompatActivity;
+
+public class ControllerActivity extends AppCompatActivity {
private ToggleButton mToggleStatus;
private SeekBar mSeekStatus;
@@ -48,6 +56,29 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.controller_activity);
+ setSupportActionBar(findViewById(R.id.toolbar));
+ getWindow().setDecorFitsSystemWindows(false);
+ findViewById(R.id.root).setOnApplyWindowInsetsListener(
+ (v, insets) -> {
+ final int visibleTypes = systemBars() | displayCutout();
+ final Insets i = insets.getInsets(visibleTypes);
+ v.setPadding(i.left, i.top, i.right, i.bottom);
+
+ // Make the content view not obscured by gesture insets to prevent triggering
+ // system gestures while controlling seek bars.
+ final Insets gi = Insets.subtract(
+ insets.getInsets(systemGestures() | visibleTypes), i);
+ findViewById(R.id.content).setPadding(gi.left, gi.top, gi.right, gi.bottom);
+
+ mNotFromUser[0] = true;
+ updateWidgets(insets, statusBars(), mToggleStatus, mSeekStatus);
+ updateWidgets(insets, navigationBars(), mToggleNavigation, mSeekNavigation);
+ updateWidgets(insets, ime(), mToggleIme, mSeekIme);
+ mLastInsets = insets;
+ mNotFromUser[0] = false;
+
+ return WindowInsets.CONSUMED;
+ });
final Spinner spinnerBehavior = findViewById(R.id.spinnerBehavior);
ArrayAdapter<CharSequence> adapterBehavior = ArrayAdapter.createFromResource(this,
R.array.behaviors, android.R.layout.simple_spinner_item);
@@ -66,23 +97,21 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn
});
mToggleStatus = findViewById(R.id.toggleButtonStatus);
mToggleStatus.setTag(mNotFromUser);
- mToggleStatus.setOnCheckedChangeListener(new ToggleListener(Type.statusBars()));
+ mToggleStatus.setOnCheckedChangeListener(new ToggleListener(statusBars()));
mSeekStatus = findViewById(R.id.seekBarStatus);
- mSeekStatus.setOnSeekBarChangeListener(new SeekBarListener(Type.statusBars()));
+ mSeekStatus.setOnSeekBarChangeListener(new SeekBarListener(statusBars()));
mToggleNavigation = findViewById(R.id.toggleButtonNavigation);
mToggleNavigation.setTag(mNotFromUser);
- mToggleNavigation.setOnCheckedChangeListener(new ToggleListener(Type.navigationBars()));
+ mToggleNavigation.setOnCheckedChangeListener(new ToggleListener(navigationBars()));
mSeekNavigation = findViewById(R.id.seekBarNavigation);
- mSeekNavigation.setOnSeekBarChangeListener(new SeekBarListener(Type.navigationBars()));
+ mSeekNavigation.setOnSeekBarChangeListener(new SeekBarListener(navigationBars()));
mToggleIme = findViewById(R.id.toggleButtonIme);
mToggleIme.setTag(mNotFromUser);
- mToggleIme.setOnCheckedChangeListener(new ToggleListener(Type.ime()));
+ mToggleIme.setOnCheckedChangeListener(new ToggleListener(ime()));
mSeekIme = findViewById(R.id.seekBarIme);
- mSeekIme.setOnSeekBarChangeListener(new SeekBarListener(Type.ime()));
+ mSeekIme.setOnSeekBarChangeListener(new SeekBarListener(ime()));
mTextControllableInsets = findViewById(R.id.textViewControllableInsets);
- final View contentView = findViewById(R.id.content);
- contentView.setOnApplyWindowInsetsListener(this);
- contentView.getWindowInsetsController().addOnControllableInsetsChangedListener(
+ mTextControllableInsets.getWindowInsetsController().addOnControllableInsetsChangedListener(
(c, types) -> mTextControllableInsets.setText(
"ControllableInsetsTypes:\n" + insetsTypesToString(types)));
}
@@ -91,22 +120,6 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn
return types == 0 ? "none" : WindowInsets.Type.toString(types);
}
- @Override
- public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
- mNotFromUser[0] = true;
- updateWidgets(insets, Type.statusBars(), mToggleStatus, mSeekStatus);
- updateWidgets(insets, Type.navigationBars(), mToggleNavigation, mSeekNavigation);
- updateWidgets(insets, Type.ime(), mToggleIme, mSeekIme);
- mLastInsets = insets;
- mNotFromUser[0] = false;
-
- // Prevent triggering system gestures while controlling seek bars.
- final Insets gestureInsets = insets.getInsets(Type.systemGestures());
- v.setPadding(gestureInsets.left, 0, gestureInsets.right, 0);
-
- return v.onApplyWindowInsets(insets);
- }
-
private void updateWidgets(WindowInsets insets, int types, ToggleButton toggle, SeekBar seek) {
final boolean isVisible = insets.isVisible(types);
final boolean wasVisible = mLastInsets != null ? mLastInsets.isVisible(types) : !isVisible;
@@ -121,7 +134,7 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn
private static class ToggleListener implements CompoundButton.OnCheckedChangeListener {
- private final @Type.InsetsType int mTypes;
+ private final @InsetsType int mTypes;
ToggleListener(int types) {
mTypes = types;
@@ -143,7 +156,7 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn
private static class SeekBarListener implements SeekBar.OnSeekBarChangeListener {
- private final @Type.InsetsType int mTypes;
+ private final @InsetsType int mTypes;
private WindowInsetsAnimationController mController;
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
index 8b77a78ff51e..278ad845d2bb 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
@@ -16,16 +16,30 @@
package com.google.android.test.windowinsetstests;
-import android.app.Activity;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.systemBars;
+
import android.content.Intent;
+import android.graphics.Insets;
import android.os.Bundle;
+import android.view.WindowInsets;
+
+import androidx.appcompat.app.AppCompatActivity;
-public class WindowInsetsTestsMainActivity extends Activity {
+public class WindowInsetsTestsMainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
+ setSupportActionBar(findViewById(R.id.toolbar));
+
+ findViewById(R.id.root).setOnApplyWindowInsetsListener(
+ (v, insets) -> {
+ final Insets i = insets.getInsets(systemBars() | displayCutout());
+ v.setPadding(i.left, i.top, i.right, i.bottom);
+ return WindowInsets.CONSUMED;
+ });
findViewById(R.id.chat_button).setOnClickListener(
v -> startActivity(new Intent(this, ChatActivity.class)));
diff --git a/tests/graphics/SilkFX/AndroidManifest.xml b/tests/graphics/SilkFX/AndroidManifest.xml
index c293589bdbaf..25092b52e2b6 100644
--- a/tests/graphics/SilkFX/AndroidManifest.xml
+++ b/tests/graphics/SilkFX/AndroidManifest.xml
@@ -23,12 +23,13 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application android:label="SilkFX"
- android:theme="@android:style/Theme.Material">
+ android:theme="@style/Theme.UsefulDefault">
<activity android:name=".Main"
android:label="SilkFX Demos"
android:banner="@drawable/background1"
- android:exported="true">
+ android:exported="true"
+ android:theme="@style/Theme.UsefulDefault">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
diff --git a/tests/graphics/SilkFX/res/values/style.xml b/tests/graphics/SilkFX/res/values/style.xml
index 66edbb5c9382..4dd626dfb8f5 100644
--- a/tests/graphics/SilkFX/res/values/style.xml
+++ b/tests/graphics/SilkFX/res/values/style.xml
@@ -23,9 +23,14 @@
<item name="android:windowElevation">0dp</item>
<item name="buttonStyle">@style/AppTheme.Button</item>
<item name="colorAccent">#bbffffff</item>
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
<style name="AppTheme.Button" parent="Widget.AppCompat.Button">
<item name="android:textColor">#ffffffff</item>
</style>
+ <style name="Theme.UsefulDefault" parent="android:Theme.Material">
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ </style>
+
</resources>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
index 8d05a974dc40..4c531b8f9ee0 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
@@ -20,17 +20,29 @@ package {
android_test {
name: "ConcurrentMultiSessionImeTest",
srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
"platform-test-annotations",
"platform-test-rules",
"truth",
+
+ // beadstead
+ "Nene",
+ "Harrier",
+ "TestApp",
],
test_suites: [
"general-tests",
],
- sdk_version: "current",
+ sdk_version: "test_current",
+
+ data: [
+ ":CtsMockInputMethod",
+ ],
// Store test artifacts in separated directories for easier debugging.
per_testcase_directory: true,
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
index 0defe5b3f2ff..2e336ca4f845 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
@@ -17,6 +17,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.inputmethod.multisessiontest">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".MainActivity"
+ android:theme="@android:style/Theme.Material.NoActionBar"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.server.inputmethod.multisessiontest"></instrumentation>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
index fd598c568974..d5ed203488d5 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
@@ -17,13 +17,28 @@
<configuration description="Config for Concurrent Multi-Session IME tests">
<object class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController"
type="module_controller">
- <option name="required-feature" value="android.software.input_methods" />
+ <!-- TODO(b/323372972): require this feature once the bug is fixed. -->
+ <!-- option name="required-feature" value="android.software.input_methods" -->
<!-- Currently enabled to automotive only -->
<option name="required-feature" value="android.hardware.type.automotive" />
</object>
<option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="force-install-mode" value="FULL" />
+ <option name="test-file-name" value="ConcurrentMultiSessionImeTest.apk" />
+ <option name="test-file-name" value="CtsMockInputMethod.apk" />
+ </target_preparer>
+
+ <!-- RunOnSecondaryUserTargetPreparer must run after SuiteApkInstaller. -->
+ <target_preparer class="com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer">
+ <option name="start-background-user" value="true" />
+ <option name="test-package-name" value="com.android.server.inputmethod.multisessiontest" />
+ <option name="test-package-name" value="com.android.cts.mockime" />
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
@@ -31,12 +46,6 @@
value="settings delete secure show_ime_with_hard_keyboard" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="force-install-mode" value="FULL" />
- <option name="test-file-name" value="ConcurrentMultiSessionImeTest.apk" />
- </target_preparer>
-
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.server.inputmethod.multisessiontest" />
</test>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml
new file mode 100644
index 000000000000..e16d28615c4d
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+ <EditText
+ android:id="@+id/edit_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:hint="Input text here"/>
+</FrameLayout>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
index b66ceba458ac..fff1dd1a7cb1 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
@@ -16,34 +16,92 @@
package com.android.server.inputmethod.multisessiontest;
-import static com.google.common.truth.Truth.assertThat;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import android.content.Context;
-import android.content.pm.PackageManager;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.getResponderUserId;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.launchActivityAsUserSync;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.sendBundleAndWaitForReply;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS;
-import androidx.test.platform.app.InstrumentationRegistry;
+import static com.google.common.truth.Truth.assertWithMessage;
+import android.content.ComponentName;
+import android.os.Bundle;
+
+import androidx.test.core.app.ActivityScenario;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+
+import org.junit.After;
import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-@RunWith(JUnit4.class)
+@RunWith(BedsteadJUnit4.class)
+@Ignore("b/345557347")
public final class ConcurrentMultiUserTest {
+ @ClassRule
+ @Rule
+ public static final DeviceState sDeviceState = new DeviceState();
+
+ private static final ComponentName TEST_ACTIVITY = new ComponentName(
+ getInstrumentation().getTargetContext().getPackageName(),
+ MainActivity.class.getName());
+
+ private ActivityScenario<MainActivity> mActivityScenario;
+ private MainActivity mActivity;
+ private int mPeerUserId;
+
@Before
- public void doBeforeEachTest() {
- // No op
+ public void setUp() {
+ // Launch passenger activity.
+ mPeerUserId = getResponderUserId();
+ launchActivityAsUserSync(TEST_ACTIVITY, mPeerUserId);
+
+ // Launch driver activity.
+ mActivityScenario = ActivityScenario.launch(MainActivity.class);
+ mActivityScenario.onActivity(activity -> mActivity = activity);
+ }
+
+ @After
+ public void tearDown() {
+ if (mActivityScenario != null) {
+ mActivityScenario.close();
+ }
}
@Test
- public void behaviorBeingTested_expectedResult() {
- // Sample test
- Context context =
- InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertThat(context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE)).isTrue();
- assertThat(context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_INPUT_METHODS)).isTrue();
+ public void driverShowImeNotAffectPassenger() {
+ assertDriverImeHidden();
+ assertPassengerImeHidden();
+
+ showDriverImeAndAssert();
+ assertPassengerImeHidden();
+ }
+
+ private void assertDriverImeHidden() {
+ assertWithMessage("Driver IME should be hidden")
+ .that(mActivity.isMyImeVisible()).isFalse();
+ }
+
+ private void assertPassengerImeHidden() {
+ final Bundle bundleToSend = new Bundle();
+ bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_IME_STATUS);
+ Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(),
+ mPeerUserId, bundleToSend);
+ assertWithMessage("Passenger IME should be hidden")
+ .that(receivedBundle.getInt(KEY_RESULT_CODE)).isEqualTo(REPLY_IME_HIDDEN);
+ }
+
+ private void showDriverImeAndAssert() {
+ mActivity.showMyImeAndWait();
}
}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java
new file mode 100644
index 000000000000..f1260008ca59
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java
@@ -0,0 +1,97 @@
+/*
+ * 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.server.inputmethod.multisessiontest;
+
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_SHOWN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityBase;
+
+/**
+ * An {@link Activity} to test multiple concurrent session IME.
+ */
+public final class MainActivity extends ConcurrentUserActivityBase {
+ private static final String TAG = ConcurrentMultiUserTest.class.getSimpleName();
+ private static final long WAIT_IME_TIMEOUT_MS = 3000;
+
+ private EditText mEditor;
+ private InputMethodManager mImm;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.v(TAG, "Create MainActivity as user "
+ + Process.myUserHandle().getIdentifier() + " on display "
+ + getDisplay().getDisplayId());
+ setContentView(R.layout.main_activity);
+ mImm = getSystemService(InputMethodManager.class);
+ mEditor = requireViewById(R.id.edit_text);
+ }
+
+ @Override
+ protected Bundle onBundleReceived(Bundle receivedBundle) {
+ final int requestCode = receivedBundle.getInt(KEY_REQUEST_CODE);
+ Log.v(TAG, "onBundleReceived() with request code:" + requestCode);
+ final Bundle replyBundle = new Bundle();
+ switch (requestCode) {
+ case REQUEST_IME_STATUS:
+ replyBundle.putInt(KEY_RESULT_CODE,
+ isMyImeVisible() ? REPLY_IME_SHOWN : REPLY_IME_HIDDEN);
+ break;
+ default:
+ throw new RuntimeException("Received undefined request code:" + requestCode);
+ }
+ return replyBundle;
+ }
+
+ boolean isMyImeVisible() {
+ final WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(mEditor);
+ return insets == null ? false : insets.isVisible(WindowInsetsCompat.Type.ime());
+ }
+
+ void showMyImeAndWait() {
+ Log.v(TAG, "showSoftInput");
+ runOnUiThread(() -> {
+ // requestFocus() must run on UI thread.
+ if (!mEditor.requestFocus()) {
+ Log.e(TAG, "Failed to focus on mEditor");
+ return;
+ }
+ if (!mImm.showSoftInput(mEditor, /* flags= */ 0)) {
+ Log.e(TAG, String.format("Failed to show my IME as user %d, "
+ + "mEditor:focused=%b,hasWindowFocus=%b", getUserId(),
+ mEditor.isFocused(), mEditor.hasWindowFocus()));
+ }
+ });
+ PollingCheck.waitFor(WAIT_IME_TIMEOUT_MS, () -> isMyImeVisible(),
+ String.format("My IME (user %d) didn't show up", getUserId()));
+ }
+}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java
new file mode 100644
index 000000000000..1501bfb69c92
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java
@@ -0,0 +1,29 @@
+/*
+ * 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.server.inputmethod.multisessiontest;
+
+final class TestRequestConstants {
+ private TestRequestConstants() {
+ }
+
+ public static final String KEY_REQUEST_CODE = "key_request_code";
+ public static final String KEY_RESULT_CODE = "key_result_code";
+
+ public static final int REQUEST_IME_STATUS = 1;
+ public static final int REPLY_IME_SHOWN = 2;
+ public static final int REPLY_IME_HIDDEN = 3;
+}
diff --git a/tests/testables/src/android/testing/TestableResources.java b/tests/testables/src/android/testing/TestableResources.java
index 0ec106e329f6..384a21e7c91a 100644
--- a/tests/testables/src/android/testing/TestableResources.java
+++ b/tests/testables/src/android/testing/TestableResources.java
@@ -26,6 +26,8 @@ import android.util.SparseArray;
import org.mockito.invocation.InvocationOnMock;
+import java.util.Arrays;
+
/**
* Provides a version of Resources that defaults to all existing resources, but can have ids
* changed to return specific values.
@@ -103,6 +105,15 @@ public class TestableResources {
if (index >= 0) {
Object value = mOverrides.valueAt(index);
if (value == null) throw new Resources.NotFoundException();
+ // Support for Resources.getString(resId, Object... formatArgs)
+ if (value instanceof String
+ && invocationOnMock.getMethod().getName().equals("getString")
+ && invocationOnMock.getArguments().length > 1) {
+ value = String.format(mResources.getConfiguration().getLocales().get(0),
+ (String) value,
+ Arrays.copyOfRange(invocationOnMock.getArguments(), 1,
+ invocationOnMock.getArguments().length));
+ }
return value;
}
} catch (Resources.NotFoundException e) {
diff --git a/tests/testables/src/android/testing/ViewUtils.java b/tests/testables/src/android/testing/ViewUtils.java
index 80c2e8ddd907..0fad79d40c7a 100644
--- a/tests/testables/src/android/testing/ViewUtils.java
+++ b/tests/testables/src/android/testing/ViewUtils.java
@@ -31,13 +31,20 @@ public class ViewUtils {
* This is currently done by adding the view to a window.
*/
public static void attachView(View view) {
+ attachView(view, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ }
+
+ /**
+ * Causes the view (and its children) to have {@link View#onAttachedToWindow()} called.
+ *
+ * This is currently done by adding the view to a window.
+ */
+ public static void attachView(View view, int width, int height) {
// Make sure hardware acceleration isn't turned on.
view.getContext().getApplicationInfo().flags &=
~(ApplicationInfo.FLAG_HARDWARE_ACCELERATED);
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_APPLICATION_OVERLAY,
- 0, PixelFormat.TRANSLUCENT);
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
+ LayoutParams.TYPE_APPLICATION_OVERLAY, 0, PixelFormat.TRANSLUCENT);
view.getContext().getSystemService(WindowManager.class).addView(view, lp);
}
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 7c5dcf8b95f7..e8be33cba3a1 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -51,6 +51,7 @@ public final class FrameworksTestsFilter extends SelectTest {
"android.view.CutoutSpecificationTest",
"android.view.DisplayCutoutTest",
"android.view.DisplayShapeTest",
+ "android.view.ImeBackAnimationControllerTest",
"android.view.InsetsAnimationControlImplTest",
"android.view.InsetsControllerTest",
"android.view.InsetsFlagsTest",