Fix PickerUriResolverTests with picker db enabled
As a unit test, we need to mock several operations in the test:
1. Binder calls to other processes (in another user)
2. FUSE synthetic path IO
3. Picker db querying for mimetype
Test: adb shell setprop sys.photopicker.pickerdb.enabled true
Test: atest PickerUriResolverTests
Bug: 195009139
Change-Id: I22fae1c563ef7d964ac60869b1e9fbbc2b56ab0f
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 8760947..6bddbc8 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -1196,6 +1196,12 @@
}
@VisibleForTesting
+ public void setUriResolver(PickerUriResolver resolver) {
+ Log.w(TAG, "Changing the PickerUriResolver!!! Should only be called during test");
+ mPickerUriResolver = resolver;
+ }
+
+ @VisibleForTesting
void detectSpecialFormat(@NonNull CancellationSignal signal) {
mExternalDatabase.runWithTransaction((db) -> {
updateSpecialFormatColumn(db, signal);
diff --git a/src/com/android/providers/media/PickerUriResolver.java b/src/com/android/providers/media/PickerUriResolver.java
index 2473877..a104068 100644
--- a/src/com/android/providers/media/PickerUriResolver.java
+++ b/src/com/android/providers/media/PickerUriResolver.java
@@ -216,20 +216,22 @@
if (file == null) {
throw new FileNotFoundException("File not found for uri: " + uri);
}
- return ParcelFileDescriptor.open(toFuseFile(file), ParcelFileDescriptor.MODE_READ_ONLY);
+ return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
- private File getPickerFileFromUri(Uri uri) {
+ @VisibleForTesting
+ File getPickerFileFromUri(Uri uri) {
try (Cursor cursor = queryPickerUri(uri)) {
if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) {
String path = getCursorString(cursor, CloudMediaProviderContract.MediaColumns.DATA);
- return new File(path);
+ return toFuseFile(new File(path));
}
}
return null;
}
- private Cursor queryPickerUri(Uri uri) {
+ @VisibleForTesting
+ Cursor queryPickerUri(Uri uri) {
uri = unwrapProviderUri(uri);
return mDbFacade.queryMediaId(uri.getHost(), uri.getLastPathSegment());
}
@@ -328,7 +330,7 @@
private boolean canHandleUriInUser(Uri uri) {
// If MPs user_id matches the URIs user_id, we can handle this URI in this MP user,
// otherwise, we'd have to re-route to MP matching URI user_id
- return getUserId(uri) == MediaStore.MY_USER_ID;
+ return getUserId(uri) == mContext.getUser().getIdentifier();
}
@VisibleForTesting
diff --git a/tests/src/com/android/providers/media/PickerUriResolverTest.java b/tests/src/com/android/providers/media/PickerUriResolverTest.java
index 863525f..fb78ef3 100644
--- a/tests/src/com/android/providers/media/PickerUriResolverTest.java
+++ b/tests/src/com/android/providers/media/PickerUriResolverTest.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -74,12 +75,11 @@
private static Context sCurrentContext;
private static TestPickerUriResolver sTestPickerUriResolver;
private static Uri sTestPickerUri;
- private static PickerDbFacade sPickerDbFacade;
private static String TEST_ID;
private static class TestPickerUriResolver extends PickerUriResolver {
- TestPickerUriResolver(Context context, PickerDbFacade facade) {
- super(context, facade);
+ TestPickerUriResolver(Context context) {
+ super(context, new PickerDbFacade(getTargetContext()));
}
@Override
@@ -89,6 +89,31 @@
// well.
return uri;
}
+
+ @Override
+ Cursor queryPickerUri(Uri uri) {
+ if (!uri.getLastPathSegment().equals(TEST_ID)) {
+ return super.queryPickerUri(uri);
+ }
+
+ final String[] projection = new String[] {
+ CloudMediaProviderContract.MediaColumns.ID,
+ CloudMediaProviderContract.MediaColumns.MIME_TYPE
+ };
+
+ final MatrixCursor c = new MatrixCursor(projection);
+ c.addRow(new String[] { TEST_ID, "image/jpeg"});
+ return c;
+ }
+
+ @Override
+ File getPickerFileFromUri(Uri uri) {
+ if (!uri.getLastPathSegment().equals(TEST_ID)) {
+ return super.getPickerFileFromUri(uri);
+ }
+
+ return TEST_FILE;
+ }
}
@BeforeClass
@@ -99,9 +124,10 @@
android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
Manifest.permission.INTERACT_ACROSS_USERS);
sCurrentContext = mock(Context.class);
+ when(sCurrentContext.getUser()).thenReturn(UserHandle.of(UserHandle.myUserId()));
+
final Context otherUserContext = createOtherUserContext(TEST_USER);
- sPickerDbFacade = new PickerDbFacade(otherUserContext);
- sTestPickerUriResolver = new TestPickerUriResolver(sCurrentContext, sPickerDbFacade);
+ sTestPickerUriResolver = new TestPickerUriResolver(sCurrentContext);
final Uri mediaStoreUriInOtherContext = createTestFileInContext(otherUserContext);
TEST_ID = mediaStoreUriInOtherContext.getLastPathSegment();
@@ -289,8 +315,11 @@
// For unit testing: IsolatedContext is the context of another User: user.
// PickerUriResolver should correctly be able to call into other user's content resolver
// from the current context.
- final Context otherUserContext = new MediaScannerTest.IsolatedContext(getTargetContext(),
- "databases", /* asFuseThread */ false);
+ final MediaScannerTest.IsolatedContext otherUserContext =
+ new MediaScannerTest.IsolatedContext(getTargetContext(), "databases",
+ /* asFuseThread */ false, userHandle);
+ otherUserContext.setPickerUriResolver(new TestPickerUriResolver(otherUserContext));
+
when(sCurrentContext.createPackageContextAsUser("android", /* flags= */ 0, userHandle)).
thenReturn(otherUserContext);
return otherUserContext;
diff --git a/tests/src/com/android/providers/media/scan/MediaScannerTest.java b/tests/src/com/android/providers/media/scan/MediaScannerTest.java
index 9faf50d..96e90cc 100644
--- a/tests/src/com/android/providers/media/scan/MediaScannerTest.java
+++ b/tests/src/com/android/providers/media/scan/MediaScannerTest.java
@@ -33,6 +33,7 @@
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.BaseColumns;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.MediaStore;
@@ -45,6 +46,7 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.providers.media.PickerUriResolver;
import com.android.providers.media.MediaDocumentsProvider;
import com.android.providers.media.MediaProvider;
import com.android.providers.media.R;
@@ -74,14 +76,21 @@
private final MediaProvider mProvider;
private final MediaDocumentsProvider mDocumentsProvider;
private final PhotoPickerProvider mPhotoPickerProvider;
+ private final UserHandle mUserHandle;
public IsolatedContext(Context base, String tag, boolean asFuseThread) {
+ this(base, tag, asFuseThread, base.getUser());
+ }
+
+ public IsolatedContext(Context base, String tag, boolean asFuseThread,
+ UserHandle userHandle) {
super(base);
mDir = new File(base.getFilesDir(), tag);
mDir.mkdirs();
FileUtils.deleteContents(mDir);
mResolver = new MockContentResolver(this);
+ mUserHandle = userHandle;
final ProviderInfo info = base.getPackageManager()
.resolveContentProvider(MediaStore.AUTHORITY, 0);
@@ -147,6 +156,15 @@
public ContentResolver getContentResolver() {
return mResolver;
}
+
+ @Override
+ public UserHandle getUser() {
+ return mUserHandle;
+ }
+
+ public void setPickerUriResolver(PickerUriResolver resolver) {
+ mProvider.setUriResolver(resolver);
+ }
}
private MediaScanner mLegacy;