summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andrey Epin <ayepin@google.com> 2024-05-09 12:08:06 -0700
committer Andrey Epin <ayepin@google.com> 2024-05-10 10:55:51 -0700
commit90bddf71b63f5082c4ec9e697b0baaacb5f81ecd (patch)
treec3a4cdb1f86ddf96bd8f5dc8f685812f9dba2963
parent2f1c0975679a342121489fa8ce8aa60a5782941c (diff)
Add support for preview size columns in the additional content query.
Add support for MediaStore WIDTH and HEIGHT columns in the additional content query reponse. Parse those columns if they are present but do not actually use the values (yet). Bug: 339679442 Test: atest IntentResolver-tests-unit Test: atest IntentResolver-tests-activity Change-Id: I2a3ebc2c166d1cb9203824b2ac1bf0f9c4ec76da
-rw-r--r--java/src/com/android/intentresolver/contentpreview/UriMetadataHelpers.kt22
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolver.kt27
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractor.kt44
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractor.kt3
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/CursorRow.kt23
-rw-r--r--tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt4
-rw-r--r--tests/unit/src/com/android/intentresolver/contentpreview/CursorReadSizeTest.kt71
-rw-r--r--tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolverTest.kt106
-rw-r--r--tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt6
-rw-r--r--tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt7
10 files changed, 277 insertions, 36 deletions
diff --git a/java/src/com/android/intentresolver/contentpreview/UriMetadataHelpers.kt b/java/src/com/android/intentresolver/contentpreview/UriMetadataHelpers.kt
index 41638b1f..c532b9a5 100644
--- a/java/src/com/android/intentresolver/contentpreview/UriMetadataHelpers.kt
+++ b/java/src/com/android/intentresolver/contentpreview/UriMetadataHelpers.kt
@@ -23,9 +23,12 @@ import android.net.Uri
import android.provider.DocumentsContract
import android.provider.DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL
import android.provider.Downloads
+import android.provider.MediaStore.MediaColumns.HEIGHT
+import android.provider.MediaStore.MediaColumns.WIDTH
import android.provider.OpenableColumns
import android.text.TextUtils
import android.util.Log
+import android.util.Size
import com.android.intentresolver.measurements.runTracing
internal fun ContentInterface.getTypeSafe(uri: Uri): String? =
@@ -83,6 +86,25 @@ internal fun Cursor.readPreviewUri(): Uri? =
}
.getOrNull()
+fun Cursor.readSize(): Size? {
+ val widthIdx = columnNames.indexOf(WIDTH)
+ val heightIdx = columnNames.indexOf(HEIGHT)
+ return if (widthIdx < 0 || heightIdx < 0 || isNull(widthIdx) || isNull(heightIdx)) {
+ null
+ } else {
+ runCatching {
+ val width = getInt(widthIdx)
+ val height = getInt(heightIdx)
+ if (width >= 0 && height > 0) {
+ Size(width, height)
+ } else {
+ null
+ }
+ }
+ .getOrNull()
+ }
+}
+
internal fun Cursor.readTitle(): String =
runCatching {
var nameColIndex = -1
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolver.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolver.kt
index 3cf2af13..d9612696 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolver.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolver.kt
@@ -16,11 +16,14 @@
package com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor
-import android.content.ContentResolver
+import android.content.ContentInterface
import android.content.Intent
+import android.database.Cursor
import android.net.Uri
import android.service.chooser.AdditionalContentContract.Columns.URI
import androidx.core.os.bundleOf
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
+import com.android.intentresolver.contentpreview.readSize
import com.android.intentresolver.inject.AdditionalContent
import com.android.intentresolver.inject.ChooserIntent
import com.android.intentresolver.util.cursor.CursorView
@@ -37,23 +40,31 @@ import javax.inject.Qualifier
class PayloadToggleCursorResolver
@Inject
constructor(
- private val contentResolver: ContentResolver,
+ private val contentResolver: ContentInterface,
@AdditionalContent private val cursorUri: Uri,
@ChooserIntent private val chooserIntent: Intent,
-) : CursorResolver<Uri?> {
- override suspend fun getCursor(): CursorView<Uri?>? = withCancellationSignal { signal ->
+) : CursorResolver<CursorRow?> {
+ override suspend fun getCursor(): CursorView<CursorRow?>? = withCancellationSignal { signal ->
runCatching {
contentResolver.query(
cursorUri,
- arrayOf(URI),
+ // TODO: uncomment to start using that data
+ arrayOf(URI /*, WIDTH, HEIGHT*/),
bundleOf(Intent.EXTRA_INTENT to chooserIntent),
signal,
)
}
.getOrNull()
- ?.viewBy {
- getString(0)?.let(Uri::parse)?.takeIf { it.authority != cursorUri.authority }
+ ?.viewBy { readUri()?.let { uri -> CursorRow(uri, readSize()) } }
+ }
+
+ private fun Cursor.readUri(): Uri? {
+ val uriIdx = columnNames.indexOf(URI)
+ if (uriIdx < 0) return null
+ return runCatching {
+ getString(uriIdx)?.let(Uri::parse)?.takeIf { it.authority != cursorUri.authority }
}
+ .getOrNull()
}
@Module
@@ -61,7 +72,7 @@ constructor(
interface Binding {
@Binds
@PayloadToggle
- fun bind(cursorResolver: PayloadToggleCursorResolver): CursorResolver<Uri?>
+ fun bind(cursorResolver: PayloadToggleCursorResolver): CursorResolver<CursorRow?>
}
}
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractor.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractor.kt
index f642f420..9d62ffa2 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractor.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractor.kt
@@ -21,6 +21,7 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.interacto
import android.net.Uri
import android.service.chooser.AdditionalContentContract.CursorExtraKeys.POSITION
import com.android.intentresolver.contentpreview.UriMetadataReader
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.LoadDirection
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.LoadedWindow
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.expandWindowLeft
@@ -64,7 +65,7 @@ constructor(
}
/** Start reading data from [uriCursor], and listen for requests to load more. */
- suspend fun launch(uriCursor: CursorView<Uri?>, initialPreviews: Iterable<PreviewModel>) {
+ suspend fun launch(uriCursor: CursorView<CursorRow?>, initialPreviews: Iterable<PreviewModel>) {
// Unclaimed values from the initial selection set. Entries will be removed as the cursor is
// read, and any still present are inserted at the start / end of the cursor when it is
// reached by the user.
@@ -73,7 +74,7 @@ constructor(
.asSequence()
.mapIndexed { i, m -> Pair(m.uri, Pair(i, m)) }
.toMap(ConcurrentHashMap())
- val pagedCursor: PagedCursor<Uri?> = uriCursor.paged(pageSize)
+ val pagedCursor: PagedCursor<CursorRow?> = uriCursor.paged(pageSize)
val startPosition = uriCursor.extras?.getInt(POSITION, 0) ?: 0
val state = readInitialState(pagedCursor, startPosition, unclaimedRecords)
processLoadRequests(state, pagedCursor, unclaimedRecords)
@@ -82,7 +83,7 @@ constructor(
/** Loop forever, processing any loading requests from the UI and updating local cache. */
private suspend fun processLoadRequests(
initialState: CursorWindow,
- pagedCursor: PagedCursor<Uri?>,
+ pagedCursor: PagedCursor<CursorRow?>,
unclaimedRecords: MutableUnclaimedMap,
) {
var state = initialState
@@ -108,7 +109,7 @@ constructor(
*/
private suspend fun Flow<LoadDirection?>.handleOneLoadRequest(
state: CursorWindow,
- pagedCursor: PagedCursor<Uri?>,
+ pagedCursor: PagedCursor<CursorRow?>,
unclaimedRecords: MutableUnclaimedMap,
): CursorWindow =
mapLatest { loadDirection ->
@@ -127,7 +128,7 @@ constructor(
* [startPosition].
*/
private suspend fun readInitialState(
- cursor: PagedCursor<Uri?>,
+ cursor: PagedCursor<CursorRow?>,
startPosition: Int,
unclaimedRecords: MutableUnclaimedMap,
): CursorWindow {
@@ -138,13 +139,13 @@ constructor(
if (!hasMoreLeft) {
// First read the initial page; this might claim some unclaimed Uris
val page =
- cursor.getPageUris(startPageIdx)?.toPage(mutableMapOf(), unclaimedRecords)
+ cursor.getPageRows(startPageIdx)?.toPage(mutableMapOf(), unclaimedRecords)
// Now that unclaimed Uris are up-to-date, add them first.
putAllUnclaimedLeft(unclaimedRecords)
// Then add the loaded page
page?.let(::putAll)
} else {
- cursor.getPageUris(startPageIdx)?.toPage(this, unclaimedRecords)
+ cursor.getPageRows(startPageIdx)?.toPage(this, unclaimedRecords)
}
// Finally, add the remainder of the unclaimed Uris.
if (!hasMoreRight) {
@@ -162,7 +163,7 @@ constructor(
}
private suspend fun CursorWindow.loadMoreRight(
- cursor: PagedCursor<Uri?>,
+ cursor: PagedCursor<CursorRow?>,
unclaimedRecords: MutableUnclaimedMap,
): CursorWindow {
val pageNum = lastLoadedPageNum + 1
@@ -181,7 +182,7 @@ constructor(
}
private suspend fun CursorWindow.loadMoreLeft(
- cursor: PagedCursor<Uri?>,
+ cursor: PagedCursor<CursorRow?>,
unclaimedRecords: MutableUnclaimedMap,
): CursorWindow {
val pageNum = firstLoadedPageNum - 1
@@ -207,7 +208,7 @@ constructor(
private suspend fun readPage(
state: CursorWindow,
- pagedCursor: PagedCursor<Uri?>,
+ pagedCursor: PagedCursor<CursorRow?>,
pageNum: Int,
unclaimedRecords: MutableUnclaimedMap,
): PreviewMap =
@@ -216,30 +217,33 @@ constructor(
private suspend fun <M : MutablePreviewMap> M.readAndPutPage(
state: CursorWindow,
- pagedCursor: PagedCursor<Uri?>,
+ pagedCursor: PagedCursor<CursorRow?>,
pageNum: Int,
unclaimedRecords: MutableUnclaimedMap,
): M =
pagedCursor
- .getPageUris(pageNum) // TODO: what do we do if the load fails?
- ?.filter { it !in state.merged }
+ .getPageRows(pageNum) // TODO: what do we do if the load fails?
+ ?.filter { it.uri !in state.merged }
?.toPage(this, unclaimedRecords)
?: this
- private suspend fun <M : MutablePreviewMap> Sequence<Uri>.toPage(
+ private suspend fun <M : MutablePreviewMap> Sequence<CursorRow>.toPage(
destination: M,
unclaimedRecords: MutableUnclaimedMap,
): M =
// Restrict parallelism so as to not overload the metadata reader; anecdotally, too
// many parallel queries causes failures.
- mapParallel(parallelism = 4) { uri -> createPreviewModel(uri, unclaimedRecords) }
+ mapParallel(parallelism = 4) { row -> createPreviewModel(row, unclaimedRecords) }
.associateByTo(destination) { it.uri }
- private fun createPreviewModel(uri: Uri, unclaimedRecords: MutableUnclaimedMap): PreviewModel =
- unclaimedRecords.remove(uri)?.second
+ private fun createPreviewModel(
+ row: CursorRow,
+ unclaimedRecords: MutableUnclaimedMap,
+ ): PreviewModel =
+ unclaimedRecords.remove(row.uri)?.second
?: PreviewModel(
- uri = uri,
- mimeType = uriMetadataReader.getMetadata(uri).mimeType,
+ uri = row.uri,
+ mimeType = uriMetadataReader.getMetadata(row.uri).mimeType,
)
private fun <M : MutablePreviewMap> M.putAllUnclaimedRight(unclaimed: UnclaimedMap): M =
@@ -275,7 +279,7 @@ private fun <M : MutablePreviewMap> M.putAllUnclaimedWhere(
.map { it.key to it.value.second }
.toMap(this)
-private fun PagedCursor<Uri?>.getPageUris(pageNum: Int): Sequence<Uri>? =
+private fun PagedCursor<CursorRow?>.getPageRows(pageNum: Int): Sequence<CursorRow>? =
get(pageNum)?.filterNotNull()
@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class PageSize
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractor.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractor.kt
index 9bc7ae63..927a3a84 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractor.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractor.kt
@@ -21,6 +21,7 @@ import com.android.intentresolver.contentpreview.UriMetadataReader
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PreviewSelectionsRepository
import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.CursorResolver
import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.PayloadToggle
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel
import com.android.intentresolver.inject.ContentUris
import com.android.intentresolver.inject.FocusedItemIndex
@@ -39,7 +40,7 @@ constructor(
@FocusedItemIndex private val focusedItemIdx: Int,
@ContentUris private val selectedItems: List<@JvmSuppressWildcards Uri>,
private val uriMetadataReader: UriMetadataReader,
- @PayloadToggle private val cursorResolver: CursorResolver<@JvmSuppressWildcards Uri?>,
+ @PayloadToggle private val cursorResolver: CursorResolver<@JvmSuppressWildcards CursorRow?>,
) {
suspend fun activate() = coroutineScope {
val cursor = async { cursorResolver.getCursor() }
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/CursorRow.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/CursorRow.kt
new file mode 100644
index 00000000..f1d856ac
--- /dev/null
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/CursorRow.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.intentresolver.contentpreview.payloadtoggle.domain.model
+
+import android.net.Uri
+import android.util.Size
+
+/** Represents additional content cursor row */
+data class CursorRow(val uri: Uri, val previewSize: Size?)
diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt
index 10b89c71..d53210bd 100644
--- a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt
+++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt
@@ -16,13 +16,13 @@
package com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor
-import android.net.Uri
import com.android.intentresolver.contentResolver
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
import com.android.intentresolver.inject.additionalContentUri
import com.android.intentresolver.inject.chooserIntent
import com.android.systemui.kosmos.Kosmos
-var Kosmos.payloadToggleCursorResolver: CursorResolver<Uri?> by
+var Kosmos.payloadToggleCursorResolver: CursorResolver<CursorRow?> by
Kosmos.Fixture { payloadToggleCursorResolverImpl }
val Kosmos.payloadToggleCursorResolverImpl
get() =
diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/CursorReadSizeTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/CursorReadSizeTest.kt
new file mode 100644
index 00000000..0c346095
--- /dev/null
+++ b/tests/unit/src/com/android/intentresolver/contentpreview/CursorReadSizeTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.intentresolver.contentpreview
+
+import android.database.MatrixCursor
+import android.provider.MediaStore.MediaColumns.HEIGHT
+import android.provider.MediaStore.MediaColumns.WIDTH
+import android.util.Size
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class CursorReadSizeTest {
+ @Test
+ fun missingSizeColumns() {
+ val cursor = MatrixCursor(arrayOf("column")).apply { addRow(arrayOf("abc")) }
+ cursor.moveToFirst()
+
+ assertThat(cursor.readSize()).isNull()
+ }
+
+ @Test
+ fun testIncorrectSizeValues() = runTest {
+ val cursor =
+ MatrixCursor(arrayOf(WIDTH, HEIGHT)).apply {
+ addRow(arrayOf(null, null))
+ addRow(arrayOf("100", null))
+ addRow(arrayOf(null, "100"))
+ addRow(arrayOf("-100", "100"))
+ addRow(arrayOf("100", "-100"))
+ addRow(arrayOf("100", "abc"))
+ addRow(arrayOf("abc", "100"))
+ }
+
+ var i = 0
+ while (cursor.moveToNext()) {
+ i++
+ assertWithMessage("Row $i").that(cursor.readSize()).isNull()
+ }
+ }
+
+ @Test
+ fun testCorrectSizeValues() = runTest {
+ val cursor =
+ MatrixCursor(arrayOf(HEIGHT, WIDTH)).apply {
+ addRow(arrayOf("100", 0))
+ addRow(arrayOf("100", "50"))
+ }
+
+ cursor.moveToNext()
+ assertThat(cursor.readSize()).isEqualTo(Size(0, 100))
+
+ cursor.moveToNext()
+ assertThat(cursor.readSize()).isEqualTo(Size(50, 100))
+ }
+}
diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolverTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolverTest.kt
new file mode 100644
index 00000000..9eaee233
--- /dev/null
+++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/PayloadToggleCursorResolverTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor
+
+import android.content.ContentInterface
+import android.content.Intent
+import android.database.MatrixCursor
+import android.net.Uri
+import android.provider.MediaStore.MediaColumns.HEIGHT
+import android.provider.MediaStore.MediaColumns.WIDTH
+import android.service.chooser.AdditionalContentContract.Columns.URI
+import android.util.Size
+import com.android.intentresolver.util.cursor.get
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+
+class PayloadToggleCursorResolverTest {
+ private val cursorUri = Uri.parse("content://org.pkg.app.extra")
+ private val chooserIntent = Intent()
+
+ @Test
+ fun missingSizeColumns() = runTest {
+ val uri = createUri(1)
+ val sourceCursor =
+ MatrixCursor(arrayOf(URI)).apply {
+ addRow(arrayOf(uri.toString()))
+ addRow(
+ arrayOf(
+ cursorUri.buildUpon().appendPath("should-be-ignored.png").build().toString()
+ )
+ )
+ addRow(arrayOf(null))
+ }
+ val fakeContentProvider =
+ mock<ContentInterface> {
+ on { query(eq(cursorUri), any(), any(), any()) } doReturn sourceCursor
+ }
+ val testSubject =
+ PayloadToggleCursorResolver(
+ fakeContentProvider,
+ cursorUri,
+ chooserIntent,
+ )
+
+ val cursor = testSubject.getCursor()
+ assertThat(cursor).isNotNull()
+ assertThat(cursor!!.count).isEqualTo(3)
+ cursor[0].let { row ->
+ assertThat(row).isNotNull()
+ assertThat(row!!.uri).isEqualTo(uri)
+ assertThat(row.previewSize).isNull()
+ }
+ assertThat(cursor[1]).isNull()
+ assertThat(cursor[2]).isNull()
+ }
+
+ @Test
+ fun testCorrectSizeValues() = runTest {
+ val uri = createUri(1)
+ val sourceCursor =
+ MatrixCursor(arrayOf(URI, WIDTH, HEIGHT)).apply {
+ addRow(arrayOf(uri.toString(), "100", "50"))
+ }
+ val fakeContentProvider =
+ mock<ContentInterface> {
+ on { query(eq(cursorUri), any(), any(), any()) } doReturn sourceCursor
+ }
+ val testSubject =
+ PayloadToggleCursorResolver(
+ fakeContentProvider,
+ cursorUri,
+ chooserIntent,
+ )
+
+ val cursor = testSubject.getCursor()
+ assertThat(cursor).isNotNull()
+ assertThat(cursor!!.count).isEqualTo(1)
+
+ cursor[0].let { row ->
+ assertThat(row).isNotNull()
+ assertThat(row!!.uri).isEqualTo(uri)
+ assertThat(row.previewSize).isEqualTo(Size(100, 50))
+ }
+ }
+}
+
+private fun createUri(id: Int) = Uri.parse("content://org.pkg/app/img-$id.png")
diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt
index af6de833..81e6b77d 100644
--- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt
+++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt
@@ -24,9 +24,11 @@ import androidx.core.os.bundleOf
import com.android.intentresolver.contentpreview.FileInfo
import com.android.intentresolver.contentpreview.UriMetadataReader
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel
import com.android.intentresolver.contentpreview.uriMetadataReader
import com.android.intentresolver.util.KosmosTestScope
+import com.android.intentresolver.util.cursor.CursorView
import com.android.intentresolver.util.cursor.viewBy
import com.android.intentresolver.util.runTest
import com.android.systemui.kosmos.Kosmos
@@ -70,7 +72,7 @@ class CursorPreviewsInteractorTest {
private val cursorRange: Iterable<Int>,
private val cursorStartPosition: Int,
) {
- val cursor =
+ val cursor: CursorView<CursorRow?> =
MatrixCursor(arrayOf("uri"))
.apply {
extras = bundleOf("position" to cursorStartPosition)
@@ -78,7 +80,7 @@ class CursorPreviewsInteractorTest {
newRow().add("uri", uri(i).toString())
}
}
- .viewBy { getString(0)?.let(Uri::parse) }
+ .viewBy { getString(0)?.let { uriStr -> CursorRow(Uri.parse(uriStr), null) } }
val initialPreviews: List<PreviewModel> =
initialSelectionRange.map { i -> PreviewModel(uri = uri(i), mimeType = "image/bitmap") }
diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt
index f012fcc6..da73f4cf 100644
--- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt
+++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt
@@ -26,6 +26,7 @@ import com.android.intentresolver.contentpreview.UriMetadataReader
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository
import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.CursorResolver
import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.payloadToggleCursorResolver
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel
import com.android.intentresolver.contentpreview.uriMetadataReader
@@ -74,12 +75,12 @@ class FetchPreviewsInteractorTest {
private class FakeCursorResolver(
private val cursorRange: Iterable<Int>,
private val cursorStartPosition: Int,
- ) : CursorResolver<Uri?> {
+ ) : CursorResolver<CursorRow?> {
private val mutex = Mutex(locked = true)
fun complete() = mutex.unlock()
- override suspend fun getCursor(): CursorView<Uri?> =
+ override suspend fun getCursor(): CursorView<CursorRow?> =
mutex.withLock {
MatrixCursor(arrayOf("uri"))
.apply {
@@ -88,7 +89,7 @@ class FetchPreviewsInteractorTest {
newRow().add("uri", uri(i).toString())
}
}
- .viewBy { getString(0)?.let(Uri::parse) }
+ .viewBy { getString(0)?.let(Uri::parse)?.let { CursorRow(it, null) } }
}
}