summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shubhi <shubhisaxena@google.com> 2024-04-17 13:08:38 +0000
committer Shubhi <shubhisaxena@google.com> 2024-04-22 11:34:55 +0000
commit7818402c3952dbe863aa2cc61543e940ddeefe8c (patch)
tree9b15221a1979b9f88fda06562d7d1d679b1a6bdc
parent509d19bb76559333a71d6e94b4d9f7cc8d91feac (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
-rw-r--r--AndroidManifest.xml3
-rw-r--r--photopicker/src/com/android/photopicker/data/MediaProviderClient.kt21
-rw-r--r--photopicker/src/com/android/photopicker/data/model/Media.kt34
-rw-r--r--photopicker/tests/src/com/android/photopicker/core/components/mediagrid/MediaGridTest.kt26
-rw-r--r--photopicker/tests/src/com/android/photopicker/data/TestMediaProvider.kt12
-rw-r--r--photopicker/tests/src/com/android/photopicker/data/model/MediaParcelableTest.kt50
-rw-r--r--photopicker/tests/src/com/android/photopicker/data/paging/FakeInMemoryMediaPagingSource.kt14
-rw-r--r--photopicker/tests/src/com/android/photopicker/features/photogrid/PhotoGridViewModelTest.kt26
-rw-r--r--photopicker/tests/src/com/android/photopicker/features/preview/PreviewFeatureTest.kt26
-rw-r--r--photopicker/tests/src/com/android/photopicker/features/preview/PreviewViewModelTest.kt14
-rw-r--r--photopicker/tests/src/com/android/photopicker/features/selectionbar/SelectionBarFeatureTest.kt26
-rw-r--r--src/com/android/providers/media/photopicker/v2/PickerDataLayerV2.java5
-rw-r--r--src/com/android/providers/media/photopicker/v2/PickerSQLConstants.java46
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 {