Snap for 11397440 from 6f739e937fdaaaf838424d91b32ba67c1496855f to mainline-ipsec-release

Change-Id: Id1191b3460e288146d337622253db675fc814d24
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/Step.java b/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
index 8064df3..223b7c9 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
@@ -81,6 +81,7 @@
     private static final Automator sAutomator = new Automator(AUTOMATION_FILE);
 
     private View mInstructionView;
+    private Button mCollapseButton;
 
     private static final WindowManager sWindowManager =
             TestApis.context().instrumentedContext().getSystemService(WindowManager.class);
@@ -284,6 +285,28 @@
     }
 
     /**
+     * Adds a small button that allows users to collapse the instructions.
+     */
+    protected void addCollapseInstructionsButton() {
+        mCollapseButton = new Button(TestApis.context().instrumentedContext());
+        mCollapseButton.setText("\u21F1");
+        mCollapseButton.setOnClickListener(v -> collapse());
+        GridLayout layout = mInstructionView.findViewById(R.id.buttons);
+        layout.addView(mCollapseButton);
+    }
+
+    private void collapse() {
+        TextView instructionsTextView = mInstructionView.findViewById(R.id.text);
+        if (instructionsTextView.getVisibility() != View.GONE) {
+            instructionsTextView.setVisibility(View.GONE);
+            mCollapseButton.setText("\u21F2");
+        } else {
+            instructionsTextView.setVisibility(View.VISIBLE);
+            mCollapseButton.setText("\u21F1");
+        }
+    }
+
+    /**
      * Adds a button to immediately mark the test as failed and request the tester to provide the
      * reason for failure.
      */
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
index cb32055..5c45fa1 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
@@ -694,4 +694,18 @@
         return isAudioOutputDeviceInList(audioOutputDevice,
                 "dumpsys audio | grep 'adjust-only absolute volume devices'");
     }
+
+    /**
+     * On Google TV devices the only stream played is STREAM_MUSIC.
+     * The method returns whether "Devices" in "STREAM_MUSIC" contains "hdmi" in audio dumpsys.
+     * This is required by tests where the DUT has to redirect volume key events as CEC
+     * <User Control Pressed> messages.
+     * This method might return false, because the set-up contains an HDMI Stub.
+     * See {@link android.media.AudioSystem#STREAM_MUSIC} and
+     * {@link android.media.AudioSystem#DEVICE_OUT_HDMI}.
+     */
+    public boolean isPlayingStreamMusicOnHdmiOut() throws DeviceNotAvailableException {
+        return getDevice().executeShellCommand("dumpsys audio | sed -n '/^- STREAM_MUSIC:/,/^$/p'"
+                + " | grep \"Devices\"").contains("hdmi");
+    }
 }
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
index 298a0ad..03f6931 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
@@ -94,11 +94,13 @@
         // DeviceDiscoveryAction will send GIVE_OSD_NAME and GIVE_DEVICE_VENDOR_ID
         // HotplugDetectionAction will send GIVE_PHYSICAL_ADDRESS
         // PowerStatusMonitorAction will send GIVE_POWER_STATUS
+        // AbsoluteVolumeAudioStatusAction will send GIVE_AUDIO_STATUS
         List<CecOperand> excludeOperands = new ArrayList<>();
         excludeOperands.add(CecOperand.GIVE_PHYSICAL_ADDRESS);
         excludeOperands.add(CecOperand.GIVE_DEVICE_VENDOR_ID);
         excludeOperands.add(CecOperand.GIVE_OSD_NAME);
         excludeOperands.add(CecOperand.GIVE_POWER_STATUS);
+        excludeOperands.add(CecOperand.GIVE_AUDIO_STATUS);
 
         hdmiCecClient.sendCecMessage(message, params);
         // Default timeout for the incoming command to arrive in response to a request is 2 secs
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index 4a64e5c..d0f26e9 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -19,6 +19,8 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hdmicec.cts.BaseHdmiCecCtsTest;
 import android.hdmicec.cts.CecMessage;
 import android.hdmicec.cts.CecOperand;
@@ -206,6 +208,9 @@
      */
     @Test
     public void cect_sendVolumeKeyPressToTv() throws Exception {
+        // The DUT won't send <User Control Pressed> messages if this condition is not met.
+        assumeTrue(isPlayingStreamMusicOnHdmiOut());
+
         ITestDevice device = getDevice();
         String ucpMessage;
         String command = "cmd hdmi_control setsam ";
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
index 701b6d7..3f3b55f 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hdmicec.cts.BaseHdmiCecCtsTest;
 import android.hdmicec.cts.CecMessage;
 import android.hdmicec.cts.CecOperand;
@@ -60,6 +62,8 @@
     public void cect_hf4_10_5_RemoteControlCommandsWithSystemAudioControlProperty()
             throws Exception {
         setCec20();
+        // The DUT won't send <User Control Pressed> messages if this condition is not met.
+        assumeTrue(isPlayingStreamMusicOnHdmiOut());
 
         ITestDevice device = getDevice();
         String volumeControlEnabled =
diff --git a/tests/tests/attributionsource/src/android/attributionsource/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/attributionsource/src/android/attributionsource/cts/RuntimePermissionsAppOpTrackingTest.kt
index df38cf9..1f6fe38 100644
--- a/tests/tests/attributionsource/src/android/attributionsource/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/attributionsource/src/android/attributionsource/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -1001,7 +1001,17 @@
                 }
                 assertThat(opProxyInfo!!.uid).isEqualTo(attributionSource.uid)
                 assertThat(opProxyInfo.packageName).isEqualTo(attributionSource.packageName)
-                assertThat(opProxyInfo.attributionTag).isEqualTo(attributionSource.attributionTag)
+
+                /* Fix made to b/304983146 treats the attribution coming from shell as invalid
+                 because it will not exist in shell package. Hence this change is to
+                 validate them as null instead of actual values
+                */
+                if (attributionSource.packageName == SHELL_PACKAGE_NAME) {
+                    assertThat(opProxyInfo.attributionTag).isNull()
+                } else {
+                    assertThat(opProxyInfo.attributionTag)
+                        .isEqualTo(attributionSource.attributionTag)
+                }
             }
         }
 
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/AssociateTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/AssociateTest.kt
index 839403e..3bd4e84 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/AssociateTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/AssociateTest.kt
@@ -24,8 +24,10 @@
 import android.companion.cts.common.SIMPLE_EXECUTOR
 import android.platform.test.annotations.AppModeFull
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compatibility.common.util.FeatureUtil
 import kotlin.test.assertEquals
 import kotlin.test.assertIs
+import org.junit.Assume.assumeFalse
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -42,6 +44,8 @@
 
     @Test
     fun test_associate() {
+        assumeFalse(FeatureUtil.isWatch())
+
         val request: AssociationRequest = AssociationRequest.Builder()
                 .build()
         val callback = RecordingCallback()
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/DeviceProfilesTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/DeviceProfilesTest.kt
index dff8565..c11cb23 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/DeviceProfilesTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/DeviceProfilesTest.kt
@@ -1,5 +1,6 @@
 package android.companion.cts.core
 
+import android.annotation.CallSuper
 import android.app.role.RoleManager.ROLE_ASSISTANT
 import android.app.role.RoleManager.ROLE_BROWSER
 import android.app.role.RoleManager.ROLE_CALL_REDIRECTION
@@ -18,12 +19,14 @@
 import android.companion.cts.common.assertEmpty
 import android.platform.test.annotations.AppModeFull
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.junit.Test
-import org.junit.runner.RunWith
+import com.android.compatibility.common.util.FeatureUtil
 import kotlin.test.assertEquals
 import kotlin.test.assertFailsWith
 import kotlin.test.assertIs
 import kotlin.test.assertNotNull
+import org.junit.Assume.assumeFalse
+import org.junit.Test
+import org.junit.runner.RunWith
 
 /**
  * Test CDM device profiles.
@@ -38,6 +41,14 @@
 @AppModeFull(reason = "CompanionDeviceManager APIs are not available to the instant apps.")
 @RunWith(AndroidJUnit4::class)
 class DeviceProfilesTest : CoreTestBase() {
+
+    @CallSuper
+    override fun setUp() {
+        super.setUp()
+
+        assumeFalse(FeatureUtil.isWatch())
+    }
+
     /** Test that all supported device profiles require a permission. */
     @Test
     fun test_supportedProfiles() {
@@ -123,4 +134,4 @@
                 ""
         )
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/SystemDataTransferTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/SystemDataTransferTest.kt
index 7033f59..30e3b39 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/SystemDataTransferTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/SystemDataTransferTest.kt
@@ -28,6 +28,7 @@
 import android.os.OutcomeReceiver
 import android.platform.test.annotations.AppModeFull
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compatibility.common.util.FeatureUtil
 import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
 import java.io.PipedInputStream
@@ -45,6 +46,7 @@
 import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
 import libcore.util.EmptyArray
+import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -69,6 +71,8 @@
     override fun setUp() {
         super.setUp()
 
+        assumeFalse(FeatureUtil.isWatch())
+
         // Assume Permission Transfer is enabled, otherwise skip the test.
         try {
             val association = associate()
diff --git a/tests/tests/packageinstaller/tapjacking/src/android/packageinstaller/tapjacking/cts/TapjackingTest.java b/tests/tests/packageinstaller/tapjacking/src/android/packageinstaller/tapjacking/cts/TapjackingTest.java
index 4f0630e..486b635 100644
--- a/tests/tests/packageinstaller/tapjacking/src/android/packageinstaller/tapjacking/cts/TapjackingTest.java
+++ b/tests/tests/packageinstaller/tapjacking/src/android/packageinstaller/tapjacking/cts/TapjackingTest.java
@@ -119,12 +119,12 @@
                 waitForView(mPackageName, OVERLAY_ACTIVITY_TEXT_VIEW_ID));
 
         installButton = waitForButton(INSTALL_BUTTON_ID);
-        assertNotNull("Cannot find install button below overlay activity", installButton);
-
-        Log.i(LOG_TAG, "installButton.click");
-        installButton.click();
-        assertFalse("Tap on install button succeeded", mUiDevice.wait(
-            Until.gone(getBySelector(INSTALL_BUTTON_ID)), WAIT_FOR_UI_TIMEOUT));
+        if (installButton != null) {
+            Log.i(LOG_TAG, "installButton.click");
+            installButton.click();
+            assertFalse("Tap on install button succeeded", mUiDevice.wait(
+                Until.gone(getBySelector(INSTALL_BUTTON_ID)), WAIT_FOR_UI_TIMEOUT));
+        }
 
         mUiDevice.pressBack();
     }
@@ -144,15 +144,16 @@
             waitForView(mPackageName, OVERLAY_ACTIVITY_TEXT_VIEW_ID));
 
         installButton = waitForButton(INSTALL_BUTTON_ID);
-        assertNotNull("Cannot find install button below overlay activity", installButton);
-
-        Log.i(LOG_TAG, "installButton.click");
-        installButton.click();
-        assertFalse("Tap on install button succeeded", mUiDevice.wait(
-            Until.gone(getBySelector(INSTALL_BUTTON_ID)), WAIT_FOR_UI_TIMEOUT));
+        if (installButton != null) {
+            Log.i(LOG_TAG, "installButton.click");
+            installButton.click();
+            assertFalse("Tap on install button succeeded", mUiDevice.wait(
+                    Until.gone(getBySelector(INSTALL_BUTTON_ID)), WAIT_FOR_UI_TIMEOUT));
+        }
 
         mUiDevice.pressBack();
 
+        // Overlay should be gone and we require that the button can be found.
         installButton = waitForButton(INSTALL_BUTTON_ID);
         assertNotNull("Cannot find install button", installButton);
 
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 5533063..59cd528 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -104,6 +104,11 @@
         @JvmStatic
         protected val isAutomotive =
             packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+        @JvmStatic
+        protected val isAutomotiveSplitscreen = isAutomotive &&
+            packageManager.hasSystemFeature(
+                    /* PackageManager.FEATURE_CAR_SPLITSCREEN_MULTITASKING */
+                    "android.software.car.splitscreen_multitasking")
     }
 
     @get:Rule
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
index fadaa27..73fe137 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
@@ -43,6 +43,9 @@
         // PermissionController for television uses a floating window.
         assumeFalse(isTv)
 
+        // Automotive split-screen multitasking uses multi-window mode
+        assumeFalse(isAutomotiveSplitscreen)
+
         assertAppHasPermission(ACCESS_FINE_LOCATION, false)
         requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
 
@@ -63,6 +66,9 @@
         // PermissionController for television uses a floating window.
         assumeFalse(isTv)
 
+        // Automotive split-screen multitasking uses multi-window mode
+        assumeFalse(isAutomotiveSplitscreen)
+
         assertAppHasPermission(ACCESS_FINE_LOCATION, false)
         requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
 
diff --git a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTestRule.java b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTestRule.java
index cc9e422..125c46b 100644
--- a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTestRule.java
+++ b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTestRule.java
@@ -54,8 +54,21 @@
 
     @Override
     public Statement apply(final Statement base, final Description description) {
+        // If WebView is not available, simply skip loading the SDK and then throw an assumption
+        // failure for each test run attempt.
+        // We can't throw the assumptions in the apply because WebViewSandboxTestRule can be used as
+        // a class rule.
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return base;
+        }
+
+        return super.apply(base, description);
+    }
+
+    @Override
+    public void assertSdkTestRunPasses(String testMethodName, Bundle params) throws Throwable {
         // This will prevent shared webview tests from running if a WebView provider does not exist.
         Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
-        return super.apply(base, description);
+        super.assertSdkTestRunPasses(testMethodName, params);
     }
 }
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index e1b612c..ef11ad1 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -288,7 +288,7 @@
     per_testcase_directory: true,
     test_config: "AndroidTest_PackageSignatureTest.xml",
     manifest: "AndroidManifest_PackageSignatureTest.xml",
-    min_sdk_version: "31",
+    min_sdk_version: "30",
     sdk_version: "system_34",
     target_sdk_version: "34",
 }
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
index aa0b3d1..8ee4a20 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
@@ -41,7 +41,7 @@
     private static final String COMMAND_MODEM_SERVICE_UNKNOWN = "unknown";
     private static final String COMMAND_MODEM_SERVICE_DEFAULT = "default";
 
-    private static final int BIND_LOCAL_MOCKMODEM_SERVICE_TIMEOUT_MS = 5000;
+    private static final int BIND_LOCAL_MOCKMODEM_SERVICE_TIMEOUT_MS = 25000;
     private static final int BIND_RADIO_INTERFACE_READY_TIMEOUT_MS = 5000;
 
     private class MockModemServiceConnection implements ServiceConnection {
diff --git a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
index c8f16ef..1cad13a 100644
--- a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
+++ b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
@@ -87,7 +87,8 @@
         private CountDownLatch mCountDownLatch = new CountDownLatch(1);
 
         void waitForModeToChange(int modeId) throws InterruptedException {
-            while (modeId != mDisplay.getMode().getModeId()) {
+            while (modeId != mDisplay.getMode().getModeId()
+                && mDisplay.getMode().getRefreshRate() != mDisplay.getRefreshRate()) {
                 mCountDownLatch.await(5, TimeUnit.SECONDS);
             }
         }
@@ -167,9 +168,9 @@
     @Test
     public void testRefreshRate() {
         boolean fpsOk = false;
-        float claimedFps = mDisplay.getRefreshRate();
 
         for (int i = 0; i < 3; i++) {
+            float claimedFps = mDisplay.getRefreshRate();
             float achievedFps = mFpsResult.waitResult();
             Log.d(TAG, "claimed " + claimedFps + " fps, " +
                        "achieved " + achievedFps + " fps");