Snap for 9890127 from 901943e3ce4df6147ac637d37a8307622c09b0f8 to mainline-permission-release
Change-Id: I7e65ed7d351690f17d3bda09ff17af1b32e7b299
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index af32358..cd52317 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -265,6 +265,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_features" />
+ <meta-data android:name="test_required_configs" android:value="config_no_emulator"/>
<meta-data android:name="test_required_features"
android:value="android.software.companion_device_setup" />
<meta-data android:name="display_mode"
@@ -284,6 +285,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_features" />
+ <meta-data android:name="test_required_configs" android:value="config_no_emulator"/>
<meta-data android:name="test_required_features"
android:value="android.software.companion_device_setup" />
<meta-data android:name="display_mode"
@@ -5361,6 +5363,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_audio" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.hdmi.cec" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.media.AudioDescriptor#getStandard|
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
index 3ca4ee0..bf7f985 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
@@ -33,7 +33,6 @@
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -138,13 +137,9 @@
// Turn device off
sendDeviceToSleep();
- List<Integer> keycodes = new ArrayList<>();
- keycodes.add(HdmiCecConstants.CEC_KEYCODE_POWER_ON_FUNCTION);
- keycodes.add(HdmiCecConstants.CEC_KEYCODE_POWER_OFF_FUNCTION);
-
- // Send a <UCP>[Power On] immediately followed by a <UCP>[Power Off]
- hdmiCecClient.sendMultipleUserControlPressAndRelease(
- hdmiCecClient.getSelfDevice(), keycodes);
+ device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ TimeUnit.MILLISECONDS.sleep(200);
+ device.executeShellCommand("input keyevent KEYCODE_SLEEP");
String reportPowerStatus =
hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_POWER_STATUS);
@@ -198,13 +193,9 @@
wakeUpDevice();
WakeLockHelper.acquirePartialWakeLock(getDevice());
- List<Integer> keycodes = new ArrayList<>();
- keycodes.add(HdmiCecConstants.CEC_KEYCODE_POWER_OFF_FUNCTION);
- keycodes.add(HdmiCecConstants.CEC_KEYCODE_POWER_ON_FUNCTION);
-
- // Send a <UCP>[Power Off] immediately followed by a <UCP>[Power On]
- hdmiCecClient.sendMultipleUserControlPressAndRelease(
- hdmiCecClient.getSelfDevice(), keycodes);
+ device.executeShellCommand("input keyevent KEYCODE_SLEEP");
+ TimeUnit.MILLISECONDS.sleep(200);
+ device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
String reportPowerStatus =
hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_POWER_STATUS);
diff --git a/hostsidetests/incident/AndroidTest.xml b/hostsidetests/incident/AndroidTest.xml
index 727277d..73be7b4 100644
--- a/hostsidetests/incident/AndroidTest.xml
+++ b/hostsidetests/incident/AndroidTest.xml
@@ -20,9 +20,6 @@
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
- <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
- <option name="user-type" value="system" />
- </target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsIncidentHostTestCases.jar" />
</test>
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
index 90d8196..645f909 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -20,7 +20,7 @@
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,41 +28,39 @@
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0963 extends StsExtraBusinessLogicHostTestBase {
- static final String TEST_PKG = "android.security.cts.CVE_2021_0963";
+public class CVE_2021_0963 extends NonRootSecurityTestCase {
- /**
- * b/199754277
- * Vulnerable app : KeyChain.apk
- * Vulnerable module : com.android.keychain
- * Is Play managed : No
- */
+ // b/199754277
+ // Vulnerable app : KeyChain.apk
+ // Vulnerable module : com.android.keychain
+ // Is Play managed : No
@AsbSecurityTest(cveBugId = 199754277)
@Test
public void testPocCVE_2021_0963() {
+ int userId = 0;
+ String component = null;
+ ITestDevice device = null;
try {
- ITestDevice device = getDevice();
+ // Install the application
+ installPackage("CVE-2021-0963.apk", "-t");
- /* Wake up the device */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ // Set test-app as device owner.
+ final String testPkg = "android.security.cts.CVE_2021_0963";
+ component = testPkg + "/" + testPkg + ".PocDeviceAdminReceiver";
+ device = getDevice();
+ device.setDeviceOwner(component, userId);
- /* Install the application */
- installPackage("CVE-2021-0963.apk");
-
- /*
- * Set device as owner. After the test is completed, this change is reverted in the
- * DeviceTest.java's tearDown() method by calling clearDeviceOwnerApp() on an instance
- * of DevicePolicyManager.
- */
- AdbUtils.runCommandLine("dpm set-device-owner --user 0 '" + TEST_PKG + "/" + TEST_PKG
- + ".PocDeviceAdminReceiver" + "'", device);
-
- /* Run the device test "testOverlayButtonPresence" */
- runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+ // Run the device test "testOverlayButtonPresence"
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence");
} catch (Exception e) {
assumeNoException(e);
+ } finally {
+ try {
+ // Remove test-app as device owner.
+ device.removeAdmin(component, userId);
+ } catch (Exception e) {
+ // ignore
+ }
}
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20955.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20955.java
new file mode 100644
index 0000000..96f2257
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20955.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_20955 extends NonRootSecurityTestCase {
+
+ // b/258653813
+ // Vulnerable app : Settings.apk
+ // Vulnerable package : com.android.settings
+ // Is Play Managed : No
+ @AsbSecurityTest(cveBugId = 240663194)
+ @Test
+ public void testPocCVE_2023_20955() {
+ int userId = -1;
+ ITestDevice device = null;
+ final String testPkg = "android.security.cts.CVE_2023_20955_test";
+ final String componentName = testPkg + "/.PocDeviceAdminReceiver";
+ try {
+ device = getDevice();
+
+ // Install the test app
+ installPackage("CVE-2023-20955-test.apk", "-t");
+
+ // Set test app as device owner
+ assumeTrue("Failed to set test app as device owner",
+ device.setDeviceOwner(componentName, 0));
+
+ // Create a new user
+ userId = device.createUser("CTSUser");
+ assumeTrue("Failed to create a user. ITestDevice.createUser() returned -1",
+ userId != -1);
+
+ // Install test helper app for all users
+ installPackage("CVE-2023-20955-test-helper.apk", "--user all");
+
+ // Run device test to check if App Info window allows uninstall for all users if
+ // DevicePolicyManager has restricted it.
+ runDeviceTests(testPkg, testPkg + ".DeviceTest",
+ "testAppInfoUninstallForAllUsersDisabled");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // Remove user
+ device.removeUser(userId);
+
+ // Remove test app as device owner
+ device.removeAdmin(componentName, 0);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
index ea39e68..2a30791 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -35,5 +35,5 @@
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
- platform_apis: true,
+ platform_apis: true, // required for using RemoteCallback
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
index ae0d416..dec0ae4 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2022 The Android Open Source Project
+ Copyright 2023 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.
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.security.cts.CVE_2021_0963">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- <application>
+ <application android:testOnly="true">
<activity android:name=".PocActivity"
android:exported="true">
<intent-filter>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_pkey b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_pkey
new file mode 100644
index 0000000..3a07113
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_pkey
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_usercert b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_usercert
new file mode 100644
index 0000000..4665a94
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/raw/cve_2021_0963_usercert
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
index 6a14b4a..18ccaba 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2022 The Android Open Source Project
+ Copyright 2023 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.
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
index 1da84fe..e6915d6 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2022 The Android Open Source Project
+ Copyright 2023 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.
@@ -16,25 +16,32 @@
-->
<resources>
- <string name="actionKeychainActivity">com.android.keychain.CHOOSER</string>
- <string name="activityNotFoundMsg">The activity with intent was not found : </string>
- <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+ <string name="action">com.android.keychain.CHOOSER</string>
<string name="alias">Client</string>
- <string name="callbackKey">callback</string>
- <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
- <string name="certType">X.509</string>
- <string name="dumpsysActivity">dumpsys activity %1$s</string>
- <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command
- </string>
- <string name="errorMessage">Device is vulnerable to b/199754277 hence any app with
- "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
- <string name="keyType">RSA</string>
- <string name="mResumedTrue">mResumed=true</string>
- <string name="messageKey">message</string>
- <string name="overlayButtonText">OverlayButton</string>
- <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
- <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
- <string name="statusKey">status</string>
- <string name="vulActivityNotRunningError">The activity %1$s is not currently running
- on the device</string>
+ <string name="callback">callback</string>
+ <string name="cmdAdbHome">input keyevent KEYCODE_HOME</string>
+ <string name="cmdDumpsysActivityByActivity">dumpsys activity %1$s</string>
+ <string name="cmdDumpsysActivityByPkg">dumpsys activity -p %1$s activities</string>
+ <string name="exceptionActivityNotFound">The activity with intent was not found : </string>
+ <string name="exceptionActivityNotStart">Unable to start the activity with intent : </string>
+ <string name="exceptionCanNotDrawOverlays">The application cannot draw overlays</string>
+ <string name="exceptionOverlayUiNotVisible">Overlay UI did not appear on the screen</string>
+ <string name="exceptionServiceNotStart">Unable to start the overlay service</string>
+ <string name="exceptionVulActivityNotResume">The activity %1$s is not currently resumed on the
+ device</string>
+ <string name="exceptionVulUiNotVisible">UI of vulnerable activity %1$s is not visible</string>
+ <string name="failMsg">Device is vulnerable to b/199754277 !! Any app with SYSTEM_ALERT_WINDOW
+ can overlay the %1$s screen</string>
+ <string name="flagActivityResumed">mResumed=true</string>
+ <string name="flagActivityVisible">mVisible=true</string>
+ <string name="message">message</string>
+ <string name="pKey">cve_2021_0963_pkey</string>
+ <string name="rawResOpenError">Could not open the raw resource %1$s</string>
+ <string name="status">status</string>
+ <string name="strSplitRegex"><![CDATA[((?<=mVisible=(true|false)))]]></string>
+ <string name="streamReadError">Could not read from stream of the raw resource %1$s</string>
+ <string name="txtOverlayBtn">CVE_2021_0963_button</string>
+ <string name="typeCert">X.509</string>
+ <string name="typeKey">RSA</string>
+ <string name="userCert">cve_2021_0963_usercert</string>
</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
index a826e80..ed5352d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2022 The Android Open Source Project
+ Copyright 2023 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.
@@ -16,6 +16,5 @@
-->
<device-admin>
- <uses-policies>
- </uses-policies>
+ <uses-policies />
</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
index 3d1c0df..209bdf0 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -43,6 +43,9 @@
import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.cert.Certificate;
@@ -56,256 +59,31 @@
public class DeviceTest {
private DevicePolicyManager mDevicePolicyManager;
private ComponentName mComponentName;
- Context mContext;
+ private Context mContext;
+ private UiDevice mDevice;
+ private Resources mResources;
- /**
- * Generated from above and converted with:
- *
- * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
- */
- private static final byte[] PRIVATE_KEY =
- new byte[] {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x76, (byte) 0x02,
- (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
- (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
- (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04,
- (byte) 0x82, (byte) 0x02, (byte) 0x60, (byte) 0x30, (byte) 0x82, (byte) 0x02,
- (byte) 0x5c, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81,
- (byte) 0x81, (byte) 0x00, (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8,
- (byte) 0xc4, (byte) 0x44, (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1,
- (byte) 0xb9, (byte) 0x1b, (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f,
- (byte) 0x06, (byte) 0xe7, (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8,
- (byte) 0xaa, (byte) 0x0a, (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b,
- (byte) 0xad, (byte) 0xfe, (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d,
- (byte) 0xc9, (byte) 0xf5, (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1,
- (byte) 0xcc, (byte) 0x3f, (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67,
- (byte) 0x6a, (byte) 0xe8, (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a,
- (byte) 0x53, (byte) 0xd9, (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90,
- (byte) 0xbb, (byte) 0x95, (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32,
- (byte) 0xce, (byte) 0xf8, (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19,
- (byte) 0x91, (byte) 0x29, (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1,
- (byte) 0xcb, (byte) 0xa7, (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a,
- (byte) 0x0c, (byte) 0x07, (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d,
- (byte) 0x08, (byte) 0xf4, (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66,
- (byte) 0x28, (byte) 0xcb, (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f,
- (byte) 0x7e, (byte) 0x83, (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83,
- (byte) 0x2d, (byte) 0xa0, (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68,
- (byte) 0x47, (byte) 0x31, (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e,
- (byte) 0x12, (byte) 0x1b, (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8,
- (byte) 0x84, (byte) 0x5f, (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03,
- (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80,
- (byte) 0x24, (byte) 0x95, (byte) 0xb8, (byte) 0xe1, (byte) 0xf4, (byte) 0x7b,
- (byte) 0xbc, (byte) 0x0c, (byte) 0x6d, (byte) 0x4d, (byte) 0x01, (byte) 0xe2,
- (byte) 0x42, (byte) 0xe2, (byte) 0x9a, (byte) 0xe4, (byte) 0xab, (byte) 0xe2,
- (byte) 0x9a, (byte) 0x8c, (byte) 0xd5, (byte) 0x93, (byte) 0xe8, (byte) 0x43,
- (byte) 0x77, (byte) 0x85, (byte) 0xfd, (byte) 0xf3, (byte) 0xd8, (byte) 0xd6,
- (byte) 0xe9, (byte) 0x02, (byte) 0xf3, (byte) 0xbf, (byte) 0x82, (byte) 0x65,
- (byte) 0xc3, (byte) 0x7c, (byte) 0x96, (byte) 0x09, (byte) 0x04, (byte) 0x16,
- (byte) 0x1d, (byte) 0x03, (byte) 0x3d, (byte) 0x82, (byte) 0xb8, (byte) 0xdc,
- (byte) 0xbb, (byte) 0xd6, (byte) 0xbf, (byte) 0x2a, (byte) 0x52, (byte) 0x83,
- (byte) 0x76, (byte) 0x5b, (byte) 0xae, (byte) 0x59, (byte) 0xf6, (byte) 0xee,
- (byte) 0x84, (byte) 0x44, (byte) 0x4a, (byte) 0xa7, (byte) 0x25, (byte) 0x50,
- (byte) 0x89, (byte) 0x63, (byte) 0x43, (byte) 0x0b, (byte) 0xc8, (byte) 0xd5,
- (byte) 0x17, (byte) 0x9d, (byte) 0x8b, (byte) 0x62, (byte) 0xd5, (byte) 0xf1,
- (byte) 0xde, (byte) 0x45, (byte) 0xe6, (byte) 0x35, (byte) 0x10, (byte) 0xba,
- (byte) 0x58, (byte) 0x18, (byte) 0x44, (byte) 0xc1, (byte) 0x6d, (byte) 0xb6,
- (byte) 0x1d, (byte) 0x2f, (byte) 0x53, (byte) 0xb6, (byte) 0x5a, (byte) 0xf1,
- (byte) 0x66, (byte) 0xbc, (byte) 0x0e, (byte) 0x63, (byte) 0xa7, (byte) 0x0f,
- (byte) 0x81, (byte) 0x4b, (byte) 0x07, (byte) 0x31, (byte) 0xa5, (byte) 0x70,
- (byte) 0xec, (byte) 0x30, (byte) 0x57, (byte) 0xc4, (byte) 0x14, (byte) 0xb2,
- (byte) 0x8b, (byte) 0x6f, (byte) 0x26, (byte) 0x7e, (byte) 0x55, (byte) 0x60,
- (byte) 0x63, (byte) 0x7d, (byte) 0x90, (byte) 0xd7, (byte) 0x5f, (byte) 0xef,
- (byte) 0x7d, (byte) 0xc1, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xfe,
- (byte) 0x92, (byte) 0xa9, (byte) 0xf1, (byte) 0x29, (byte) 0x1e, (byte) 0xd4,
- (byte) 0x72, (byte) 0xd3, (byte) 0x3f, (byte) 0x9d, (byte) 0xd6, (byte) 0x3d,
- (byte) 0xe9, (byte) 0xcf, (byte) 0x3e, (byte) 0x06, (byte) 0xdc, (byte) 0x65,
- (byte) 0x8f, (byte) 0xc0, (byte) 0x81, (byte) 0xc2, (byte) 0x66, (byte) 0xc1,
- (byte) 0x5c, (byte) 0x2c, (byte) 0xfa, (byte) 0x08, (byte) 0x65, (byte) 0xb6,
- (byte) 0x47, (byte) 0xc5, (byte) 0x14, (byte) 0x8d, (byte) 0x69, (byte) 0xe9,
- (byte) 0xaf, (byte) 0x42, (byte) 0x02, (byte) 0x53, (byte) 0x04, (byte) 0x63,
- (byte) 0x47, (byte) 0xaf, (byte) 0xcc, (byte) 0xae, (byte) 0x08, (byte) 0x31,
- (byte) 0xba, (byte) 0xea, (byte) 0x85, (byte) 0xda, (byte) 0xd6, (byte) 0xb2,
- (byte) 0xe7, (byte) 0x4c, (byte) 0xda, (byte) 0xad, (byte) 0x52, (byte) 0x76,
- (byte) 0x48, (byte) 0x16, (byte) 0xeb, (byte) 0x02, (byte) 0x41, (byte) 0x00,
- (byte) 0xef, (byte) 0xc4, (byte) 0x7d, (byte) 0x69, (byte) 0x7b, (byte) 0xcb,
- (byte) 0xcb, (byte) 0xf7, (byte) 0x00, (byte) 0x2d, (byte) 0x05, (byte) 0x3c,
- (byte) 0xe4, (byte) 0xfd, (byte) 0x5c, (byte) 0xea, (byte) 0xcf, (byte) 0x40,
- (byte) 0x84, (byte) 0x10, (byte) 0xf1, (byte) 0xc0, (byte) 0xaf, (byte) 0xc7,
- (byte) 0xc8, (byte) 0x51, (byte) 0xac, (byte) 0x18, (byte) 0x25, (byte) 0x63,
- (byte) 0x75, (byte) 0xc7, (byte) 0x0e, (byte) 0xa9, (byte) 0xed, (byte) 0x9c,
- (byte) 0x78, (byte) 0x08, (byte) 0x28, (byte) 0x1d, (byte) 0x9e, (byte) 0xfa,
- (byte) 0x17, (byte) 0x0f, (byte) 0x7a, (byte) 0x6a, (byte) 0x78, (byte) 0x63,
- (byte) 0x6e, (byte) 0xb3, (byte) 0x6b, (byte) 0xd6, (byte) 0x43, (byte) 0x4b,
- (byte) 0x58, (byte) 0xb8, (byte) 0x77, (byte) 0x10, (byte) 0x07, (byte) 0x70,
- (byte) 0xa6, (byte) 0xa9, (byte) 0xae, (byte) 0x0d, (byte) 0x02, (byte) 0x41,
- (byte) 0x00, (byte) 0x92, (byte) 0x4c, (byte) 0x79, (byte) 0x0b, (byte) 0x95,
- (byte) 0xc5, (byte) 0x18, (byte) 0xf4, (byte) 0x90, (byte) 0x40, (byte) 0x8c,
- (byte) 0x15, (byte) 0x96, (byte) 0x69, (byte) 0x2a, (byte) 0xe7, (byte) 0x8b,
- (byte) 0x8b, (byte) 0xd7, (byte) 0x76, (byte) 0x00, (byte) 0x7c, (byte) 0xd1,
- (byte) 0xda, (byte) 0xb9, (byte) 0x9e, (byte) 0x9e, (byte) 0x5e, (byte) 0x66,
- (byte) 0xbb, (byte) 0x05, (byte) 0x41, (byte) 0x43, (byte) 0x9a, (byte) 0x67,
- (byte) 0x16, (byte) 0x89, (byte) 0xec, (byte) 0x65, (byte) 0x33, (byte) 0xee,
- (byte) 0xbf, (byte) 0xa3, (byte) 0xca, (byte) 0x8b, (byte) 0xd6, (byte) 0x45,
- (byte) 0xe1, (byte) 0x81, (byte) 0xaa, (byte) 0xd8, (byte) 0xa2, (byte) 0x6a,
- (byte) 0x3c, (byte) 0x5e, (byte) 0x7e, (byte) 0x1c, (byte) 0xa5, (byte) 0xc3,
- (byte) 0x5b, (byte) 0x93, (byte) 0x8c, (byte) 0x24, (byte) 0x57, (byte) 0x02,
- (byte) 0x40, (byte) 0x0a, (byte) 0x6d, (byte) 0x3f, (byte) 0x0e, (byte) 0xf1,
- (byte) 0x45, (byte) 0x41, (byte) 0x8f, (byte) 0x72, (byte) 0x40, (byte) 0x82,
- (byte) 0xf3, (byte) 0xcc, (byte) 0xf9, (byte) 0x7f, (byte) 0xaa, (byte) 0xee,
- (byte) 0x6c, (byte) 0x5d, (byte) 0xd1, (byte) 0xe6, (byte) 0xd1, (byte) 0x7c,
- (byte) 0x53, (byte) 0x71, (byte) 0xd0, (byte) 0xab, (byte) 0x6d, (byte) 0x39,
- (byte) 0x63, (byte) 0x03, (byte) 0xe2, (byte) 0x2e, (byte) 0x2f, (byte) 0x11,
- (byte) 0x98, (byte) 0x36, (byte) 0x58, (byte) 0x14, (byte) 0x76, (byte) 0x85,
- (byte) 0x4d, (byte) 0x56, (byte) 0xe7, (byte) 0x63, (byte) 0x69, (byte) 0x71,
- (byte) 0xe6, (byte) 0xd1, (byte) 0x0f, (byte) 0x98, (byte) 0x66, (byte) 0xee,
- (byte) 0xf2, (byte) 0x3d, (byte) 0xdf, (byte) 0x77, (byte) 0xbe, (byte) 0x08,
- (byte) 0xb4, (byte) 0xcb, (byte) 0x6a, (byte) 0xa1, (byte) 0x99, (byte) 0x02,
- (byte) 0x40, (byte) 0x52, (byte) 0x01, (byte) 0xde, (byte) 0x62, (byte) 0xc2,
- (byte) 0x25, (byte) 0xbf, (byte) 0x5d, (byte) 0x77, (byte) 0xe4, (byte) 0x6b,
- (byte) 0xb6, (byte) 0xd7, (byte) 0x8f, (byte) 0x89, (byte) 0x2c, (byte) 0xe6,
- (byte) 0x8d, (byte) 0xe5, (byte) 0xad, (byte) 0x39, (byte) 0x17, (byte) 0x54,
- (byte) 0x2b, (byte) 0x35, (byte) 0x53, (byte) 0xd1, (byte) 0xa1, (byte) 0xef,
- (byte) 0x48, (byte) 0xbc, (byte) 0x95, (byte) 0x48, (byte) 0xcf, (byte) 0x62,
- (byte) 0xf4, (byte) 0x33, (byte) 0xcf, (byte) 0x37, (byte) 0x78, (byte) 0xeb,
- (byte) 0x17, (byte) 0xb4, (byte) 0x0b, (byte) 0x83, (byte) 0x4f, (byte) 0xb6,
- (byte) 0xab, (byte) 0x7d, (byte) 0x67, (byte) 0x3e, (byte) 0x4e, (byte) 0x44,
- (byte) 0x4a, (byte) 0x55, (byte) 0x2e, (byte) 0x34, (byte) 0x12, (byte) 0x0b,
- (byte) 0x59, (byte) 0xb3, (byte) 0xb1, (byte) 0x1e, (byte) 0x3d};
-
-
- /**
- * Generated from above and converted with:
- *
- * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
- */
- private static final byte[] USER_CERT =
- {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xd8, (byte) 0x30, (byte) 0x82,
- (byte) 0x01, (byte) 0xc0, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
- (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
- (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
- (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05,
- (byte) 0x00, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
- (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
- (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13,
- (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
- (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
- (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74,
- (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
- (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x06,
- (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65,
- (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x32,
- (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x30, (byte) 0x37,
- (byte) 0x32, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x5a, (byte) 0x17,
- (byte) 0x0d, (byte) 0x33, (byte) 0x32, (byte) 0x30, (byte) 0x33, (byte) 0x32,
- (byte) 0x32, (byte) 0x30, (byte) 0x37, (byte) 0x32, (byte) 0x30, (byte) 0x31,
- (byte) 0x32, (byte) 0x5a, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b,
- (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
- (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31,
- (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55,
- (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f,
- (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61,
- (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d,
- (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c,
- (byte) 0x06, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c,
- (byte) 0x65, (byte) 0x30, (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d,
- (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
- (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05,
- (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30,
- (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00,
- (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, (byte) 0xc4, (byte) 0x44,
- (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, (byte) 0xb9, (byte) 0x1b,
- (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, (byte) 0x06, (byte) 0xe7,
- (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, (byte) 0xaa, (byte) 0x0a,
- (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, (byte) 0xad, (byte) 0xfe,
- (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, (byte) 0xc9, (byte) 0xf5,
- (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, (byte) 0xcc, (byte) 0x3f,
- (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, (byte) 0x6a, (byte) 0xe8,
- (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, (byte) 0x53, (byte) 0xd9,
- (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, (byte) 0xbb, (byte) 0x95,
- (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, (byte) 0xce, (byte) 0xf8,
- (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, (byte) 0x91, (byte) 0x29,
- (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, (byte) 0xcb, (byte) 0xa7,
- (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, (byte) 0x0c, (byte) 0x07,
- (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, (byte) 0x08, (byte) 0xf4,
- (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, (byte) 0x28, (byte) 0xcb,
- (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, (byte) 0x7e, (byte) 0x83,
- (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, (byte) 0x2d, (byte) 0xa0,
- (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, (byte) 0x47, (byte) 0x31,
- (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, (byte) 0x12, (byte) 0x1b,
- (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, (byte) 0x84, (byte) 0x5f,
- (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00,
- (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, (byte) 0x79, (byte) 0x30,
- (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13,
- (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, (byte) 0x30, (byte) 0x2c,
- (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
- (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, (byte) 0x0d, (byte) 0x04,
- (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, (byte) 0x70, (byte) 0x65,
- (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, (byte) 0x20, (byte) 0x47,
- (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, (byte) 0x61, (byte) 0x74,
- (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, (byte) 0x65, (byte) 0x72,
- (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x63, (byte) 0x61,
- (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03,
- (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04,
- (byte) 0x14, (byte) 0xee, (byte) 0xec, (byte) 0x08, (byte) 0xcc, (byte) 0xdd,
- (byte) 0xa3, (byte) 0x29, (byte) 0x6e, (byte) 0x2b, (byte) 0x78, (byte) 0x23,
- (byte) 0xb3, (byte) 0xf0, (byte) 0xb8, (byte) 0x9d, (byte) 0x53, (byte) 0x41,
- (byte) 0x2e, (byte) 0x3c, (byte) 0x61, (byte) 0x30, (byte) 0x1f, (byte) 0x06,
- (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18,
- (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x86, (byte) 0xdb,
- (byte) 0xa5, (byte) 0x5e, (byte) 0x0e, (byte) 0x03, (byte) 0xbc, (byte) 0xe4,
- (byte) 0xc1, (byte) 0xc8, (byte) 0xf3, (byte) 0xed, (byte) 0x24, (byte) 0x48,
- (byte) 0xb1, (byte) 0x37, (byte) 0x3a, (byte) 0x52, (byte) 0x10, (byte) 0x57,
- (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
- (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
- (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82, (byte) 0x01,
- (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x5a, (byte) 0x5c, (byte) 0x08,
- (byte) 0xe4, (byte) 0x0e, (byte) 0x28, (byte) 0x4c, (byte) 0xa9, (byte) 0x0e,
- (byte) 0x35, (byte) 0xbe, (byte) 0xe3, (byte) 0xd5, (byte) 0xd1, (byte) 0xb4,
- (byte) 0x47, (byte) 0x87, (byte) 0x63, (byte) 0xd2, (byte) 0x5e, (byte) 0x7e,
- (byte) 0xf6, (byte) 0xd8, (byte) 0xce, (byte) 0xdf, (byte) 0x10, (byte) 0x15,
- (byte) 0x61, (byte) 0xc4, (byte) 0x9a, (byte) 0xf1, (byte) 0xba, (byte) 0x33,
- (byte) 0xf2, (byte) 0xc2, (byte) 0x01, (byte) 0x95, (byte) 0xa7, (byte) 0x74,
- (byte) 0x97, (byte) 0xc1, (byte) 0x43, (byte) 0x68, (byte) 0x92, (byte) 0xbe,
- (byte) 0x9a, (byte) 0x6f, (byte) 0x38, (byte) 0xcb, (byte) 0xa0, (byte) 0xcf,
- (byte) 0x1e, (byte) 0x5b, (byte) 0x03, (byte) 0xde, (byte) 0x45, (byte) 0x6d,
- (byte) 0xea, (byte) 0xf0, (byte) 0x46, (byte) 0x4d, (byte) 0xb6, (byte) 0x4b,
- (byte) 0x88, (byte) 0xc7, (byte) 0xb8, (byte) 0xe3, (byte) 0x9f, (byte) 0x58,
- (byte) 0x8b, (byte) 0x2d, (byte) 0xbf, (byte) 0x4b, (byte) 0x3f, (byte) 0x54,
- (byte) 0x2d, (byte) 0xa8, (byte) 0x27, (byte) 0x72, (byte) 0x5e, (byte) 0x36,
- (byte) 0x67, (byte) 0x5c, (byte) 0x6e, (byte) 0x9a, (byte) 0x67, (byte) 0x73,
- (byte) 0x44, (byte) 0xaf, (byte) 0x46, (byte) 0x7f, (byte) 0xd6, (byte) 0x2b,
- (byte) 0x9d, (byte) 0x28, (byte) 0xb1, (byte) 0xc4, (byte) 0xc4, (byte) 0x72,
- (byte) 0x3d, (byte) 0x6d, (byte) 0x7d, (byte) 0x28, (byte) 0x40, (byte) 0x62,
- (byte) 0x40, (byte) 0x21, (byte) 0x52, (byte) 0xb5, (byte) 0x0b, (byte) 0xf3,
- (byte) 0xcc, (byte) 0x36, (byte) 0x03, (byte) 0x10, (byte) 0x19, (byte) 0xe3,
- (byte) 0xc2, (byte) 0xfe, (byte) 0xe9, (byte) 0x08, (byte) 0x0d, (byte) 0xd4,
- (byte) 0x8b, (byte) 0x12, (byte) 0xd6, (byte) 0x3d, (byte) 0xc5, (byte) 0xb8,
- (byte) 0x8c, (byte) 0xbd, (byte) 0xa5, (byte) 0xcd, (byte) 0xb3, (byte) 0xe4,
- (byte) 0xd1, (byte) 0xd8, (byte) 0x4c, (byte) 0x32, (byte) 0x44, (byte) 0x3f,
- (byte) 0x63, (byte) 0x32, (byte) 0x09, (byte) 0xdb, (byte) 0x8b, (byte) 0x7b,
- (byte) 0x30, (byte) 0x58, (byte) 0xc7, (byte) 0xcf, (byte) 0xc3, (byte) 0x44,
- (byte) 0xd9, (byte) 0xff, (byte) 0x63, (byte) 0x91, (byte) 0x74, (byte) 0xd8,
- (byte) 0x62, (byte) 0x2b, (byte) 0x52, (byte) 0xc8, (byte) 0x82, (byte) 0x9f,
- (byte) 0xeb, (byte) 0x22, (byte) 0x5c, (byte) 0xa2, (byte) 0x26, (byte) 0xfe,
- (byte) 0x04, (byte) 0x31, (byte) 0x53, (byte) 0x09, (byte) 0xa7, (byte) 0x23,
- (byte) 0xe3, (byte) 0x0f, (byte) 0xf8, (byte) 0xe9, (byte) 0x99, (byte) 0xad,
- (byte) 0x4b, (byte) 0x23, (byte) 0x07, (byte) 0xfb, (byte) 0xfa, (byte) 0xc3,
- (byte) 0x55, (byte) 0x59, (byte) 0xdb, (byte) 0x6b, (byte) 0x71, (byte) 0xdf,
- (byte) 0x25, (byte) 0x0f, (byte) 0xaa, (byte) 0xa2, (byte) 0xfa, (byte) 0x28,
- (byte) 0x49, (byte) 0x65, (byte) 0x7e, (byte) 0x0b, (byte) 0x74, (byte) 0x30,
- (byte) 0xd9, (byte) 0x9a, (byte) 0xfe, (byte) 0x2c, (byte) 0x8c, (byte) 0x67,
- (byte) 0x50, (byte) 0x0c, (byte) 0x6d, (byte) 0x4c, (byte) 0xba, (byte) 0x34,
- (byte) 0x3b, (byte) 0x0d, (byte) 0x16, (byte) 0x45, (byte) 0x63, (byte) 0x73,
- (byte) 0xc2, (byte) 0x9f, (byte) 0xb4, (byte) 0xdd, (byte) 0x6f, (byte) 0xde,
- (byte) 0x9d, (byte) 0x71, (byte) 0xbf, (byte) 0x8d, (byte) 0x1b, (byte) 0x79,
- (byte) 0xa0, (byte) 0x0a, (byte) 0x66, (byte) 0x7e, (byte) 0x56, (byte) 0x83,
- (byte) 0x8f, (byte) 0x3f, (byte) 0x7d, (byte) 0x93, (byte) 0xf6, (byte) 0xc9,
- (byte) 0x42, (byte) 0xfc, (byte) 0xc5, (byte) 0xf2, (byte) 0x49, (byte) 0xec};
+ private byte[] getByteArrayFromRawRes(int resId, String resName) throws IOException {
+ byte[] byteArray = null;
+ try (InputStream inStream = mResources.openRawResource(resId);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); ) {
+ assumeTrue(mContext.getString(R.string.rawResOpenError, resName), inStream != null);
+ byteArray = new byte[1024];
+ int nRead = inStream.read(byteArray, 0, byteArray.length);
+ assumeTrue(mContext.getString(R.string.streamReadError, resName), nRead > 0);
+ outStream.write(byteArray, 0, nRead);
+ }
+ return byteArray;
+ }
@After
public void tearDown() {
try {
+ // Go to home screen
+ mDevice.executeShellCommand(mContext.getString(R.string.cmdAdbHome));
+
+ // Remove key pair added by the test as part of cleanup
mDevicePolicyManager.removeKeyPair(mComponentName, mContext.getString(R.string.alias));
- mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName());
} catch (Exception e) {
// ignore all exceptions as the test is already complete
}
@@ -314,85 +92,146 @@
@Test
public void testOverlayButtonPresence() {
try {
- /* Install key pair required to launch KeyChainActivity dialog */
+ // Create the byte arrays from raw resources of private key and user certificate
+ // respectively.
mContext = getInstrumentation().getContext();
- Resources resources = mContext.getResources();
- KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.keyType));
- PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(PRIVATE_KEY));
- CertificateFactory cf =
- CertificateFactory.getInstance(mContext.getString(R.string.certType));
- Certificate cert = cf.generateCertificate(new ByteArrayInputStream(USER_CERT));
- mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
- mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
- PocDeviceAdminReceiver.class.getName());
- assumeTrue(mDevicePolicyManager.installKeyPair(mComponentName, privKey, cert,
- mContext.getString(R.string.alias)));
+ mResources = mContext.getResources();
+ byte[] privateKeyByteArray =
+ getByteArrayFromRawRes(
+ R.raw.cve_2021_0963_pkey, mContext.getString(R.string.pKey));
+ byte[] userCertByteArray =
+ getByteArrayFromRawRes(
+ R.raw.cve_2021_0963_usercert, mContext.getString(R.string.userCert));
- /* Start the overlay service */
+ // Install key pair required to launch KeyChainActivity dialog
+ KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.typeKey));
+ PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyByteArray));
+ CertificateFactory cf =
+ CertificateFactory.getInstance(mContext.getString(R.string.typeCert));
+ Certificate cert = cf.generateCertificate(new ByteArrayInputStream(userCertByteArray));
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ mComponentName =
+ new ComponentName(
+ PocDeviceAdminReceiver.class.getPackage().getName(),
+ PocDeviceAdminReceiver.class.getName());
+ assumeTrue(
+ mDevicePolicyManager.installKeyPair(
+ mComponentName, privKey, cert, mContext.getString(R.string.alias)));
+
+ // Start the overlay service
Intent intent = new Intent(mContext, PocService.class);
- assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+ assumeTrue(
+ mContext.getString(R.string.exceptionCanNotDrawOverlays),
Settings.canDrawOverlays(mContext));
CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
- RemoteCallback cb = new RemoteCallback((Bundle result) -> {
- PocStatus pocStatus =
- new PocStatus(result.getInt(mContext.getString(R.string.statusKey)),
- result.getString(mContext.getString(R.string.messageKey)));
- callbackReturn.complete(pocStatus);
- });
- intent.putExtra(mContext.getString(R.string.callbackKey), cb);
+ RemoteCallback cb =
+ new RemoteCallback(
+ (Bundle result) -> {
+ PocStatus pocStatus =
+ new PocStatus(
+ result.getInt(mContext.getString(R.string.status)),
+ result.getString(
+ mContext.getString(R.string.message)));
+ callbackReturn.complete(pocStatus);
+ });
+ intent.putExtra(mContext.getString(R.string.callback), cb);
mContext.startService(intent);
- PocStatus result = callbackReturn.get(resources.getInteger(R.integer.timeoutMs),
- TimeUnit.MILLISECONDS);
- assumeTrue(result.getErrorMessage(),
- result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
-
- /* Wait for the overlay window */
- Pattern overlayTextPattern = Pattern.compile(
- mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
- UiDevice device = UiDevice.getInstance(getInstrumentation());
- assumeTrue(mContext.getString(R.string.overlayUiScreenError),
- device.wait(Until.hasObject(By.text(overlayTextPattern)),
- mContext.getResources().getInteger(R.integer.timeoutMs)));
-
- /* Start PocActivity which starts the vulnerable activity */
- intent = new Intent(mContext, PocActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>();
- RemoteCallback pocActivityCb = new RemoteCallback((Bundle pocActivityResult) -> {
- PocStatus pocStatus = new PocStatus(
- pocActivityResult.getInt(mContext.getString(R.string.statusKey)),
- pocActivityResult.getString(mContext.getString(R.string.messageKey)));
- pocActivityReturn.complete(pocStatus);
- });
- intent.putExtra(mContext.getString(R.string.callbackKey), pocActivityCb);
- mContext.startActivity(intent);
- result = pocActivityReturn.get(resources.getInteger(R.integer.timeoutMs),
- TimeUnit.MILLISECONDS);
- assumeTrue(result.getErrorMessage(),
- result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
-
- /* Get the vulnerable activity name by using an alternative intent */
- Intent vulIntent = new Intent(mContext.getString(R.string.actionKeychainActivity));
- ResolveInfo ri = mContext.getPackageManager().resolveActivity(vulIntent,
- PackageManager.MATCH_DEFAULT_ONLY);
- String vulnerableActivityName = ri.activityInfo.name;
-
- /* Wait until the object of launcher activity is gone */
- boolean overlayDisallowed = device.wait(Until.gone(By.pkg(mContext.getPackageName())),
- mContext.getResources().getInteger(R.integer.timeoutMs));
-
- /* Check if the currently running activity is the vulnerable activity */
- String activityDump = "";
- activityDump = device.executeShellCommand(
- mContext.getString(R.string.dumpsysActivity, vulnerableActivityName));
- Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
- Pattern.CASE_INSENSITIVE);
+ PocStatus result =
+ callbackReturn.get(
+ mResources.getInteger(R.integer.timeoutMs), TimeUnit.MILLISECONDS);
assumeTrue(
- mContext.getString(R.string.vulActivityNotRunningError, vulnerableActivityName),
+ result.getErrorMessage(),
+ result.getStatusCode() != mResources.getInteger(R.integer.assumptionFailure));
+
+ // Wait for the overlay window
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ Pattern overlayTextPattern =
+ Pattern.compile(
+ mContext.getString(R.string.txtOverlayBtn), Pattern.CASE_INSENSITIVE);
+ assumeTrue(
+ mContext.getString(R.string.exceptionOverlayUiNotVisible),
+ mDevice.wait(
+ Until.hasObject(By.text(overlayTextPattern)),
+ mResources.getInteger(R.integer.timeoutMs)));
+
+ // Start PocActivity which in turn starts the vulnerable activity
+ intent = new Intent(mContext, PocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>();
+ RemoteCallback pocActivityCb =
+ new RemoteCallback(
+ (Bundle pocActivityResult) -> {
+ PocStatus pocStatus =
+ new PocStatus(
+ pocActivityResult.getInt(
+ mContext.getString(R.string.status)),
+ pocActivityResult.getString(
+ mContext.getString(R.string.message)));
+ pocActivityReturn.complete(pocStatus);
+ });
+ intent.putExtra(mContext.getString(R.string.callback), pocActivityCb);
+ mContext.startActivity(intent);
+ result =
+ pocActivityReturn.get(
+ mResources.getInteger(R.integer.timeoutMs), TimeUnit.MILLISECONDS);
+ assumeTrue(
+ result.getErrorMessage(),
+ result.getStatusCode() != mResources.getInteger(R.integer.assumptionFailure));
+
+ // Get the vulnerable activity name by using an alternative intent
+ Intent vulIntent = new Intent(mContext.getString(R.string.action));
+ ResolveInfo ri =
+ mContext.getPackageManager()
+ .resolveActivity(vulIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ String vulnerableActivityName = ri.activityInfo.name;
+ String vulnerablePkgName = ri.activityInfo.packageName;
+
+ // Wait until the object of launcher activity is gone
+ boolean overlayDisallowed =
+ mDevice.wait(
+ Until.gone(By.pkg(mContext.getPackageName())),
+ mResources.getInteger(R.integer.timeoutMs));
+
+ // Check if the currently resumed activity is the vulnerable activity
+ String activityDump =
+ mDevice.executeShellCommand(
+ mContext.getString(
+ R.string.cmdDumpsysActivityByActivity, vulnerableActivityName));
+ Pattern activityPattern =
+ Pattern.compile(
+ mContext.getString(R.string.flagActivityResumed),
+ Pattern.CASE_INSENSITIVE);
+ assumeTrue(
+ mContext.getString(
+ R.string.exceptionVulActivityNotResume, vulnerableActivityName),
activityPattern.matcher(activityDump).find());
- /* Failing the test as fix is not present */
- assertTrue(mContext.getString(R.string.errorMessage, vulnerableActivityName),
+ // Check if vulnerable activity's UI is visible
+ String vulPkgDump =
+ mDevice.executeShellCommand(
+ mContext.getString(
+ R.string.cmdDumpsysActivityByPkg, vulnerablePkgName));
+ boolean isVisible = false;
+ for (String vulPkgDumpElement :
+ vulPkgDump.split(mContext.getString(R.string.strSplitRegex))) {
+ if (vulPkgDumpElement
+ .toLowerCase()
+ .contains(vulnerableActivityName.toLowerCase())) {
+ if (vulPkgDumpElement.contains(
+ mContext.getString(R.string.flagActivityVisible))) {
+ isVisible = true;
+ break;
+ }
+ }
+ }
+ assumeTrue(
+ mContext.getString(R.string.exceptionVulUiNotVisible, vulnerableActivityName),
+ isVisible);
+
+ // On vulnerable device, vulnerable activity will be overlaid so 'overlayDisallowed'
+ // will be set to true so the test fails, else it passes.
+ assertTrue(
+ mContext.getString(R.string.failMsg, vulnerableActivityName),
overlayDisallowed);
} catch (Exception e) {
assumeNoException(e);
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
index ac8ea15..bcf98e1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -27,13 +27,19 @@
public class PocActivity extends Activity {
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onResume() {
try {
- super.onCreate(savedInstanceState);
- KeyChainAliasCallback callback = new KeyChainAliasCallback() {
- @Override
- public void alias(@Nullable String alias) {}
- };
+ super.onResume();
+
+ // Waiting briefly for the PocActivity window transition animation to complete.
+ Thread.sleep(500);
+
+ // Launching the vulnerable activity KeyChainActivity
+ KeyChainAliasCallback callback =
+ new KeyChainAliasCallback() {
+ @Override
+ public void alias(@Nullable String alias) {}
+ };
KeyChain.choosePrivateKeyAlias(this, callback, null, null, null, -1, null);
sendTestResult(getResources().getInteger(R.integer.noException), "");
} catch (Exception e) {
@@ -44,10 +50,10 @@
void sendTestResult(int status, String message) {
try {
RemoteCallback cb =
- (RemoteCallback) getIntent().getExtras().get(getString(R.string.callbackKey));
+ (RemoteCallback) getIntent().getExtras().get(getString(R.string.callback));
Bundle res = new Bundle();
- res.putString(getString(R.string.messageKey), message);
- res.putInt(getString(R.string.statusKey), status);
+ res.putString(getString(R.string.message), message);
+ res.putInt(getString(R.string.status), status);
cb.sendResult(res);
} catch (Exception e) {
// ignore all exceptions
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
index 5592323..b8ef104 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -18,5 +18,4 @@
import android.app.admin.DeviceAdminReceiver;
-public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
-}
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
index b83e824..c78d7d4 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -55,8 +55,8 @@
mWindowManager = getSystemService(WindowManager.class);
mLayoutParams = new LayoutParams();
mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
- mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
- LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.flags =
+ LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
mLayoutParams.format = PixelFormat.OPAQUE;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.width = getScreenWidth();
@@ -65,7 +65,7 @@
mLayoutParams.y = getScreenHeight() / 2;
Context context = getApplicationContext();
mButton = new Button(context);
- mButton.setText(context.getString(R.string.overlayButtonText));
+ mButton.setText(context.getString(R.string.txtOverlayBtn));
mWindowManager.addView(mButton, mLayoutParams);
sendTestResult(getResources().getInteger(R.integer.noException), "");
} catch (Exception e) {
@@ -87,10 +87,10 @@
void sendTestResult(int status, String message) {
try {
RemoteCallback cb =
- (RemoteCallback) mIntent.getExtras().get(getString(R.string.callbackKey));
+ (RemoteCallback) mIntent.getExtras().get(getString(R.string.callback));
Bundle res = new Bundle();
- res.putString(getString(R.string.messageKey), message);
- res.putInt(getString(R.string.statusKey), status);
+ res.putString(getString(R.string.message), message);
+ res.putInt(getString(R.string.status), status);
cb.sendResult(res);
} catch (Exception e) {
// ignore exception here
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
index de67f0f..7e6c63d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/Android.bp
new file mode 100644
index 0000000..e856574
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2023-20955-test",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "test-app/src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ resource_dirs: [
+ "test-app/res",
+ ],
+ manifest: "test-app/AndroidManifest.xml",
+ sdk_version: "current",
+}
+
+android_test_helper_app {
+ name: "CVE-2023-20955-test-helper",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ manifest: "test-helper-app/AndroidManifest.xml",
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..2d74f54
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2023_20955_test">
+ <application android:testOnly="true">
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN"
+ android:exported="true">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_policies" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_20955_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/values/strings.xml
new file mode 100644
index 0000000..194436b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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>
+ <string name="failMsg">Vulnerable to b/258653813 !!</string>
+ <string name="msgNotFoundTxt">Did not find an object with selector %1$s on the screen</string>
+ <string name="msgSetUserRestrictionFailed">Failed to set user restriction DISALLOW_APPS_CONTROL
+ </string>
+ <string name="patternMoreOptions">.*more options.*</string>
+ <string name="patternUninstall">.*uninstall.*</string>
+ <string name="patternUninstallAllUsers">.*uninstall for all users.*</string>
+ <string name="pkgNameHelper">android.security.cts.CVE_2023_20955_test_helper</string>
+ <string name="pkgNameInstaller">com.android.packageinstaller</string>
+ <string name="uriScheme">package</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/xml/device_policies.xml
new file mode 100644
index 0000000..ed5352d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/res/xml/device_policies.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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.
+ -->
+
+<device-admin>
+ <uses-policies />
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/DeviceTest.java
new file mode 100644
index 0000000..8b76904
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/DeviceTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 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.security.cts.CVE_2023_20955_test;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.widget.ImageButton;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int TIMEOUT_MS = 5000;
+ private Context mContext;
+ private UiDevice mDevice;
+
+ private void waitAndClick(BySelector selector) {
+ assumeTrue(mContext.getString(R.string.msgNotFoundTxt, selector.toString()),
+ mDevice.wait(Until.hasObject(selector), TIMEOUT_MS));
+ mDevice.findObject(selector).click();
+ }
+
+ @Test
+ public void testAppInfoUninstallForAllUsersDisabled() {
+ try {
+ mContext = getInstrumentation().getTargetContext();
+ mDevice = UiDevice.getInstance(getInstrumentation());
+
+ // Restrict current user to disallow controlling apps
+ ComponentName deviceAdminComponent =
+ new ComponentName(mContext, PocDeviceAdminReceiver.class);
+ DevicePolicyManager policyManager = null;
+ policyManager = mContext.getSystemService(DevicePolicyManager.class);
+ policyManager.addUserRestriction(deviceAdminComponent,
+ UserManager.DISALLOW_APPS_CONTROL);
+
+ // Waiting for user restriction to be added
+ boolean disallowAppsControlVal =
+ (boolean) policyManager.getUserRestrictions(deviceAdminComponent)
+ .getBoolean(UserManager.DISALLOW_APPS_CONTROL);
+ while (!disallowAppsControlVal && System.currentTimeMillis() < TIMEOUT_MS) {
+ disallowAppsControlVal = policyManager.getUserRestrictions(deviceAdminComponent)
+ .getBoolean(UserManager.DISALLOW_APPS_CONTROL);
+ Thread.sleep(100);
+ }
+ assumeTrue(mContext.getString(R.string.msgSetUserRestrictionFailed),
+ disallowAppsControlVal);
+
+ // Launching "application info" window for test helper app
+ Uri pkgUri = Uri.fromParts(mContext.getString(R.string.uriScheme),
+ mContext.getString(R.string.pkgNameHelper), null);
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, pkgUri);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
+
+ // Wait for the application info window and click on 3 dots with:
+ // content description = "More options"
+ Pattern descPattern = Pattern.compile(mContext.getString(R.string.patternMoreOptions),
+ Pattern.CASE_INSENSITIVE);
+ waitAndClick(By.clazz(ImageButton.class).desc(descPattern));
+
+ // Wait for a menu to appear. When it appears, click on the text "Uninstall for all
+ // users".
+ Pattern textPattern =
+ Pattern.compile(mContext.getString(R.string.patternUninstallAllUsers),
+ Pattern.CASE_INSENSITIVE);
+ waitAndClick(By.text(textPattern));
+
+ // Retrieve the package name of installer app
+ Intent packageInstallerIntent = new Intent(Intent.ACTION_DELETE, pkgUri);
+ ComponentName componentName =
+ packageInstallerIntent.resolveActivity(mContext.getPackageManager());
+ String pkgNameInstaller = mContext.getString(R.string.pkgNameInstaller);
+ if (componentName != null && componentName.getPackageName() != null) {
+ pkgNameInstaller = componentName.getPackageName();
+ }
+
+ // Wait for UI with package = "com.android.packageinstaller" (AOSP), text containing
+ // "uninstall". If found, it indicates vulnerable behaviour and anyone can uninstall
+ // app for all users despite the user restrictions.
+ textPattern = Pattern.compile(mContext.getString(R.string.patternUninstall),
+ Pattern.CASE_INSENSITIVE);
+ assertFalse(mContext.getString(R.string.failMsg), mDevice
+ .wait(Until.hasObject(By.pkg(pkgNameInstaller).text(textPattern)), TIMEOUT_MS));
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // Go to the home screen
+ mDevice.pressHome();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/PocDeviceAdminReceiver.java
new file mode 100644
index 0000000..7141a40
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-app/src/android/security/cts/CVE_2023_20955_test/PocDeviceAdminReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 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.security.cts.CVE_2023_20955_test;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-helper-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-helper-app/AndroidManifest.xml
new file mode 100644
index 0000000..73420e4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/test-helper-app/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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.
+ -->
+
+<manifest package="android.security.cts.CVE_2023_20955_test_helper">
+ <application />
+</manifest>
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index 7cc1576..d79668d 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -947,6 +947,7 @@
assumeFalse("not testable in automotive device", mAutomotiveDevice);
assumeFalse("not testable in leanback device", mLeanbackOnly);
+ assumeTrue(BatteryUtils.hasBattery());
assumeTrue(mNetworkingHelper.hasWifiFeature());
mNetworkingHelper.ensureSavedWifiNetwork();
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index ee74c65..d812c33 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -18,6 +18,7 @@
import static android.photopicker.cts.PhotoPickerCloudUtils.addImage;
import static android.photopicker.cts.PhotoPickerCloudUtils.containsExcept;
+import static android.photopicker.cts.PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders;
import static android.photopicker.cts.PhotoPickerCloudUtils.extractMediaIds;
import static android.photopicker.cts.PickerProviderMediaGenerator.MediaGenerator;
import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
@@ -91,6 +92,9 @@
mCloudPrimaryMediaGenerator.setMediaCollectionId(COLLECTION_1);
mCloudSecondaryMediaGenerator.setMediaCollectionId(COLLECTION_1);
+ // This is a self-instrumentation test, so both "target" package name and "own" package name
+ // should be the same (android.photopicker.cts).
+ enableCloudMediaAndSetAllowedCloudProviders(sTargetPackageName);
setCloudProvider(mContext, null);
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
index f0f582f..cf65e39 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
@@ -16,6 +16,10 @@
package android.photopicker.cts;
+import static android.photopicker.cts.PhotoPickerCloudUtils.disableCloudMediaAndClearAllowedCloudProviders;
+import static android.photopicker.cts.PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders;
+import static android.photopicker.cts.PhotoPickerCloudUtils.getAllowedProvidersDeviceConfig;
+import static android.photopicker.cts.PhotoPickerCloudUtils.isCloudMediaEnabled;
import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImage;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
@@ -52,23 +56,30 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class PhotoPickerBannersTest extends PhotoPickerBaseTest {
+ private static boolean sCloudMediaPreviouslyEnabled;
private static String sPreviouslyAllowedCloudProviders;
private Uri mLocalMediaFileUri;
@BeforeClass
public static void setUpBeforeClass() {
- // Store the current allowed cloud providers for reset at the end of tests.
- sPreviouslyAllowedCloudProviders = PhotoPickerCloudUtils.getAllowedProvidersDeviceConfig();
+ // Store the current CMP configs, so that we can reset them at the end of the test.
+ sCloudMediaPreviouslyEnabled = isCloudMediaEnabled();
+ if (sCloudMediaPreviouslyEnabled) {
+ sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
+ }
// Override the allowed cloud providers config to enable the banners.
- final String allowedCloudProviders = CloudProviderPrimary.AUTHORITY;
- PhotoPickerCloudUtils.setAllowedProvidersDeviceConfig(allowedCloudProviders);
+ enableCloudMediaAndSetAllowedCloudProviders(sTargetPackageName);
}
@AfterClass
public static void tearDownClass() {
- // Reset the allowed cloud providers device config.
- PhotoPickerCloudUtils.setAllowedProvidersDeviceConfig(sPreviouslyAllowedCloudProviders);
+ // Reset CloudMedia configs.
+ if (sCloudMediaPreviouslyEnabled) {
+ enableCloudMediaAndSetAllowedCloudProviders(sPreviouslyAllowedCloudProviders);
+ } else {
+ disableCloudMediaAndClearAllowedCloudProviders();
+ }
}
@Before
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index 845cb78..067cd78 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -36,6 +36,8 @@
public static int REQUEST_CODE = 42;
private static final Instrumentation sInstrumentation =
InstrumentationRegistry.getInstrumentation();
+ protected static final String sTargetPackageName =
+ sInstrumentation.getTargetContext().getPackageName();
protected static final UiDevice sDevice = UiDevice.getInstance(sInstrumentation);
protected GetResultActivity mActivity;
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java
index 59b552c..891917d 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java
@@ -45,7 +45,8 @@
public class PhotoPickerCloudUtils {
private static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot";
- private static final String ALLOWED_CLOUD_PROVIDERS_KEY = "allowed_cloud_providers";
+ private static final String KEY_ALLOWED_CLOUD_PROVIDERS = "allowed_cloud_providers";
+ private static final String KEY_CLOUD_MEDIA_FEATURE_ENABLED = "cloud_media_feature_enabled";
public static List<String> extractMediaIds(ClipData clipData, int minCount) {
final int count = clipData.getItemCount();
@@ -109,40 +110,64 @@
assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained));
}
- @Nullable
- static String getAllowedProvidersDeviceConfig() {
- getUiAutomation().adoptShellPermissionIdentity(READ_DEVICE_CONFIG);
- try {
- return DeviceConfig.getProperty(NAMESPACE_STORAGE_NATIVE_BOOT,
- ALLOWED_CLOUD_PROVIDERS_KEY);
- } finally {
- getUiAutomation().dropShellPermissionIdentity();
- }
+ public static boolean isCloudMediaEnabled() {
+ return Boolean.parseBoolean(readDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED));
}
- static void setAllowedProvidersDeviceConfig(@Nullable String allowedCloudProviders) {
- getUiAutomation().adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG);
- try {
- if (allowedCloudProviders == null) {
- DeviceConfig.deleteProperty(NAMESPACE_STORAGE_NATIVE_BOOT,
- ALLOWED_CLOUD_PROVIDERS_KEY);
- assertWithMessage("Failed to delete the allowed cloud providers device config")
- .that(getAllowedProvidersDeviceConfig())
- .isNull();
- } else {
- DeviceConfig.setProperty(NAMESPACE_STORAGE_NATIVE_BOOT, ALLOWED_CLOUD_PROVIDERS_KEY,
- allowedCloudProviders, /* makeDefault */ false);
- assertWithMessage("Failed to update the allowed cloud providers device config")
- .that(getAllowedProvidersDeviceConfig())
- .isEqualTo(allowedCloudProviders);
- }
- } finally {
- getUiAutomation().dropShellPermissionIdentity();
- }
+ @Nullable
+ static String getAllowedProvidersDeviceConfig() {
+ return readDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS);
+ }
+
+ static void enableCloudMediaAndSetAllowedCloudProviders(@NonNull String allowedPackagesJoined) {
+ writeDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS, allowedPackagesJoined);
+ assertWithMessage("Failed to update the allowed cloud providers device config")
+ .that(getAllowedProvidersDeviceConfig())
+ .isEqualTo(allowedPackagesJoined);
+
+ writeDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED, true);
+ }
+
+
+ static void disableCloudMediaAndClearAllowedCloudProviders() {
+ writeDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED, false);
+
+ deleteDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS);
+ assertWithMessage("Failed to delete the allowed cloud providers device config")
+ .that(getAllowedProvidersDeviceConfig())
+ .isNull();
}
@NonNull
private static UiAutomation getUiAutomation() {
return InstrumentationRegistry.getInstrumentation().getUiAutomation();
}
+
+ @Nullable
+ private static String readDeviceConfigProp(@NonNull String name) {
+ getUiAutomation().adoptShellPermissionIdentity(READ_DEVICE_CONFIG);
+ try {
+ return DeviceConfig.getProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name);
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ private static void writeDeviceConfigProp(@NonNull String name, boolean value) {
+ writeDeviceConfigProp(name, Boolean.toString(value));
+ }
+
+ private static void writeDeviceConfigProp(@NonNull String name, @NonNull String value) {
+ getUiAutomation().adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG);
+ try {
+ DeviceConfig.setProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name, value,
+ /* makeDefault*/ false);
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ private static void deleteDeviceConfigProp(@NonNull String name) {
+ DeviceConfig.deleteProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name);
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
index d8cc456..70e0502 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
@@ -16,6 +16,10 @@
package android.photopicker.cts;
+import static android.photopicker.cts.PhotoPickerCloudUtils.disableCloudMediaAndClearAllowedCloudProviders;
+import static android.photopicker.cts.PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders;
+import static android.photopicker.cts.PhotoPickerCloudUtils.getAllowedProvidersDeviceConfig;
+import static android.photopicker.cts.PhotoPickerCloudUtils.isCloudMediaEnabled;
import static android.photopicker.cts.util.PhotoPickerUiUtils.isPhotoPickerVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActionBarIsVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActivityIsVisible;
@@ -45,22 +49,30 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
+ private static boolean sCloudMediaPreviouslyEnabled;
private static String sPreviouslyAllowedCloudProviders;
@BeforeClass
public static void setUpBeforeClass() {
- // Store current allowed cloud providers for reset at the end of tests.
- sPreviouslyAllowedCloudProviders = PhotoPickerCloudUtils.getAllowedProvidersDeviceConfig();
+ // Store the current CMP configs, so that we can reset them at the end of the test.
+ sCloudMediaPreviouslyEnabled = isCloudMediaEnabled();
+ if (sCloudMediaPreviouslyEnabled) {
+ sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
+ }
// Enable Settings menu item in PhotoPickerActivity's overflow menu.
- PhotoPickerCloudUtils.setAllowedProvidersDeviceConfig(
+ PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders(
/* allowedCloudProviders */ "not_empty");
}
@AfterClass
public static void tearDownClass() {
- // Reset allowed cloud providers device config.
- PhotoPickerCloudUtils.setAllowedProvidersDeviceConfig(sPreviouslyAllowedCloudProviders);
+ // Reset CloudMedia configs.
+ if (sCloudMediaPreviouslyEnabled) {
+ enableCloudMediaAndSetAllowedCloudProviders(sPreviouslyAllowedCloudProviders);
+ } else {
+ disableCloudMediaAndClearAllowedCloudProviders();
+ }
}
@Test
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java b/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
index 5110781..216b5de 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
@@ -432,8 +432,7 @@
}
albumId = bundle.getString(CloudMediaProviderContract.EXTRA_ALBUM_ID, null);
- mimeType = bundle.getString(CloudMediaProviderContract.EXTRA_MIME_TYPE,
- null);
+ mimeType = bundle.getString(Intent.EXTRA_MIME_TYPES, null);
sizeBytes = bundle.getLong(CloudMediaProviderContract.EXTRA_SIZE_LIMIT_BYTES, 0);
generation = bundle.getLong(CloudMediaProviderContract.EXTRA_SYNC_GENERATION, 0);
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index 0c19f5c..382be79 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -16,6 +16,7 @@
package android.photopicker.cts;
+import static android.photopicker.cts.PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders;
import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
@@ -93,6 +94,10 @@
mCloudPrimaryMediaGenerator.resetAll();
mCloudPrimaryMediaGenerator.setMediaCollectionId(COLLECTION_1);
+ // This is a self-instrumentation test, so both "target" package name and "own" package name
+ // should be the same (android.photopicker.cts).
+ enableCloudMediaAndSetAllowedCloudProviders(sTargetPackageName);
+
setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
CloudProviderPrimary.AUTHORITY)).isTrue();
diff --git a/tests/accessibilityservice/res/values/dimens.xml b/tests/accessibilityservice/res/values/dimens.xml
new file mode 100644
index 0000000..a50549c
--- /dev/null
+++ b/tests/accessibilityservice/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 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>
+ <dimen name="button_touchable_width_increment_amount">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 52fb4c37..655494f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -910,7 +910,8 @@
final Button buttonWithTooltip = mActivity.findViewById(R.id.buttonWithTooltip);
final int[] buttonWithTooltipLocation = new int[2];
buttonWithTooltip.getLocationOnScreen(buttonWithTooltipLocation);
- final int touchableSize = 48;
+ final int touchableSize = resources.getDimensionPixelSize(
+ R.dimen.button_touchable_width_increment_amount);
final int hoverRight = buttonWithTooltipLocation[0] + touchableSize / 2;
final int hoverLeft = buttonLocation[0] + button.getWidth() + touchableSize / 2;
final int hoverMiddle = (hoverLeft + hoverRight) / 2;
@@ -965,8 +966,9 @@
throws Throwable {
mActivity.waitForEnterAnimationComplete();
- final int touchableSize = 48;
final Resources resources = sInstrumentation.getTargetContext().getResources();
+ final int touchableSize = resources.getDimensionPixelSize(
+ R.dimen.button_touchable_width_increment_amount);
final String targetResourceName = resources.getResourceName(R.id.buttonDelegated);
final View textView = mActivity.findViewById(R.id.delegateText);
final Button target = mActivity.findViewById(R.id.buttonDelegated);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/AccessibilityEndToEndActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/AccessibilityEndToEndActivity.java
index 0e16b79..7f2b95d 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/AccessibilityEndToEndActivity.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/AccessibilityEndToEndActivity.java
@@ -74,7 +74,8 @@
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(listAdapter);
- final int touchableSize = 48;
+ final int touchableSize = getResources().getDimensionPixelSize(
+ R.dimen.button_touchable_width_increment_amount);
Button button = findViewById(R.id.button);
Function<View, Rect> withTouchableAtRight = (v) -> new Rect(
v.getLeft(), 0, v.getRight() + touchableSize, v.getHeight());
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index f7e1761..9418ce2 100755
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -3652,6 +3652,56 @@
.getParcelable(Notification.EXTRA_MEDIA_REMOTE_INTENT));
}
+ public void testCustomMediaStyleRemotePlayback_noPermission() throws Exception {
+ int id = 99;
+ final String deviceName = "device name";
+ final int deviceIcon = 123;
+ final PendingIntent deviceIntent = getPendingIntent();
+ final Notification notification =
+ new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(R.drawable.black)
+ .setStyle(new Notification.DecoratedMediaCustomViewStyle()
+ .setRemotePlaybackInfo(deviceName, deviceIcon, deviceIntent))
+ .build();
+ mNotificationManager.notify(id, notification);
+
+ StatusBarNotification sbn = findPostedNotification(id, false);
+ assertNotNull(sbn);
+
+ assertFalse(sbn.getNotification().extras
+ .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
+ assertFalse(sbn.getNotification().extras
+ .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON));
+ assertFalse(sbn.getNotification().extras
+ .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT));
+ }
+
+ public void testCustomMediaStyleRemotePlayback_hasPermission() throws Exception {
+ int id = 99;
+ final String deviceName = "device name";
+ final int deviceIcon = 123;
+ final PendingIntent deviceIntent = getPendingIntent();
+ final Notification notification =
+ new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(R.drawable.black)
+ .setStyle(new Notification.DecoratedMediaCustomViewStyle()
+ .setRemotePlaybackInfo(deviceName, deviceIcon, deviceIntent))
+ .build();
+
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ mNotificationManager.notify(id, notification);
+ }, android.Manifest.permission.MEDIA_CONTENT_CONTROL);
+
+ StatusBarNotification sbn = findPostedNotification(id, false);
+ assertNotNull(sbn);
+ assertEquals(deviceName, sbn.getNotification().extras
+ .getString(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
+ assertEquals(deviceIcon, sbn.getNotification().extras
+ .getInt(Notification.EXTRA_MEDIA_REMOTE_ICON));
+ assertEquals(deviceIntent, sbn.getNotification().extras
+ .getParcelable(Notification.EXTRA_MEDIA_REMOTE_INTENT));
+ }
+
public void testNoPermission() throws Exception {
int id = 7;
SystemUtil.runWithShellPermissionIdentity(
diff --git a/tests/autofillservice/res/layout/scrollable_login_activity.xml b/tests/autofillservice/res/layout/scrollable_login_activity.xml
new file mode 100644
index 0000000..dfa5227
--- /dev/null
+++ b/tests/autofillservice/res/layout/scrollable_login_activity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2023 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:orientation="vertical" >
+
+ <ScrollView android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <include layout="@layout/login_activity" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 6dd4d1a..381eefb 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -543,10 +543,9 @@
// It works fine for portrait but for the platforms that the default orientation
// is landscape, e.g. automotive. Depending on the height of the IME, the ID_LOGIN
// button may not be visible.
- // In order to avoid that,
- // generate back key event to hide IME before pressing ID_LOGIN button.
- mUiBot.pressBack();
+ // In order to avoid that, scroll until the ID_LOGIN button appears.
+ mUiBot.scrollToTextObject(ID_LOGIN);
mUiBot.selectByRelativeId(ID_LOGIN);
mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
index 4cab12c..ca91090 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
@@ -41,7 +41,7 @@
Log.i(TAG, "onCreate(" + savedInstanceState + ")");
super.onCreate(savedInstanceState);
- setContentView(R.layout.login_activity);
+ setContentView(R.layout.scrollable_login_activity);
findViewById(R.id.login).setOnClickListener((v) -> finish());
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index 28bb02e..6090cdc 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -59,12 +59,14 @@
import android.media.Image.Plane;
import android.media.ImageReader;
import android.media.ImageWriter;
+import android.os.Build;
import android.os.SystemClock;
import android.os.ConditionVariable;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
+import com.android.compatibility.common.util.PropertyUtil;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import org.junit.Test;
@@ -1454,7 +1456,9 @@
if (mStaticInfo.isCapabilitySupported(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS)) {
StaticMetadata staticInfo = mStaticInfo;
- if (mStaticInfo.isLogicalMultiCamera()
+ boolean supportActivePhysicalIdConsistency =
+ PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S;
+ if (mStaticInfo.isLogicalMultiCamera() && supportActivePhysicalIdConsistency
&& mStaticInfo.isActivePhysicalCameraIdSupported()) {
String activePhysicalId =
result.get(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
diff --git a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
index 7e51289..3fbf06a 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -460,6 +460,9 @@
" SYSTEM_CAMERA permissons", mAdoptShellPerm);
}
return;
+ case REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING:
+ //Tested in OfflineSessionTest
+ return;
default:
capabilityName = "Unknown";
assertTrue(String.format("Unknown capability set: %d", capability),
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index 55eae8c..81173bb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -361,6 +361,7 @@
final Rect keepClearRect = new Rect(0, 0, 25, 25);
final View v = createTestViewInActivity(activity, keepClearRect);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
assertSameElementsEventually(Arrays.asList(keepClearRect),
() -> getKeepClearRectsForActivity(activity));
@@ -372,15 +373,16 @@
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
() -> getKeepClearRectsForActivity(activity));
- final List<Rect> expectedRectsInScreenSpace =
- getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName());
- assertSameElementsEventually(expectedRectsInScreenSpace,
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(
+ getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
() -> getKeepClearRectsOnDefaultDisplay());
activity.finishAndRemoveTask();
- assertTrue(Collections.disjoint(
- expectedRectsInScreenSpace,
- getKeepClearRectsOnDefaultDisplay()));
+ assertSameElementsEventually(prevKeepClearRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -419,6 +421,7 @@
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
assertSameElementsEventually(Arrays.asList(viewBounds),
() -> getKeepClearRectsForActivity(activity1));
@@ -438,8 +441,12 @@
mWmState.assertVisibility(activity2.getComponentName(), true);
// Since both activities are fullscreen, WM only takes the keep clear areas from the top one
- assertSameElementsEventually(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
- activity2.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
+ activity2.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -449,15 +456,24 @@
translucentTestSession.launchTestActivityOnDisplaySync(
TranslucentTestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity1 = translucentTestSession.getActivity();
-
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
translucentTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
- assertSameElementsEventually(getRectsInScreenSpace(Arrays.asList(viewBounds),
- activity1.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
+ // Add keep-clear rects in the activity
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(Arrays.asList(viewBounds),
+ activity1.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
+
+ // Start an opaque activity on top
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity2 = mTestSession.getActivity();
+
+ // Add keep-clear rects in the opaque activity
final View v2 = createTestViewInActivity(activity2);
mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
@@ -466,8 +482,13 @@
mWmState.waitAndAssertVisibilityGone(activity1.getComponentName());
mWmState.assertVisibility(activity2.getComponentName(), true);
- assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
- () -> getKeepClearRectsForActivity(activity2));
+ // Only the opaque activity's keep-clear areas should be reported on the display
+ expectedRectsOnDisplay.clear();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(
+ TEST_KEEP_CLEAR_RECTS, activity2.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -475,30 +496,15 @@
assumeTrue("Skipping test: no split multi-window support",
supportsSplitScreenMultiWindow());
- final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
- .setUseInstrumentation()
- .setIntentExtra(extra -> {
- extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
- new ArrayList(TEST_KEEP_CLEAR_RECTS));
- })
- .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY);
+ startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+ KEEP_CLEAR_RECTS_ACTIVITY2, Collections.emptyList(), Collections.emptyList());
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
- final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
- .setUseInstrumentation()
- .setIntentExtra(extra -> {
- extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
- new ArrayList(TEST_KEEP_CLEAR_RECTS_2));
- })
- .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY2);
+ removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY).mTaskId);
+ removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY2).mTaskId);
- launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
-
- waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY, KEEP_CLEAR_RECTS_ACTIVITY
- + " must be resumed");
- waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY2, KEEP_CLEAR_RECTS_ACTIVITY2
- + " must be resumed");
- mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY, true);
- mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY2, true);
+ startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+ KEEP_CLEAR_RECTS_ACTIVITY2, TEST_KEEP_CLEAR_RECTS, TEST_KEEP_CLEAR_RECTS_2);
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
() -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY));
@@ -506,11 +512,38 @@
() -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY2));
final List<Rect> expected = new ArrayList();
+ expected.addAll(prevKeepClearRectsOnDisplay);
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, KEEP_CLEAR_RECTS_ACTIVITY));
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS_2, KEEP_CLEAR_RECTS_ACTIVITY2));
assertSameElementsEventually(expected, () -> getKeepClearRectsOnDefaultDisplay());
}
+ private void startKeepClearActivitiesInSplitscreen(ComponentName activity1,
+ ComponentName activity2, List<Rect> keepClearRects1, List<Rect> keepClearRects2) {
+ final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(activity1)
+ .setIntentExtra(extra -> {
+ extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+ new ArrayList(keepClearRects1));
+ });
+
+ final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(activity2)
+ .setIntentExtra(extra -> {
+ extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+ new ArrayList(keepClearRects2));
+ });
+
+ launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
+
+ waitAndAssertResumedActivity(activity1, activity1 + " must be resumed");
+ waitAndAssertResumedActivity(activity2, activity2 + " must be resumed");
+ mWmState.assertVisibility(activity1, true);
+ mWmState.assertVisibility(activity2, true);
+ }
+
@Test
public void testUnrestrictedKeepClearRects() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
@@ -547,6 +580,7 @@
mTestSession.runOnMainSyncAndWait(() -> {
activity.addView(newView, params);
});
+ waitForIdle();
return newView;
}
@@ -607,7 +641,8 @@
private static <T> void assertSameElementsEventually(List<T> expected, Callable<List<T>> actual)
throws Exception {
- PollingCheck.check("Lists do not have the same elements.",
+ PollingCheck.check("Lists do not have the same elements."
+ + "Expected=" + expected + ", actual=" + actual.call(),
SAME_ELEMENT_ASSERTION_TIMEOUT,
() -> hasSameElements(expected, actual.call()));
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index e7d6650..c5b520d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -565,7 +565,7 @@
mWmState.assertFocusedActivity("Top activity must be the latest launched one",
VIRTUAL_DISPLAY_ACTIVITY);
- launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+ launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, newDisplay.mId);
waitAndAssertActivityStateOnDisplay(TEST_ACTIVITY, STATE_RESUMED, newDisplay.mId,
"Activity launched on secondary display must be resumed");
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
index e6e1e81..06ca39f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
@@ -457,21 +457,24 @@
mAm.getLockTaskModeState() != LOCK_TASK_MODE_NONE);
// Verify specifying non-fullscreen windowing mode will fail.
- boolean exceptionThrown = false;
- try {
- runWithShellPermission(() -> {
- final WindowContainerTransaction wct = new WindowContainerTransaction()
- .setWindowingMode(
- mTaskOrganizer.getTaskInfo(task.mTaskId).getToken(),
- WINDOWING_MODE_MULTI_WINDOW);
- mTaskOrganizer.applyTransaction(wct);
- });
- } catch (UnsupportedOperationException e) {
- exceptionThrown = true;
- }
- assertTrue("Not allowed to specify windowing mode while in locked task mode.",
- exceptionThrown);
+ runWithShellPermission(() -> {
+ final WindowContainerTransaction wct = new WindowContainerTransaction()
+ .setWindowingMode(
+ mTaskOrganizer.getTaskInfo(task.mTaskId).getToken(),
+ WINDOWING_MODE_MULTI_WINDOW);
+ mTaskOrganizer.applyTransaction(wct);
+ });
+ } catch (UnsupportedOperationException e) {
+ // Non-fullscreen windowing mode change can cause an exception.
} finally {
+ // The default behavior in T is to throw an exception, but this has changed in U+ to
+ // ensure Core won't crash with some timing issues. Thus, in T, we allow both throwing
+ // and not throwing an exception in this case, but at least the windowing mode change
+ // must be rejected.
+ mWmState.computeState(TEST_ACTIVITY);
+ assertEquals(WINDOWING_MODE_FULLSCREEN,
+ mWmState.getWindowState(TEST_ACTIVITY).getWindowingMode());
+
runWithShellPermission(() -> {
mAtm.stopSystemLockTaskMode();
});
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
index 1a452c0..7b92787 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
@@ -21,11 +21,15 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.server.wm.RoundedCornerTests.TestActivity.EXTRA_ORIENTATION;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT;
import static android.view.RoundedCorner.POSITION_TOP_LEFT;
import static android.view.RoundedCorner.POSITION_TOP_RIGHT;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -49,12 +53,12 @@
import android.view.WindowManager;
import android.view.WindowMetrics;
+import androidx.annotation.NonNull;
import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.PollingCheck;
import org.junit.After;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,8 +68,8 @@
@RunWith(Parameterized.class)
public class RoundedCornerTests extends ActivityManagerTestBase {
private static final String TAG = "RoundedCornerTests";
- private final static int POSITION_LENGTH = 4;
- private final static long TIMEOUT = 1000; // milliseconds
+ private static final int POSITION_LENGTH = 4;
+ private static final long TIMEOUT_IN_MILLISECONDS = 1000;
@Parameterized.Parameters(name= "{1}({0})")
public static Object[][] data() {
@@ -83,65 +87,115 @@
@Parameterized.Parameter(1)
public String orientationName;
- @Before
- public void setUp() {
- // On devices with ignore_orientation_request set to true, the test activity will be
- // letterboxed in a landscape display which make the activity not a fullscreen one.
- // We should set it to false while testing.
- mObjectTracker.manage(new IgnoreOrientationRequestSession(false /* enable */));
- }
+ private final WindowManagerStateHelper mWindowManagerStateHelper =
+ new WindowManagerStateHelper();
@After
public void tearDown() {
- mTestActivity.finishActivity();
- new WindowManagerStateHelper().waitForDisplayUnfrozen();
+ mTestActivityRule.finishActivity();
+ mWindowManagerStateHelper.waitForDisplayUnfrozen();
}
@Rule
- public final ActivityTestRule<TestActivity> mTestActivity =
+ public final ActivityTestRule<TestActivity> mTestActivityRule =
new ActivityTestRule<>(TestActivity.class, false /* initialTouchMode */,
false /* launchActivity */);
@Test
public void testRoundedCorner_fullscreen() {
- final TestActivity activity = mTestActivity.launchActivity(
- new Intent().putExtra(EXTRA_ORIENTATION, orientation));
- runOnMainSync(() -> {
- activity.addChildWindow(
- activity.calculateWindowBounds(false /* excludeRoundedCorners */));
- });
- // Make sure the child window has been laid out.
- final View childWindowRoot = activity.getChildWindowRoot();
- PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
- PollingCheck.waitFor(TIMEOUT, () -> activity.getDispatchedInsets() != null);
- final WindowInsets insets = activity.getDispatchedInsets();
-
- final Display display = activity.getDisplay();
- for (int i = 0; i < POSITION_LENGTH; i++) {
- assertEquals(insets.getRoundedCorner(i), display.getRoundedCorner(i));
- }
+ verifyRoundedCorners(false /* excludeRoundedCorners */);
}
@Test
public void testRoundedCorner_excludeRoundedCorners() {
- final TestActivity activity = mTestActivity.launchActivity(
- new Intent().putExtra(EXTRA_ORIENTATION, orientation));
- if (!activity.hasRoundedCorners()) {
+ verifyRoundedCorners(true /* excludeRoundedCorners */);
+ }
+
+ private void verifyRoundedCorners(boolean excludedRoundedCorners) {
+ final TestActivity activity = mTestActivityRule.launchActivity(new Intent());
+
+ if (excludedRoundedCorners && !activity.hasRoundedCorners()) {
Log.d(TAG, "There is no rounded corner on the display. Skipped!!");
return;
}
- runOnMainSync(() -> {
- activity.addChildWindow(
- activity.calculateWindowBounds(true /* excludeRoundedCorners */));
- });
- // Make sure the child window has been laid out.
- PollingCheck.waitFor(TIMEOUT, () -> activity.getDispatchedInsets() != null);
- final WindowInsets insets = activity.getDispatchedInsets();
+ waitAndAssertResumedActivity(activity.getComponentName(), "Activity must be resumed.");
- for (int i = 0; i < POSITION_LENGTH; i++) {
- assertNull("The rounded corners should be null.", insets.getRoundedCorner(i));
+ int rotation = getRotation(activity, orientation);
+
+ if (rotation != ROTATION_0) {
+ // If the device doesn't support rotation, just verify the rounded corner with
+ // the current orientation.
+ if (!supportsRotation()) {
+ return;
+ }
+ RotationSession rotationSession = createManagedRotationSession();
+ rotationSession.set(rotation);
}
+
+ runOnMainSync(() -> activity.addChildWindow(
+ activity.calculateWindowBounds(excludedRoundedCorners)));
+ try {
+ // Make sure the child window has been laid out.
+ PollingCheck.waitFor(TIMEOUT_IN_MILLISECONDS,
+ () -> activity.getDispatchedInsets() != null);
+ final WindowInsets insets = activity.getDispatchedInsets();
+
+ if (excludedRoundedCorners) {
+ for (int i = 0; i < POSITION_LENGTH; i++) {
+ assertNull("The rounded corners should be null.",
+ insets.getRoundedCorner(i));
+ }
+ } else {
+ final Display display = activity.getDisplay();
+ for (int j = 0; j < POSITION_LENGTH; j++) {
+ assertEquals(insets.getRoundedCorner(j), display.getRoundedCorner(j));
+ }
+ }
+ } finally {
+ runOnMainSync(activity::removeChildWindow);
+ }
+ }
+
+ /**
+ * Returns the rotation based on {@code orientations}.
+ */
+ private static int getRotation(@NonNull Activity activity, int requestedOrientation) {
+ // Not use Activity#getRequestedOrientation because the possible values are dozens and hard
+ // to determine the rotation.
+ int currentOrientation = activity.getResources().getConfiguration().orientation;
+ if (currentOrientation == ORIENTATION_PORTRAIT) {
+ switch (requestedOrientation) {
+ case SCREEN_ORIENTATION_PORTRAIT: {
+ return ROTATION_0;
+ }
+ case SCREEN_ORIENTATION_LANDSCAPE: {
+ return ROTATION_90;
+ }
+ case SCREEN_ORIENTATION_REVERSE_PORTRAIT: {
+ return ROTATION_180;
+ }
+ case SCREEN_ORIENTATION_REVERSE_LANDSCAPE: {
+ return ROTATION_270;
+ }
+ }
+ } else {
+ switch (requestedOrientation) {
+ case SCREEN_ORIENTATION_PORTRAIT: {
+ return ROTATION_90;
+ }
+ case SCREEN_ORIENTATION_LANDSCAPE: {
+ return ROTATION_0;
+ }
+ case SCREEN_ORIENTATION_REVERSE_PORTRAIT: {
+ return ROTATION_270;
+ }
+ case SCREEN_ORIENTATION_REVERSE_LANDSCAPE: {
+ return ROTATION_180;
+ }
+ }
+ }
+ throw new IllegalArgumentException("Unknown orientation value:" + requestedOrientation);
}
private void runOnMainSync(Runnable runnable) {
@@ -184,8 +238,10 @@
getWindowManager().addView(mChildWindowRoot, attrs);
}
- View getChildWindowRoot() {
- return mChildWindowRoot;
+ void removeChildWindow() {
+ if (mChildWindowRoot != null) {
+ getWindowManager().removeViewImmediate(mChildWindowRoot);
+ }
}
WindowInsets getDispatchedInsets() {
@@ -202,7 +258,7 @@
Rect calculateWindowBounds(boolean excludeRoundedCorners) {
final Display display = getDisplay();
- final WindowMetrics windowMetrics = getWindowManager().getMaximumWindowMetrics();
+ final WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
if (!excludeRoundedCorners) {
return windowMetrics.getBounds();
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
index 59a1a2b..198e4b3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
@@ -17,6 +17,7 @@
package android.server.wm;
import static android.server.wm.WindowManagerTestBase.startActivity;
+import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -85,6 +86,9 @@
@Test
public void testSetDisablePreviewScreenshots() throws Exception {
+ final View decor = mActivity.getWindow().getDecorView();
+ final int captionBarHeight = decor.getRootWindowInsets().getInsets(captionBar()).top;
+
BitmapPixelChecker pixelChecker = new BitmapPixelChecker(PixelColor.RED);
int retries = 0;
@@ -93,7 +97,8 @@
Bitmap bitmap = mWindowManager.snapshotTaskForRecents(mActivity.getTaskId());
if (bitmap != null) {
int expectedMatching =
- bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED;
+ bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED
+ - (captionBarHeight * decor.getWidth());
Rect boundToCheck = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
int matchingPixels = pixelChecker.getNumMatchingPixels(bitmap, boundToCheck);
matchesPixels = matchingPixels >= expectedMatching;
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index bf2e941..56dd1b0 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -16,13 +16,11 @@
package android.keystore.cts;
-import static com.google.common.truth.Truth.assertThat;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -39,13 +37,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.bedstead.nene.annotations.Nullable;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
@@ -72,7 +63,6 @@
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
@@ -88,6 +78,11 @@
import javax.crypto.SecretKey;
import javax.security.auth.x500.X500Principal;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@RunWith(AndroidJUnit4.class)
public class AndroidKeyStoreTest {
private static final String TAG = AndroidKeyStoreTest.class.getSimpleName();
@@ -828,12 +823,6 @@
expectedAliases.length, count);
}
- private void deleteEntryIfNotNull(@Nullable String alias) throws Exception {
- if (alias != null) {
- mKeyStore.deleteEntry(alias);
- }
- }
-
@Test
public void testKeyStore_Aliases_Unencrypted_Success() throws Exception {
mKeyStore.load(null, null);
@@ -2172,9 +2161,8 @@
PrivateKey privateKey3 = generatePrivateKey("RSA", FAKE_RSA_KEY_1);
final int MAX_NUMBER_OF_KEYS = 2500;
- final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_rsa_keys_");
+ final String ALIAS_PREFIX = "test_large_number_of_rsa_keys_";
int keyCount = 0;
- String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2187,12 +2175,11 @@
new KeyStore.PrivateKeyEntry(privateKey1, new Certificate[] {cert1}),
protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
- new PrivateKeyEntry(privateKey3, new Certificate[] {cert3}),
- protectionParams);
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
+ new PrivateKeyEntry(privateKey3, new Certificate[] {cert3}), protectionParams);
keyCount++;
- entryName2 = "test" + keyCount;
+ String entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2,
new KeyStore.PrivateKeyEntry(privateKey2, new Certificate[] {cert2}),
protectionParams);
@@ -2219,9 +2206,7 @@
sig.update(message);
assertTrue(sig.verify(signature));
} finally {
- mKeyStore.deleteEntry(entryName1);
- deleteEntryIfNotNull(entryName2);
- deleteManyTestKeys(keyCount, aliasPrefix);
+ deleteManyTestKeys(keyCount, ALIAS_PREFIX);
}
}
@@ -2250,9 +2235,8 @@
PrivateKey privateKey3 = generatePrivateKey("EC", FAKE_EC_KEY_1);
final int MAX_NUMBER_OF_KEYS = 2500;
- final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_ec_keys_");
+ final String ALIAS_PREFIX = "test_large_number_of_ec_keys_";
int keyCount = 0;
- String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2264,12 +2248,12 @@
new KeyStore.PrivateKeyEntry(privateKey1, new Certificate[] {cert1}),
protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
new KeyStore.PrivateKeyEntry(privateKey3, new Certificate[] {cert3}),
protectionParams);
keyCount++;
- entryName2 = "test" + keyCount;
+ String entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2,
new KeyStore.PrivateKeyEntry(privateKey2, new Certificate[] {cert2}),
protectionParams);
@@ -2296,9 +2280,7 @@
sig.update(message);
assertTrue(sig.verify(signature));
} finally {
- mKeyStore.deleteEntry(entryName1);
- deleteEntryIfNotNull(entryName2);
- deleteManyTestKeys(keyCount, aliasPrefix);
+ deleteManyTestKeys(keyCount, ALIAS_PREFIX);
}
}
@@ -2325,9 +2307,8 @@
HexEncoding.decode("33333333333333333333777777777777"), "AES");
final int MAX_NUMBER_OF_KEYS = 10000;
- final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_aes_keys_");
+ final String ALIAS_PREFIX = "test_large_number_of_aes_keys_";
int keyCount = 0;
- String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2338,11 +2319,11 @@
.build();
mKeyStore.setEntry(entryName1, new KeyStore.SecretKeyEntry(key1), protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
new KeyStore.SecretKeyEntry(key3), protectionParams);
++keyCount;
- entryName2 = "test" + keyCount;
+ String entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2, new KeyStore.SecretKeyEntry(key2), protectionParams);
SecretKey keystoreKey2 = (SecretKey) mKeyStore.getKey(entryName2, null);
SecretKey keystoreKey1 = (SecretKey) mKeyStore.getKey(entryName1, null);
@@ -2364,9 +2345,7 @@
cipher.init(Cipher.DECRYPT_MODE, key2, cipherParams);
assertArrayEquals(plaintext, cipher.doFinal(ciphertext));
} finally {
- mKeyStore.deleteEntry(entryName1);
- deleteEntryIfNotNull(entryName2);
- deleteManyTestKeys(keyCount, aliasPrefix);
+ deleteManyTestKeys(keyCount, ALIAS_PREFIX);
}
}
@@ -2395,9 +2374,8 @@
HexEncoding.decode("33333333333333333333777777777777"), "HmacSHA256");
final int MAX_NUMBER_OF_KEYS = 10000;
- final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_hmac_keys_");
+ final String ALIAS_PREFIX = "test_large_number_of_hmac_keys_";
int keyCount = 0;
- String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2406,11 +2384,11 @@
.build();
mKeyStore.setEntry(entryName1, new KeyStore.SecretKeyEntry(key1), protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
new KeyStore.SecretKeyEntry(key3), protectionParams);
keyCount++;
- entryName2 = "test" + keyCount;
+ String entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2, new KeyStore.SecretKeyEntry(key2), protectionParams);
SecretKey keystoreKey2 = (SecretKey) mKeyStore.getKey(entryName2, null);
SecretKey keystoreKey1 = (SecretKey) mKeyStore.getKey(entryName1, null);
@@ -2430,9 +2408,7 @@
"59b57e77e4e2cb36b5c7b84af198ac004327bc549de6931a1b5505372dd8c957"),
mac.doFinal(message));
} finally {
- mKeyStore.deleteEntry(entryName1);
- deleteEntryIfNotNull(entryName2);
- deleteManyTestKeys(keyCount, aliasPrefix);
+ deleteManyTestKeys(keyCount, ALIAS_PREFIX);
}
}
@@ -2630,8 +2606,8 @@
*
* This method is time-bounded
*/
- private int importKeyManyTimes(int numberOfKeys, StringBuilder aliasPrefix, Entry keyEntry,
- KeyProtection protectionParams, boolean isTimeBound)
+ private int importKeyManyTimes(int numberOfKeys, String aliasPrefix, Entry keyEntry,
+ KeyProtection protectionParams)
throws InterruptedException {
TimeBox timeBox = new TimeBox(mMaxImportDuration);
AtomicInteger keyCounter = new AtomicInteger(0);
@@ -2640,7 +2616,7 @@
threads.add(new Thread(() -> {
// Import key lots of times, under different aliases. Do this until we either run
// out of time or we import the key numberOfKeys times.
- while (!isTimeBound || !timeBox.isOutOfTime()) {
+ while (!timeBox.isOutOfTime()) {
int count = keyCounter.incrementAndGet();
if (count > numberOfKeys) {
// The loop is inherently racy, as multiple threads are simultaneously
@@ -2653,7 +2629,7 @@
if ((count % 1000) == 0) {
Log.i(TAG, "Imported " + count + " keys");
}
- String entryAlias = aliasPrefix.toString() + count;
+ String entryAlias = aliasPrefix + count;
try {
mKeyStore.setEntry(entryAlias, keyEntry, protectionParams);
} catch (Throwable e) {
@@ -2670,7 +2646,7 @@
threads.get(i).join();
}
Log.i(TAG, "Imported " + keyCounter.get() + " keys in " + timeBox.elapsed());
- if (keyCounter.get() != numberOfKeys && keyCounter.get() < MIN_SUPPORTED_KEY_COUNT) {
+ if (keyCounter.get() < MIN_SUPPORTED_KEY_COUNT) {
fail("Failed to import " + MIN_SUPPORTED_KEY_COUNT + " keys in "
+ timeBox.elapsed() + ". Imported: " + keyCounter.get() + " keys");
}
@@ -2678,22 +2654,11 @@
return keyCounter.get();
}
- private int importKeyManyTimes(int numberOfKeys, StringBuilder aliasPrefix, Entry keyEntry,
- KeyProtection protectionParams) throws InterruptedException {
- return importKeyManyTimes(numberOfKeys, aliasPrefix, keyEntry, protectionParams, true);
- }
-
- private int importKeyManyTimesWithoutTimeLimit(int numberOfKeys, StringBuilder aliasPrefix,
- Entry keyEntry,
- KeyProtection protectionParams) throws InterruptedException {
- return importKeyManyTimes(numberOfKeys, aliasPrefix, keyEntry, protectionParams, false);
- }
-
/**
* Delete <code>numberOfKeys</code> keys that follow the pattern "[aliasPrefix][keyCounter]".
* This is done across multiple threads to both increase throughput as well as stress keystore.
*/
- private void deleteManyTestKeys(int numberOfKeys, StringBuilder aliasPrefix)
+ private void deleteManyTestKeys(int numberOfKeys, String aliasPrefix)
throws InterruptedException {
// Clean up Keystore without using KeyStore.aliases() which can't handle this many
// entries.
@@ -2708,9 +2673,8 @@
if ((key > 0) && ((key % 1000) == 0)) {
Log.i(TAG, "Deleted " + key + " keys");
}
- String entryAlias = aliasPrefix.toString() + key;
try {
- mKeyStore.deleteEntry(entryAlias);
+ mKeyStore.deleteEntry("test" + key);
} catch (Exception e) {
fail("Unexpected exception in key cleanup: " + e);
}
@@ -2726,114 +2690,4 @@
}
Log.i(TAG, "Deleted " + numberOfKeys + " keys");
}
-
- private Set<String> createLargeNumberOfKeyStoreEntryAliases(int numberOfKeys,
- StringBuilder aliasPrefix)
- throws Exception {
- Certificate cert = generateCertificate(FAKE_RSA_USER_1);
- PrivateKey privateKey = generatePrivateKey("RSA", FAKE_RSA_KEY_1);
-
- mKeyStore.load(null);
- KeyProtection protectionParams = new KeyProtection.Builder(
- KeyProperties.PURPOSE_SIGN)
- .setDigests(KeyProperties.DIGEST_SHA256)
- .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
- .build();
-
- int keyCount = importKeyManyTimesWithoutTimeLimit(numberOfKeys, aliasPrefix,
- new PrivateKeyEntry(privateKey, new Certificate[]{cert}), protectionParams);
-
- // Construct expected aliases list.
- final Set<String> expectedAliases = new HashSet<>(keyCount);
- for (int count = 1; count <= keyCount; count++) {
- String entryAlias = aliasPrefix.toString() + count;
- expectedAliases.add(entryAlias);
- }
-
- return expectedAliases;
- }
-
- private void importLargeNumberOfKeysValidateAliases(int numberOfKeys, StringBuilder aliasPrefix)
- throws Exception {
- Set<String> importedKeyAliases = createLargeNumberOfKeyStoreEntryAliases(numberOfKeys,
- aliasPrefix);
- assertThat(importedKeyAliases.size()).isEqualTo(numberOfKeys);
-
- try {
- // b/222287335 Currently, limiting Keystore `listEntries` API to return subset of the
- // Keystore entries to avoid running out of binder buffer space.
- // To verify that all the imported key aliases are present in Keystore, get the list of
- // aliases from Keystore, delete the matched aliases from Keystore and imported list of
- // key aliases, continue this till all the imported key aliases are matched.
- while (!importedKeyAliases.isEmpty()) {
- // List the keystore entries aliases until all the imported key aliases are matched.
- Set<String> aliases = new HashSet<String>(Collections.list(mKeyStore.aliases()));
-
- // Try to match the aliases with imported key aliases.
- // Cleanup matching aliases from Keystore and imported key aliases list.
- for (String alias: aliases) {
- if (importedKeyAliases.contains(alias)) {
- mKeyStore.deleteEntry(alias);
- importedKeyAliases.remove(alias);
- }
- }
- }
- assertTrue("Failed to match imported keystore entries.",
- importedKeyAliases.isEmpty());
- } finally {
- if (!importedKeyAliases.isEmpty()) {
- Log.i(TAG, "Final cleanup of imported keys");
- for (String alias: importedKeyAliases) {
- mKeyStore.deleteEntry(alias);
- }
- }
- }
- assertTrue(importedKeyAliases.isEmpty());
- }
-
- /**
- * Create long alias prefix of length 6000 characters.
- */
- private StringBuilder createLongAliasPrefix() {
- char[] prefixChar = new char[6000];
- Arrays.fill(prefixChar, 'T');
- StringBuilder prefixAlias = new StringBuilder();
- prefixAlias.append(prefixChar);
-
- return prefixAlias;
- }
-
- /**
- * Create large number of Keystore entries with long aliases and try to list aliases of all the
- * entries in the keystore.
- */
- @Test
- public void testKeyStore_LargeNumberOfLongAliases() throws Exception {
- final int maxNumberOfKeys = 100;
-
- importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, createLongAliasPrefix());
- }
-
- /**
- * Create limited number of Keystore entries with long aliases and try to list aliases of all
- * the entries in the keystore. Test should successfully list all the Keystore entries aliases.
- */
- @Test
- public void testKeyStore_LimitedNumberOfLongAliasesSuccess() throws Exception {
- final int maxNumberOfKeys = 10;
- importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, createLongAliasPrefix());
- }
-
- /**
- * Create large number of Keystore entries with short length aliases and try to list aliases of
- * all the entries in the keystore. Test should successfully list all the Keystore entries
- * aliases.
- */
- @Test
- public void testKeyStore_LargeNumberShortAliasesSuccess() throws Exception {
- final int maxNumberOfKeys = 2500;
- final StringBuilder aliasPrefix = new StringBuilder("test_short_key_alias_");
-
- importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, aliasPrefix);
- }
}
diff --git a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
index ffc2dcf..9fc07d3 100644
--- a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
+++ b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
@@ -1016,8 +1016,8 @@
MediaUtils.skipTest("no microphone, camera, or codecs");
return;
}
- long fileSize = 128 * 1024;
- long tolerance = 50 * 1024;
+ long fileSize = 1028 * 1024;
+ long tolerance = 400 * 1024;
int width;
int height;
List<String> recordFileList = new ArrayList<String>();
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
deleted file mode 100644
index af5f908..0000000
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ /dev/null
@@ -1,1966 +0,0 @@
-/*
- * Copyright (C) 2009 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.media.cts;
-
-import static org.junit.Assert.assertNotEquals;
-
-import static android.media.AudioManager.ADJUST_LOWER;
-import static android.media.AudioManager.ADJUST_RAISE;
-import static android.media.AudioManager.ADJUST_SAME;
-import static android.media.AudioManager.MODE_IN_CALL;
-import static android.media.AudioManager.MODE_IN_COMMUNICATION;
-import static android.media.AudioManager.MODE_NORMAL;
-import static android.media.AudioManager.MODE_RINGTONE;
-import static android.media.AudioManager.RINGER_MODE_NORMAL;
-import static android.media.AudioManager.RINGER_MODE_SILENT;
-import static android.media.AudioManager.RINGER_MODE_VIBRATE;
-import static android.media.AudioManager.STREAM_ACCESSIBILITY;
-import static android.media.AudioManager.STREAM_ALARM;
-import static android.media.AudioManager.STREAM_DTMF;
-import static android.media.AudioManager.STREAM_MUSIC;
-import static android.media.AudioManager.STREAM_NOTIFICATION;
-import static android.media.AudioManager.STREAM_RING;
-import static android.media.AudioManager.STREAM_SYSTEM;
-import static android.media.AudioManager.STREAM_VOICE_CALL;
-import static android.media.AudioManager.USE_DEFAULT_STREAM_TYPE;
-import static android.media.AudioManager.VIBRATE_SETTING_OFF;
-import static android.media.AudioManager.VIBRATE_SETTING_ON;
-import static android.media.AudioManager.VIBRATE_SETTING_ONLY_SILENT;
-import static android.media.AudioManager.VIBRATE_TYPE_NOTIFICATION;
-import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
-import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;
-
-import android.Manifest;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.media.AudioAttributes;
-import android.media.AudioDeviceAttributes;
-import android.media.AudioDeviceInfo;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioProfile;
-import android.media.AudioDescriptor;
-import android.media.MediaPlayer;
-import android.media.MediaRecorder;
-import android.media.MicrophoneInfo;
-import android.media.audiopolicy.AudioProductStrategy;
-import android.os.Build;
-import android.os.SystemClock;
-import android.os.Vibrator;
-import android.platform.test.annotations.AppModeFull;
-import android.provider.Settings;
-import android.provider.Settings.System;
-import android.test.InstrumentationTestCase;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.SoundEffectConstants;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.ApiLevelUtil;
-import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.MediaUtils;
-import com.android.compatibility.common.util.SettingsStateKeeperRule;
-import com.android.internal.annotations.GuardedBy;
-
-import org.junit.ClassRule;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-@NonMediaMainlineTest
-public class AudioManagerTest extends InstrumentationTestCase {
- private final static String TAG = "AudioManagerTest";
-
- private final static long ASYNC_TIMING_TOLERANCE_MS = 50;
- private final static long POLL_TIME_VOLUME_ADJUST = 200;
- private final static long POLL_TIME_UPDATE_INTERRUPTION_FILTER = 5000;
- private final static int MP3_TO_PLAY = R.raw.testmp3; // ~ 5 second mp3
- private final static long POLL_TIME_PLAY_MUSIC = 2000;
- private final static long TIME_TO_PLAY = 2000;
- private final static String APPOPS_OP_STR = "android:write_settings";
- private final static Set<Integer> ALL_KNOWN_ENCAPSULATION_TYPES = new HashSet<>() {{
- add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937);
- }};
- private final static Set<Integer> ALL_ENCAPSULATION_TYPES = new HashSet<>() {{
- add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE);
- add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937);
- }};
- private final static HashSet<Integer> ALL_AUDIO_STANDARDS = new HashSet<>() {{
- add(AudioDescriptor.STANDARD_NONE);
- add(AudioDescriptor.STANDARD_EDID);
- }};
- private AudioManager mAudioManager;
- private NotificationManager mNm;
- private boolean mHasVibrator;
- private boolean mUseFixedVolume;
- private boolean mIsTelevision;
- private boolean mIsSingleVolume;
- private boolean mSkipRingerTests;
- // From N onwards, ringer mode adjustments that toggle DND are not allowed unless
- // package has DND access. Many tests in this package toggle DND access in order
- // to get device out of the DND state for the test to proceed correctly.
- // But DND access is disabled completely on low ram devices,
- // so completely skip those tests here.
- // These tests are migrated to CTS verifier tests to ensure test coverage.
- private Context mContext;
- private int mOriginalRingerMode;
- private Map<Integer, Integer> mOriginalStreamVolumes = new HashMap<>();
- private NotificationManager.Policy mOriginalNotificationPolicy;
- private int mOriginalZen;
- private boolean mDoNotCheckUnmute;
- private boolean mAppsBypassingDnd;
-
- @ClassRule
- public static final SettingsStateKeeperRule mSurroundSoundFormatsSettingsKeeper =
- new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(),
- Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
-
- @ClassRule
- public static final SettingsStateKeeperRule mSurroundSoundModeSettingsKeeper =
- new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(),
- Settings.Global.ENCODED_SURROUND_OUTPUT);
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = getInstrumentation().getContext();
- Utils.enableAppOps(mContext.getPackageName(), APPOPS_OP_STR, getInstrumentation());
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
- mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- mAppsBypassingDnd = NotificationManager.getService().areChannelsBypassingDnd();
- mHasVibrator = (vibrator != null) && vibrator.hasVibrator();
- mUseFixedVolume = mContext.getResources().getBoolean(
- Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
- PackageManager packageManager = mContext.getPackageManager();
- mIsTelevision = packageManager != null
- && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
- || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
- mIsSingleVolume = mContext.getResources().getBoolean(
- Resources.getSystem().getIdentifier("config_single_volume", "bool", "android"));
- mSkipRingerTests = mUseFixedVolume || mIsTelevision || mIsSingleVolume;
-
- // Store the original volumes that that they can be recovered in tearDown().
- final int[] streamTypes = {
- STREAM_VOICE_CALL,
- STREAM_SYSTEM,
- STREAM_RING,
- STREAM_MUSIC,
- STREAM_ALARM,
- STREAM_NOTIFICATION,
- STREAM_DTMF,
- STREAM_ACCESSIBILITY,
- };
- mOriginalRingerMode = mAudioManager.getRingerMode();
- for (int streamType : streamTypes) {
- mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType));
- }
-
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mOriginalNotificationPolicy = mNm.getNotificationPolicy();
- mOriginalZen = mNm.getCurrentInterruptionFilter();
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- }
-
- // Check original microphone mute/unmute status
- mDoNotCheckUnmute = false;
- if (mAudioManager.isMicrophoneMute()) {
- mAudioManager.setMicrophoneMute(false);
- if (mAudioManager.isMicrophoneMute()) {
- Log.w(TAG, "Mic seems muted by hardware! Please unmute and rerrun the test.");
- mDoNotCheckUnmute = true;
- }
- }
- }
-
- @Override
- protected void tearDown() throws Exception {
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mNm.setNotificationPolicy(mOriginalNotificationPolicy);
- setInterruptionFilter(mOriginalZen);
-
- // Recover the volume and the ringer mode that the test may have overwritten.
- for (Map.Entry<Integer, Integer> e : mOriginalStreamVolumes.entrySet()) {
- mAudioManager.setStreamVolume(e.getKey(), e.getValue(),
- AudioManager.FLAG_ALLOW_RINGER_MODES);
- }
- mAudioManager.setRingerMode(mOriginalRingerMode);
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- }
- }
-
- @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
- public void testMicrophoneMute() throws Exception {
- mAudioManager.setMicrophoneMute(true);
- assertTrue(mAudioManager.isMicrophoneMute());
- mAudioManager.setMicrophoneMute(false);
- assertFalse(mAudioManager.isMicrophoneMute() && !mDoNotCheckUnmute);
- }
-
- @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
- public void testMicrophoneMuteIntent() throws Exception {
- if (!mDoNotCheckUnmute) {
- final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver(
- AudioManager.ACTION_MICROPHONE_MUTE_CHANGED);
- final boolean initialMicMute = mAudioManager.isMicrophoneMute();
- try {
- mContext.registerReceiver(receiver,
- new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED));
- // change the mic mute state
- mAudioManager.setMicrophoneMute(!initialMicMute);
- // verify a change was reported
- final boolean intentFired = receiver.waitForExpectedAction(500/*ms*/);
- assertTrue("ACTION_MICROPHONE_MUTE_CHANGED wasn't fired", intentFired);
- // verify the mic mute state is expected
- final boolean newMicMute = mAudioManager.isMicrophoneMute();
- assertTrue("new mic mute state not as expected (" + !initialMicMute + ")",
- (newMicMute == !initialMicMute));
- } finally {
- mContext.unregisterReceiver(receiver);
- mAudioManager.setMicrophoneMute(initialMicMute);
- }
- }
- }
-
- @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
- public void testSpeakerphoneIntent() throws Exception {
- if (!hasBuiltinSpeaker()) {
- return;
- }
- final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver(
- AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
- final boolean initialSpeakerphoneState = mAudioManager.isSpeakerphoneOn();
- try {
- mContext.registerReceiver(receiver,
- new IntentFilter(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED));
- // change the speakerphone state
- mAudioManager.setSpeakerphoneOn(!initialSpeakerphoneState);
- // verify a change was reported
- final boolean intentFired = receiver.waitForExpectedAction(500/*ms*/);
- assertTrue("ACTION_SPEAKERPHONE_STATE_CHANGED wasn't fired", intentFired);
- // verify the speakerphon state is expected
- final boolean newSpeakerphoneState = mAudioManager.isSpeakerphoneOn();
- assertTrue("new mic mute state not as expected ("
- + !initialSpeakerphoneState + ")",
- newSpeakerphoneState == !initialSpeakerphoneState);
- } finally {
- mContext.unregisterReceiver(receiver);
- mAudioManager.setSpeakerphoneOn(initialSpeakerphoneState);
- }
- }
-
- private boolean hasBuiltinSpeaker() {
- AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
- for (AudioDeviceInfo device : devices) {
- final int type = device.getType();
- if (type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER
- || type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE) {
- return true;
- }
- }
- return false;
- }
-
- private static final class MyBlockingIntentReceiver extends BroadcastReceiver {
- private final SafeWaitObject mLock = new SafeWaitObject();
- // the action for the intent to check
- private final String mAction;
- @GuardedBy("mLock")
- private boolean mIntentReceived = false;
-
- MyBlockingIntentReceiver(String action) {
- mAction = action;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!TextUtils.equals(intent.getAction(), mAction)) {
- // move along, this is not the action we're looking for
- return;
- }
- synchronized (mLock) {
- mIntentReceived = true;
- mLock.safeNotify();
- }
- }
-
- public boolean waitForExpectedAction(long timeOutMs) {
- synchronized (mLock) {
- try {
- mLock.safeWait(timeOutMs);
- } catch (InterruptedException e) { }
- return mIntentReceived;
- }
- }
- }
-
- public void testSoundEffects() throws Exception {
- Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);
-
- // should hear sound after loadSoundEffects() called.
- mAudioManager.loadSoundEffects();
- Thread.sleep(TIME_TO_PLAY);
- float volume = 0.5f; // volume should be between 0.f to 1.f (or -1).
- mAudioManager.playSoundEffect(SoundEffectConstants.CLICK);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
-
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume);
-
- // won't hear sound after unloadSoundEffects() called();
- mAudioManager.unloadSoundEffects();
- mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
-
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume);
- mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume);
- }
-
- public void testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess() throws Exception {
- try {
- // set zen mode to priority only, so playSoundEffect will check notification policy
- Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
- true);
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
- Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);
-
- // take away write-notification policy access from the package
- Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
- false);
-
- // playSoundEffect should NOT throw a security exception; all apps have read-access
- mAudioManager.playSoundEffect(SoundEffectConstants.CLICK);
- } finally {
- Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
- true);
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
- false);
- }
- }
-
- public void testMusicActive() throws Exception {
- if (mAudioManager.isMusicActive()) {
- return;
- }
- MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
- assertNotNull(mp);
- mp.setAudioStreamType(STREAM_MUSIC);
- mp.start();
- assertMusicActive(true);
- mp.stop();
- mp.release();
- assertMusicActive(false);
- }
-
- @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
- public void testAccessMode() throws Exception {
- mAudioManager.setMode(MODE_RINGTONE);
- assertEquals(MODE_RINGTONE, mAudioManager.getMode());
- mAudioManager.setMode(MODE_IN_COMMUNICATION);
- assertEquals(MODE_IN_COMMUNICATION, mAudioManager.getMode());
- mAudioManager.setMode(MODE_NORMAL);
- assertEquals(MODE_NORMAL, mAudioManager.getMode());
- }
-
- public void testSetSurroundFormatEnabled() throws Exception {
- getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
- Manifest.permission.WRITE_SETTINGS);
-
- int audioFormat = AudioFormat.ENCODING_DTS;
-
- mAudioManager.setSurroundFormatEnabled(audioFormat, true /*enabled*/);
- assertTrue(mAudioManager.isSurroundFormatEnabled(audioFormat));
-
- mAudioManager.setSurroundFormatEnabled(audioFormat, false /*enabled*/);
- assertFalse(mAudioManager.isSurroundFormatEnabled(audioFormat));
-
- getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
- }
-
- public void testSetEncodedSurroundMode() throws Exception {
- getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
- Manifest.permission.WRITE_SETTINGS);
-
- int expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL;
- mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode);
- assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode());
-
- expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER;
- mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode);
- assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode());
-
- getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
- }
-
- @SuppressWarnings("deprecation")
- @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
- public void testRouting() throws Exception {
- // setBluetoothA2dpOn is a no-op, and getRouting should always return -1
- boolean oldA2DP = mAudioManager.isBluetoothA2dpOn();
- mAudioManager.setBluetoothA2dpOn(true);
- assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());
- mAudioManager.setBluetoothA2dpOn(false);
- assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());
-
- assertEquals(-1, mAudioManager.getRouting(MODE_RINGTONE));
- assertEquals(-1, mAudioManager.getRouting(MODE_NORMAL));
- assertEquals(-1, mAudioManager.getRouting(MODE_IN_CALL));
- assertEquals(-1, mAudioManager.getRouting(MODE_IN_COMMUNICATION));
-
- mAudioManager.setBluetoothScoOn(true);
- assertTrueCheckTimeout(mAudioManager, p -> p.isBluetoothScoOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned false");
-
- mAudioManager.setBluetoothScoOn(false);
- assertTrueCheckTimeout(mAudioManager, p -> !p.isBluetoothScoOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned true");
-
- mAudioManager.setSpeakerphoneOn(true);
- assertTrueCheckTimeout(mAudioManager, p -> p.isSpeakerphoneOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned false");
-
- mAudioManager.setSpeakerphoneOn(false);
- assertTrueCheckTimeout(mAudioManager, p -> !p.isSpeakerphoneOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned true");
- }
-
- public void testVibrateNotification() throws Exception {
- if (mUseFixedVolume || !mHasVibrator) {
- return;
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // VIBRATE_SETTING_ON
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- // VIBRATE_SETTING_OFF
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- // VIBRATE_SETTING_ONLY_SILENT
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
-
- // VIBRATE_TYPE_NOTIFICATION
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager
- .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- }
-
- public void testVibrateRinger() throws Exception {
- if (mUseFixedVolume || !mHasVibrator) {
- return;
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // VIBRATE_TYPE_RINGER
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- // VIBRATE_SETTING_OFF
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
- // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
- // disable the vibration for incoming calls only.
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- // VIBRATE_SETTING_ONLY_SILENT
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
-
- // VIBRATE_TYPE_NOTIFICATION
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- }
-
- public void testAccessRingMode() throws Exception {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- // AudioService#setRingerMode() has:
- // if (isTelevision) return;
- if (mSkipRingerTests) {
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } else {
- assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- }
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- if (mSkipRingerTests) {
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } else {
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- }
- }
-
- public void testSetRingerModePolicyAccess() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- // Apps without policy access cannot change silent -> normal or silent -> vibrate.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- // Apps without policy access cannot change normal -> silent.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-
- if (mHasVibrator) {
- // Apps without policy access cannot change vibrate -> silent.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- // Apps without policy access can change vibrate -> normal and vice versa.
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- }
- }
-
- public void testVolume() throws Exception {
- if (MediaUtils.check(mIsTelevision, "No volume test due to fixed/full vol devices"))
- return;
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- int volume, volumeDelta;
- int[] streams = {STREAM_ALARM,
- STREAM_MUSIC,
- STREAM_VOICE_CALL,
- STREAM_RING};
-
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- // adjusting volume is asynchronous, wait before other volume checks
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- mAudioManager.adjustSuggestedStreamVolume(
- ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
-
- for (int stream : streams) {
- if (mIsSingleVolume && stream != STREAM_MUSIC) {
- continue;
- }
-
- // set ringer mode to back normal to not interfere with volume tests
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-
- int maxVolume = mAudioManager.getStreamMaxVolume(stream);
- int minVolume = mAudioManager.getStreamMinVolume(stream);
-
- // validate min
- assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
- assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
- maxVolume),
- minVolume < maxVolume);
-
- final int minNonZeroVolume = Math.max(minVolume, 1);
- mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0);
- if (mUseFixedVolume) {
- assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
- continue;
- }
- assertEquals(String.format("stream=%d", stream),
- minNonZeroVolume, mAudioManager.getStreamVolume(stream));
-
- if (stream == STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
- // due to new regulations, music sent over a wired headset may be volume limited
- // until the user explicitly increases the limit, so we can't rely on being able
- // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
- // by increasing the volume until it won't go any higher, then use that volume as
- // the maximum for the purposes of this test
- int curvol = 0;
- int prevvol = 0;
- do {
- prevvol = curvol;
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- curvol = mAudioManager.getStreamVolume(stream);
- } while (curvol != prevvol);
- maxVolume = maxMusicVolume = curvol;
- }
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
-
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
- assertStreamVolumeEquals(stream, maxVolume - volumeDelta,
- "Vol ADJUST_LOWER suggested stream:" + stream + " maxVol:" + maxVolume);
-
- // volume lower
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- volume = mAudioManager.getStreamVolume(stream);
- while (volume > minVolume) {
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
- assertStreamVolumeEquals(stream, Math.max(0, volume - volumeDelta),
- "Vol ADJUST_LOWER on stream:" + stream + " vol:" + volume
- + " minVol:" + minVolume + " volDelta:" + volumeDelta);
- volume = mAudioManager.getStreamVolume(stream);
- }
-
- mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
-
- // volume raise
- mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0);
- volume = mAudioManager.getStreamVolume(stream);
- while (volume < maxVolume) {
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- assertStreamVolumeEquals(stream, Math.min(volume + volumeDelta, maxVolume),
- "Vol ADJUST_RAISE on stream:" + stream + " vol:" + volume
- + " maxVol:" + maxVolume + " volDelta:" + volumeDelta);
- volume = mAudioManager.getStreamVolume(stream);
- }
-
- // volume same
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertEquals("Vol ADJUST_RAISE onADJUST_SAME stream:" + stream,
- maxVolume, mAudioManager.getStreamVolume(stream));
-
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- }
-
- if (mUseFixedVolume) {
- return;
- }
-
- // adjust volume
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-
- boolean isMusicPlayingBeforeTest = false;
- if (mAudioManager.isMusicActive()) {
- isMusicPlayingBeforeTest = true;
- }
-
- MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
- assertNotNull(mp);
- mp.setAudioStreamType(STREAM_MUSIC);
- mp.setLooping(true);
- mp.start();
- assertMusicActive(true);
-
- // adjust volume as ADJUST_SAME
- mAudioManager.adjustVolume(ADJUST_SAME, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertStreamVolumeEquals(STREAM_MUSIC, maxMusicVolume);
-
- // adjust volume as ADJUST_RAISE
- mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertStreamVolumeEquals(STREAM_MUSIC, Math.min(volumeDelta, maxMusicVolume));
-
- // adjust volume as ADJUST_LOWER
- mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
- maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
- mAudioManager.adjustVolume(ADJUST_LOWER, 0);
- assertStreamVolumeEquals(STREAM_MUSIC, Math.max(0, maxMusicVolume - volumeDelta));
-
- mp.stop();
- mp.release();
- if (!isMusicPlayingBeforeTest) {
- assertMusicActive(false);
- }
- }
-
- public void testAccessibilityVolume() throws Exception {
- if (mUseFixedVolume) {
- Log.i("AudioManagerTest", "testAccessibilityVolume() skipped: fixed volume");
- return;
- }
- final int maxA11yVol = mAudioManager.getStreamMaxVolume(STREAM_ACCESSIBILITY);
- assertTrue("Max a11yVol not strictly positive", maxA11yVol > 0);
- int originalVol = mAudioManager.getStreamVolume(STREAM_ACCESSIBILITY);
-
- // changing STREAM_ACCESSIBILITY is subject to permission, shouldn't be able to change it
- // test setStreamVolume
- final int testSetVol;
- if (originalVol != maxA11yVol) {
- testSetVol = maxA11yVol;
- } else {
- testSetVol = maxA11yVol - 1;
- }
- mAudioManager.setStreamVolume(STREAM_ACCESSIBILITY, testSetVol, 0);
- assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
- "Should not be able to change A11y vol");
-
- // test adjustStreamVolume
- // LOWER
- if (originalVol > 0) {
- mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_LOWER, 0);
- assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
- "Should not be able to change A11y vol");
- }
- // RAISE
- if (originalVol < maxA11yVol) {
- mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_RAISE, 0);
- assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
- "Should not be able to change A11y vol");
- }
- }
-
- public void testSetVoiceCallVolumeToZeroPermission() {
- // Verify that only apps with MODIFY_PHONE_STATE can set VOICE_CALL_STREAM to 0
- mAudioManager.setStreamVolume(STREAM_VOICE_CALL, 0, 0);
- assertTrue("MODIFY_PHONE_STATE is required in order to set voice call volume to 0",
- mAudioManager.getStreamVolume(STREAM_VOICE_CALL) != 0);
- }
-
- public void testMuteFixedVolume() throws Exception {
- int[] streams = {
- STREAM_VOICE_CALL,
- STREAM_MUSIC,
- STREAM_RING,
- STREAM_ALARM,
- STREAM_NOTIFICATION,
- STREAM_SYSTEM};
- if (mUseFixedVolume) {
- for (int stream : streams) {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertFalse("Muting should not affect a fixed volume device.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
- assertFalse("Toggling mute should not affect a fixed volume device.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.setStreamMute(stream, true);
- assertFalse("Muting should not affect a fixed volume device.",
- mAudioManager.isStreamMute(stream));
- }
- }
- }
-
- public void testMuteDndAffectedStreams() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- int[] streams = { STREAM_RING };
- // Mute streams
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- // Verify streams cannot be unmuted without policy access.
- for (int stream : streams) {
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
- 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setStreamMute(stream, false);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
- }
-
- // This ensures we're out of vibrate or silent modes.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- for (int stream : streams) {
- // ensure each stream is on and turned up.
- mAudioManager.setStreamVolume(stream,
- mAudioManager.getStreamMaxVolume(stream),
- 0);
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.adjustStreamVolume(
- stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setStreamMute(stream, true);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- testStreamMuting(stream);
- }
- }
-
- public void testMuteDndUnaffectedStreams() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- int[] streams = {
- STREAM_VOICE_CALL,
- STREAM_MUSIC,
- STREAM_ALARM
- };
-
- int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
- System.MUTE_STREAMS_AFFECTED,
- // same defaults as in AudioService. Should be kept in sync.
- (1 << STREAM_MUSIC) |
- (1 << STREAM_RING) |
- (1 << STREAM_NOTIFICATION) |
- (1 << STREAM_SYSTEM) |
- (1 << STREAM_VOICE_CALL));
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // This ensures we're out of vibrate or silent modes.
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- for (int stream : streams) {
- // ensure each stream is on and turned up.
- mAudioManager.setStreamVolume(stream,
- mAudioManager.getStreamMaxVolume(stream),
- 0);
- if (((1 << stream) & muteAffectedStreams) == 0) {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- mAudioManager.setStreamMute(stream, true);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
- 0);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- continue;
- }
- testStreamMuting(stream);
- }
- }
-
- private void testStreamMuting(int stream) {
- // Voice call requires MODIFY_PHONE_STATE, so we should not be able to mute
- if (stream == STREAM_VOICE_CALL) {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertFalse("Muting voice call stream (" + stream + ") should require "
- + "MODIFY_PHONE_STATE.", mAudioManager.isStreamMute(stream));
- } else {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertTrue("Muting stream " + stream + " failed.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
- assertFalse("Unmuting stream " + stream + " failed.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
- assertTrue("Toggling mute on stream " + stream + " failed.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
- assertFalse("Toggling mute on stream " + stream + " failed.",
- mAudioManager.isStreamMute(stream));
-
- mAudioManager.setStreamMute(stream, true);
- assertTrue("Muting stream " + stream + " using setStreamMute failed",
- mAudioManager.isStreamMute(stream));
-
- // mute it three more times to verify the ref counting is gone.
- mAudioManager.setStreamMute(stream, true);
- mAudioManager.setStreamMute(stream, true);
- mAudioManager.setStreamMute(stream, true);
-
- mAudioManager.setStreamMute(stream, false);
- assertFalse("Unmuting stream " + stream + " using setStreamMute failed.",
- mAudioManager.isStreamMute(stream));
- }
- }
-
- public void testSetInvalidRingerMode() {
- int ringerMode = mAudioManager.getRingerMode();
- mAudioManager.setRingerMode(-1337);
- assertEquals(ringerMode, mAudioManager.getRingerMode());
-
- mAudioManager.setRingerMode(-3007);
- assertEquals(ringerMode, mAudioManager.getRingerMode());
- }
-
- public void testAdjustVolumeInTotalSilenceMode() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- mAudioManager.adjustStreamVolume(
- STREAM_MUSIC, ADJUST_RAISE, 0);
- assertStreamVolumeEquals(STREAM_MUSIC, musicVolume);
-
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testAdjustVolumeInAlarmsOnlyMode() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
-
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- mAudioManager.adjustStreamVolume(
- STREAM_MUSIC, ADJUST_RAISE, 0);
- int volumeDelta =
- getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
- assertStreamVolumeEquals(STREAM_MUSIC, musicVolume + volumeDelta);
-
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testSetStreamVolumeInTotalSilenceMode() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
-
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
- // delay for streams interruption filter to get into correct state
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-
- // cannot adjust music, can adjust ringer since it could exit DND
- int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 7, 0);
- assertStreamVolumeEquals(STREAM_MUSIC, musicVolume);
- mAudioManager.setStreamVolume(STREAM_RING, 7, 0);
- assertStreamVolumeEquals(STREAM_RING, 7);
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testSetStreamVolumeInAlarmsOnlyMode() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS);
- // delay for streams to get into correct volume states
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-
- // can still adjust music and ring volume
- mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0);
- assertStreamVolumeEquals(STREAM_MUSIC, 3);
- mAudioManager.setStreamVolume(STREAM_RING, 7, 0);
- assertStreamVolumeEquals(STREAM_RING, 7);
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testSetStreamVolumeInPriorityOnlyMode() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
-
- try {
- // turn off zen, set stream volumes to check for later
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-
- final int testRingerVol = getTestRingerVol();
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- int alarmVolume = mAudioManager.getStreamVolume(STREAM_ALARM);
-
- // disallow all sounds in priority only, turn on priority only DND, try to change volume
- mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0 , 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
- // delay for streams to get into correct volume states
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 5, 0);
- mAudioManager.setStreamVolume(STREAM_RING, testRingerVol, 0);
-
- // Turn off zen and make sure stream levels are still the same prior to zen
- // aside from ringer since ringer can exit dnd
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS); // delay for streams to get into correct states
- assertEquals(musicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
- assertEquals(alarmVolume, mAudioManager.getStreamVolume(STREAM_ALARM));
- assertEquals(testRingerVol, mAudioManager.getStreamVolume(STREAM_RING));
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testAdjustVolumeInPriorityOnly() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // turn off zen, set stream volumes to check for later
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- int ringVolume = mAudioManager.getStreamVolume(STREAM_RING);
- int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- int alarmVolume = mAudioManager.getStreamVolume(STREAM_ALARM);
-
- // disallow all sounds in priority only, turn on priority only DND, try to change volume
- mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
- // delay for streams to get into correct mute states
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- mAudioManager.adjustStreamVolume(
- STREAM_RING, ADJUST_RAISE, 0);
- mAudioManager.adjustStreamVolume(
- STREAM_MUSIC, ADJUST_RAISE, 0);
- mAudioManager.adjustStreamVolume(
- STREAM_ALARM, ADJUST_RAISE, 0);
-
- // Turn off zen and make sure stream levels are still the same prior to zen
- // aside from ringer since ringer can exit dnd
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS); // delay for streams to get into correct states
- assertEquals(musicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
- assertEquals(alarmVolume, mAudioManager.getStreamVolume(STREAM_ALARM));
-
- int volumeDelta =
- getVolumeDelta(mAudioManager.getStreamVolume(STREAM_RING));
- assertEquals(ringVolume + volumeDelta,
- mAudioManager.getStreamVolume(STREAM_RING));
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlyMuteAll() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // disallow all sounds in priority only, turn on priority only DND
- mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
-
- // if channels cannot bypass DND, the Ringer stream should be muted, else it
- // shouldn't be muted
- assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
- "Ringer stream should be muted if channels cannot bypassDnd");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlyMediaAllowed() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // allow only media in priority only
- mNm.setNotificationPolicy(new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, false,
- "Music (media) stream should not be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
-
- // if channels cannot bypass DND, the Ringer stream should be muted, else it
- // shouldn't be muted
- assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
- "Ringer stream should be muted if channels cannot bypassDnd");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlySystemAllowed() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // allow only system in priority only
- mNm.setNotificationPolicy(new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, false,
- "System stream should not be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
- assertStreamMuted(STREAM_RING, false,
- "Ringer stream should not be muted");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlySystemDisallowedWithRingerMuted() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test, but then mute ringer
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 0, 0);
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-
- // allow only system in priority only
- mNm.setNotificationPolicy(new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
- assertStreamMuted(STREAM_RING, true,
- "Ringer stream should be muted");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlyAlarmsAllowed() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // allow only alarms in priority only
- mNm.setNotificationPolicy(new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, false,
- "Alarm stream should not be muted");
-
- // if channels cannot bypass DND, the Ringer stream should be muted, else it
- // shouldn't be muted
- assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
- "Ringer stream should be muted if channels cannot bypassDnd");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlyRingerAllowed() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // allow only reminders in priority only
- mNm.setNotificationPolicy(new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS, 0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
- assertStreamMuted(STREAM_RING, false,
- "Ringer stream should not be muted");
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- }
- }
-
- public void testPriorityOnlyChannelsCanBypassDnd() throws Exception {
- if (mSkipRingerTests) {
- return;
- }
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
-
- final String NOTIFICATION_CHANNEL_ID = "test_id_" + SystemClock.uptimeMillis();
- NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "TEST",
- NotificationManager.IMPORTANCE_DEFAULT);
- try {
- // ensure volume is not muted/0 to start test
- mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
- mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
- mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
-
- // create a channel that can bypass dnd
- channel.setBypassDnd(true);
- mNm.createNotificationChannel(channel);
-
- // allow nothing
- mNm.setNotificationPolicy(new NotificationManager.Policy(0,0, 0));
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
- assertStreamMuted(STREAM_RING, false,
- "Ringer stream should not be muted."
- + " areChannelsBypassing="
- + NotificationManager.getService().areChannelsBypassingDnd());
-
- // delete the channel that can bypass dnd
- mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
-
- assertStreamMuted(STREAM_MUSIC, true,
- "Music (media) stream should be muted");
- assertStreamMuted(STREAM_SYSTEM, true,
- "System stream should be muted");
- assertStreamMuted(STREAM_ALARM, true,
- "Alarm stream should be muted");
- // if channels cannot bypass DND, the Ringer stream should be muted, else it
- // shouldn't be muted
- assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
- "Ringer stream should be muted if apps are bypassing dnd"
- + " areChannelsBypassing="
- + NotificationManager.getService().areChannelsBypassingDnd());
- } finally {
- setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
- Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
- false);
- }
- }
-
- public void testAdjustVolumeWithIllegalDirection() throws Exception {
- // Call the method with illegal direction. System should not reboot.
- mAudioManager.adjustVolume(37, 0);
- }
-
- private final int[] PUBLIC_STREAM_TYPES = { STREAM_VOICE_CALL,
- STREAM_SYSTEM, STREAM_RING, STREAM_MUSIC,
- STREAM_ALARM, STREAM_NOTIFICATION,
- STREAM_DTMF, STREAM_ACCESSIBILITY };
-
- public void testGetStreamVolumeDbWithIllegalArguments() throws Exception {
- Exception ex = null;
- // invalid stream type
- try {
- float gain = mAudioManager.getStreamVolumeDb(-100 /*streamType*/, 0,
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
- } catch (Exception e) {
- ex = e; // expected
- }
- assertNotNull("No exception was thrown for an invalid stream type", ex);
- assertEquals("Wrong exception thrown for invalid stream type",
- ex.getClass(), IllegalArgumentException.class);
-
- // invalid volume index
- ex = null;
- try {
- float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, -101 /*volume*/,
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
- } catch (Exception e) {
- ex = e; // expected
- }
- assertNotNull("No exception was thrown for an invalid volume index", ex);
- assertEquals("Wrong exception thrown for invalid volume index",
- ex.getClass(), IllegalArgumentException.class);
-
- // invalid out of range volume index
- ex = null;
- try {
- final int maxVol = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
- float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, maxVol + 1,
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
- } catch (Exception e) {
- ex = e; // expected
- }
- assertNotNull("No exception was thrown for an invalid out of range volume index", ex);
- assertEquals("Wrong exception thrown for invalid out of range volume index",
- ex.getClass(), IllegalArgumentException.class);
-
- // invalid device type
- ex = null;
- try {
- float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0,
- -102 /*deviceType*/);
- } catch (Exception e) {
- ex = e; // expected
- }
- assertNotNull("No exception was thrown for an invalid device type", ex);
- assertEquals("Wrong exception thrown for invalid device type",
- ex.getClass(), IllegalArgumentException.class);
-
- // invalid input device type
- ex = null;
- try {
- float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0,
- AudioDeviceInfo.TYPE_BUILTIN_MIC);
- } catch (Exception e) {
- ex = e; // expected
- }
- assertNotNull("No exception was thrown for an invalid input device type", ex);
- assertEquals("Wrong exception thrown for invalid input device type",
- ex.getClass(), IllegalArgumentException.class);
- }
-
- public void testGetStreamVolumeDb() throws Exception {
- for (int streamType : PUBLIC_STREAM_TYPES) {
- // verify mininum index is strictly inferior to maximum index
- final int minIndex = mAudioManager.getStreamMinVolume(streamType);
- final int maxIndex = mAudioManager.getStreamMaxVolume(streamType);
- assertTrue("Min vol index (" + minIndex + ") for stream " + streamType + " not inferior"
- + " to max vol index (" + maxIndex + ")", minIndex <= maxIndex);
- float prevGain = Float.NEGATIVE_INFINITY;
- // verify gain increases with the volume indices
- for (int idx = minIndex ; idx <= maxIndex ; idx++) {
- float gain = mAudioManager.getStreamVolumeDb(streamType, idx,
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
- assertTrue("Non-monotonically increasing gain at index " + idx + " for stream"
- + streamType, prevGain <= gain);
- prevGain = gain;
- }
- }
- }
-
- public void testAdjustSuggestedStreamVolumeWithIllegalArguments() throws Exception {
- // Call the method with illegal direction. System should not reboot.
- mAudioManager.adjustSuggestedStreamVolume(37, STREAM_MUSIC, 0);
-
- // Call the method with illegal stream. System should not reboot.
- mAudioManager.adjustSuggestedStreamVolume(ADJUST_RAISE, 66747, 0);
- }
-
- @CddTest(requirement="5.4.1/C-1-4")
- public void testGetMicrophones() throws Exception {
- if (!mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_MICROPHONE)) {
- return;
- }
- List<MicrophoneInfo> microphones = mAudioManager.getMicrophones();
- assertTrue(microphones.size() > 0);
- for (int i = 0; i < microphones.size(); i++) {
- MicrophoneInfo microphone = microphones.get(i);
- Log.i(TAG, "deviceId:" + microphone.getDescription());
- Log.i(TAG, "portId:" + microphone.getId());
- Log.i(TAG, "type:" + microphone.getType());
- Log.i(TAG, "address:" + microphone.getAddress());
- Log.i(TAG, "deviceLocation:" + microphone.getLocation());
- Log.i(TAG, "deviceGroup:" + microphone.getGroup()
- + " index:" + microphone.getIndexInTheGroup());
- MicrophoneInfo.Coordinate3F position = microphone.getPosition();
- Log.i(TAG, "position:" + position.x + " " + position.y + " " + position.z);
- MicrophoneInfo.Coordinate3F orientation = microphone.getOrientation();
- Log.i(TAG, "orientation:" + orientation.x + " "
- + orientation.y + " " + orientation.z);
- Log.i(TAG, "frequencyResponse:" + microphone.getFrequencyResponse());
- Log.i(TAG, "channelMapping:" + microphone.getChannelMapping());
- Log.i(TAG, "sensitivity:" + microphone.getSensitivity());
- Log.i(TAG, "max spl:" + microphone.getMaxSpl());
- Log.i(TAG, "min spl:" + microphone.getMinSpl());
- Log.i(TAG, "directionality:" + microphone.getDirectionality());
- Log.i(TAG, "--------------");
- }
- }
-
- public void testIsHapticPlaybackSupported() {
- // Calling the API to make sure it doesn't crash.
- Log.i(TAG, "isHapticPlaybackSupported: " + AudioManager.isHapticPlaybackSupported());
- }
-
- public void testGetAudioHwSyncForSession() {
- // AudioManager.getAudioHwSyncForSession is not supported before S
- if (ApiLevelUtil.isAtMost(Build.VERSION_CODES.R)) {
- Log.i(TAG, "testGetAudioHwSyncForSession skipped, release: " + Build.VERSION.SDK_INT);
- return;
- }
- try {
- int sessionId = mAudioManager.generateAudioSessionId();
- assertNotEquals("testGetAudioHwSyncForSession cannot get audio session ID",
- AudioManager.ERROR, sessionId);
- int hwSyncId = mAudioManager.getAudioHwSyncForSession(sessionId);
- Log.i(TAG, "getAudioHwSyncForSession: " + hwSyncId);
- } catch (UnsupportedOperationException e) {
- Log.i(TAG, "getAudioHwSyncForSession not supported");
- } catch (Exception e) {
- fail("Unexpected exception thrown by getAudioHwSyncForSession: " + e);
- }
- }
-
- private void setInterruptionFilter(int filter) {
- mNm.setInterruptionFilter(filter);
- final long startPoll = SystemClock.uptimeMillis();
- int currentFilter = -1;
- while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_UPDATE_INTERRUPTION_FILTER) {
- currentFilter = mNm.getCurrentInterruptionFilter();
- if (currentFilter == filter) {
- return;
- }
- }
- Log.e(TAG, "interruption filter unsuccessfully set. wanted=" + filter
- + " actual=" + currentFilter);
- }
-
- private int getVolumeDelta(int volume) {
- return 1;
- }
-
- private int getTestRingerVol() {
- final int currentRingVol = mAudioManager.getStreamVolume(STREAM_RING);
- final int maxRingVol = mAudioManager.getStreamMaxVolume(STREAM_RING);
- if (currentRingVol != maxRingVol) {
- return maxRingVol;
- } else {
- return maxRingVol - 1;
- }
- }
-
- public void testAllowedCapturePolicy() throws Exception {
- final int policy = mAudioManager.getAllowedCapturePolicy();
- assertEquals("Wrong default capture policy", AudioAttributes.ALLOW_CAPTURE_BY_ALL, policy);
-
- for (int setPolicy : new int[] { AudioAttributes.ALLOW_CAPTURE_BY_NONE,
- AudioAttributes.ALLOW_CAPTURE_BY_SYSTEM,
- AudioAttributes.ALLOW_CAPTURE_BY_ALL}) {
- mAudioManager.setAllowedCapturePolicy(setPolicy);
- final int getPolicy = mAudioManager.getAllowedCapturePolicy();
- assertEquals("Allowed capture policy doesn't match", setPolicy, getPolicy);
- }
- }
-
- public void testIsHdmiSystemAudidoSupported() {
- // just make sure the call works
- boolean isSupported = mAudioManager.isHdmiSystemAudioSupported();
- Log.d(TAG, "isHdmiSystemAudioSupported() = " + isSupported);
- }
-
- public void testIsBluetoothScoAvailableOffCall() {
- // just make sure the call works
- boolean isSupported = mAudioManager.isBluetoothScoAvailableOffCall();
- Log.d(TAG, "isBluetoothScoAvailableOffCall() = " + isSupported);
- }
-
- public void testStartStopBluetoothSco() {
- mAudioManager.startBluetoothSco();
- mAudioManager.stopBluetoothSco();
- }
-
- public void testStartStopBluetoothScoVirtualCall() {
- mAudioManager.startBluetoothScoVirtualCall();
- mAudioManager.stopBluetoothSco();
- }
-
- public void testGetAdditionalOutputDeviceDelay() {
- AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
- for (AudioDeviceInfo device : devices) {
- long delay = mAudioManager.getAdditionalOutputDeviceDelay(device);
- assertTrue("getAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)",
- delay >= 0);
- delay = mAudioManager.getMaxAdditionalOutputDeviceDelay(device);
- assertTrue("getMaxAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)",
- delay >= 0);
- }
- }
-
- static class MyPrevDevForStrategyListener implements
- AudioManager.OnPreferredDevicesForStrategyChangedListener {
- @Override
- public void onPreferredDevicesForStrategyChanged(AudioProductStrategy strategy,
- List<AudioDeviceAttributes> devices) {
- fail("onPreferredDevicesForStrategyChanged must not be called");
- }
- }
-
- public void testPreferredDevicesForStrategy() {
- // setPreferredDeviceForStrategy
- AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
- if (devices.length <= 0) {
- Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no output device");
- return;
- }
- final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]);
-
- final AudioAttributes mediaAttr = new AudioAttributes.Builder().setUsage(
- AudioAttributes.USAGE_MEDIA).build();
- final List<AudioProductStrategy> strategies =
- AudioProductStrategy.getAudioProductStrategies();
- AudioProductStrategy strategyForMedia = null;
- for (AudioProductStrategy strategy : strategies) {
- if (strategy.supportsAudioAttributes(mediaAttr)) {
- strategyForMedia = strategy;
- break;
- }
- }
- if (strategyForMedia == null) {
- Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no strategy for media");
- return;
- }
-
- try {
- mAudioManager.setPreferredDeviceForStrategy(strategyForMedia, ada);
- fail("setPreferredDeviceForStrategy must fail due to no permission");
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.getPreferredDeviceForStrategy(strategyForMedia);
- fail("getPreferredDeviceForStrategy must fail due to no permission");
- } catch (SecurityException e) {
- }
- final List<AudioDeviceAttributes> adas = new ArrayList<>();
- adas.add(ada);
- try {
- mAudioManager.setPreferredDevicesForStrategy(strategyForMedia, adas);
- fail("setPreferredDevicesForStrategy must fail due to no permission");
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.getPreferredDevicesForStrategy(strategyForMedia);
- fail("getPreferredDevicesForStrategy must fail due to no permission");
- } catch (SecurityException e) {
- }
- MyPrevDevForStrategyListener listener = new MyPrevDevForStrategyListener();
- try {
- mAudioManager.addOnPreferredDevicesForStrategyChangedListener(
- Executors.newSingleThreadExecutor(), listener);
- fail("addOnPreferredDevicesForStrategyChangedListener must fail due to no permission");
- } catch (SecurityException e) {
- }
- // There is not listener added at server side. Nothing to remove.
- mAudioManager.removeOnPreferredDevicesForStrategyChangedListener(listener);
- }
-
- static class MyPrevDevicesForCapturePresetChangedListener implements
- AudioManager.OnPreferredDevicesForCapturePresetChangedListener {
- @Override
- public void onPreferredDevicesForCapturePresetChanged(
- int capturePreset, List<AudioDeviceAttributes> devices) {
- fail("onPreferredDevicesForCapturePresetChanged must not be called");
- }
- }
-
- public void testPreferredDeviceForCapturePreset() {
- AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
- if (devices.length <= 0) {
- Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no input device");
- return;
- }
- final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]);
-
- try {
- mAudioManager.setPreferredDeviceForCapturePreset(MediaRecorder.AudioSource.MIC, ada);
- fail("setPreferredDeviceForCapturePreset must fail due to no permission");
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.getPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC);
- fail("getPreferredDevicesForCapturePreset must fail due to no permission");
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.clearPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC);
- fail("clearPreferredDevicesForCapturePreset must fail due to no permission");
- } catch (SecurityException e) {
- }
- MyPrevDevicesForCapturePresetChangedListener listener =
- new MyPrevDevicesForCapturePresetChangedListener();
- try {
- mAudioManager.addOnPreferredDevicesForCapturePresetChangedListener(
- Executors.newSingleThreadExecutor(), listener);
- fail("addOnPreferredDevicesForCapturePresetChangedListener must fail"
- + "due to no permission");
- } catch (SecurityException e) {
- }
- // There is not listener added at server side. Nothing to remove.
- mAudioManager.removeOnPreferredDevicesForCapturePresetChangedListener(listener);
- }
-
- public void testGetDevices() {
- AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
- for (AudioDeviceInfo device : devices) {
- HashSet<Integer> formats = IntStream.of(device.getEncodings()).boxed()
- .collect(Collectors.toCollection(HashSet::new));
- HashSet<Integer> channelMasks = IntStream.of(device.getChannelMasks()).boxed()
- .collect(Collectors.toCollection(HashSet::new));
- HashSet<Integer> channelIndexMasks = IntStream.of(device.getChannelIndexMasks()).boxed()
- .collect(Collectors.toCollection(HashSet::new));
- HashSet<Integer> sampleRates = IntStream.of(device.getSampleRates()).boxed()
- .collect(Collectors.toCollection(HashSet::new));
- HashSet<Integer> formatsFromProfile = new HashSet<>();
- HashSet<Integer> channelMasksFromProfile = new HashSet<>();
- HashSet<Integer> channelIndexMasksFromProfile = new HashSet<>();
- HashSet<Integer> sampleRatesFromProfile = new HashSet<>();
- for (AudioProfile profile : device.getAudioProfiles()) {
- formatsFromProfile.add(profile.getFormat());
- channelMasksFromProfile.addAll(Arrays.stream(profile.getChannelMasks()).boxed()
- .collect(Collectors.toList()));
- channelIndexMasksFromProfile.addAll(Arrays.stream(profile.getChannelIndexMasks())
- .boxed().collect(Collectors.toList()));
- sampleRatesFromProfile.addAll(Arrays.stream(profile.getSampleRates()).boxed()
- .collect(Collectors.toList()));
- assertTrue(ALL_ENCAPSULATION_TYPES.contains(profile.getEncapsulationType()));
- }
- for (AudioDescriptor descriptor : device.getAudioDescriptors()) {
- assertNotEquals(AudioDescriptor.STANDARD_NONE, descriptor.getStandard());
- assertNotNull(descriptor.getDescriptor());
- assertTrue(
- ALL_KNOWN_ENCAPSULATION_TYPES.contains(descriptor.getEncapsulationType()));
- }
- assertEquals(formats, formatsFromProfile);
- assertEquals(channelMasks, channelMasksFromProfile);
- assertEquals(channelIndexMasks, channelIndexMasksFromProfile);
- assertEquals(sampleRates, sampleRatesFromProfile);
- }
- }
-
- private void assertStreamVolumeEquals(int stream, int expectedVolume) throws Exception {
- assertStreamVolumeEquals(stream, expectedVolume,
- "Unexpected stream volume for stream=" + stream);
- }
-
- // volume adjustments are asynchronous, we poll the volume in case the volume state hasn't
- // been adjusted yet
- private void assertStreamVolumeEquals(int stream, int expectedVolume, String msg)
- throws Exception {
- final long startPoll = SystemClock.uptimeMillis();
- int actualVolume = mAudioManager.getStreamVolume(stream);
- while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_VOLUME_ADJUST
- && expectedVolume != actualVolume) {
- actualVolume = mAudioManager.getStreamVolume(stream);
- }
- assertEquals(msg, expectedVolume, actualVolume);
- }
-
- // volume adjustments are asynchronous, we poll the volume in case the mute state hasn't
- // changed yet
- private void assertStreamMuted(int stream, boolean expectedMuteState, String msg)
- throws Exception{
- final long startPoll = SystemClock.uptimeMillis();
- boolean actualMuteState = mAudioManager.isStreamMute(stream);
- while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_VOLUME_ADJUST
- && expectedMuteState != actualMuteState) {
- actualMuteState = mAudioManager.isStreamMute(stream);
- }
- assertEquals(msg, expectedMuteState, actualMuteState);
- }
-
- private void assertMusicActive(boolean expectedIsMusicActive) throws Exception {
- final long startPoll = SystemClock.uptimeMillis();
- boolean actualIsMusicActive = mAudioManager.isMusicActive();
- while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_PLAY_MUSIC
- && expectedIsMusicActive != actualIsMusicActive) {
- actualIsMusicActive = mAudioManager.isMusicActive();
- }
- assertEquals(actualIsMusicActive, actualIsMusicActive);
- }
-
- private static final long REPEATED_CHECK_POLL_PERIOD_MS = 100; // 100ms
- private static final long DEFAULT_ASYNC_CALL_TIMEOUT_MS = 5 * REPEATED_CHECK_POLL_PERIOD_MS;
-
- /**
- * Makes multiple attempts over a given timeout period to test the predicate on an AudioManager
- * instance. Test success is evaluated against a true predicate result.
- * @param am the AudioManager instance to use for the test
- * @param predicate the test to run either until it returns true, or until the timeout expires
- * @param timeoutMs the maximum time allowed for the test to pass
- * @param errorString the string to be displayed in case of failure
- * @throws Exception
- */
- private void assertTrueCheckTimeout(AudioManager am, Predicate<AudioManager> predicate,
- long timeoutMs, String errorString) throws Exception {
- long checkStart = SystemClock.uptimeMillis();
- boolean result = false;
- while (SystemClock.uptimeMillis() - checkStart < timeoutMs) {
- result = predicate.test(am);
- if (result) {
- break;
- }
- Thread.sleep(REPEATED_CHECK_POLL_PERIOD_MS);
- }
- assertTrue(errorString, result);
- }
-
- // getParameters() & setParameters() are deprecated, so don't test
-
- // setAdditionalOutputDeviceDelay(), getAudioVolumeGroups(), getVolumeIndexForAttributes()
- // getMinVolumeIndexForAttributes(), getMaxVolumeIndexForAttributes() &
- // setVolumeIndexForAttributes() require privledged permission MODIFY_AUDIO_ROUTING
- // and thus cannot be tested here.
-}
diff --git a/tests/tests/permission2/res/raw/wear_android_manifest.xml b/tests/tests/permission2/res/raw/wear_android_manifest.xml
deleted file mode 100644
index 08488bc..0000000
--- a/tests/tests/permission2/res/raw/wear_android_manifest.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<!-- This file contains permissions which were back ported.
- These permissions are already present on future platform releases.
- -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android" coreApp="true" android:sharedUserId="android.uid.system"
- android:sharedUserLabel="@string/android_system_label">
-
- <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
- <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
- <p>Protection level: dangerous -->
- <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
- android:permissionGroup="android.permission-group.UNDEFINED"
- android:label="@string/permlab_bodySensorsWristTemperature"
- android:description="@string/permdesc_bodySensorsWristTemperature"
- android:backgroundPermission="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- android:protectionLevel="dangerous" />
-
- <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
- If you're requesting this permission, you must also request
- {@link #BODY_SENSORS_WRIST_TEMPERATURE}. Requesting this permission by itself doesn't
- give you wrist temperature body sensors access.
- <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
- <p>Protection level: dangerous
-
- <p> This is a hard restricted permission which cannot be held by an app until
- the installer on record allowlists the permission. For more details see
- {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
- -->
- <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- android:permissionGroup="android.permission-group.UNDEFINED"
- android:label="@string/permlab_bodySensors_wristTemperature_background"
- android:description="@string/permdesc_bodySensors_wristTemperature_background"
- android:protectionLevel="dangerous"
- android:permissionFlags="hardRestricted" />
-
-</manifest>
\ No newline at end of file
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 6373803..576df28 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -176,9 +176,6 @@
}
declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap);
}
- if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- expectedPermissions.addAll(loadExpectedPermissions(R.raw.wear_android_manifest));
- }
for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
String expectedPermissionName = expectedPermission.name;
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index 2a9f815..e10131c 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -55,7 +55,6 @@
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.Manifest.permission_group.UNDEFINED
import android.app.AppOpsManager.permissionToOp
-import android.content.pm.PackageManager
import android.content.pm.PackageManager.GET_PERMISSIONS
import android.content.pm.PermissionInfo.PROTECTION_DANGEROUS
import android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP
@@ -166,24 +165,6 @@
// Add runtime permissions added in U which were _not_ split from a previously existing
// runtime permission
expectedPerms.add(READ_MEDIA_VISUAL_USER_SELECTED)
-
- // Add runtime permissions added in V (back ported from U) which were _not_ split from a
- // previously existing runtime permission
- if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE)
- expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND)
- }
-
assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
}
-
- companion object {
- // These permissions are back ported from Android U to tm-wear, hidden in the
- // "core/res/AndroidManifest.xml" file of /framework/base repo. Added these 2 constants here
- // because hidden permissions can't be imported like other imported permissions in this file
- private const val BODY_SENSORS_WRIST_TEMPERATURE =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
- private const val BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- }
}
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
index 104655f..3c8a35c 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
+++ b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
@@ -22,6 +22,7 @@
import android.app.NotificationManager
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -43,9 +44,13 @@
lateinit var notificationManager: NotificationManager
var launchActivityOnSecondResume = false
var isFirstResume = true
+ var windowHasFocus = false
+ var pendingCreateChannel = false
val handler = Handler(Looper.getMainLooper())
- override fun onStart() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
val launchSecondActivity = intent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)
notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
if (intent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
@@ -73,7 +78,6 @@
}
}
-
if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
} else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
@@ -85,8 +89,6 @@
if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
}
-
- super.onStart()
}
private fun launchSecondActivity() {
@@ -99,7 +101,21 @@
}, LONG_DELAY_MS)
}
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ windowHasFocus = hasFocus
+ if (windowHasFocus && pendingCreateChannel) {
+ pendingCreateChannel = false
+ createChannel()
+ }
+ }
+
private fun createChannel() {
+ // Wait until window has focus so the permission prompt can be displayed
+ if (!windowHasFocus) {
+ pendingCreateChannel = true
+ return
+ }
+
if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
"Foreground Services", NotificationManager.IMPORTANCE_HIGH))
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index d55e3a4..dee76c2 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -194,6 +194,7 @@
fun notificationPromptShownForSubsequentStartsIfTaskStartWasLauncher() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
launchApp(startSecondActivity = true)
+ waitFindObject(By.res(ALLOW_BUTTON))
pressBack()
clickPermissionRequestAllowButton()
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 0b88e01..7499e0f 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -65,6 +65,7 @@
@Before
fun setup() {
Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
// TODO(b/203784852) Auto will eventually support the blocked sensor banner, but there won't
// be support in T or below
Assume.assumeFalse(isAutomotive)
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 56d02d2..989edca 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -104,6 +104,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert1",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-1",
manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
}
@@ -111,6 +113,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert1Dup",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-1",
manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
}
@@ -118,6 +122,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert2",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-2",
manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
}
@@ -125,6 +131,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert3",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-3",
manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
}
@@ -132,6 +140,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert4",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-4",
manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
}
@@ -139,6 +149,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert12",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-1",
additional_certificates: [
":permission-test-cert-2",
@@ -149,6 +161,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert12Dup",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-1",
additional_certificates: [
":permission-test-cert-2",
@@ -159,6 +173,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert34",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-3",
additional_certificates: [
":permission-test-cert-4",
@@ -169,6 +185,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert123",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-1",
additional_certificates: [
":permission-test-cert-2",
@@ -180,6 +198,8 @@
android_test_helper_app {
name: "CtsPermissionBackupAppCert4History124",
min_sdk_version: "30",
+ resource_dirs: [],
+ asset_dirs: [],
certificate: ":permission-test-cert-4",
additional_certificates: [
":permission-test-cert-1",
@@ -197,6 +217,8 @@
android_test_helper_app {
name: "RolePermissionOverrideTestApp",
+ resource_dirs: [],
+ asset_dirs: [],
manifest: "testdata/rolepermissionoverridetestapp.xml",
}
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 5487fb4..4e43d57 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -238,6 +238,9 @@
android:resource="@xml/syncadapter" />
</service>
+ <activity android:name="android.security.cts.CVE_2023_20953.PocActivity"
+ android:exported="true" />
+
<activity android:name="android.security.cts.CVE_2021_0642.PocActivity"
android:exported="true">
<intent-filter>
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_20953/CVE_2023_20953.java b/tests/tests/security/src/android/security/cts/CVE_2023_20953/CVE_2023_20953.java
new file mode 100644
index 0000000..8c1863c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_20953/CVE_2023_20953.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 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.security.cts.CVE_2023_20953;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.SystemUtil;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2023_20953 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 251778420)
+ @Test
+ public void testCliboardIfUserSetupNotComplete() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ Context context = instrumentation.getContext();
+ UiDevice device = UiDevice.getInstance(instrumentation);
+
+ // Change the setting 'user_setup_complete' to 0.
+ try (AutoCloseable withSettingCloseable =
+ SystemUtil.withSetting(instrumentation, "secure", "user_setup_complete", "0")) {
+ // Launch the PocActivity which shows a basic view to edit some text.
+ final String pkgName = context.getPackageName();
+ Intent intent = new Intent();
+ intent.setClassName(pkgName, pkgName + ".CVE_2023_20953.PocActivity");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ // Look for UI with text "CVE-2023-20955" and select it. Doing so will show some
+ // clipboard options such as 'copy', 'select all', 'cut'.
+ final String uiNotFoundMsg = "UI not found with selector %s";
+ BySelector selector = By.text("CVE-2023-20955");
+ final long timeoutMs = 5000;
+ boolean uiFound = device.wait(Until.findObject(selector), timeoutMs) != null;
+ assumeTrue(String.format(uiNotFoundMsg, selector), uiFound);
+ UiObject2 object = device.findObject(selector);
+ device.drag(object.getVisibleBounds().left, object.getVisibleCenter().y,
+ object.getVisibleBounds().right, object.getVisibleCenter().y, 1);
+
+ // Click on 'Copy' option.
+ selector = By.desc(Pattern.compile(".*copy.*", Pattern.CASE_INSENSITIVE));
+ uiFound = device.wait(Until.findObject(selector), timeoutMs) != null;
+ assumeTrue(String.format(uiNotFoundMsg, selector), uiFound);
+ device.findObject(selector).click();
+
+ // Retrieve System UI package name dynamically.
+ String systemUiPkgName = "com.android.systemui";
+ intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY);
+ if (info != null && info.activityInfo != null
+ && info.activityInfo.packageName != null) {
+ systemUiPkgName = info.activityInfo.packageName;
+ }
+
+ // On vulnerable device, user whose setup is not yet complete will be able to share
+ // the copied text, in which case test fails, else it passes.
+ // Look for UI with resource = com.android.systemui:id/share_chip, if found test
+ // will fail.
+ final String shareBtnResName = "%s:id/share_chip";
+ selector = By.res(String.format(shareBtnResName, systemUiPkgName));
+ assertFalse("Vulnerable to b/251778420 !!",
+ device.wait(Until.hasObject(selector), timeoutMs));
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_20953/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2023_20953/PocActivity.java
new file mode 100644
index 0000000..5ef6ceb
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_20953/PocActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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.security.cts.CVE_2023_20953;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.EditText;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ EditText editText = new EditText(this);
+ editText.setText("CVE-2023-20955");
+ setContentView(editText);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_20959.java b/tests/tests/security/src/android/security/cts/CVE_2023_20959.java
new file mode 100644
index 0000000..00c0e6d
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_20959.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2023 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.security.cts;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2023_20959 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 249057848)
+ @Test
+ public void testPocCVE_2023_20959() {
+ UiAutomation uiAutomation = null;
+ try {
+ String settingsPackageName = "com.android.settings";
+ Instrumentation instrumentation = getInstrumentation();
+ PackageManager packageManager = instrumentation.getTargetContext().getPackageManager();
+ uiAutomation = instrumentation.getUiAutomation();
+ uiAutomation.adoptShellPermissionIdentity(
+ android.Manifest.permission.INTERACT_ACROSS_USERS);
+ ResolveInfo info =
+ packageManager.resolveActivityAsUser(new Intent(Settings.ACTION_SETTINGS),
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ if (info != null && info.activityInfo != null) {
+ settingsPackageName = info.activityInfo.packageName;
+ }
+ assertNull(new Intent()
+ .setComponent(new ComponentName(settingsPackageName,
+ settingsPackageName + ".users.AddSupervisedUserActivity"))
+ .resolveActivityInfo(packageManager, PackageManager.MATCH_SYSTEM_ONLY));
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ uiAutomation.dropShellPermissionIdentity();
+ } catch (Exception e) {
+ // Ignore exceptions as the test has finished
+ }
+ }
+ }
+}
diff --git a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
index 314f29d..2d640e1 100644
--- a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
+++ b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import android.app.ActivityManager;
import android.app.Instrumentation;
@@ -207,6 +208,10 @@
*/
@Test
public void bulkTest1() {
+ // Skip the test for automotive platform
+ assumeFalse("Skip test: does not apply to automotive",
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+
if (!mMeetsResolutionRequirements) return; // Skip test if resolution is too low
try {
launchSharesheet(createShareIntent(false /* do not test preview */,
@@ -232,6 +237,9 @@
@Test
public void bulkTest2() {
+ // Skip the test for automotive platform
+ assumeFalse("Skip test: does not apply to automotive",
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
if (!mMeetsResolutionRequirements) return; // Skip test if resolution is too low
try {
addShortcuts(1);
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 57d09e7..da8f52c 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -96,6 +96,13 @@
</intent-filter>
</service>
+ <service android:name=".NullBindingCallRedirectionServiceController"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telecom.cts.ACTION_CONTROL_CALL_REDIRECTION_SERVICE"/>
+ </intent-filter>
+ </service>
+
<service android:name="android.telecom.cts.MockInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
index 53a36c9..060afe9 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
@@ -25,7 +25,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -33,13 +32,14 @@
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
-
import android.telecom.Call;
import android.telecom.PhoneAccount;
+import android.telecom.TelecomManager;
import android.telecom.cts.redirectiontestapp.CtsCallRedirectionService;
import android.telecom.cts.redirectiontestapp.CtsCallRedirectionServiceController;
import android.telecom.cts.redirectiontestapp.ICtsCallRedirectionServiceController;
import android.text.TextUtils;
+import android.util.Log;
import com.android.compatibility.common.util.CddTest;
@@ -91,7 +91,7 @@
NewOutgoingCallBroadcastReceiver.reset();
mHandler = new Handler(Looper.getMainLooper());
mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
- setupControlBinder();
+ setupControlBinder(null, null);
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
rememberPreviousCallRedirectionApp();
// Ensure CTS app holds the call redirection role.
@@ -230,16 +230,46 @@
assertFalse(mCallRedirectionServiceController.waitForOnPlaceCallInvoked());
}
+ public void testServiceUnbindOnNullBinding()
+ throws Exception {
+ if (!shouldTestTelecom(mContext)) {
+ return;
+ }
+ // Set up control binder using NullBindingCallRedirectionServiceController.
+ // This will invoke onNullBinding.
+ setupControlBinder(NullBindingCallRedirectionServiceController.CONTROL_INTERFACE_ACTION,
+ NullBindingCallRedirectionServiceController.CONTROL_INTERFACE_COMPONENT);
+ Bundle extras = new Bundle();
+ extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
+ TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
+ mTelecomManager.placeCall(createTestNumber(), extras);
+ TestUtils.waitOnLocalMainLooper(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ TestUtils.waitOnAllHandlers(getInstrumentation());
+ // Assert bind and unbind latch countdown
+ assertTrue(TestUtils.waitForLatchCountDown(
+ NullBindingCallRedirectionServiceController.sBindLatch));
+ assertTrue(TestUtils.waitForLatchCountDown(
+ NullBindingCallRedirectionServiceController.sUnbindLatch));
+ }
+
/**
* Sets up a binder used to control the CallRedirectionServiceCtsTestApp.
* This app is a standalone APK so that it can reside in a package name outside of the one the
* CTS test itself runs in.
* @throws InterruptedException
*/
- private void setupControlBinder() throws InterruptedException {
- Intent bindIntent = new Intent(
- CtsCallRedirectionServiceController.CONTROL_INTERFACE_ACTION);
- bindIntent.setComponent(CtsCallRedirectionServiceController.CONTROL_INTERFACE_COMPONENT);
+ private void setupControlBinder(String interfaceAction,
+ ComponentName interfaceComponentName) throws InterruptedException {
+ if (interfaceAction == null) {
+ interfaceAction = CtsCallRedirectionServiceController.CONTROL_INTERFACE_ACTION;
+ }
+ if (interfaceComponentName == null) {
+ interfaceComponentName =
+ CtsCallRedirectionServiceController.CONTROL_INTERFACE_COMPONENT;
+ }
+
+ Intent bindIntent = new Intent(interfaceAction);
+ bindIntent.setComponent(interfaceComponentName);
final CountDownLatch bindLatch = new CountDownLatch(1);
boolean success = mContext.bindService(bindIntent, new ServiceConnection() {
@@ -253,6 +283,15 @@
public void onServiceDisconnected(ComponentName name) {
mCallRedirectionServiceController = null;
}
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ // This path will only be hit if NullBindingCallRedirectionServiceController is set
+ // as the controller.
+ Log.i(TAG, "onNullBinding: null binding received from onBind");
+ bindLatch.countDown();
+ mContext.unbindService(this);
+ }
}, Context.BIND_AUTO_CREATE);
if (!success) {
fail("Failed to get control interface -- bind error");
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingCallRedirectionServiceController.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallRedirectionServiceController.java
new file mode 100644
index 0000000..2ffc6d6
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallRedirectionServiceController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.telecom.cts;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+public class NullBindingCallRedirectionServiceController extends Service {
+ private static final String TAG = NullBindingCallRedirectionServiceController.class
+ .getSimpleName();
+ public static final String CONTROL_INTERFACE_ACTION =
+ "android.telecom.cts.ACTION_CONTROL_CALL_REDIRECTION_SERVICE";
+ public static final ComponentName CONTROL_INTERFACE_COMPONENT =
+ ComponentName.unflattenFromString(
+ "android.telecom.cts/.NullBindingCallRedirectionServiceController");
+
+ public static CountDownLatch sBindLatch = new CountDownLatch(1);
+ public static CountDownLatch sUnbindLatch = new CountDownLatch(1);
+
+ private static NullBindingCallRedirectionServiceController
+ sCallRedirectionServiceController = null;
+
+
+ public static NullBindingCallRedirectionServiceController getInstance() {
+ return sCallRedirectionServiceController;
+ }
+
+ public static void resetBindLatches() {
+ sBindLatch = new CountDownLatch(1);
+ sUnbindLatch = new CountDownLatch(1);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind: returning null binding");
+ sCallRedirectionServiceController = this;
+ // Treat case as null binding from onBind. This should hit onNullBinding.
+ sUnbindLatch = new CountDownLatch(1);
+ sBindLatch.countDown();
+ return null;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ Log.i(TAG, "onUnbind: unbinding service");
+ sCallRedirectionServiceController = null;
+ sUnbindLatch.countDown();
+ return false;
+ }
+}
+
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index ba1205e..f58fe04 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -214,7 +214,7 @@
android:label="PixelCopyViewProducerDialogActivity"
android:screenOrientation="portrait"
android:rotationAnimation="jumpcut"
- android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
+ android:theme="@style/PixelCopyViewProducerDialogActivityTheme"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"/>
<activity android:name="android.view.cts.FocusFinderCtsActivity"
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
index bb513bfc..34df7cc 100644
--- a/tests/tests/view/res/values/styles.xml
+++ b/tests/tests/view/res/values/styles.xml
@@ -184,6 +184,10 @@
<item name="android:windowAnimationStyle">@null</item>
</style>
+ <style name="PixelCopyViewProducerDialogActivityTheme" parent="@android:style/Theme.Material.Dialog.NoActionBar">
+ <item name="android:windowLayoutInDisplayCutoutMode">default</item>
+ </style>
+
<style name="ViewAttributeTestTheme" parent="@android:Theme.Material"/>
<style name="ExplicitStyle1" parent="@style/ParentOfExplicitStyle1">
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
index c89cdb8..9cff62b 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
@@ -72,6 +72,9 @@
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
mContent.getViewTreeObserver().addOnDrawListener(this);
mContent.setOnApplyWindowInsetsListener(this);
+
+ //setDecorFitsSystemWindows to false will ignore the cutout
+ getWindow().setDecorFitsSystemWindows(false);
}
@Override
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index d1e388b..08c2231 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
@@ -97,6 +97,7 @@
decorView.setPointerIcon(
PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getWindow().setDecorFitsSystemWindows(false);
mLayoutParams = new FrameLayout.LayoutParams(DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
Gravity.LEFT | Gravity.TOP);
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 39e5c1f..0eadc06 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -23,6 +23,10 @@
<option name="compatibility:exclude-filter" value="CtsLocationTestCases android.location.cts.GnssTtffTests#testTtffWithNetwork" />
<option name="compatibility:exclude-filter" value="CtsLocationTestCases[instant] android.location.cts.GnssTtffTests#testTtffWithNetwork" />
+ <!-- b/17989532 -->
+ <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance" />
+ <option name="compatibility:exclude-filter" value="CtsCameraTestCases[instant] android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance" />
+
<!-- b/23776893 -->
<option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testBatterystatsOutput" />
<option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testGfxinfoFramestats" />
@@ -319,4 +323,7 @@
<option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode" />
<option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode_withParams" />
<option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStateStandardMode" />
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases[instant] android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode" />
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases[instant] android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode_withParams" />
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases[instant] android.gamemanager.cts.GameManagerTest#testSetGameStateStandardMode" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-system.xml b/tools/cts-tradefed/res/config/cts-system.xml
index 530fe79..c830701 100644
--- a/tools/cts-tradefed/res/config/cts-system.xml
+++ b/tools/cts-tradefed/res/config/cts-system.xml
@@ -15,11 +15,12 @@
-->
<configuration description="Runs a subset of CTS tests when vendor image is not changed">
- <option name="plan" value="cts-system" />
- <option name="result-attribute" key="system" value="1" />
<include name="cts" />
+ <option name="plan" value="cts-system" />
+ <option name="result-attribute" key="system" value="1" />
+
<!-- dEQP tests to be included in this plan-->
<option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-EGL.*" />
<option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.wsi.*" />