diff options
| author | 2024-04-17 13:08:38 +0000 | |
|---|---|---|
| committer | 2024-04-22 11:34:55 +0000 | |
| commit | 7818402c3952dbe863aa2cc61543e940ddeefe8c (patch) | |
| tree | 9b15221a1979b9f88fda06562d7d1d679b1a6bdc | |
| parent | 509d19bb76559333a71d6e94b4d9f7cc8d91feac (diff) | |
Allow Glide to load thumbnails directly from the CMP
Currently, MediaProvider intercepts all calls from the kotlin picker to
the CMP to open thumbnails. However, this can cause binder threadpool
exhaustion in MediaProvider.
With this change, the kotlin picker can directly call try to open the
thumbnails instead of the call being rerouted through MediaProvider.
Bug: 329118546
Test: atest PickerDataLayerV2Test
Change-Id: I62ee02b62904263c6bcb81b48118372cc88b14ee
13 files changed, 227 insertions, 76 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2e54d0d5c..1c01fc78e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -92,7 +92,8 @@ <provider android:name="com.android.providers.media.photopicker.PhotoPickerProvider" android:authorities="com.android.providers.media.photopicker" - android:exported="false" /> + android:exported="true" + android:permission="com.android.providers.media.permission.MANAGE_CLOUD_MEDIA_PROVIDERS" /> <provider android:name="com.android.providers.media.photopicker.RemoteVideoPreviewProvider" diff --git a/photopicker/src/com/android/photopicker/data/MediaProviderClient.kt b/photopicker/src/com/android/photopicker/data/MediaProviderClient.kt index bf8dc08d4..ce0534d2c 100644 --- a/photopicker/src/com/android/photopicker/data/MediaProviderClient.kt +++ b/photopicker/src/com/android/photopicker/data/MediaProviderClient.kt @@ -61,7 +61,9 @@ open class MediaProviderClient { MEDIA_ID("id"), PICKER_ID("picker_id"), AUTHORITY("authority"), - URI("uri"), + MEDIA_SOURCE("media_source"), + MEDIA_URI("wrapped_uri"), + LOADABLE_URI("unwrapped_uri"), DATE_TAKEN("date_taken_millis"), SIZE("size_bytes"), MIME_TYPE("mime_type"), @@ -179,8 +181,13 @@ open class MediaProviderClient { cursor.getColumnIndexOrThrow(MediaResponse.PICKER_ID.key)) val authority: String = cursor.getString( cursor.getColumnIndexOrThrow(MediaResponse.AUTHORITY.key)) - val uri: Uri = Uri.parse(cursor.getString( - cursor.getColumnIndexOrThrow(MediaResponse.URI.key))) + val mediaSource: MediaSource = MediaSource.valueOf( + cursor.getString( + cursor.getColumnIndexOrThrow(MediaResponse.MEDIA_SOURCE.key))) + val mediaUri: Uri = Uri.parse(cursor.getString( + cursor.getColumnIndexOrThrow(MediaResponse.MEDIA_URI.key))) + val loadableUri: Uri = Uri.parse(cursor.getString( + cursor.getColumnIndexOrThrow(MediaResponse.LOADABLE_URI.key))) val dateTakenMillisLong: Long = cursor.getLong( cursor.getColumnIndexOrThrow(MediaResponse.DATE_TAKEN.key)) val sizeInBytes: Long = cursor.getLong( @@ -196,7 +203,9 @@ open class MediaProviderClient { mediaId = mediaId, pickerId = pickerId, authority = authority, - uri = uri, + mediaSource = mediaSource, + mediaUri = mediaUri, + glideLoadableUri = loadableUri, dateTakenMillisLong = dateTakenMillisLong, sizeInBytes = sizeInBytes, mimeType = mimeType, @@ -209,7 +218,9 @@ open class MediaProviderClient { mediaId = mediaId, pickerId = pickerId, authority = authority, - uri = uri, + mediaSource = mediaSource, + mediaUri = mediaUri, + glideLoadableUri = loadableUri, dateTakenMillisLong = dateTakenMillisLong, sizeInBytes = sizeInBytes, mimeType = mimeType, diff --git a/photopicker/src/com/android/photopicker/data/model/Media.kt b/photopicker/src/com/android/photopicker/data/model/Media.kt index defe6183f..97c538408 100644 --- a/photopicker/src/com/android/photopicker/data/model/Media.kt +++ b/photopicker/src/com/android/photopicker/data/model/Media.kt @@ -32,23 +32,27 @@ sealed interface Media : GlideLoadable, Parcelable { /** This is the Picker ID auto-generated in Picker DB */ val pickerId: Long val authority: String - val uri: Uri + val mediaSource: MediaSource + val mediaUri: Uri + val glideLoadableUri: Uri val dateTakenMillisLong: Long val sizeInBytes: Long val mimeType: String val standardMimeTypeExtension: Int override fun getSignature(resolution: Resolution): ObjectKey { - return ObjectKey("${uri}_$resolution") + return ObjectKey("${mediaUri}_$resolution") } override fun getLoadableUri(): Uri { - return uri + return glideLoadableUri } override fun getDataSource(): DataSource { - // TODO(b/303782563): Use MediaSource to determine datasource. - return DataSource.LOCAL + return when (mediaSource) { + MediaSource.LOCAL -> DataSource.LOCAL + MediaSource.REMOTE -> DataSource.REMOTE + } } override fun getTimestamp(): Long { @@ -65,7 +69,9 @@ sealed interface Media : GlideLoadable, Parcelable { out.writeString(mediaId) out.writeLong(pickerId) out.writeString(authority) - out.writeString(uri.toString()) + out.writeString(mediaSource.toString()) + out.writeString(mediaUri.toString()) + out.writeString(glideLoadableUri.toString()) out.writeLong(dateTakenMillisLong) out.writeLong(sizeInBytes) out.writeString(mimeType) @@ -77,7 +83,9 @@ sealed interface Media : GlideLoadable, Parcelable { override val mediaId: String, override val pickerId: Long, override val authority: String, - override val uri: Uri, + override val mediaSource: MediaSource, + override val mediaUri: Uri, + override val glideLoadableUri: Uri, override val dateTakenMillisLong: Long, override val sizeInBytes: Long, override val mimeType: String, @@ -96,7 +104,9 @@ sealed interface Media : GlideLoadable, Parcelable { /* mediaId=*/ parcel.readString() ?: "", /* pickerId=*/ parcel.readLong(), /* authority=*/ parcel.readString() ?: "", - /* uri= */ Uri.parse(parcel.readString() ?: ""), + /* mediaSource=*/ MediaSource.valueOf(parcel.readString() ?: "LOCAL"), + /* mediaUri= */ Uri.parse(parcel.readString() ?: ""), + /* loadableUri= */ Uri.parse(parcel.readString() ?: ""), /* dateTakenMillisLong=*/ parcel.readLong(), /* sizeInBytes=*/ parcel.readLong(), /* mimeType=*/ parcel.readString() ?: "", @@ -117,7 +127,9 @@ sealed interface Media : GlideLoadable, Parcelable { override val mediaId: String, override val pickerId: Long, override val authority: String, - override val uri: Uri, + override val mediaSource: MediaSource, + override val mediaUri: Uri, + override val glideLoadableUri: Uri, override val dateTakenMillisLong: Long, override val sizeInBytes: Long, override val mimeType: String, @@ -138,7 +150,9 @@ sealed interface Media : GlideLoadable, Parcelable { /* mediaId=*/ parcel.readString() ?: "", /* pickerId=*/ parcel.readLong(), /* authority=*/ parcel.readString() ?: "", - /* uri= */ Uri.parse(parcel.readString() ?: ""), + /* mediaSource=*/ MediaSource.valueOf(parcel.readString() ?: "LOCAL"), + /* mediaUri= */ Uri.parse(parcel.readString() ?: ""), + /* loadableUri= */ Uri.parse(parcel.readString() ?: ""), /* dateTakenMillisLong=*/ parcel.readLong(), /* sizeInBytes=*/ parcel.readLong(), /* mimeType=*/ parcel.readString() ?: "", diff --git a/photopicker/tests/src/com/android/photopicker/core/components/mediagrid/MediaGridTest.kt b/photopicker/tests/src/com/android/photopicker/core/components/mediagrid/MediaGridTest.kt index fdbf7c2fb..4bddbf1cb 100644 --- a/photopicker/tests/src/com/android/photopicker/core/components/mediagrid/MediaGridTest.kt +++ b/photopicker/tests/src/com/android/photopicker/core/components/mediagrid/MediaGridTest.kt @@ -56,6 +56,7 @@ import com.android.photopicker.core.ApplicationOwned import com.android.photopicker.core.selection.Selection import com.android.photopicker.data.model.Media import com.android.photopicker.data.model.MediaPageKey +import com.android.photopicker.data.model.MediaSource import com.android.photopicker.data.paging.FakeInMemoryMediaPagingSource import com.android.photopicker.extensions.insertMonthSeparators import com.android.photopicker.extensions.toMediaGridItem @@ -136,14 +137,23 @@ class MediaGridTest { mediaId = "$i", pickerId = i.toLong(), authority = "a", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("$i") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("$i") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("$i") + } + .build(), dateTakenMillisLong = LocalDateTime.now() .minus(i.toLong(), ChronoUnit.DAYS) diff --git a/photopicker/tests/src/com/android/photopicker/data/TestMediaProvider.kt b/photopicker/tests/src/com/android/photopicker/data/TestMediaProvider.kt index 24837ec1f..8eb066105 100644 --- a/photopicker/tests/src/com/android/photopicker/data/TestMediaProvider.kt +++ b/photopicker/tests/src/com/android/photopicker/data/TestMediaProvider.kt @@ -58,7 +58,9 @@ fun createMediaImage(pickerId: Long): Media { mediaId = UUID.randomUUID().toString(), pickerId = pickerId, authority = "authority", - uri = Uri.parse("content://media/picker/authority/media/$pickerId"), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.parse("content://media/picker/authority/media/$pickerId"), + glideLoadableUri = Uri.parse("content://authority/media/$pickerId"), dateTakenMillisLong = Long.MAX_VALUE, sizeInBytes = 10, mimeType = "image/*", @@ -128,7 +130,9 @@ class TestMediaProvider( MediaProviderClient.MediaResponse.MEDIA_ID.key, MediaProviderClient.MediaResponse.PICKER_ID.key, MediaProviderClient.MediaResponse.AUTHORITY.key, - MediaProviderClient.MediaResponse.URI.key, + MediaProviderClient.MediaResponse.MEDIA_SOURCE.key, + MediaProviderClient.MediaResponse.MEDIA_URI.key, + MediaProviderClient.MediaResponse.LOADABLE_URI.key, MediaProviderClient.MediaResponse.DATE_TAKEN.key, MediaProviderClient.MediaResponse.SIZE.key, MediaProviderClient.MediaResponse.MIME_TYPE.key, @@ -143,7 +147,9 @@ class TestMediaProvider( media.mediaId, media.pickerId.toString(), media.authority, - media.uri.toString(), + media.mediaSource.toString(), + media.mediaUri.toString(), + media.glideLoadableUri.toString(), media.dateTakenMillisLong.toString(), media.sizeInBytes.toString(), media.mimeType, diff --git a/photopicker/tests/src/com/android/photopicker/data/model/MediaParcelableTest.kt b/photopicker/tests/src/com/android/photopicker/data/model/MediaParcelableTest.kt index 4c1026664..6dcc5ba76 100644 --- a/photopicker/tests/src/com/android/photopicker/data/model/MediaParcelableTest.kt +++ b/photopicker/tests/src/com/android/photopicker/data/model/MediaParcelableTest.kt @@ -38,14 +38,23 @@ class MediaParcelableTest { mediaId = "image_id", pickerId = 123456789L, authority = "authority", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("image_id") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("image_id") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("image_id") + } + .build(), dateTakenMillisLong = 987654321L, sizeInBytes = 1000L, mimeType = "image/png", @@ -74,14 +83,23 @@ class MediaParcelableTest { mediaId = "video_id", pickerId = 123456789L, authority = "authority", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("video_id") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("video_id") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("video_id") + } + .build(), dateTakenMillisLong = 987654321L, sizeInBytes = 1000L, mimeType = "video/mp4", diff --git a/photopicker/tests/src/com/android/photopicker/data/paging/FakeInMemoryMediaPagingSource.kt b/photopicker/tests/src/com/android/photopicker/data/paging/FakeInMemoryMediaPagingSource.kt index 594f68d3f..2467e3dd9 100644 --- a/photopicker/tests/src/com/android/photopicker/data/paging/FakeInMemoryMediaPagingSource.kt +++ b/photopicker/tests/src/com/android/photopicker/data/paging/FakeInMemoryMediaPagingSource.kt @@ -23,6 +23,7 @@ import androidx.paging.PagingSource.LoadResult import androidx.paging.PagingState import com.android.photopicker.data.model.Media import com.android.photopicker.data.model.MediaPageKey +import com.android.photopicker.data.model.MediaSource import java.time.LocalDateTime import java.time.ZoneOffset import java.time.temporal.ChronoUnit @@ -46,8 +47,17 @@ class FakeInMemoryMediaPagingSource(val DATA_SIZE: Int = 10_000) : mediaId = "$i", pickerId = i.toLong(), authority = "a", - uri = - Uri.EMPTY.buildUpon() + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("$i") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() .apply { scheme("content") authority("a") diff --git a/photopicker/tests/src/com/android/photopicker/features/photogrid/PhotoGridViewModelTest.kt b/photopicker/tests/src/com/android/photopicker/features/photogrid/PhotoGridViewModelTest.kt index 7a7c5785c..53d3d014c 100644 --- a/photopicker/tests/src/com/android/photopicker/features/photogrid/PhotoGridViewModelTest.kt +++ b/photopicker/tests/src/com/android/photopicker/features/photogrid/PhotoGridViewModelTest.kt @@ -22,6 +22,7 @@ import androidx.test.filters.SmallTest import com.android.photopicker.core.selection.Selection import com.android.photopicker.data.TestDataServiceImpl import com.android.photopicker.data.model.Media +import com.android.photopicker.data.model.MediaSource import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.advanceTimeBy @@ -39,14 +40,23 @@ class PhotoGridViewModelTest { mediaId = "id", pickerId = 1000L, authority = "a", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("id") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("id") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("id") + } + .build(), dateTakenMillisLong = 123456789L, sizeInBytes = 1000L, mimeType = "image/png", diff --git a/photopicker/tests/src/com/android/photopicker/features/preview/PreviewFeatureTest.kt b/photopicker/tests/src/com/android/photopicker/features/preview/PreviewFeatureTest.kt index bffa444e8..ce209cc3c 100644 --- a/photopicker/tests/src/com/android/photopicker/features/preview/PreviewFeatureTest.kt +++ b/photopicker/tests/src/com/android/photopicker/features/preview/PreviewFeatureTest.kt @@ -46,6 +46,7 @@ import com.android.photopicker.core.features.FeatureToken import com.android.photopicker.core.navigation.PhotopickerDestinations import com.android.photopicker.core.selection.Selection import com.android.photopicker.data.model.Media +import com.android.photopicker.data.model.MediaSource import com.android.photopicker.extensions.navigateToPreviewMedia import com.android.photopicker.extensions.navigateToPreviewSelection import com.android.photopicker.features.PhotopickerFeatureBaseTest @@ -130,14 +131,23 @@ class PreviewFeatureTest : PhotopickerFeatureBaseTest() { mediaId = "image_id", pickerId = 123456789L, authority = "a", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("image_id") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("image_id") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("image_id") + } + .build(), dateTakenMillisLong = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) * 1000, sizeInBytes = 1000L, mimeType = "image/png", diff --git a/photopicker/tests/src/com/android/photopicker/features/preview/PreviewViewModelTest.kt b/photopicker/tests/src/com/android/photopicker/features/preview/PreviewViewModelTest.kt index f71b8dc29..04666ac58 100644 --- a/photopicker/tests/src/com/android/photopicker/features/preview/PreviewViewModelTest.kt +++ b/photopicker/tests/src/com/android/photopicker/features/preview/PreviewViewModelTest.kt @@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.photopicker.core.selection.Selection import com.android.photopicker.data.model.Media +import com.android.photopicker.data.model.MediaSource import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first @@ -39,8 +40,17 @@ class PreviewViewModelTest { mediaId = "id", pickerId = 1000L, authority = "a", - uri = - Uri.EMPTY.buildUpon() + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("id") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() .apply { scheme("content") authority("a") diff --git a/photopicker/tests/src/com/android/photopicker/features/selectionbar/SelectionBarFeatureTest.kt b/photopicker/tests/src/com/android/photopicker/features/selectionbar/SelectionBarFeatureTest.kt index 73beac5c3..6a4059624 100644 --- a/photopicker/tests/src/com/android/photopicker/features/selectionbar/SelectionBarFeatureTest.kt +++ b/photopicker/tests/src/com/android/photopicker/features/selectionbar/SelectionBarFeatureTest.kt @@ -48,6 +48,7 @@ import com.android.photopicker.core.navigation.LocalNavController import com.android.photopicker.core.selection.LocalSelection import com.android.photopicker.core.selection.Selection import com.android.photopicker.data.model.Media +import com.android.photopicker.data.model.MediaSource import com.android.photopicker.features.PhotopickerFeatureBaseTest import com.android.photopicker.features.simpleuifeature.SimpleUiFeature import com.android.photopicker.inject.PhotopickerTestModule @@ -112,14 +113,23 @@ class SelectionBarFeatureTest : PhotopickerFeatureBaseTest() { mediaId = "1", pickerId = 1L, authority = "a", - uri = - Uri.EMPTY.buildUpon() - .apply { - scheme("content") - authority("a") - path("$1") - } - .build(), + mediaSource = MediaSource.LOCAL, + mediaUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("media") + path("picker") + path("a") + path("1") + } + .build(), + glideLoadableUri = Uri.EMPTY.buildUpon() + .apply { + scheme("content") + authority("a") + path("1") + } + .build(), dateTakenMillisLong = 123456789L, sizeInBytes = 1000L, mimeType = "image/png", diff --git a/src/com/android/providers/media/photopicker/v2/PickerDataLayerV2.java b/src/com/android/providers/media/photopicker/v2/PickerDataLayerV2.java index 1198655b8..737229e34 100644 --- a/src/com/android/providers/media/photopicker/v2/PickerDataLayerV2.java +++ b/src/com/android/providers/media/photopicker/v2/PickerDataLayerV2.java @@ -265,8 +265,11 @@ public class PickerDataLayerV2 { PickerSQLConstants.MediaResponse.PICKER_ID.getProjection(), PickerSQLConstants.MediaResponse .AUTHORITY.getProjection(localAuthority, cloudAuthority), + PickerSQLConstants.MediaResponse.MEDIA_SOURCE.getProjection(), PickerSQLConstants.MediaResponse - .URI.getProjection(localAuthority, cloudAuthority), + .WRAPPED_URI.getProjection(localAuthority, cloudAuthority), + PickerSQLConstants.MediaResponse + .UNWRAPPED_URI.getProjection(localAuthority, cloudAuthority), PickerSQLConstants.MediaResponse.DATE_TAKEN_MS.getProjection(), PickerSQLConstants.MediaResponse.SIZE_IN_BYTES.getProjection(), PickerSQLConstants.MediaResponse.MIME_TYPE.getProjection(), diff --git a/src/com/android/providers/media/photopicker/v2/PickerSQLConstants.java b/src/com/android/providers/media/photopicker/v2/PickerSQLConstants.java index 78fbcd46a..77a34096e 100644 --- a/src/com/android/providers/media/photopicker/v2/PickerSQLConstants.java +++ b/src/com/android/providers/media/photopicker/v2/PickerSQLConstants.java @@ -32,6 +32,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.providers.media.PickerUriResolver; +import com.android.providers.media.photopicker.v2.model.MediaSource; /** * Helper class that keeps track of Picker related Constants. @@ -70,7 +71,9 @@ public class PickerSQLConstants { enum MediaResponse { MEDIA_ID(CloudMediaProviderContract.MediaColumns.ID), AUTHORITY(CloudMediaProviderContract.MediaColumns.AUTHORITY), - URI("uri"), + MEDIA_SOURCE("media_source"), + WRAPPED_URI("wrapped_uri"), + UNWRAPPED_URI("unwrapped_uri"), PICKER_ID(KEY_ID, "picker_id"), DATE_TAKEN_MS(KEY_DATE_TAKEN_MS, CloudMediaProviderContract.MediaColumns.DATE_TAKEN_MILLIS), SIZE_IN_BYTES(KEY_SIZE_BYTES, CloudMediaProviderContract.MediaColumns.SIZE_BYTES), @@ -117,10 +120,16 @@ public class PickerSQLConstants { getAuthority(localAuthority, cloudAuthority), mProjectedName ); - case URI: + case WRAPPED_URI: return String.format( DEFAULT_PROJECTION, - getUri(localAuthority, cloudAuthority), + getWrappedUri(localAuthority, cloudAuthority), + mProjectedName + ); + case UNWRAPPED_URI: + return String.format( + DEFAULT_PROJECTION, + getUnwrappedUri(localAuthority, cloudAuthority), mProjectedName ); default: @@ -137,6 +146,12 @@ public class PickerSQLConstants { getMediaId(), mProjectedName ); + case MEDIA_SOURCE: + return String.format( + DEFAULT_PROJECTION, + getMediaSource(), + mProjectedName + ); default: if (mColumnName == null) { throw new IllegalArgumentException( @@ -155,6 +170,15 @@ public class PickerSQLConstants { ); } + private String getMediaSource() { + return String.format( + "CASE WHEN %s IS NULL THEN '%s' ELSE '%s' END", + KEY_CLOUD_ID, + MediaSource.LOCAL, + MediaSource.REMOTE + ); + } + private String getAuthority( @Nullable String localAuthority, @Nullable String cloudAuthority @@ -167,7 +191,7 @@ public class PickerSQLConstants { ); } - private String getUri( + private String getWrappedUri( @Nullable String localAuthority, @Nullable String cloudAuthority ) { @@ -182,6 +206,20 @@ public class PickerSQLConstants { getMediaId() ); } + + private String getUnwrappedUri( + @Nullable String localAuthority, + @Nullable String cloudAuthority + ) { + // The format is: + // content://<cloud-provider-authority>/media/<media-id> + return String.format( + "'content://%s@' || %s || '/media/' || %s", + MediaStore.MY_USER_ID, + getAuthority(localAuthority, cloudAuthority), + getMediaId() + ); + } } enum MediaResponseExtras { |