diff options
author | 2024-05-22 09:41:34 -0400 | |
---|---|---|
committer | 2024-05-23 13:54:42 -0400 | |
commit | 1dc90519a76292138c346a5622ac5571713fc030 (patch) | |
tree | b659a4aa3d76f7786ba008d57fdbc519f1367f69 | |
parent | f1fd7bf9ce6db12ff68430f4c563bf04ebcf1a41 (diff) |
Preload full set of preview image metadata pages
This is the first step in mitigating the bottleneck of slow metadata
loading by proactively loading pages to the max window size.
Test: atest CursorPreviewsInteractorTest FetchPreviewsInteractorTest
Test: manual test using ShareTest with high metadata latency
BUG: 341923886
Flag: android.service.chooser.chooser_payload_toggling
Change-Id: I1192e7bdf7db77573990745dd5b05d7ef86d7f20
3 files changed, 61 insertions, 157 deletions
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 97b087e1..f02834e0 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 @@ -76,10 +76,42 @@ constructor( .toMap(ConcurrentHashMap()) val pagedCursor: PagedCursor<CursorRow?> = uriCursor.paged(pageSize) val startPosition = uriCursor.extras?.getInt(POSITION, 0) ?: 0 - val state = readInitialState(pagedCursor, startPosition, unclaimedRecords) + val state = + loadToMaxPages( + initialState = readInitialState(pagedCursor, startPosition, unclaimedRecords), + pagedCursor = pagedCursor, + unclaimedRecords = unclaimedRecords, + ) processLoadRequests(state, pagedCursor, unclaimedRecords) } + private suspend fun loadToMaxPages( + initialState: CursorWindow, + pagedCursor: PagedCursor<CursorRow?>, + unclaimedRecords: MutableUnclaimedMap, + ): CursorWindow { + var state = initialState + val startPageNum = state.firstLoadedPageNum + while ((state.hasMoreLeft || state.hasMoreRight) && state.numLoadedPages < maxLoadedPages) { + interactor.setPreviews( + previewsByKey = state.merged.values.toSet(), + startIndex = startPageNum, + hasMoreLeft = state.hasMoreLeft, + hasMoreRight = state.hasMoreRight, + ) + val loadedLeft = startPageNum - state.firstLoadedPageNum + val loadedRight = state.lastLoadedPageNum - startPageNum + state = + when { + state.hasMoreLeft && loadedLeft < loadedRight -> + state.loadMoreLeft(pagedCursor, unclaimedRecords) + state.hasMoreRight -> state.loadMoreRight(pagedCursor, unclaimedRecords) + else -> state.loadMoreLeft(pagedCursor, unclaimedRecords) + } + } + return state + } + /** Loop forever, processing any loading requests from the UI and updating local cache. */ private suspend fun processLoadRequests( initialState: CursorWindow, @@ -301,5 +333,5 @@ annotation class MaxLoadedPages object ShareouselConstants { @Provides @PageSize fun pageSize(): Int = 16 - @Provides @MaxLoadedPages fun maxLoadedPages(): Int = 3 + @Provides @MaxLoadedPages fun maxLoadedPages(): Int = 8 } 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 ff699373..45e456e0 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 @@ -111,8 +111,12 @@ class CursorPreviewsInteractorTest { @Test fun initialCursorLoad() = runTestWithDeps( + cursor = (0 until 10), + cursorStartPosition = 2, cursorSizes = mapOf(0 to (200 x 100)), - metadatSizes = mapOf(0 to (300 x 100), 3 to (400 x 100)) + metadatSizes = mapOf(0 to (300 x 100), 3 to (400 x 100)), + pageSize = 2, + maxLoadedPages = 3, ) { deps -> backgroundScope.launch { cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) @@ -120,31 +124,27 @@ class CursorPreviewsInteractorTest { runCurrent() assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.startIdx).isEqualTo(0) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels) - .containsExactly( - PreviewModel( - uri = Uri.fromParts("scheme0", "ssp0", "fragment0"), - mimeType = "image/bitmap", - aspectRatio = 2f, - ), - PreviewModel( - uri = Uri.fromParts("scheme1", "ssp1", "fragment1"), - mimeType = "image/bitmap" - ), - PreviewModel( - uri = Uri.fromParts("scheme2", "ssp2", "fragment2"), - mimeType = "image/bitmap" - ), - PreviewModel( - uri = Uri.fromParts("scheme3", "ssp3", "fragment3"), - mimeType = "image/bitmap", - aspectRatio = 4f, - ), - ) - .inOrder() + with(cursorPreviewsRepository.previewsModel.value!!) { + assertThat(previewModels) + .containsExactlyElementsIn( + List(6) { + PreviewModel( + uri = Uri.fromParts("scheme$it", "ssp$it", "fragment$it"), + mimeType = "image/bitmap", + aspectRatio = + when (it) { + 0 -> 2f + 3 -> 4f + else -> 1f + } + ) + } + ) + .inOrder() + assertThat(startIdx).isEqualTo(0) + assertThat(loadMoreLeft).isNull() + assertThat(loadMoreRight).isNotNull() + } } @Test @@ -181,39 +181,6 @@ class CursorPreviewsInteractorTest { } @Test - fun loadMoreLeft_keepRight() = - runTestWithDeps( - initialSelection = listOf(24), - cursor = (0 until 48), - pageSize = 16, - maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { - cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) - } - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNotNull() - - cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() - } - - @Test fun loadMoreRight_evictLeft() = runTestWithDeps( initialSelection = listOf(24), @@ -246,38 +213,6 @@ class CursorPreviewsInteractorTest { } @Test - fun loadMoreRight_keepLeft() = - runTestWithDeps( - initialSelection = listOf(24), - cursor = (0 until 48), - pageSize = 16, - maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { - cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) - } - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - - cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) - } - - @Test fun noMoreRight_appendUnclaimedFromInitialSelection() = runTestWithDeps( initialSelection = listOf(24, 50), 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 735bcb1d..146892d0 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 @@ -53,7 +53,7 @@ class FetchPreviewsInteractorTest { cursor: Iterable<Int> = (0 until 4), cursorStartPosition: Int = cursor.count() / 2, pageSize: Int = 16, - maxLoadedPages: Int = 3, + maxLoadedPages: Int = 8, previewSizes: Map<Int, Size> = emptyMap(), block: KosmosTestScope.() -> Unit, ) { @@ -202,38 +202,6 @@ class FetchPreviewsInteractorTest { } @Test - fun loadMoreLeft_keepRight() = - runTest( - initialSelection = listOf(24), - cursor = (0 until 48), - pageSize = 16, - maxLoadedPages = 2, - ) { - backgroundScope.launch { fetchPreviewsInteractor.activate() } - fakeCursorResolver.complete() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNotNull() - - cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() - } - - @Test fun loadMoreRight_evictLeft() = runTest( initialSelection = listOf(24), @@ -265,37 +233,6 @@ class FetchPreviewsInteractorTest { } @Test - fun loadMoreRight_keepLeft() = - runTest( - initialSelection = listOf(24), - cursor = (0 until 48), - pageSize = 16, - maxLoadedPages = 2, - ) { - backgroundScope.launch { fetchPreviewsInteractor.activate() } - fakeCursorResolver.complete() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - - cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() - runCurrent() - - assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) - } - - @Test fun noMoreRight_appendUnclaimedFromInitialSelection() = runTest( initialSelection = listOf(24, 50), |