diff options
| author | 2024-02-08 11:49:57 -0800 | |
|---|---|---|
| committer | 2024-02-08 11:49:57 -0800 | |
| commit | 088ca398b615c202c536bee617a0d6d3d356159d (patch) | |
| tree | 472f3093e5d66807e03d8ef2a169ca35e4ed685e /java/src | |
| parent | 9155b17d49ec45bd787b3c45de6324278ebe0928 (diff) | |
Shareousel cursor reader
A building block for the payload toggling functinality -- a
bi-directional cursor reaer that starts reading URIs from the cursor
starting at a specified position ignoring all items thad does not match
a given predicate.
Bug: 302691505
Test: IntentResolver-tests-unit
Change-Id: I83d40435f4b73c73f6d8b49080645a008d34727b
Diffstat (limited to 'java/src')
| -rw-r--r-- | java/src/com/android/intentresolver/contentpreview/CursorUriReader.kt | 99 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt | 12 |
2 files changed, 111 insertions, 0 deletions
diff --git a/java/src/com/android/intentresolver/contentpreview/CursorUriReader.kt b/java/src/com/android/intentresolver/contentpreview/CursorUriReader.kt new file mode 100644 index 00000000..30495b8b --- /dev/null +++ b/java/src/com/android/intentresolver/contentpreview/CursorUriReader.kt @@ -0,0 +1,99 @@ +/* + * 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.Cursor +import android.net.Uri +import android.util.Log +import android.util.SparseArray + +private const val TAG = ContentPreviewUi.TAG + +/** + * A bi-directional cursor reader. Reads URI from the [cursor] starting from the given [startPos], + * filters items by [predicate]. + */ +class CursorUriReader( + private val cursor: Cursor, + startPos: Int, + private val pageSize: Int, + private val predicate: (Uri) -> Boolean, +) : PayloadToggleInteractor.CursorReader { + override val count = cursor.count + // the first position of the next unread page on the right + private var rightPos = startPos.coerceIn(0, count) + // the first position of the next from the leftmost unread page on the left + private var leftPos = rightPos + + override val hasMoreBefore + get() = leftPos > 0 + + override val hasMoreAfter + get() = rightPos < count + + override fun readPageAfter(): SparseArray<Uri> { + if (!hasMoreAfter) return SparseArray() + if (!cursor.moveToPosition(rightPos)) { + rightPos = count + Log.w(TAG, "Failed to move the cursor to position $rightPos, stop reading the cursor") + return SparseArray() + } + val result = SparseArray<Uri>(pageSize) + do { + cursor + .getString(0) + ?.let(Uri::parse) + ?.takeIf { predicate(it) } + ?.let { uri -> result.append(rightPos, uri) } + rightPos++ + } while (result.size() < pageSize && cursor.moveToNext()) + maybeCloseCursor() + return result + } + + override fun readPageBefore(): SparseArray<Uri> { + if (!hasMoreBefore) return SparseArray() + val startPos = maxOf(0, leftPos - pageSize) + if (!cursor.moveToPosition(startPos)) { + leftPos = 0 + Log.w(TAG, "Failed to move the cursor to position $startPos, stop reading cursor") + return SparseArray() + } + val result = SparseArray<Uri>(leftPos - startPos) + for (pos in startPos ..< leftPos) { + cursor + .getString(0) + ?.let(Uri::parse) + ?.takeIf { predicate(it) } + ?.let { uri -> result.append(pos, uri) } + if (!cursor.moveToNext()) break + } + leftPos = startPos + maybeCloseCursor() + return result + } + + private fun maybeCloseCursor() { + if (!hasMoreBefore && !hasMoreAfter) { + close() + } + } + + override fun close() { + cursor.close() + } +} diff --git a/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt b/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt index 0e6d3869..87f53e85 100644 --- a/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt +++ b/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt @@ -17,6 +17,8 @@ package com.android.intentresolver.contentpreview import android.net.Uri +import android.util.SparseArray +import java.io.Closeable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf @@ -48,6 +50,16 @@ class PayloadToggleInteractor { private data class Item( val previewUri: Uri?, ) + + interface CursorReader : Closeable { + val count: Int + val hasMoreBefore: Boolean + val hasMoreAfter: Boolean + + fun readPageAfter(): SparseArray<Uri> + + fun readPageBefore(): SparseArray<Uri> + } } class PayloadTogglePreviewInteractor( |