summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/common/com/android/documentsui/bots/UiBot.java52
-rw-r--r--tests/common/com/android/documentsui/testing/TestDocumentsProvider.java54
-rw-r--r--tests/functional/com/android/documentsui/ActivityTestJunit4.kt18
-rw-r--r--tests/functional/com/android/documentsui/FileCopyUiTest.java2
-rw-r--r--tests/functional/com/android/documentsui/FilesActivityDefaultsUiTest.java62
-rw-r--r--tests/functional/com/android/documentsui/FilesActivityUiTest.java37
-rw-r--r--tests/functional/com/android/documentsui/TrampolineActivityTest.kt90
-rw-r--r--tests/unit/com/android/documentsui/UserManagerStateTest.java15
-rw-r--r--tests/unit/com/android/documentsui/files/ActionHandlerTest.java42
-rw-r--r--tests/unit/com/android/documentsui/loaders/BaseLoaderTest.kt5
-rw-r--r--tests/unit/com/android/documentsui/loaders/FolderLoaderTest.kt26
-rw-r--r--tests/unit/com/android/documentsui/loaders/SearchLoaderTest.kt38
12 files changed, 356 insertions, 85 deletions
diff --git a/tests/common/com/android/documentsui/bots/UiBot.java b/tests/common/com/android/documentsui/bots/UiBot.java
index f30cb93b8..4ec75bdc6 100644
--- a/tests/common/com/android/documentsui/bots/UiBot.java
+++ b/tests/common/com/android/documentsui/bots/UiBot.java
@@ -25,6 +25,8 @@ import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static com.android.documentsui.flags.Flags.useMaterial3;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -68,37 +70,48 @@ import java.util.List;
*/
public class UiBot extends Bots.BaseBot {
- public static String targetPackageName;
-
@SuppressWarnings("unchecked")
private static final Matcher<View> TOOLBAR = allOf(
isAssignableFrom(Toolbar.class),
withId(R.id.toolbar));
-
@SuppressWarnings("unchecked")
private static final Matcher<View> ACTIONBAR = allOf(
withClassName(endsWith("ActionBarContextView")));
-
@SuppressWarnings("unchecked")
private static final Matcher<View> TEXT_ENTRY = allOf(
withClassName(endsWith("EditText")));
-
@SuppressWarnings("unchecked")
private static final Matcher<View> TOOLBAR_OVERFLOW = allOf(
withClassName(endsWith("OverflowMenuButton")),
ViewMatchers.isDescendantOfA(TOOLBAR));
-
@SuppressWarnings("unchecked")
private static final Matcher<View> ACTIONBAR_OVERFLOW = allOf(
withClassName(endsWith("OverflowMenuButton")),
ViewMatchers.isDescendantOfA(ACTIONBAR));
+ public static String targetPackageName;
+
public UiBot(UiDevice device, Context context, int timeout) {
super(device, context, timeout);
targetPackageName =
InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName();
}
+ private static Matcher<Object> withToolbarTitle(final Matcher<CharSequence> textMatcher) {
+ return new BoundedMatcher<Object, Toolbar>(Toolbar.class) {
+ @Override
+ public boolean matchesSafely(Toolbar toolbar) {
+ return textMatcher.matches(toolbar.getTitle());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("with toolbar title: ");
+ textMatcher.describeTo(description);
+ }
+ };
+ }
+
public void assertWindowTitle(String expected) {
onView(TOOLBAR)
.check(matches(withToolbarTitle(is(expected))));
@@ -198,7 +211,11 @@ public class UiBot extends Bots.BaseBot {
}
public void clickActionbarOverflowItem(String label) {
- onView(ACTIONBAR_OVERFLOW).perform(click());
+ if (useMaterial3()) {
+ onView(TOOLBAR_OVERFLOW).perform(click());
+ } else {
+ onView(ACTIONBAR_OVERFLOW).perform(click());
+ }
// Click the item by label, since Espresso doesn't support lookup by id on overflow.
onView(withText(label)).perform(click());
}
@@ -214,9 +231,10 @@ public class UiBot extends Bots.BaseBot {
}
public boolean waitForActionModeBarToAppear() {
+ String actionModeId = useMaterial3() ? "toolbar" : "action_mode_bar";
UiObject2 bar =
- mDevice.wait(Until.findObject(
- By.res(mTargetPackage + ":id/action_mode_bar")), mTimeout);
+ mDevice.wait(
+ Until.findObject(By.res(mTargetPackage + ":id/" + actionModeId)), mTimeout);
return (bar != null);
}
@@ -307,20 +325,4 @@ public class UiBot extends Bots.BaseBot {
// TODO: use the system string ? android.R.string.action_menu_overflow_description
return mDevice.findObject(selector);
}
-
- private static Matcher<Object> withToolbarTitle(
- final Matcher<CharSequence> textMatcher) {
- return new BoundedMatcher<Object, Toolbar>(Toolbar.class) {
- @Override
- public boolean matchesSafely(Toolbar toolbar) {
- return textMatcher.matches(toolbar.getTitle());
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("with toolbar title: ");
- textMatcher.describeTo(description);
- }
- };
- }
}
diff --git a/tests/common/com/android/documentsui/testing/TestDocumentsProvider.java b/tests/common/com/android/documentsui/testing/TestDocumentsProvider.java
index 5c5ed856f..c7e884fde 100644
--- a/tests/common/com/android/documentsui/testing/TestDocumentsProvider.java
+++ b/tests/common/com/android/documentsui/testing/TestDocumentsProvider.java
@@ -17,6 +17,7 @@
package com.android.documentsui.testing;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
@@ -25,6 +26,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsProvider;
@@ -91,13 +93,59 @@ public class TestDocumentsProvider extends DocumentsProvider {
return mNextRecentDocuments;
}
+ private String getStringColumn(Cursor cursor, String name) {
+ return cursor.getString(cursor.getColumnIndexOrThrow(name));
+ }
+
+ private long getLongColumn(Cursor cursor, String name) {
+ return cursor.getLong(cursor.getColumnIndexOrThrow(name));
+ }
+
+ @Override
+ public Cursor querySearchDocuments(@NonNull String rootId, @Nullable String[] projection,
+ @NonNull Bundle queryArgs) {
+ TestCursor cursor = new TestCursor(DOCUMENTS_PROJECTION);
+ if (mNextChildDocuments == null) {
+ return cursor;
+ }
+ for (boolean hasNext = mNextChildDocuments.moveToFirst(); hasNext;
+ hasNext = mNextChildDocuments.moveToNext()) {
+ String displayName = getStringColumn(mNextChildDocuments, Document.COLUMN_DISPLAY_NAME);
+ String mimeType = getStringColumn(mNextChildDocuments, Document.COLUMN_MIME_TYPE);
+ long lastModified = getLongColumn(mNextChildDocuments, Document.COLUMN_LAST_MODIFIED);
+ long size = getLongColumn(mNextChildDocuments, Document.COLUMN_SIZE);
+
+ if (DocumentsContract.matchSearchQueryArguments(queryArgs, displayName, mimeType,
+ lastModified, size)) {
+ cursor.newRow()
+ .add(Document.COLUMN_DOCUMENT_ID,
+ getStringColumn(mNextChildDocuments, Document.COLUMN_DOCUMENT_ID))
+ .add(Document.COLUMN_MIME_TYPE,
+ getStringColumn(mNextChildDocuments, Document.COLUMN_MIME_TYPE))
+ .add(Document.COLUMN_DISPLAY_NAME,
+ getStringColumn(mNextChildDocuments, Document.COLUMN_DISPLAY_NAME))
+ .add(Document.COLUMN_LAST_MODIFIED,
+ getLongColumn(mNextChildDocuments, Document.COLUMN_LAST_MODIFIED))
+ .add(Document.COLUMN_FLAGS,
+ getLongColumn(mNextChildDocuments, Document.COLUMN_FLAGS))
+ .add(Document.COLUMN_SUMMARY,
+ getStringColumn(mNextChildDocuments, Document.COLUMN_SUMMARY))
+ .add(Document.COLUMN_SIZE,
+ getLongColumn(mNextChildDocuments, Document.COLUMN_SIZE))
+ .add(Document.COLUMN_ICON,
+ getLongColumn(mNextChildDocuments, Document.COLUMN_ICON));
+ }
+ }
+ return cursor;
+ }
+
@Override
public Cursor querySearchDocuments(String rootId, String query, String[] projection) {
- if (mNextChildDocuments != null) {
- return filterCursorByString(mNextChildDocuments, query);
+ if (mNextChildDocuments == null) {
+ return null;
}
- return mNextChildDocuments;
+ return filterCursorByString(mNextChildDocuments, query);
}
@Override
diff --git a/tests/functional/com/android/documentsui/ActivityTestJunit4.kt b/tests/functional/com/android/documentsui/ActivityTestJunit4.kt
index daab0cdb4..8f1d4f860 100644
--- a/tests/functional/com/android/documentsui/ActivityTestJunit4.kt
+++ b/tests/functional/com/android/documentsui/ActivityTestJunit4.kt
@@ -47,11 +47,16 @@ import java.util.Objects
abstract class ActivityTestJunit4<T : Activity?> {
@JvmField
var bots: Bots? = null
+
+ @JvmField
var device: UiDevice? = null
+
+ @JvmField
var context: Context? = null
var userId: UserId? = null
var automation: UiAutomation? = null
+ @JvmField
var features: Features? = null
/**
@@ -60,7 +65,12 @@ abstract class ActivityTestJunit4<T : Activity?> {
* Override the method if you want to open different root on start.
* @return Root that will be opened. Return null if you want to open activity's default root.
*/
- protected var initialRoot: RootInfo? = null
+ protected open var initialRoot: RootInfo? = null
+
+ @JvmField
+ var rootDir0: RootInfo? = null
+
+ @JvmField
var rootDir1: RootInfo? = null
protected var mResolver: ContentResolver? = null
@@ -83,8 +93,9 @@ abstract class ActivityTestJunit4<T : Activity?> {
*/
@Throws(RemoteException::class)
protected fun setupTestingRoots() {
- this.initialRoot = mDocsHelper!!.getRoot(StubProvider.ROOT_0_ID)
+ rootDir0 = mDocsHelper!!.getRoot(StubProvider.ROOT_0_ID)
rootDir1 = mDocsHelper!!.getRoot(StubProvider.ROOT_1_ID)
+ this.initialRoot = rootDir0
}
@Throws(Exception::class)
@@ -154,7 +165,7 @@ abstract class ActivityTestJunit4<T : Activity?> {
}
@Throws(RemoteException::class)
- protected fun initTestFiles() {
+ protected open fun initTestFiles() {
mDocsHelper!!.createFolder(this.initialRoot, dirName1)
mDocsHelper!!.createDocument(this.initialRoot, "text/plain", fileName1)
mDocsHelper!!.createDocument(this.initialRoot, "image/png", fileName2)
@@ -201,6 +212,7 @@ abstract class ActivityTestJunit4<T : Activity?> {
companion object {
// Testing files. For custom ones, override initTestFiles().
const val dirName1 = "Dir1"
+ const val childDir1 = "ChildDir1"
const val fileName1 = "file1.log"
const val fileName2 = "file12.png"
const val fileName3 = "anotherFile0.log"
diff --git a/tests/functional/com/android/documentsui/FileCopyUiTest.java b/tests/functional/com/android/documentsui/FileCopyUiTest.java
index 65a5d257f..42681ee82 100644
--- a/tests/functional/com/android/documentsui/FileCopyUiTest.java
+++ b/tests/functional/com/android/documentsui/FileCopyUiTest.java
@@ -489,7 +489,7 @@ public class FileCopyUiTest extends ActivityTest<FilesActivity> {
}
@HugeLongTest
- public void ignored_testRecursiveCopyDocuments_InternalStorageToDownloadsProvider()
+ public void testRecursiveCopyDocuments_InternalStorageToDownloadsProvider()
throws Exception {
// Create Download folder if it doesn't exist.
DocumentInfo info = mStorageDocsHelper.findFile(mPrimaryRoot.documentId, "Download");
diff --git a/tests/functional/com/android/documentsui/FilesActivityDefaultsUiTest.java b/tests/functional/com/android/documentsui/FilesActivityDefaultsUiTest.java
index a33cca37a..2cea176ba 100644
--- a/tests/functional/com/android/documentsui/FilesActivityDefaultsUiTest.java
+++ b/tests/functional/com/android/documentsui/FilesActivityDefaultsUiTest.java
@@ -18,24 +18,46 @@ package com.android.documentsui;
import static com.android.documentsui.StubProvider.ROOT_0_ID;
import static com.android.documentsui.StubProvider.ROOT_1_ID;
+import static com.android.documentsui.flags.Flags.FLAG_HIDE_ROOTS_ON_DESKTOP;
-import android.os.RemoteException;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.files.FilesActivity;
import com.android.documentsui.filters.HugeLongTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@LargeTest
-public class FilesActivityDefaultsUiTest extends ActivityTest<FilesActivity> {
+@RunWith(AndroidJUnit4.class)
+public class FilesActivityDefaultsUiTest extends ActivityTestJunit4<FilesActivity> {
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
- public FilesActivityDefaultsUiTest() {
- super(FilesActivity.class);
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
}
@Override
- protected void initTestFiles() throws RemoteException {
+ protected void initTestFiles() {
// Overriding to init with no items in test roots
}
@@ -44,6 +66,7 @@ public class FilesActivityDefaultsUiTest extends ActivityTest<FilesActivity> {
return null; // test the default, unaffected state of the app.
}
+ @Test
@HugeLongTest
public void testNavigate_FromEmptyDirectory() throws Exception {
device.waitForIdle();
@@ -57,8 +80,10 @@ public class FilesActivityDefaultsUiTest extends ActivityTest<FilesActivity> {
device.pressBack();
}
+ @Test
@HugeLongTest
- public void testDefaultRoots() throws Exception {
+ @RequiresFlagsDisabled(FLAG_HIDE_ROOTS_ON_DESKTOP)
+ public void testDefaultRoots_hideRootsOnDesktopFlagDisabled() throws Exception {
device.waitForIdle();
// Should also have Drive, but that requires pre-configuration of devices
@@ -71,4 +96,29 @@ public class FilesActivityDefaultsUiTest extends ActivityTest<FilesActivity> {
ROOT_0_ID,
ROOT_1_ID);
}
+
+ @Test
+ @HugeLongTest
+ @RequiresFlagsEnabled(FLAG_HIDE_ROOTS_ON_DESKTOP)
+ public void testDefaultRoots_hideRootsOnDesktopFlagEnabled() throws Exception {
+ device.waitForIdle();
+
+ String[] expectedRoots;
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) {
+ expectedRoots = new String[]{"Downloads",
+ ROOT_0_ID,
+ ROOT_1_ID};
+ } else {
+ expectedRoots = new String[]{
+ "Images",
+ "Videos",
+ "Audio",
+ "Downloads",
+ ROOT_0_ID,
+ ROOT_1_ID};
+ }
+ // Should also have Drive, but that requires pre-configuration of devices
+ // We omit for now.
+ bots.roots.assertRootsPresent(expectedRoots);
+ }
}
diff --git a/tests/functional/com/android/documentsui/FilesActivityUiTest.java b/tests/functional/com/android/documentsui/FilesActivityUiTest.java
index 697dee6df..1a160c130 100644
--- a/tests/functional/com/android/documentsui/FilesActivityUiTest.java
+++ b/tests/functional/com/android/documentsui/FilesActivityUiTest.java
@@ -16,29 +16,46 @@
package com.android.documentsui;
+import static com.android.documentsui.flags.Flags.FLAG_HIDE_ROOTS_ON_DESKTOP;
+
import android.app.Instrumentation;
import android.net.Uri;
import android.os.RemoteException;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import com.android.documentsui.files.FilesActivity;
import com.android.documentsui.filters.HugeLongTest;
import com.android.documentsui.inspector.InspectorActivity;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@LargeTest
-public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
+@RunWith(AndroidJUnit4.class)
+public class FilesActivityUiTest extends ActivityTestJunit4<FilesActivity> {
- public FilesActivityUiTest() {
- super(FilesActivity.class);
- }
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
- @Override
+ @Before
public void setUp() throws Exception {
super.setUp();
initTestFiles();
}
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
@Override
public void initTestFiles() throws RemoteException {
Uri uri = mDocsHelper.createFolder(rootDir0, dirName1);
@@ -55,6 +72,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
// Recents is a strange meta root that gathers entries from other providers.
// It is special cased in a variety of ways, which is why we just want
// to be able to click on it.
+ @Test
public void testClickRecent() throws Exception {
bots.roots.openRoot("Recent");
@@ -67,15 +85,19 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
}
}
+ @Test
+ @RequiresFlagsDisabled(FLAG_HIDE_ROOTS_ON_DESKTOP)
public void testRootClick_SetsWindowTitle() throws Exception {
bots.roots.openRoot("Images");
bots.main.assertWindowTitle("Images");
}
+ @Test
public void testFilesListed() throws Exception {
bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
}
+ @Test
public void testFilesList_LiveUpdate() throws Exception {
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
@@ -84,6 +106,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
"file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
}
+ @Test
public void testNavigate_byBreadcrumb() throws Exception {
bots.directory.openDocument(dirName1);
bots.directory.waitForDocument(childDir1); // wait for known content
@@ -96,6 +119,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
bots.directory.waitForDocument(dirName1);
}
+ @Test
public void testNavigate_inFixedLayout_whileHasSelection() throws Exception {
if (bots.main.inFixedLayout()) {
bots.roots.openRoot(rootDir0.title);
@@ -107,6 +131,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
}
}
+ @Test
public void testNavigationToInspector() throws Exception {
if(!features.isInspectorEnabled()) {
return;
@@ -118,7 +143,9 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
monitor.waitForActivityWithTimeout(TIMEOUT);
}
+ @Test
@HugeLongTest
+ @RequiresFlagsDisabled(FLAG_HIDE_ROOTS_ON_DESKTOP)
public void testRootChange_UpdatesSortHeader() throws Exception {
// switch to separate display modes for two separate roots. Each
diff --git a/tests/functional/com/android/documentsui/TrampolineActivityTest.kt b/tests/functional/com/android/documentsui/TrampolineActivityTest.kt
index c2201789b..76d703701 100644
--- a/tests/functional/com/android/documentsui/TrampolineActivityTest.kt
+++ b/tests/functional/com/android/documentsui/TrampolineActivityTest.kt
@@ -15,7 +15,10 @@
*/
package com.android.documentsui
+import android.app.Instrumentation
import android.content.Intent
+import android.content.Intent.ACTION_GET_CONTENT
+import android.content.IntentFilter
import android.os.Build.VERSION_CODES
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.CheckFlagsRule
@@ -29,7 +32,9 @@ import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.documentsui.flags.Flags.FLAG_REDIRECT_GET_CONTENT
import com.android.documentsui.picker.TrampolineActivity
+import java.util.Optional
import java.util.regex.Pattern
+import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.BeforeClass
@@ -49,15 +54,27 @@ import org.junit.runners.Suite.SuiteClasses
class TrampolineActivityTest() {
companion object {
const val UI_TIMEOUT = 5000L
- val PHOTOPICKER_PACKAGE_REGEX: Pattern = Pattern.compile(".*photopicker.*")
+ val PHOTOPICKER_PACKAGE_REGEX: Pattern = Pattern.compile(".*(photopicker|media\\.module).*")
val DOCUMENTSUI_PACKAGE_REGEX: Pattern = Pattern.compile(".*documentsui.*")
- private var device: UiDevice? = null
+ private lateinit var device: UiDevice
+
+ private lateinit var monitor: Instrumentation.ActivityMonitor
@BeforeClass
@JvmStatic
fun setUp() {
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+ // Monitor to wait for the activity that starts with the `ACTION_GET_CONTENT` intent.
+ val intentFilter = IntentFilter().apply { addAction(ACTION_GET_CONTENT) }
+ monitor =
+ Instrumentation.ActivityMonitor(
+ intentFilter,
+ null, // Expected result from startActivityForResult.
+ true, // Whether to block until activity started or not.
+ )
+ InstrumentationRegistry.getInstrumentation().addMonitor(monitor)
}
}
@@ -72,11 +89,11 @@ class TrampolineActivityTest() {
data class GetContentIntentData(
val mimeType: String,
val expectedApp: AppType,
- val extraMimeTypes: Array<String>? = null,
+ val extraMimeTypes: Optional<Array<String>> = Optional.empty(),
) {
override fun toString(): String {
- if (extraMimeTypes != null) {
- return "${mimeType}_${extraMimeTypes.joinToString("_")}"
+ if (extraMimeTypes.isPresent) {
+ return "${mimeType}_${extraMimeTypes.get().joinToString("_")}"
}
return mimeType
}
@@ -101,32 +118,32 @@ class TrampolineActivityTest() {
),
GetContentIntentData(
mimeType = "image/*",
- extraMimeTypes = arrayOf("video/*"),
+ extraMimeTypes = Optional.of(arrayOf("video/*")),
expectedApp = AppType.PHOTOPICKER,
),
GetContentIntentData(
mimeType = "video/*",
- extraMimeTypes = arrayOf("image/*"),
+ extraMimeTypes = Optional.of(arrayOf("image/*")),
expectedApp = AppType.PHOTOPICKER,
),
GetContentIntentData(
mimeType = "video/*",
- extraMimeTypes = arrayOf("text/*"),
+ extraMimeTypes = Optional.of(arrayOf("text/*")),
expectedApp = AppType.DOCUMENTSUI,
),
GetContentIntentData(
mimeType = "video/*",
- extraMimeTypes = arrayOf("image/*", "text/*"),
+ extraMimeTypes = Optional.of(arrayOf("image/*", "text/*")),
expectedApp = AppType.DOCUMENTSUI,
),
GetContentIntentData(
mimeType = "*/*",
- extraMimeTypes = arrayOf("image/*", "video/*"),
- expectedApp = AppType.DOCUMENTSUI,
+ extraMimeTypes = Optional.of(arrayOf("image/*", "video/*")),
+ expectedApp = AppType.PHOTOPICKER,
),
GetContentIntentData(
mimeType = "image/*",
- extraMimeTypes = arrayOf(),
+ extraMimeTypes = Optional.of(arrayOf()),
expectedApp = AppType.DOCUMENTSUI,
)
)
@@ -141,15 +158,23 @@ class TrampolineActivityTest() {
@Before
fun setUp() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
- val intent = Intent(Intent.ACTION_GET_CONTENT)
+ val intent = Intent(ACTION_GET_CONTENT)
intent.setClass(context, TrampolineActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setType(testData.mimeType)
- testData.extraMimeTypes?.let { intent.putExtra(Intent.EXTRA_MIME_TYPES, it) }
+ if (testData.extraMimeTypes.isPresent) {
+ testData.extraMimeTypes.get()
+ .forEach { intent.putExtra(Intent.EXTRA_MIME_TYPES, it) }
+ }
context.startActivity(intent)
}
+ @After
+ fun tearDown() {
+ monitor.waitForActivityWithTimeout(UI_TIMEOUT)?.finish()
+ }
+
@Test
fun testCorrectAppIsLaunched() {
val bySelector = when (testData.expectedApp) {
@@ -157,7 +182,23 @@ class TrampolineActivityTest() {
else -> By.pkg(DOCUMENTSUI_PACKAGE_REGEX)
}
- assertNotNull(device?.wait(Until.findObject(bySelector), UI_TIMEOUT))
+ val builder = StringBuilder()
+ builder.append("Intent with mimetype ${testData.mimeType}")
+ if (testData.extraMimeTypes.isPresent) {
+ builder.append(
+ " and EXTRA_MIME_TYPES of ${
+ testData.extraMimeTypes.get().joinToString(", ")
+ }"
+ )
+ }
+ builder.append(
+ " didn't cause ${testData.expectedApp.name} to appear after ${UI_TIMEOUT}ms"
+ )
+
+ assertNotNull(
+ builder.toString(),
+ device.wait(Until.findObject(bySelector), UI_TIMEOUT)
+ )
}
}
@@ -170,21 +211,22 @@ class TrampolineActivityTest() {
@Test
fun testReferredGetContentFromPhotopickerShouldNotRedirectBack() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
- val intent = Intent(Intent.ACTION_GET_CONTENT)
+ val intent = Intent(ACTION_GET_CONTENT)
intent.setClass(context, TrampolineActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- intent.setType("image/*")
+ intent.setType("*/*")
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*"))
context.startActivity(intent)
- val moreButton = device?.wait(Until.findObject(By.desc("More")), UI_TIMEOUT)
+ val moreButton = device.wait(Until.findObject(By.descContains("More")), UI_TIMEOUT)
moreButton?.click()
- val browseButton = device?.wait(Until.findObject(By.textContains("Browse")), UI_TIMEOUT)
+ val browseButton = device.wait(Until.findObject(By.textContains("Browse")), UI_TIMEOUT)
browseButton?.click()
assertNotNull(
"DocumentsUI has not launched",
- device?.wait(Until.findObject(By.pkg(DOCUMENTSUI_PACKAGE_REGEX)), UI_TIMEOUT)
+ device.wait(Until.findObject(By.pkg(DOCUMENTSUI_PACKAGE_REGEX)), UI_TIMEOUT)
)
}
@@ -192,7 +234,7 @@ class TrampolineActivityTest() {
@SdkSuppress(minSdkVersion = VERSION_CODES.S, maxSdkVersion = VERSION_CODES.S_V2)
fun testAndroidSWithTakeoverGetContentDisabledShouldNotReferToDocumentsUI() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
- val intent = Intent(Intent.ACTION_GET_CONTENT)
+ val intent = Intent(ACTION_GET_CONTENT)
intent.setClass(context, TrampolineActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setType("image/*")
@@ -201,15 +243,15 @@ class TrampolineActivityTest() {
// Disable Photopicker from taking over `ACTION_GET_CONTENT`. In this situation, it
// should ALWAYS defer to DocumentsUI regardless if the mimetype satisfies the
// conditions.
- device?.executeShellCommand(
+ device.executeShellCommand(
"device_config put mediaprovider take_over_get_content false"
)
context.startActivity(intent)
assertNotNull(
- device?.wait(Until.findObject(By.pkg(DOCUMENTSUI_PACKAGE_REGEX)), UI_TIMEOUT)
+ device.wait(Until.findObject(By.pkg(DOCUMENTSUI_PACKAGE_REGEX)), UI_TIMEOUT)
)
} finally {
- device?.executeShellCommand(
+ device.executeShellCommand(
"device_config delete mediaprovider take_over_get_content"
)
}
diff --git a/tests/unit/com/android/documentsui/UserManagerStateTest.java b/tests/unit/com/android/documentsui/UserManagerStateTest.java
index 574d65552..6f869dcd5 100644
--- a/tests/unit/com/android/documentsui/UserManagerStateTest.java
+++ b/tests/unit/com/android/documentsui/UserManagerStateTest.java
@@ -67,6 +67,7 @@ public class UserManagerStateTest {
private static final String PERSONAL = "Personal";
private static final String WORK = "Work";
private static final String PRIVATE = "Private";
+ private static final String PACKAGE_NAME = "com.android.documentsui";
/**
* Assume that the current user is SYSTEM_USER.
@@ -158,6 +159,20 @@ public class UserManagerStateTest {
.thenReturn(mDevicePolicyManager);
when(mMockContext.getResources()).thenReturn(
InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());
+
+ when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mSystemUser)).thenReturn(
+ mMockContext);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mManagedUser)).thenReturn(
+ mMockContext);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mPrivateUser)).thenReturn(
+ mMockContext);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mOtherUser)).thenReturn(
+ mMockContext);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mNormalUser)).thenReturn(
+ mMockContext);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, 0, mPrimaryUser)).thenReturn(
+ mMockContext);
}
@Test
diff --git a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
index 2554ea52b..01dfa1c76 100644
--- a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
@@ -16,6 +16,7 @@
package com.android.documentsui.files;
+import static com.android.documentsui.flags.Flags.useMaterial3;
import static com.android.documentsui.testing.IntentAsserts.assertHasAction;
import static com.android.documentsui.testing.IntentAsserts.assertHasData;
import static com.android.documentsui.testing.IntentAsserts.assertHasExtra;
@@ -31,6 +32,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.app.DownloadManager;
@@ -89,6 +92,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
@@ -108,6 +113,7 @@ public class ActionHandlerTest {
private TestFeatures mFeatures;
private TestConfigStore mTestConfigStore;
private boolean refreshAnswer = false;
+ @Mock private Runnable mMockCloseSelectionBar;
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -126,6 +132,7 @@ public class ActionHandlerTest {
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mFeatures = new TestFeatures();
mEnv = TestEnv.create(mFeatures);
mActivity = TestActivity.create(mEnv);
@@ -152,6 +159,14 @@ public class ActionHandlerTest {
mEnv.selectDocument(TestEnv.FILE_GIF);
}
+ private void assertSelectionContainerClosed() {
+ if (useMaterial3()) {
+ verify(mMockCloseSelectionBar, times(1)).run();
+ } else {
+ assertTrue(mActionModeAddons.finishActionModeCalled);
+ }
+ }
+
@Test
public void testOpenSelectedInNewWindow() {
mHandler.openSelectedInNewWindow();
@@ -195,7 +210,7 @@ public class ActionHandlerTest {
@Test
public void testSpringOpenDirectory() {
mHandler.springOpenDirectory(TestEnv.FOLDER_0);
- assertTrue(mActionModeAddons.finishActionModeCalled);
+ assertSelectionContainerClosed();
assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.peek());
}
@@ -250,7 +265,7 @@ public class ActionHandlerTest {
mHandler.deleteSelectedDocuments(docs, mEnv.state.stack.peek());
mActivity.startService.assertCalled();
- assertTrue(mActionModeAddons.finishActionModeCalled);
+ assertSelectionContainerClosed();
}
@Test
@@ -810,6 +825,23 @@ public class ActionHandlerTest {
assertFalse(intent.getExtras().containsKey(Intent.EXTRA_TITLE));
}
+ @Test
+ public void testViewInOwner() {
+ mEnv.populateStack();
+
+ mEnv.selectionMgr.clearSelection();
+ mEnv.selectDocument(TestEnv.FILE_PNG);
+
+ mHandler.viewInOwner();
+ mActivity.assertActivityStarted(DocumentsContract.ACTION_DOCUMENT_SETTINGS);
+ }
+
+ @Test
+ public void testOpenSettings() {
+ mHandler.openSettings(TestProvidersAccess.HAMMY);
+ mActivity.assertActivityStarted(DocumentsContract.ACTION_DOCUMENT_ROOT_SETTINGS);
+ }
+
private void assertRootPicked(Uri expectedUri) throws Exception {
mEnv.beforeAsserts();
@@ -828,10 +860,10 @@ public class ActionHandlerTest {
mEnv.searchViewManager,
mEnv::lookupExecutor,
mActionModeAddons,
+ mMockCloseSelectionBar,
mClipper,
- null, // clip storage, not utilized unless we venture into *jumbo* clip territory.
+ null, // clip storage, not utilized unless we venture into *jumbo* clip territory.
mDragAndDropManager,
- mEnv.injector
- );
+ mEnv.injector);
}
}
diff --git a/tests/unit/com/android/documentsui/loaders/BaseLoaderTest.kt b/tests/unit/com/android/documentsui/loaders/BaseLoaderTest.kt
index 62434b71f..55f83bfea 100644
--- a/tests/unit/com/android/documentsui/loaders/BaseLoaderTest.kt
+++ b/tests/unit/com/android/documentsui/loaders/BaseLoaderTest.kt
@@ -15,6 +15,7 @@
*/
package com.android.documentsui.loaders
+import android.os.Bundle
import android.os.Parcel
import android.provider.DocumentsContract
import com.android.documentsui.DirectoryResult
@@ -47,8 +48,10 @@ data class LoaderTestParams(
val query: String,
// The delta from now that indicates maximum age of matched files.
val lastModifiedDelta: Duration?,
+ // The extra arguments typically supplied by search view manager.
+ val otherArgs: Bundle,
// The number of files that are expected, for the above parameters, to be found by a loader.
- val expectedCount: Int
+ val expectedCount: Int,
)
/**
diff --git a/tests/unit/com/android/documentsui/loaders/FolderLoaderTest.kt b/tests/unit/com/android/documentsui/loaders/FolderLoaderTest.kt
index cb0735b17..44c410eff 100644
--- a/tests/unit/com/android/documentsui/loaders/FolderLoaderTest.kt
+++ b/tests/unit/com/android/documentsui/loaders/FolderLoaderTest.kt
@@ -15,13 +15,19 @@
*/
package com.android.documentsui.loaders
+import android.os.Bundle
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import androidx.test.filters.SmallTest
import com.android.documentsui.ContentLock
import com.android.documentsui.base.DocumentInfo
+import com.android.documentsui.flags.Flags.FLAG_USE_SEARCH_V2_RW
import com.android.documentsui.testing.TestFileTypeLookup
import com.android.documentsui.testing.TestProvidersAccess
import java.time.Duration
import junit.framework.Assert.assertEquals
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -36,15 +42,24 @@ class FolderLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
@JvmStatic
@Parameters(name = "with parameters {0}")
fun data() = listOf(
- LoaderTestParams("", null, TOTAL_FILE_COUNT),
+ LoaderTestParams("", null, Bundle(), TOTAL_FILE_COUNT),
// The first file is at NOW, the second at NOW - 1h, etc.
- LoaderTestParams("", Duration.ofMinutes(1L), 1),
- LoaderTestParams("", Duration.ofMinutes(60L + 1), 2),
- LoaderTestParams("", Duration.ofMinutes(TOTAL_FILE_COUNT * 60L + 1), TOTAL_FILE_COUNT),
+ LoaderTestParams("", Duration.ofMinutes(1L), Bundle(), 1),
+ LoaderTestParams("", Duration.ofMinutes(60L + 1), Bundle(), 2),
+ LoaderTestParams(
+ "",
+ Duration.ofMinutes(TOTAL_FILE_COUNT * 60L + 1),
+ Bundle(),
+ TOTAL_FILE_COUNT
+ ),
)
}
+ @get:Rule
+ val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
@Test
+ @RequiresFlagsEnabled(FLAG_USE_SEARCH_V2_RW)
fun testLoadInBackground() {
val mockProvider = mEnv.mockProviders[TestProvidersAccess.DOWNLOADS.authority]
val docs = createDocuments(TOTAL_FILE_COUNT)
@@ -56,7 +71,8 @@ class FolderLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
testParams.lastModifiedDelta,
null,
true,
- arrayOf<String>("*/*")
+ arrayOf<String>("*/*"),
+ testParams.otherArgs,
)
val contentLock = ContentLock()
// TODO(majewski): Is there a better way to create Downloads root folder DocumentInfo?
diff --git a/tests/unit/com/android/documentsui/loaders/SearchLoaderTest.kt b/tests/unit/com/android/documentsui/loaders/SearchLoaderTest.kt
index 94012b7ff..e480337ab 100644
--- a/tests/unit/com/android/documentsui/loaders/SearchLoaderTest.kt
+++ b/tests/unit/com/android/documentsui/loaders/SearchLoaderTest.kt
@@ -15,10 +15,16 @@
*/
package com.android.documentsui.loaders
+import android.os.Bundle
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.provider.DocumentsContract
import androidx.test.filters.SmallTest
import com.android.documentsui.ContentLock
import com.android.documentsui.LockingContentObserver
import com.android.documentsui.base.DocumentInfo
+import com.android.documentsui.flags.Flags.FLAG_USE_SEARCH_V2_RW
import com.android.documentsui.testing.TestFileTypeLookup
import com.android.documentsui.testing.TestProvidersAccess
import java.time.Duration
@@ -27,6 +33,8 @@ import java.util.concurrent.Executors
import junit.framework.Assert.assertEquals
import org.junit.Assert.assertThrows
import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -34,6 +42,12 @@ import org.junit.runners.Parameterized.Parameters
private const val TOTAL_FILE_COUNT = 8
+fun createQueryArgs(vararg mimeTypes: String): Bundle {
+ val args = Bundle()
+ args.putStringArray(DocumentsContract.QUERY_ARG_MIME_TYPES, arrayOf<String>(*mimeTypes))
+ return args
+}
+
@RunWith(Parameterized::class)
@SmallTest
class SearchLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTest() {
@@ -45,15 +59,20 @@ class SearchLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
@JvmStatic
@Parameters(name = "with parameters {0}")
fun data() = listOf(
- LoaderTestParams("sample", null, TOTAL_FILE_COUNT),
- LoaderTestParams("txt", null, 2),
- LoaderTestParams("foozig", null, 0),
+ LoaderTestParams("sample", null, Bundle(), TOTAL_FILE_COUNT),
+ LoaderTestParams("txt", null, Bundle(), 2),
+ LoaderTestParams("foozig", null, Bundle(), 0),
// The first file is at NOW, the second at NOW - 1h; expect 2.
- LoaderTestParams("sample", Duration.ofMinutes(60 + 1), 2),
- // TODO(b:378590632): Add test for recents.
+ LoaderTestParams("sample", Duration.ofMinutes(60 + 1), Bundle(), 2),
+ LoaderTestParams("sample", null, createQueryArgs("image/*"), 2),
+ LoaderTestParams("sample", null, createQueryArgs("image/*", "video/*"), 6),
+ LoaderTestParams("sample", null, createQueryArgs("application/pdf"), 0),
)
}
+ @get:Rule
+ val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
@Before
override fun setUp() {
super.setUp()
@@ -61,6 +80,7 @@ class SearchLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
}
@Test
+ @RequiresFlagsEnabled(FLAG_USE_SEARCH_V2_RW)
fun testLoadInBackground() {
val mockProvider = mEnv.mockProviders[TestProvidersAccess.DOWNLOADS.authority]
val docs = createDocuments(TOTAL_FILE_COUNT)
@@ -72,7 +92,8 @@ class SearchLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
testParams.lastModifiedDelta,
null,
true,
- arrayOf("*/*")
+ arrayOf("*/*"),
+ testParams.otherArgs,
)
val rootIds = listOf(TestProvidersAccess.DOWNLOADS)
@@ -98,10 +119,13 @@ class SearchLoaderTest(private val testParams: LoaderTestParams) : BaseLoaderTes
}
@Test
+ @RequiresFlagsEnabled(FLAG_USE_SEARCH_V2_RW)
+ @Ignore("b/397095797")
fun testBlankQueryAndRecency() {
val userIds = listOf(TestProvidersAccess.DOWNLOADS.userId)
val rootIds = listOf(TestProvidersAccess.DOWNLOADS)
- val noLastModifiedQueryOptions = QueryOptions(10, null, null, true, arrayOf("*/*"))
+ val noLastModifiedQueryOptions =
+ QueryOptions(10, null, null, true, arrayOf("*/*"), Bundle())
// Blank query and no last modified duration is invalid.
assertThrows(IllegalArgumentException::class.java) {