diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-05 13:53:16 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-05 13:53:16 +0000 |
commit | af9ffd533c5654ac08697335f126918812e33d07 (patch) | |
tree | b0da53849534f7db7f652422f3db5319ad93b3e3 | |
parent | 5fb8b9d5031f4f76b45c9133c65f654c6dcff666 (diff) | |
parent | 901943e3ce4df6147ac637d37a8307622c09b0f8 (diff) | |
download | cts-android13-mainline-adservices-release.tar.gz |
Snap for 9887711 from 901943e3ce4df6147ac637d37a8307622c09b0f8 to mainline-adservices-releaseaml_ads_331814200android13-mainline-adservices-release
Change-Id: If79e31f251a75326e72a75b9a9db8692ae05b601
48 files changed, 1073 insertions, 2370 deletions
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml index af32358ebac..cd52317a4c8 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 3ca4ee0e277..bf7f9854565 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.Test; 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 @@ public final class HdmiCecPowerStatusTest extends BaseHdmiCecCtsTest { // 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 @@ public final class HdmiCecPowerStatusTest extends BaseHdmiCecCtsTest { 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/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 00000000000..96f2257ed15 --- /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-2023-20955/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20955/Android.bp new file mode 100644 index 00000000000..e856574ef9c --- /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 00000000000..2d74f5492fc --- /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 00000000000..194436bd2b9 --- /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 00000000000..ed5352d7c0f --- /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 00000000000..8b769040010 --- /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 00000000000..7141a402e65 --- /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 00000000000..73420e4b366 --- /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 7cc15765747..d79668dc6f3 100644 --- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java +++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java @@ -947,6 +947,7 @@ public class JobThrottlingTest { 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 ee74c656271..d812c338a6a 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java @@ -18,6 +18,7 @@ package android.photopicker.cts; 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 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { 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 f0f582fcaca..cf65e3967dc 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 @@ import org.junit.Test; @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 845cb78cb9b..067cd7821d4 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java @@ -36,6 +36,8 @@ public class PhotoPickerBaseTest { 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 59b552cdddf..891917d3cc6 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java @@ -45,7 +45,8 @@ import java.util.List; 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 @@ public class PhotoPickerCloudUtils { assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained)); } + public static boolean isCloudMediaEnabled() { + return Boolean.parseBoolean(readDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED)); + } + @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, - ALLOWED_CLOUD_PROVIDERS_KEY); + return DeviceConfig.getProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name); } finally { getUiAutomation().dropShellPermissionIdentity(); } } - static void setAllowedProvidersDeviceConfig(@Nullable String allowedCloudProviders) { + 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 { - 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); - } + DeviceConfig.setProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name, value, + /* makeDefault*/ false); } finally { getUiAutomation().dropShellPermissionIdentity(); } } - @NonNull - private static UiAutomation getUiAutomation() { - return InstrumentationRegistry.getInstrumentation().getUiAutomation(); + 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 d8cc456fe32..70e050212db 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 @@ import org.junit.Test; @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 5110781914f..216b5de1d1f 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java @@ -432,8 +432,7 @@ public class PickerProviderMediaGenerator { } 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 0c19f5c51dc..382be794d84 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 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest { 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 00000000000..a50549c55ed --- /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 52fb4c37e7f..655494f4fb8 100644 --- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java +++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java @@ -910,7 +910,8 @@ public class AccessibilityEndToEndTest extends StsExtraBusinessLogicTestCase { 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 @@ public class AccessibilityEndToEndTest extends StsExtraBusinessLogicTestCase { 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 0e16b790e8c..7f2b95d48d3 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 @@ public class AccessibilityEndToEndActivity extends AccessibilityTestActivity { 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 f7e1761c432..9418ce2a382 100755 --- a/tests/app/src/android/app/cts/NotificationManagerTest.java +++ b/tests/app/src/android/app/cts/NotificationManagerTest.java @@ -3652,6 +3652,56 @@ public class NotificationManagerTest extends BaseNotificationManagerTest { .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/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java index 28bb02ebba7..6090cdce8b1 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; 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 @@ public class ImageReaderTest extends Camera2AndroidTestCase { 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 7e51289f1d1..3fbf06a6e3f 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 @@ public class StaticMetadataTest extends Camera2AndroidTestCase { " 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 55eae8c3585..81173bbe767 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { () -> 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 @@ public class KeepClearRectsTests extends WindowManagerTestBase { mTestSession.runOnMainSyncAndWait(() -> { activity.addView(newView, params); }); + waitForIdle(); return newView; } @@ -607,7 +641,8 @@ public class KeepClearRectsTests extends WindowManagerTestBase { 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 e7d6650fa90..c5b520d6a02 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 @@ public class MultiDisplayPolicyTests extends MultiDisplayTestBase { 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 e6e1e81acaf..06ca39f12dc 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 @@ public class MultiWindowTests extends ActivityManagerTestBase { 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 1a452c05b4d..7b927873b5d 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_PORTRAIT; 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.WindowInsets; 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 @@ import org.junit.runners.Parameterized; @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 @@ public class RoundedCornerTests extends ActivityManagerTestBase { @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 @@ public class RoundedCornerTests extends ActivityManagerTestBase { getWindowManager().addView(mChildWindowRoot, attrs); } - View getChildWindowRoot() { - return mChildWindowRoot; + void removeChildWindow() { + if (mChildWindowRoot != null) { + getWindowManager().removeViewImmediate(mChildWindowRoot); + } } WindowInsets getDispatchedInsets() { @@ -202,7 +258,7 @@ public class RoundedCornerTests extends ActivityManagerTestBase { 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 59a1a2bcccd..198e4b344c5 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 @@ public class SnapshotTaskTests extends ActivityManagerTestBase { @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 @@ public class SnapshotTaskTests extends ActivityManagerTestBase { 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 bf2e941bfa5..56dd1b0f561 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 android.util.Log; 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.ArrayList; 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.Mac; 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { sig.update(message); assertTrue(sig.verify(signature)); } finally { - mKeyStore.deleteEntry(entryName1); - deleteEntryIfNotNull(entryName2); - deleteManyTestKeys(keyCount, aliasPrefix); + deleteManyTestKeys(keyCount, ALIAS_PREFIX); } } @@ -2250,9 +2235,8 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { sig.update(message); assertTrue(sig.verify(signature)); } finally { - mKeyStore.deleteEntry(entryName1); - deleteEntryIfNotNull(entryName2); - deleteManyTestKeys(keyCount, aliasPrefix); + deleteManyTestKeys(keyCount, ALIAS_PREFIX); } } @@ -2325,9 +2307,8 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { .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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { .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 @@ public class AndroidKeyStoreTest { "59b57e77e4e2cb36b5c7b84af198ac004327bc549de6931a1b5505372dd8c957"), mac.doFinal(message)); } finally { - mKeyStore.deleteEntry(entryName1); - deleteEntryIfNotNull(entryName2); - deleteManyTestKeys(keyCount, aliasPrefix); + deleteManyTestKeys(keyCount, ALIAS_PREFIX); } } @@ -2630,8 +2606,8 @@ public class AndroidKeyStoreTest { * * 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { 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 @@ public class AndroidKeyStoreTest { } 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 ffc2dcffac0..9fc07d36989 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 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase2<MediaStu 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 af5f908cf97..00000000000 --- 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 08488bc3d72..00000000000 --- 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 637380313a2..576df286de4 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 @@ public class PermissionPolicyTest { } 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 2a9f815aec5..e10131c3f66 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_CONTACTS 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 @@ class RuntimePermissionProperties { // 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/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt index 0b88e01f772..7499e0f2c04 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 @@ class SensorBlockedBannerTest : BaseUsePermissionTest() { @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 56d02d21ee3..989edcac454 100644 --- a/tests/tests/security/Android.bp +++ b/tests/tests/security/Android.bp @@ -104,6 +104,8 @@ android_test_helper_app { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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_app_certificate { 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 5487fb43bde..4e43d570881 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 00000000000..8c1863cffd7 --- /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 00000000000..5ef6ceba4f2 --- /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 00000000000..00c0e6dabd1 --- /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 314f29df0f9..2d640e18760 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.assertEquals; 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 @@ public class CtsSharesheetDeviceTest { */ @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 @@ public class CtsSharesheetDeviceTest { @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/src/android/telecom/cts/CallRedirectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java index 359d363a158..060afe9e305 100644 --- a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java +++ b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java @@ -243,6 +243,8 @@ public class CallRedirectionServiceTest extends BaseTelecomTestWithMockServices 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)); diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml index ba1205e5306..f58fe04bd1b 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 bb513bfc73a..34df7cce0df 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/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java index d1e388b0def..08c2231673a 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 @@ public class ASurfaceControlTestActivity extends Activity { 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 39e5c1f7bcd..0eadc06a8f6 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 530fe79beb6..c8307012f89 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.*" /> |