1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor 18 19 import android.content.ContentInterface 20 import android.content.Intent 21 import android.database.Cursor 22 import android.net.Uri 23 import android.provider.MediaStore.MediaColumns.HEIGHT 24 import android.provider.MediaStore.MediaColumns.WIDTH 25 import android.service.chooser.AdditionalContentContract.Columns.URI 26 import androidx.core.os.bundleOf 27 import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow 28 import com.android.intentresolver.contentpreview.readSize 29 import com.android.intentresolver.inject.AdditionalContent 30 import com.android.intentresolver.inject.ChooserIntent 31 import com.android.intentresolver.util.cursor.CursorView 32 import com.android.intentresolver.util.cursor.viewBy 33 import com.android.intentresolver.util.withCancellationSignal 34 import dagger.Binds 35 import dagger.Module 36 import dagger.hilt.InstallIn 37 import dagger.hilt.android.components.ViewModelComponent 38 import javax.inject.Inject 39 import javax.inject.Qualifier 40 41 /** [CursorResolver] for the [CursorView] underpinning Shareousel. */ 42 class PayloadToggleCursorResolver 43 @Inject 44 constructor( 45 private val contentResolver: ContentInterface, 46 @AdditionalContent private val cursorUri: Uri, 47 @ChooserIntent private val chooserIntent: Intent, 48 ) : CursorResolver<CursorRow?> { 49 override suspend fun getCursor(): CursorView<CursorRow?>? = withCancellationSignal { signal -> 50 runCatching { 51 contentResolver.query( 52 cursorUri, 53 arrayOf(URI, WIDTH, HEIGHT), 54 bundleOf(Intent.EXTRA_INTENT to chooserIntent), 55 signal, 56 ) 57 } 58 .getOrNull() 59 ?.viewBy { readUri()?.let { uri -> CursorRow(uri, readSize(), position) } } 60 } 61 62 private fun Cursor.readUri(): Uri? { 63 val uriIdx = columnNames.indexOf(URI) 64 if (uriIdx < 0) return null 65 return runCatching { 66 getString(uriIdx)?.let(Uri::parse)?.takeIf { it.authority != cursorUri.authority } 67 } 68 .getOrNull() 69 } 70 71 @Module 72 @InstallIn(ViewModelComponent::class) 73 interface Binding { 74 @Binds 75 @PayloadToggle 76 fun bind(cursorResolver: PayloadToggleCursorResolver): CursorResolver<CursorRow?> 77 } 78 } 79 80 /** [CursorResolver] for the [CursorView] underpinning Shareousel. */ 81 @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class PayloadToggle 82