Merge "Make IncompleteMotionTest multi-user and multi-display aware" into android15-tests-dev
diff --git a/apps/CameraITS/utils/ui_interaction_utils.py b/apps/CameraITS/utils/ui_interaction_utils.py
index f640d48..f5f097d 100644
--- a/apps/CameraITS/utils/ui_interaction_utils.py
+++ b/apps/CameraITS/utils/ui_interaction_utils.py
@@ -174,7 +174,7 @@
       camera has been switched.
   """
   flip_camera_pattern = (
-      r'(switch to|flip camera|switch camera|camera switch)'
+      r'(switch to|flip camera|switch camera|camera switch|switch)'
     )
   default_ui_dump = dut.ui.dump()
   logging.debug('Default camera UI dump: %s', default_ui_dump)
@@ -191,20 +191,21 @@
       logging.debug('Flip camera content-desc: %s', content_desc)
       camera_flip_res = True
       break
-  if facing == 'front' and camera_flip_res:
-    if ('rear' in content_desc or 'rear' in resource_id
-        or 'back' in content_desc or 'back' in resource_id
-        ):
-      logging.debug('Pattern found but camera is already switched.')
+  if content_desc and resource_id:
+    if facing == 'front' and camera_flip_res:
+      if ('rear' in content_desc.lower() or 'rear' in resource_id.lower()
+          or 'back' in content_desc.lower() or 'back' in resource_id.lower()
+          ):
+        logging.debug('Pattern found but camera is already switched.')
+      else:
+        dut.ui(desc=content_desc).click.wait()
+    elif facing == 'rear' and camera_flip_res:
+      if 'front' in content_desc.lower() or 'front' in resource_id.lower():
+        logging.debug('Pattern found but camera is already switched.')
+      else:
+        dut.ui(desc=content_desc).click.wait()
     else:
-      dut.ui(desc=content_desc).click.wait()
-  elif facing == 'rear' and camera_flip_res:
-    if 'front' in content_desc or 'front' in resource_id:
-      logging.debug('Pattern found but camera is already switched.')
-    else:
-      dut.ui(desc=content_desc).click.wait()
-  else:
-    raise ValueError(f'Unknown facing: {facing}')
+      raise ValueError(f'Unknown facing: {facing}')
 
   dut.take_screenshot(
       log_path, prefix=f'switched_to_{facing}_default_camera'
@@ -260,6 +261,7 @@
         timeout=WAIT_INTERVAL_FIVE_SECONDS):
       dut.ui(text=CANCEL_BUTTON_TXT).click.wait()
     switch_default_camera(dut, camera_facing, log_path)
+    time.sleep(ACTIVITY_WAIT_TIME_SECONDS)
     logging.debug('Taking photo')
     its_device_utils.run_adb_shell_command(device_id, TAKE_PHOTO_CMD)
     time.sleep(ACTIVITY_WAIT_TIME_SECONDS)
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventAndCacheTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventAndCacheTest.java
deleted file mode 100644
index 3bc4453..0000000
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventAndCacheTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.accessibility.cts;
-
-import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
-import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT;
-import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
-
-import static org.junit.Assert.assertEquals;
-
-import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
-import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.UiAutomation;
-import android.os.Bundle;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.text.TextUtils;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Class for testing {@link AccessibilityEvent} and caching. */
-@RunWith(AndroidJUnit4.class)
-public class AccessibilityEventAndCacheTest {
-    private static final long DEFAULT_TIMEOUT_MS = 2000;
-
-    // In case throttling is refreshed between children, this test uses 3 child views.
-    private static final int NUM_CHILD_VIEWS = 3;
-    private final List<TextView> mChildViews = new ArrayList<>();
-
-    private static Instrumentation sInstrumentation;
-    private static UiAutomation sUiAutomation;
-    private final ActivityTestRule<TestActivity> mActivityRule =
-            new ActivityTestRule<>(TestActivity.class, false, false);
-    private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
-            new AccessibilityDumpOnFailureRule();
-    private final InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
-            mInstrumentedAccessibilityServiceRule =
-            new InstrumentedAccessibilityServiceTestRule<>(
-                    SpeakingAccessibilityService.class, false);
-
-    @Rule
-    public final RuleChain mRuleChain =
-            RuleChain.outerRule(mActivityRule)
-                    .around(mInstrumentedAccessibilityServiceRule)
-                    .around(mDumpOnFailureRule);
-
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    @Before
-    public void setUp() throws Throwable {
-        sInstrumentation = InstrumentationRegistry.getInstrumentation();
-        sUiAutomation = sInstrumentation.getUiAutomation();
-        final Activity activity = launchActivityAndWaitForItToBeOnscreen(
-                sInstrumentation, sUiAutomation, mActivityRule);
-        mInstrumentedAccessibilityServiceRule.enableService();
-
-        mActivityRule.runOnUiThread(() -> {
-            final LinearLayout list = activity.findViewById(R.id.buttonsParent);
-            assertEquals(NUM_CHILD_VIEWS, list.getChildCount());
-            for (int i = 0; i < NUM_CHILD_VIEWS; i++) {
-                mChildViews.add((TextView) list.getChildAt(i));
-            }
-        });
-    }
-
-    @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_FIX_MERGED_CONTENT_CHANGE_EVENT_V2)
-    public void testSimultaneousChangesUpdatesAllChildNodes() throws Exception {
-        // Makes sure that all nodes are fetched in client side.
-        final List<AccessibilityNodeInfo> nodes = sUiAutomation.getRootInActiveWindow()
-                .findAccessibilityNodeInfosByText("Text");
-        final AccessibilityNodeInfo listNode = nodes.get(0).getParent();
-
-        // Update text and fetch it from client.
-        sUiAutomation.executeAndWaitForEvent(
-                () -> sInstrumentation.runOnMainSync(() -> {
-                    for (int i = 0; i < NUM_CHILD_VIEWS; i++) {
-                        mChildViews.get(i).setText("new " + i);
-                    }
-                }),
-                event ->
-                        event.getEventType() == TYPE_WINDOW_CONTENT_CHANGED
-                                && (event.getContentChangeTypes() & CONTENT_CHANGE_TYPE_TEXT) != 0
-                                && TextUtils.equals("new 0", listNode.getChild(0).getText())
-                                && TextUtils.equals("new 1", listNode.getChild(1).getText())
-                                && TextUtils.equals("new 2", listNode.getChild(2).getText()),
-                DEFAULT_TIMEOUT_MS);
-    }
-
-    /** Activity for this test containing three text views. */
-    public static class TestActivity extends AccessibilityTestActivity {
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            setContentView(R.layout.event_and_cache_test);
-        }
-    }
-}
diff --git a/tests/input/src/android/input/cts/InputInjectionTest.kt b/tests/input/src/android/input/cts/InputInjectionTest.kt
index 43dda1c..a0db5d5 100644
--- a/tests/input/src/android/input/cts/InputInjectionTest.kt
+++ b/tests/input/src/android/input/cts/InputInjectionTest.kt
@@ -32,6 +32,7 @@
 import androidx.test.filters.FlakyTest
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.UserHelper
 import com.android.test.inputinjection.IInputInjectionTestCallbacks
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -73,6 +74,7 @@
     private lateinit var targetContext: Context
     private lateinit var activityManager: ActivityManager
     private lateinit var windowFocusLatch: CountDownLatch
+    private val displayId = UserHelper().mainDisplayId
 
     @Before
     fun setUp() {
@@ -125,6 +127,7 @@
     fun testCannotInjectPointerEventsFromInstrumentationToUnownedApp() {
         startInjectionActivitySync(withCallbacks()).use {
             clickInCenterOfInjectionActivity { eventToInject ->
+                eventToInject.displayId = displayId
                 // The Instrumentation class should not be allowed to inject the start of a new
                 // gesture to a window owned by another uid. However, it should be allowed to inject
                 // the end of the gesture to ensure consistency.
@@ -151,6 +154,7 @@
         val keyPressLatch = CountDownLatch(2)
         startInjectionActivitySync(
                 withCallbacks(onKey = { keyPressLatch.countDown() })).use {
+            // sendKeyDownUpSync will eventually update the displayId to the test main display
             instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_A)
             assertEquals(0, keyPressLatch.count,
                 "Instrumentation should synchronously send key events to the activity")
@@ -167,6 +171,7 @@
         startInjectionActivitySync(
                 withCallbacks(onTouch = { clickLatch.countDown() })).use {
             clickInCenterOfInjectionActivity { eventToInject ->
+                eventToInject.displayId = displayId
                 instrumentation.uiAutomation.injectInputEvent(eventToInject, true /*sync*/)
             }
             assertEquals(0, clickLatch.count,
@@ -182,17 +187,23 @@
     fun testInjectKeyEventsFromUiAutomation() {
         val keyPressLatch = CountDownLatch(2)
         startInjectionActivitySync(
-                withCallbacks(onKey = { keyPressLatch.countDown() })).use {
+                withCallbacks(onKey = { keyPressLatch.countDown() })
+        ).use {
             val downTime = SystemClock.uptimeMillis()
-            instrumentation.uiAutomation.injectInputEvent(
-                KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0),
-                true /*sync*/)
+            val keyDownEvent =
+                    KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0)
+            keyDownEvent.displayId = displayId
+            instrumentation.uiAutomation.injectInputEvent(keyDownEvent, true /*sync*/)
+
             val upTime = SystemClock.uptimeMillis()
-            instrumentation.uiAutomation.injectInputEvent(
-                KeyEvent(downTime, upTime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0),
-                true /*sync*/)
-            assertEquals(0, keyPressLatch.count,
-                "UiAutomation should synchronously send key events to the activity")
+            val keyUpEvent = KeyEvent(downTime, upTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0)
+            keyUpEvent.displayId = displayId
+            instrumentation.uiAutomation.injectInputEvent(keyUpEvent, true /*sync*/)
+            assertEquals(
+                    0,
+                    keyPressLatch.count,
+                    "UiAutomation should synchronously send key events to the activity"
+            )
         }
     }
 
@@ -221,13 +232,26 @@
     private fun clickInCenterOfInjectionActivity(injector: (MotionEvent) -> Unit) {
         val bounds = getActivityBounds(INPUT_INJECTION_COMPONENT)
         val downTime = SystemClock.uptimeMillis()
-        injector(
-            MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
-                bounds.centerX().toFloat(), bounds.centerY().toFloat(), 0))
+        val downEvent = MotionEvent.obtain(
+                downTime,
+                downTime,
+                MotionEvent.ACTION_DOWN,
+                bounds.centerX().toFloat(),
+                bounds.centerY().toFloat(),
+                0)
+        downEvent.displayId = displayId
+        injector(downEvent)
+
         val upTime = SystemClock.uptimeMillis()
-        injector(
-            MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP,
-                bounds.centerX().toFloat(), bounds.centerY().toFloat(), 0))
+        val upEvent = MotionEvent.obtain(
+                downTime,
+                upTime,
+                MotionEvent.ACTION_UP,
+                bounds.centerX().toFloat(),
+                bounds.centerY().toFloat(),
+                0)
+        upEvent.displayId = displayId
+        injector(upEvent)
     }
 
     private fun withCallbacks(
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioSystemUsageTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioSystemUsageTest.java
index e20be8f..83abfb2 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioSystemUsageTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioSystemUsageTest.java
@@ -112,19 +112,4 @@
                 builder::build);
         assertThat(thrown).hasMessageThat().contains("Cannot create AudioTrack");
     }
-
-    @Test
-    public void getInputForAttr_returnsError() {
-        AudioAttributes unsupportedInputAudioAttributes = new AudioAttributes.Builder()
-                .setSystemUsage(AudioAttributes.USAGE_SAFETY)
-                .setCapturePreset(MediaRecorder.AudioSource.MIC)
-                .build();
-        AudioRecord.Builder builder = new AudioRecord.Builder()
-                .setAudioAttributes(unsupportedInputAudioAttributes);
-
-        // Calls AudioPolicyService#getInputForAttr which returns ERROR for unsupported usage
-        UnsupportedOperationException thrown = expectThrows(UnsupportedOperationException.class,
-                builder::build);
-        assertThat(thrown).hasMessageThat().contains("Cannot create AudioRecord");
-    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 84ddaa5..08c1c05 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -6034,39 +6034,6 @@
     }
 
     @Test
-    @ApiTest(apis = {"android.telephony.TelephonyManager#getPackagesWithCarrierPrivileges"})
-    public void testGetPackagesWithCarrierPrivilegesEnforcesReadPrivilege() {
-        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
-
-        try {
-            InstrumentationRegistry.getInstrumentation()
-                    .getUiAutomation()
-                    .adoptShellPermissionIdentity(
-                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
-            mTelephonyManager.getPackagesWithCarrierPrivileges();
-        } catch (SecurityException e) {
-            fail("TelephonyManager#getPackagesWithCarrierPrivileges requires "
-                    + "READ_PRIVILEGED_PHONE_STATE");
-        } finally {
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    public void testGetPackagesWithCarrierPrivilegesThrowsExceptionWithoutReadPrivilege() {
-        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
-
-        try {
-            mTelephonyManager.getPackagesWithCarrierPrivileges();
-            fail("TelephonyManager#getPackagesWithCarrierPrivileges must be protected "
-                    + "with READ_PRIVILEGED_PHONE_STATE");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    @Test
     @ApiTest(apis = {"android.telephony.TelephonyManager#getSimSlotMapping",
             "android.telephony.TelephonyManager#setSimSlotMapping"})
     public void testSimSlotMapping() {