summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hostsidetests/scopedstorage/AndroidTest.xml6
-rw-r--r--hostsidetests/scopedstorage/CoreTest.xml6
-rw-r--r--hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java6
-rw-r--r--hostsidetests/scopedstorage/device/AndroidTest.xml5
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java59
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java54
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java20
-rw-r--r--hostsidetests/scopedstorage/legacy/AndroidManifest.xml1
-rw-r--r--hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java80
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java118
-rw-r--r--hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java29
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java42
-rw-r--r--tests/MediaProviderTranscode/AndroidTest.xml5
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java9
-rw-r--r--tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java25
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTest.java25
-rw-r--r--tests/media/src/android/mediav2/cts/CodecEncoderTest.java6
-rw-r--r--tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java24
-rw-r--r--tests/tests/appop/Android.bp2
-rw-r--r--tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt (renamed from tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt)55
-rw-r--r--tests/tests/libcoreapievolution/Android.bp2
-rw-r--r--tests/tests/libcorefileio/Android.bp2
-rw-r--r--tests/tests/libcorelegacy22/Android.bp2
-rw-r--r--tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java2
-rw-r--r--tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java37
-rw-r--r--tests/tests/os/src/android/os/cts/StrictModeTest.java58
-rw-r--r--tests/tests/permission2/res/raw/android_manifest.xml4
-rw-r--r--tests/tests/role/Android.bp1
-rw-r--r--tests/tests/role/CtsRoleTestApp/AndroidManifest.xml1
-rw-r--r--tests/tests/role/src/android/app/role/cts/RoleManagerTest.java46
-rw-r--r--tests/tests/security/Android.bp8
-rw-r--r--tests/tests/security/AndroidManifest.xml1
-rw-r--r--tests/tests/security/AndroidTest.xml9
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0922.java70
-rw-r--r--tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt153
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java2
-rw-r--r--tests/tests/security/testdata/rolepermissionoverridetestapp.xml26
37 files changed, 895 insertions, 106 deletions
diff --git a/hostsidetests/scopedstorage/AndroidTest.xml b/hostsidetests/scopedstorage/AndroidTest.xml
index 42a3a362933..320d5417f17 100644
--- a/hostsidetests/scopedstorage/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/AndroidTest.xml
@@ -28,6 +28,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
<option name="test-file-name" value="CtsLegacyStorageTestAppRequestLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.LegacyStorageHostTest" />
<option name="class" value="android.scopedstorage.cts.host.PreserveLegacyStorageHostTest" />
diff --git a/hostsidetests/scopedstorage/CoreTest.xml b/hostsidetests/scopedstorage/CoreTest.xml
index 5b725e1a853..325807d45c3 100644
--- a/hostsidetests/scopedstorage/CoreTest.xml
+++ b/hostsidetests/scopedstorage/CoreTest.xml
@@ -27,6 +27,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppB.apk" />
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.ScopedStorageCoreHostTest" />
</test>
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index a93aeee3c98..ee63a8abf13 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -24,6 +24,7 @@ import static android.scopedstorage.cts.lib.TestUtils.CHECK_DATABASE_ROW_EXISTS_
import static android.scopedstorage.cts.lib.TestUtils.CREATE_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.CREATE_IMAGE_ENTRY_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.DELETE_FILE_QUERY;
+import static android.scopedstorage.cts.lib.TestUtils.DELETE_RECURSIVE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXCEPTION;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_CALLING_PKG;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_PATH;
@@ -40,6 +41,7 @@ import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_PARAMS_SEPARAT
import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.SETATTR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
@@ -93,6 +95,7 @@ public class ScopedStorageTestHelper extends Activity {
case CAN_READ_WRITE_QUERY:
case CREATE_FILE_QUERY:
case DELETE_FILE_QUERY:
+ case DELETE_RECURSIVE_QUERY:
case CAN_OPEN_FILE_FOR_READ_QUERY:
case CAN_OPEN_FILE_FOR_WRITE_QUERY:
case OPEN_FILE_FOR_READ_QUERY:
@@ -263,6 +266,9 @@ public class ScopedStorageTestHelper extends Activity {
case DELETE_FILE_QUERY:
intent.putExtra(queryType, file.delete());
return intent;
+ case DELETE_RECURSIVE_QUERY:
+ intent.putExtra(queryType, deleteRecursively(file));
+ return intent;
case SETATTR_QUERY:
int newTimeMillis = 12345000;
intent.putExtra(queryType, file.setLastModified(newTimeMillis));
diff --git a/hostsidetests/scopedstorage/device/AndroidTest.xml b/hostsidetests/scopedstorage/device/AndroidTest.xml
index 7e6f8953ed5..5730b2e2826 100644
--- a/hostsidetests/scopedstorage/device/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/device/AndroidTest.xml
@@ -23,6 +23,11 @@
<option name="test-file-name" value="CtsScopedStorageTestAppFileManager.apk" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 3c860132c50..382f74551f6 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -29,8 +29,10 @@ import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
@@ -43,6 +45,7 @@ import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursivelyAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
@@ -208,7 +211,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
"CtsScopedStorageTestAppFileManager.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
// The following apps are not installed at test startup - please install before using.
private static final TestApp APP_C = new TestApp("TestAppC",
@@ -1159,7 +1162,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
try {
// Delete the directory if it already exists
if (podcastsDir.exists()) {
- deleteAsLegacyApp(podcastsDir);
+ deleteRecursivelyAsLegacyApp(podcastsDir);
}
assertThat(podcastsDir.exists()).isFalse();
assertThat(podcastsDirLowerCase.exists()).isFalse();
@@ -2786,18 +2789,57 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ /**
+ * Tests that System Gallery apps cannot insert files in other app's private directories.
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * Tests that System Gallery apps cannot update files in other app's private directories.
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testInsertFromExternalDirsViaRelativePath() throws Exception {
verifyInsertFromExternalMediaDirViaRelativePath_allowed();
verifyInsertFromExternalPrivateDirViaRelativePath_denied();
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testUpdateToExternalDirsViaRelativePath() throws Exception {
verifyUpdateToExternalMediaDirViaRelativePath_allowed();
verifyUpdateToExternalPrivateDirsViaRelativePath_denied();
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testInsertFromExternalDirsViaRelativePathAsSystemGallery() throws Exception {
int uid = Process.myUid();
@@ -2810,6 +2852,9 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testUpdateToExternalDirsViaRelativePathAsSystemGallery() throws Exception {
int uid = Process.myUid();
@@ -3336,4 +3381,14 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
Log.d(TAG, "Deleting file " + file);
deleteFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath());
}
+
+ /**
+ * Deletes the given file/directory recursively. If the file is a directory, then deletes all
+ * of its children (files or directories) recursively.
+ */
+ private void deleteRecursivelyAsLegacyApp(File dir) throws Exception {
+ // Use a legacy app to delete this directory, since it could be outside shared storage.
+ Log.d(TAG, "Deleting directory " + dir);
+ deleteRecursivelyAs(APP_D_LEGACY_HAS_RW, dir.getAbsolutePath());
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
index 75c3f0dd79f..5638e41c0de 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -111,6 +111,46 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
}
@Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasRW");
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasRW");
+ }
+
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasMES");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasMES");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery");
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery");
+ }
+
+ @Test
public void testMkdirInRandomPlaces_hasW() throws Exception {
revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
executeShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
@@ -263,4 +303,18 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
public void testUpdateToExternalDirsViaRelativePath() throws Exception {
runDeviceTest("testUpdateToExternalDirsViaRelativePath");
}
+
+ private void allowAppOps(String... ops) throws Exception {
+ for (String op : ops) {
+ executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
+ + op + " allow");
+ }
+ }
+
+ private void denyAppOps(String... ops) throws Exception {
+ for (String op : ops) {
+ executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
+ + op + " deny");
+ }
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index d31bc33dfa9..cd9378d3047 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -125,6 +125,26 @@ public class ScopedStorageHostTest extends BaseHostTestCase {
}
@Test
+ public void testManageExternalStorageCantInsertFilesInOtherAppPrivateDir() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testManageExternalStorageCantInsertFilesInOtherAppPrivateDir");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
public void testCheckInstallerAppAccessToObbDirs() throws Exception {
allowAppOps("android:request_install_packages");
grantPermissions("android.permission.WRITE_EXTERNAL_STORAGE");
diff --git a/hostsidetests/scopedstorage/legacy/AndroidManifest.xml b/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
index c602f0ac9c0..c85b0903670 100644
--- a/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
+++ b/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application android:requestLegacyExternalStorage="true" >
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index 1c8b3f5ca89..e3b08bbb5e4 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -23,7 +23,9 @@ import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.canOpenFileAs;
@@ -47,8 +49,10 @@ import static android.scopedstorage.cts.lib.TestUtils.insertFile;
import static android.scopedstorage.cts.lib.TestUtils.insertFileFromExternalMedia;
import static android.scopedstorage.cts.lib.TestUtils.listAs;
import static android.scopedstorage.cts.lib.TestUtils.pollForExternalStorageState;
+import static android.scopedstorage.cts.lib.TestUtils.pollForManageExternalStorageAllowed;
import static android.scopedstorage.cts.lib.TestUtils.pollForPermission;
import static android.scopedstorage.cts.lib.TestUtils.resetDefaultExternalStorageVolume;
+import static android.scopedstorage.cts.lib.TestUtils.setAppOpsModeForUid;
import static android.scopedstorage.cts.lib.TestUtils.setupDefaultDirectories;
import static android.scopedstorage.cts.lib.TestUtils.trashFileAndAssert;
import static android.scopedstorage.cts.lib.TestUtils.untrashFileAndAssert;
@@ -997,6 +1001,82 @@ public class LegacyStorageTest {
}
/**
+ * Tests that legacy apps cannot insert in other app private directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /* granted */ true);
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /* granted */ true);
+
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps cannot update in other app private directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /* granted */ true);
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /* granted */ true);
+
+ TestUtils.assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps with MANAGE_EXTERNAL_STORAGE cannot insert in other app private
+ * directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps with MANAGE_EXTERNAL_STORAGE cannot update in other app private
+ * directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy System Gallery apps cannot insert in other app private directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * Tests that legacy System Gallery apps cannot update in other app private directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
* Make sure inserting files from app private directories in legacy apps is allowed via DATA.
*/
@Test
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 30683328b35..a04b86fed22 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -16,6 +16,7 @@
package android.scopedstorage.cts.lib;
+import static android.provider.MediaStore.VOLUME_EXTERNAL;
import static android.scopedstorage.cts.lib.RedactionTestHelper.EXIF_METADATA_QUERY;
import static androidx.test.InstrumentationRegistry.getContext;
@@ -98,6 +99,7 @@ public class TestUtils {
public static final String CREATE_IMAGE_ENTRY_QUERY =
"android.scopedstorage.cts.createimageentry";
public static final String DELETE_FILE_QUERY = "android.scopedstorage.cts.deletefile";
+ public static final String DELETE_RECURSIVE_QUERY = "android.scopedstorage.cts.deleteRecursive";
public static final String CAN_OPEN_FILE_FOR_READ_QUERY =
"android.scopedstorage.cts.can_openfile_read";
public static final String CAN_OPEN_FILE_FOR_WRITE_QUERY =
@@ -295,6 +297,17 @@ public class TestUtils {
}
/**
+ * Makes the given {@code testApp} delete a file or directory.
+ * If the file is a directory, then deletes all of its children (file or directories)
+ * recursively.
+ *
+ * <p>This method drops shell permission identity.
+ */
+ public static boolean deleteRecursivelyAs(TestApp testApp, String path) throws Exception {
+ return getResultFromTestApp(testApp, path, DELETE_RECURSIVE_QUERY);
+ }
+
+ /**
* Makes the given {@code testApp} delete a file. Doesn't throw in case of failure.
*/
public static boolean deleteFileAsNoThrow(TestApp testApp, String path) {
@@ -950,6 +963,111 @@ public class TestUtils {
}
/**
+ * Assert that app cannot insert files in other app's private directories
+ *
+ * @param fileName name of the file
+ * @param throwsExceptionForDataValue Apps like System Gallery for which Data column is not
+ * respected, will not throw an Exception as the Data value is ignored.
+ * @param otherApp Other test app in whose external private directory we will attempt to insert
+ * @param callingPackageName Calling package name
+ */
+ public static void assertCantInsertToOtherPrivateAppDirectories(String fileName,
+ boolean throwsExceptionForDataValue, TestApp otherApp, String callingPackageName)
+ throws Exception {
+ // Create directory in which the device test will try to insert file to
+ final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
+ callingPackageName, otherApp.getPackageName()));
+ final File file = new File(otherAppExternalDataDir, fileName);
+ try {
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+
+ final ContentValues valuesWithData = new ContentValues();
+ valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
+ try {
+ Uri uri = getContentResolver().insert(
+ MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithData);
+
+ if (throwsExceptionForDataValue) {
+ fail("File insert expected to fail: " + file);
+ } else {
+ try (Cursor c = getContentResolver().query(uri, new String[]{
+ MediaStore.MediaColumns.DATA}, null, null)) {
+ assertThat(c.moveToFirst()).isTrue();
+ assertThat(c.getString(0)).isNotEqualTo(file.getAbsolutePath());
+ }
+ }
+ } catch (IllegalArgumentException expected) {
+ }
+
+ final ContentValues valuesWithRelativePath = new ContentValues();
+ final String path = file.getAbsolutePath();
+ valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ path.substring(path.indexOf("Android")));
+ valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ try {
+ getContentResolver().insert(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithRelativePath);
+ fail("File insert expected to fail: " + file);
+ } catch (IllegalArgumentException expected) {
+ }
+ } finally {
+ deleteFileAsNoThrow(otherApp, file.getPath());
+ }
+ }
+
+ /**
+ * Assert that app cannot update files in other app's private directories
+ *
+ * @param fileName name of the file
+ * @param throwsExceptionForDataValue Apps like non-legacy System Gallery/MES for which
+ * Data column is not respected, will not throw an Exception as the Data value is ignored.
+ * @param otherApp Other test app in whose external private directory we will attempt to insert
+ * @param callingPackageName Calling package name
+ */
+ public static void assertCantUpdateToOtherPrivateAppDirectories(String fileName,
+ boolean throwsExceptionForDataValue, TestApp otherApp, String callingPackageName)
+ throws Exception {
+ // Create priv-app file and add to the database that we will try to update
+ final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
+ callingPackageName, otherApp.getPackageName()));
+ final File file = new File(otherAppExternalDataDir, fileName);
+ try {
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+ MediaStore.scanFile(getContentResolver(), file);
+
+ final ContentValues valuesWithData = new ContentValues();
+ valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
+ try {
+ int res = getContentResolver().update(
+ MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithData, Bundle.EMPTY);
+
+ if (throwsExceptionForDataValue) {
+ fail("File update expected to fail: " + file);
+ } else {
+ assertThat(res).isEqualTo(0);
+ }
+ } catch (IllegalArgumentException expected) {
+ }
+
+ final ContentValues valuesWithRelativePath = new ContentValues();
+ final String path = file.getAbsolutePath();
+ valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ path.substring(path.indexOf("Android")));
+ valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ try {
+ getContentResolver().update(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithRelativePath, Bundle.EMPTY);
+ fail("File update expected to fail: " + file);
+ } catch (IllegalArgumentException expected) {
+ }
+ } finally {
+ deleteFileAsNoThrow(otherApp, file.getPath());
+ }
+ }
+
+ /**
* Asserts can rename directory.
*/
public static void assertCanRenameDirectory(File oldDirectory, File newDirectory,
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 814f1a24654..ec4f4322ec0 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -21,6 +21,8 @@ import static android.scopedstorage.cts.lib.TestUtils.adoptShellPermissionIdenti
import static android.scopedstorage.cts.lib.TestUtils.assertCanAccessPrivateAppAndroidDataDir;
import static android.scopedstorage.cts.lib.TestUtils.assertCanAccessPrivateAppAndroidObbDir;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
@@ -142,7 +144,7 @@ public class ScopedStorageTest {
"CtsScopedStorageTestAppB.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
@Before
public void setup() throws Exception {
@@ -228,6 +230,28 @@ public class ScopedStorageTest {
});
}
+ /**
+ * Tests that apps with MANAGE_EXTERNAL_STORAGE permission cannot insert files in other app's
+ * private directories.
+ */
+ @Test
+ public void testManageExternalStorageCantInsertFilesInOtherAppPrivateDir() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that apps with MANAGE_EXTERNAL_STORAGE permission cannot update files in other app's
+ * private directories.
+ */
+ @Test
+ public void testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
@Test
public void testManageExternalStorageCanDeleteOtherAppsContents() throws Exception {
pollForManageExternalStorageAllowed();
@@ -305,7 +329,8 @@ public class ScopedStorageTest {
final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
THIS_PACKAGE_NAME, APP_B_NO_PERMS.getPackageName()));
final File otherAppExternalDataSubDir = new File(otherAppExternalDataDir, "subdir");
- final File otherAppExternalDataFile = new File(otherAppExternalDataSubDir, "abc.jpg");
+ final File otherAppExternalDataFile =
+ new File(otherAppExternalDataSubDir, IMAGE_FILE_NAME);
assertThat(createFileAs(APP_B_NO_PERMS, otherAppExternalDataFile.getAbsolutePath()))
.isTrue();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java
deleted file mode 100644
index d8f3ddfa1d3..00000000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import static org.junit.Assert.assertTrue;
-import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0922 extends SecurityTestCase {
-
- /**
- * b/195630721
- */
- @AsbSecurityTest(cveBugId = 195630721)
- @Test
- public void testPocCVE_2021_0922() throws Exception {
- String packageName = "com.android.managedprovisioning";
- String queryStr = "dumpsys package " + packageName;
- String permissions = AdbUtils.runCommandLine(queryStr, getDevice());
-
- // MANAGE_APP_OPS_MODES permission must be enforced for
- // package com.android.managedprovisioning
- assertTrue(permissions.contains("android.permission.MANAGE_APP_OPS_MODES"));
- }
-}
diff --git a/tests/MediaProviderTranscode/AndroidTest.xml b/tests/MediaProviderTranscode/AndroidTest.xml
index 8dba7414c5c..7dc78ebcd2f 100644
--- a/tests/MediaProviderTranscode/AndroidTest.xml
+++ b/tests/MediaProviderTranscode/AndroidTest.xml
@@ -19,6 +19,11 @@
<option name="install-arg" value="-g" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="cts" />
<option name="test-tag" value="MediaProviderTranscodeTests" />
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index e218d4d0aec..9b5904cefde 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -214,16 +214,17 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_longPress() throws Exception {
- final int imageCount = 3;
- createImages(imageCount, mContext.getUserId(), mUriList);
+ final int videoCount = 3;
+ createVideos(videoCount, mContext.getUserId(), mUriList);
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
// TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.setType("video/*");
mActivity.startActivityForResult(intent, REQUEST_CODE);
- final List<UiObject> itemList = findItemList(imageCount);
+ final List<UiObject> itemList = findItemList(videoCount);
final int itemCount = itemList.size();
- assertThat(itemCount).isEqualTo(imageCount);
+ assertThat(itemCount).isEqualTo(videoCount);
// Select one item from Photo grid
itemList.get(0).click();
diff --git a/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java b/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
index 8b7d348d8e6..1df830d8ff5 100644
--- a/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
+++ b/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
@@ -15,6 +15,8 @@
*/
package android.app.cts;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
@@ -32,6 +34,7 @@ import android.os.FileUtils;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,6 +102,28 @@ public class DownloadManagerApi28Test extends DownloadManagerTestBase {
}
@Test
+ public void testSetDestinationUri_privateAppDir() throws Exception {
+ // Make sure the private app directory exists
+ runShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
+ final File path = new File("/sdcard/Android/data/com.android.shell/"
+ + TAG + System.currentTimeMillis());
+
+ final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
+ try {
+ IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ mContext.registerReceiver(receiver, intentFilter);
+
+ DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
+ requestPublic.setDestinationUri(Uri.fromFile(path));
+ mDownloadManager.enqueue(requestPublic);
+ Assert.fail("Cannot download files into other app's private directories");
+ } catch (SecurityException expected) {
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ @Test
public void testDestinationInExternalPublicDir() throws Exception {
File publicLocation = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 21206871850..ae40d8989c8 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -19,6 +19,8 @@ import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -56,6 +58,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.CddTest;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -322,6 +325,28 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
}
@Test
+ public void testSetDestinationUri_privateAppDir() throws Exception {
+ // Make sure the private app directory exists
+ runShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
+ final File path = new File("/sdcard/Android/data/com.android.shell/"
+ + TAG + System.currentTimeMillis());
+
+ final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
+ try {
+ IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ mContext.registerReceiver(receiver, intentFilter);
+
+ DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
+ requestPublic.setDestinationUri(Uri.fromFile(path));
+ mDownloadManager.enqueue(requestPublic);
+ Assert.fail("Cannot download files into other app's private directories");
+ } catch (SecurityException expected) {
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ @Test
public void testSetDestinationUri_invalidRequests() throws Exception {
final File documentsFile = new File(
Environment.getExternalStoragePublicDirectory("TestDir"),
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index 832127d29b3..457ebf71b69 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -706,7 +706,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
private native boolean nativeTestSetForceSyncFrame(String encoder, String file, String mime,
int[] list0, int[] list1, int[] list2, int colorFormat);
- @Ignore("TODO(b/) = test sometimes timesout")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testSetForceSyncFrameNative() throws IOException {
@@ -742,8 +741,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
mOutputBuff = new OutputManager();
mSaveToMem = true;
{
- /* TODO(b/147574800) */
- if (mCodecName.equals("c2.android.hevc.encoder")) return;
mCodec = MediaCodec.createByCodecName(mCodecName);
format.removeKey(MediaFormat.KEY_BITRATE_MODE);
MediaCodecInfo.EncoderCapabilities cap =
@@ -803,7 +800,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
private native boolean nativeTestAdaptiveBitRate(String encoder, String file, String mime,
int[] list0, int[] list1, int[] list2, int colorFormat);
- @Ignore("TODO(b/) = test sometimes timesout")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testAdaptiveBitRateNative() throws IOException {
@@ -811,8 +807,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
mAdaptiveBitrateMimeList.contains(mMime));
int colorFormat = -1;
{
- /* TODO(b/147574800) */
- if (mCodecName.equals("c2.android.hevc.encoder")) return;
if (!mIsAudio) {
colorFormat = findByteBufferColorFormat(mCodecName, mMime);
assertTrue("no valid color formats received", colorFormat != -1);
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index a20a8f9ee00..c56103cc4bd 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -259,6 +259,19 @@ public class UsageStatsTest {
@AppModeFull(reason = "No usage events access in instant apps")
@Test
+ public void testLastTimeVisible_launchActivityShouldBeDetected() throws Exception {
+ mUiDevice.wakeUp();
+ dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+ final long startTime = System.currentTimeMillis();
+ launchSubActivity(Activities.ActivityOne.class);
+ final long endTime = System.currentTimeMillis();
+
+ verifyLastTimeVisibleWithinRange(startTime, endTime, mTargetPackage);
+ }
+
+ @AppModeFull(reason = "No usage events access in instant apps")
+ @Test
public void testLastTimeAnyComponentUsed_launchActivityShouldBeDetected() throws Exception {
mUiDevice.wakeUp();
dismissKeyguard(); // also want to start out with the keyguard dismissed.
@@ -311,6 +324,17 @@ public class UsageStatsTest {
verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
}
+ private void verifyLastTimeVisibleWithinRange(
+ long startTime, long endTime, String targetPackage) {
+ final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
+ startTime, endTime);
+ final UsageStats stats = map.get(targetPackage);
+ assertNotNull(stats);
+ final long lastTimeVisible = stats.getLastTimeVisible();
+ assertLessThanOrEqual(startTime, lastTimeVisible);
+ assertLessThanOrEqual(lastTimeVisible, endTime);
+ }
+
private void verifyLastTimeAnyComponentUsedWithinRange(
long startTime, long endTime, String targetPackage) {
final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
diff --git a/tests/tests/appop/Android.bp b/tests/tests/appop/Android.bp
index 33e53a58ee2..bd34b7d01f0 100644
--- a/tests/tests/appop/Android.bp
+++ b/tests/tests/appop/Android.bp
@@ -82,7 +82,7 @@ android_test {
"libbacktrace",
"libbase",
"libbinder",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"libc++",
"libcgrouprc",
diff --git a/tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt b/tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt
index fc635f2871d..d6e9f126272 100644
--- a/tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt
@@ -33,7 +33,9 @@ import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.ServiceConnection
import android.os.IBinder
+import android.os.Process
import android.platform.test.annotations.AppModeFull
+import android.platform.test.annotations.AsbSecurityTest
import android.provider.Settings
import android.provider.Settings.Global.APP_OPS_CONSTANTS
import android.support.test.uiautomator.UiDevice
@@ -47,12 +49,14 @@ import org.junit.Before
import org.junit.Test
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit.MILLISECONDS
+import java.util.concurrent.TimeoutException
private const val TEST_SERVICE_PKG = "android.app.appops.cts.appthatcanbeforcedintoforegroundstates"
private const val TIMEOUT_MILLIS = 45000L
+private const val EXPECTED_TIMEOUT_MILLIS = 5000L
@AppModeFull(reason = "This test connects to other test app")
-class ForegroundModeTest {
+class ForegroundModeAndActiveTest {
private var previousAppOpsConstants: String? = null
private val instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -361,6 +365,55 @@ class ForegroundModeTest {
gotCallback.get(TIMEOUT_MILLIS, MILLISECONDS)
}
+ @Test
+ @AsbSecurityTest(cveBugId = [208662370])
+ fun activeNotChangedAfterMultipleStartsUidModeChangeAndOneStop() {
+ val finishCallback = CompletableFuture<Unit>()
+ val startCallback = CompletableFuture<Unit>()
+ runWithShellPermissionIdentity {
+ appopsManager.startWatchingActive(arrayOf(OPSTR_FINE_LOCATION), context.mainExecutor) {
+ op, uid, pkgName, active ->
+ if (pkgName == context.packageName) {
+ if (active) {
+ startCallback.complete(Unit)
+ } else {
+ finishCallback.complete(Unit)
+ }
+ }
+ }
+ }
+
+ // Start three times
+ val numStarts = 3
+ for (i in 1..numStarts) {
+ appopsManager.startOp(OPSTR_FINE_LOCATION, Process.myUid(), context.packageName, null,
+ null)
+ }
+
+ // Wait for start
+ startCallback.get(TIMEOUT_MILLIS, MILLISECONDS)
+ withTopActivity {
+ // After moving to foreground, finish three times. We expect no callback until the third
+ for (i in 1..numStarts) {
+ context.getSystemService(AppOpsManager::class.java)!!.finishOp(OPSTR_FINE_LOCATION,
+ Process.myUid(), context.packageName, null)
+ val exception = try {
+ finishCallback.get(EXPECTED_TIMEOUT_MILLIS, MILLISECONDS)
+ null
+ } catch (e: TimeoutException) {
+ e
+ }
+ if (i < numStarts) {
+ Assert.assertNotNull("Got an active=false callback, but did not expect to",
+ exception)
+ } else {
+ Assert.assertNull("Expected to get an active=false callback after 3 stops",
+ exception)
+ }
+ }
+ }
+ }
+
@After
fun cleanup() {
foregroundControlService.cleanup()
diff --git a/tests/tests/libcoreapievolution/Android.bp b/tests/tests/libcoreapievolution/Android.bp
index 891ebc331ef..eed4fc3d022 100644
--- a/tests/tests/libcoreapievolution/Android.bp
+++ b/tests/tests/libcoreapievolution/Android.bp
@@ -30,6 +30,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/libcorefileio/Android.bp b/tests/tests/libcorefileio/Android.bp
index 58c388c4314..3febb32d74f 100644
--- a/tests/tests/libcorefileio/Android.bp
+++ b/tests/tests/libcorefileio/Android.bp
@@ -30,6 +30,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/libcorelegacy22/Android.bp b/tests/tests/libcorelegacy22/Android.bp
index 44a997a7e10..98684b26a93 100644
--- a/tests/tests/libcorelegacy22/Android.bp
+++ b/tests/tests/libcorelegacy22/Android.bp
@@ -26,6 +26,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
index d5d01c8f8bf..0df3b1bf447 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -162,6 +162,8 @@ abstract class MediaPlayerStressTest extends InstrumentationTestCase {
}
}
+ Preconditions.assertTestFileExists(mediaName);
+
File playbackOutput = new File(WorkDir.getTopDir(), "PlaybackTestResult.txt");
Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java b/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java
new file mode 100644
index 00000000000..6fc2b8af79d
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.mediastress.cts;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+/**
+ * Static methods used to validate preconditions in the media CTS suite
+ * to simplify failure diagnosis.
+ */
+
+public final class Preconditions {
+ private static final String TAG = "Preconditions";
+
+ public static void assertTestFileExists(String pathName) {
+ File testFile = new File(pathName);
+ Assert.assertTrue("Test Setup Error, missing file: " + pathName, testFile.exists());
+ }
+
+ private Preconditions() {}
+}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 0b5ed0d56f0..54caf6b47b8 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -77,6 +77,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -147,6 +148,63 @@ public class StrictModeTest {
}
@Test
+ public void testThreadBuilder_detectUnbufferedIo() throws Exception {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+ .penaltyLog()
+ .detectUnbufferedIo()
+ .build();
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(policy).build());
+
+ final File test = File.createTempFile("foo", "bar");
+ inspectViolation(
+ () -> {
+ writeUnbuffered(test);
+ },
+ info -> {
+ assertThat(info.getViolationDetails()).isNull();
+ assertThat(info.getStackTrace()).contains("UnbufferedIoViolation");
+ });
+ }
+
+ @Test
+ public void testThreadBuilder_permitUnbufferedIo() throws Exception {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+ .penaltyLog()
+ .permitUnbufferedIo()
+ .build();
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(policy).build());
+
+ final File test = File.createTempFile("foo", "bar");
+ inspectViolation(
+ () -> {
+ writeUnbuffered(test);
+ },
+ info -> {
+ assertThat(info).isNull();
+ });
+ }
+
+ private void writeUnbuffered(File file) throws Exception {
+ if (file.exists()) {
+ file.delete();
+ }
+
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ for (int i = 0; i < 11; i++) {
+ out.write(1);
+ out.write(2);
+ out.write(3);
+ out.write(4);
+ out.flush();
+ }
+ } finally {
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ }
+
+ @Test
public void testUnclosedCloseable() throws Exception {
//clean before test
System.gc();
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 5ff702fb325..84470cd870d 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -5638,6 +5638,10 @@
<!-- Allows input events to be monitored. Very dangerous! @hide -->
<permission android:name="android.permission.MONITOR_INPUT"
android:protectionLevel="signature|recents" />
+ <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
+ window to the window where the touch currently is on top of. @hide -->
+ <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
+ android:protectionLevel="signature|recents" />
<!-- Allows the caller to change the associations between input devices and displays.
Very dangerous! @hide -->
<permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
diff --git a/tests/tests/role/Android.bp b/tests/tests/role/Android.bp
index a98ea1fb756..a63856119a5 100644
--- a/tests/tests/role/Android.bp
+++ b/tests/tests/role/Android.bp
@@ -38,7 +38,6 @@ android_test {
"cts",
"general-tests",
"mts-permission",
- "sts",
],
data: [
diff --git a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
index 90d05f99357..eb171224235 100644
--- a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
+++ b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
@@ -20,7 +20,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.role.cts.app">
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application android:label="CtsRoleTestApp">
diff --git a/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java b/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
index b522f9550b9..766a92791d6 100644
--- a/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
+++ b/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
@@ -40,7 +40,6 @@ import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
-import android.platform.test.annotations.SecurityTest;
import android.provider.Settings;
import android.provider.Telephony;
import android.support.test.uiautomator.By;
@@ -115,9 +114,6 @@ public class RoleManagerTest {
private static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER =
"com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER";
- private static final String ROLE_SYSTEM_SPEECH_RECOGNIZER =
- "android.app.role.SYSTEM_SPEECH_RECOGNIZER";
-
private static final Instrumentation sInstrumentation =
InstrumentationRegistry.getInstrumentation();
private static final Context sContext = InstrumentationRegistry.getTargetContext();
@@ -138,7 +134,8 @@ public class RoleManagerTest {
@Before
public void saveRoleHolder() throws Exception {
- mRoleHolder = getRoleHolder(ROLE_NAME);
+ List<String> roleHolders = getRoleHolders(ROLE_NAME);
+ mRoleHolder = !roleHolders.isEmpty() ? roleHolders.get(0) : null;
if (Objects.equals(mRoleHolder, APP_PACKAGE_NAME)) {
removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
@@ -914,7 +911,7 @@ public class RoleManagerTest {
public void removeSmsRoleHolderThenPermissionIsRevoked() throws Exception {
assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
- String smsRoleHolder = getRoleHolder(RoleManager.ROLE_SMS);
+ String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
@@ -928,7 +925,7 @@ public class RoleManagerTest {
&& sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
addRoleHolder(RoleManager.ROLE_DIALER, APP_PACKAGE_NAME);
- String smsRoleHolder = getRoleHolder(RoleManager.ROLE_SMS);
+ String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
@@ -992,46 +989,11 @@ public class RoleManagerTest {
sRoleManager.isBypassingRoleQualification())).isFalse();
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
- @SecurityTest
- @Test
- public void systemRoleDoesNotOverrideUserRevokedPermission() throws Exception {
- assumeTrue(sRoleManager.isRoleAvailable(ROLE_SYSTEM_SPEECH_RECOGNIZER));
- String systemSpeechRecognizerPackageName = getRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER);
- if (systemSpeechRecognizerPackageName != null) {
- assertThat(sPackageManager.checkPermission(android.Manifest.permission.RECORD_AUDIO,
- systemSpeechRecognizerPackageName))
- .isEqualTo(PackageManager.PERMISSION_GRANTED);
- }
- assertThat(sPackageManager.checkPermission(android.Manifest.permission.RECORD_AUDIO,
- APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_DENIED);
-
- runWithShellPermissionIdentity(() -> sPackageManager.updatePermissionFlags(
- android.Manifest.permission.RECORD_AUDIO, APP_PACKAGE_NAME,
- PackageManager.FLAG_PERMISSION_USER_SET, PackageManager.FLAG_PERMISSION_USER_SET,
- Process.myUserHandle()));
- runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(true));
- try {
- addRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER, APP_PACKAGE_NAME);
-
- assertThat(sPackageManager.checkPermission(android.Manifest.permission.RECORD_AUDIO,
- APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_DENIED);
- } finally {
- runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(false));
- }
- }
-
@NonNull
private List<String> getRoleHolders(@NonNull String roleName) throws Exception {
return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));
}
- @Nullable
- private String getRoleHolder(@NonNull String roleName) throws Exception {
- List<String> roleHolders = getRoleHolders(roleName);
- return !roleHolders.isEmpty() ? roleHolders.get(0) : null;
- }
-
private void assertIsRoleHolder(@NonNull String roleName, @NonNull String packageName,
boolean shouldBeRoleHolder) throws Exception {
List<String> packageNames = getRoleHolders(roleName);
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 53d8f4ea4e5..5838d27729b 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -72,6 +72,9 @@ android_test {
"sts",
],
certificate: ":security_cts_test_certificate",
+ data: [
+ ":RolePermissionOverrideTestApp",
+ ],
}
android_test_helper_app {
@@ -84,3 +87,8 @@ android_app_certificate {
name: "security_cts_test_certificate",
certificate: "security_cts_test_cert",
}
+
+android_test_helper_app {
+ name: "RolePermissionOverrideTestApp",
+ manifest: "testdata/rolepermissionoverridetestapp.xml",
+}
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index f8402ec4c11..17aa9e8f345 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -27,6 +27,7 @@
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<!-- For FileIntegrityManager -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 6e0c8bc4f69..53a9a266b0b 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -44,6 +44,15 @@
value="pm uninstall --user 0 android.security.cts" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts/security" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="RolePermissionOverrideTestApp.apk->/data/local/tmp/cts/security/RolePermissionOverrideTestApp.apk" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.security.cts" />
<option name="runtime-hint" value="1h40m18s" />
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
new file mode 100644
index 00000000000..855ad37788b
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Instrumentation;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0922 {
+
+ private Instrumentation mInstrumentation;
+
+ @Before
+ public void setUp() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ /**
+ * b/195630721
+ */
+ @AsbSecurityTest(cveBugId = 195630721)
+ @Test
+ public void testPocCVE_2021_0922() throws Exception {
+ String packageName = "com.android.managedprovisioning";
+ try {
+ PackageInfo packageInfo = mInstrumentation.getContext().getPackageManager()
+ .getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
+ boolean isPermissionPresent = false;
+ for (int i = 0; i < packageInfo.requestedPermissions.length; ++i) {
+ if ((packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+ String permission = packageInfo.requestedPermissions[i];
+ if (permission.equals(android.Manifest.permission.MANAGE_APP_OPS_MODES)) {
+ isPermissionPresent = true;
+ break;
+ }
+ }
+ }
+ assertTrue(isPermissionPresent);
+ } catch (PackageManager.NameNotFoundException e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt b/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt
new file mode 100644
index 00000000000..2394cd22ffc
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021 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 android.app.role.RoleManager
+import android.content.pm.PackageManager
+import android.os.Process
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.mainline.MainlineModule
+import com.android.compatibility.common.util.mainline.ModuleDetector
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import java.util.function.Consumer
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class RolePermissionOverrideTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.targetContext
+ private val packageManager = context.packageManager
+ private val roleManager = context.getSystemService(RoleManager::class.java)
+ private val user = Process.myUserHandle()
+
+ @Before
+ fun setUp() {
+ installPackage(TEST_APP_APK_PATH)
+ }
+
+ @After
+ fun tearDown() {
+ uninstallPackage(TEST_APP_PACKAGE_NAME)
+ }
+
+ @AsbSecurityTest(cveBugId = [202312327])
+ @Test
+ fun systemRoleDoesNotOverrideUserRevokedPermission() {
+ assumeFalse(
+ ModuleDetector.moduleIsPlayManaged(
+ packageManager, MainlineModule.PERMISSION_CONTROLLER_APEX
+ )
+ )
+ assumeTrue(roleManager.isRoleAvailable(ROLE_SYSTEM_SPEECH_RECOGNIZER))
+ val systemSpeechRecognizerPackageName = getRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER)
+ if (systemSpeechRecognizerPackageName != null) {
+ assertPermissionState(
+ systemSpeechRecognizerPackageName, android.Manifest.permission.RECORD_AUDIO, true
+ )
+ }
+ assertPermissionState(
+ TEST_APP_PACKAGE_NAME, android.Manifest.permission.RECORD_AUDIO, false
+ )
+
+ runWithShellPermissionIdentity {
+ packageManager.updatePermissionFlags(
+ android.Manifest.permission.RECORD_AUDIO, TEST_APP_PACKAGE_NAME,
+ PackageManager.FLAG_PERMISSION_USER_SET, PackageManager.FLAG_PERMISSION_USER_SET,
+ user
+ )
+ }
+ setBypassingRoleQualification(true)
+ try {
+ addRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER, TEST_APP_PACKAGE_NAME)
+
+ assertPermissionState(
+ TEST_APP_PACKAGE_NAME, android.Manifest.permission.RECORD_AUDIO, false
+ )
+ } finally {
+ setBypassingRoleQualification(false)
+ }
+ }
+
+ private fun installPackage(apkPath: String) {
+ runShellCommand("pm install -r --user ${user.identifier} $apkPath")
+ }
+
+ private fun uninstallPackage(packageName: String) {
+ runShellCommand("pm uninstall -r --user ${user.identifier} $packageName")
+ }
+
+ private fun getRoleHolders(roleName: String): List<String> =
+ callWithShellPermissionIdentity { roleManager.getRoleHolders(roleName) }
+
+ private fun getRoleHolder(roleName: String): String? = getRoleHolders(roleName).firstOrNull()
+
+ private fun setBypassingRoleQualification(bypassRoleQualification: Boolean) {
+ runWithShellPermissionIdentity {
+ roleManager.setBypassingRoleQualification(bypassRoleQualification)
+ }
+ }
+
+ private fun addRoleHolder(roleName: String, packageName: String) {
+ val future = CallbackFuture()
+ runWithShellPermissionIdentity {
+ roleManager.addRoleHolderAsUser(
+ roleName, packageName, 0, user, context.mainExecutor, future
+ )
+ }
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(true)
+ }
+
+ private fun assertPermissionState(
+ packageName: String,
+ permissionName: String,
+ isGranted: Boolean
+ ) {
+ assertThat(packageManager.checkPermission(permissionName, packageName)).isEqualTo(
+ if (isGranted) PackageManager.PERMISSION_GRANTED else PackageManager.PERMISSION_DENIED
+ )
+ }
+
+ companion object {
+ private const val TEST_APP_APK_PATH =
+ "/data/local/tmp/cts/security/RolePermissionOverrideTestApp.apk"
+ private const val TEST_APP_PACKAGE_NAME =
+ "android.security.cts.rolepermissionoverridetestapp"
+
+ private const val ROLE_SYSTEM_SPEECH_RECOGNIZER =
+ "android.app.role.SYSTEM_SPEECH_RECOGNIZER"
+
+ private const val TIMEOUT_MILLIS = 15_000L
+ }
+
+ private class CallbackFuture : CompletableFuture<Boolean>(), Consumer<Boolean> {
+ override fun accept(successful: Boolean) {
+ complete(successful)
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 76b6549c0d9..ddecbc824c2 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1151,7 +1151,7 @@ public class StagefrightTest {
}
@Test
- @AsbSecurityTest(cveBugId = 110435401)
+ @AsbSecurityTest(cveBugId = 68664359)
public void testStagefright_bug_110435401() throws Exception {
doStagefrightTest(R.raw.bug_110435401, 60000);
}
diff --git a/tests/tests/security/testdata/rolepermissionoverridetestapp.xml b/tests/tests/security/testdata/rolepermissionoverridetestapp.xml
new file mode 100644
index 00000000000..783382abdf3
--- /dev/null
+++ b/tests/tests/security/testdata/rolepermissionoverridetestapp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2021 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.rolepermissionoverridetestapp">
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <application />
+</manifest>