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 package com.android.intentresolver.data.model 17 18 import android.content.ComponentName 19 import android.content.Intent 20 import android.content.Intent.ACTION_SEND 21 import android.content.Intent.ACTION_SEND_MULTIPLE 22 import android.content.Intent.EXTRA_REFERRER 23 import android.content.IntentFilter 24 import android.content.IntentSender 25 import android.net.Uri 26 import android.os.Bundle 27 import android.service.chooser.ChooserAction 28 import android.service.chooser.ChooserTarget 29 import androidx.annotation.StringRes 30 import com.android.intentresolver.ContentTypeHint 31 import com.android.intentresolver.IChooserInteractiveSessionCallback 32 import com.android.intentresolver.ext.hasAction 33 import com.android.systemui.shared.Flags.screenshotContextUrl 34 35 const val ANDROID_APP_SCHEME = "android-app" 36 37 /** All of the things that are consumed from an incoming share Intent (+Extras). */ 38 data class ChooserRequest( 39 /** Required. Represents the content being sent. */ 40 val targetIntent: Intent, 41 42 /** The action from [targetIntent] as retrieved with [Intent.getAction]. */ 43 val targetAction: String? = targetIntent.action, 44 45 /** 46 * Whether [targetAction] is ACTION_SEND or ACTION_SEND_MULTIPLE. These are considered the 47 * canonical "Share" actions. When handling other actions, this flag controls behavioral and 48 * visual changes. 49 */ 50 val isSendActionTarget: Boolean = targetIntent.hasAction(ACTION_SEND, ACTION_SEND_MULTIPLE), 51 52 /** The top-level content type as retrieved using [Intent.getType]. */ 53 val targetType: String? = targetIntent.type, 54 55 /** The package name of the app which started the current activity instance. */ 56 val launchedFromPackage: String, 57 58 /** A custom tile for the main UI. Ignored when the intent is ACTION_SEND(_MULTIPLE). */ 59 val title: CharSequence? = null, 60 61 /** A String resource ID to load when [title] is null. */ 62 @get:StringRes val defaultTitleResource: Int = 0, 63 64 /** 65 * The referrer value as received by the caller. It may have been supplied via [EXTRA_REFERRER] 66 * or synthesized from callerPackageName. This value is merged into outgoing intents. 67 */ 68 val referrer: Uri? = null, 69 70 /** 71 * Choices to exclude from results. 72 * 73 * Any resolved intents with a component in this list will be omitted before presentation. 74 */ 75 val filteredComponentNames: List<ComponentName> = emptyList(), 76 77 /** 78 * App provided shortcut share intents (aka "direct share targets") 79 * 80 * Normally share shortcuts are published and consumed using 81 * [ShortcutManager][android.content.pm.ShortcutManager]. This is an alternate channel to allow 82 * apps to directly inject the same information. 83 * 84 * Historical note: This option was initially integrated with other results from the 85 * ChooserTargetService API (since deprecated and removed), hence the name and data format. 86 * These are more correctly called "Share Shortcuts" now. 87 */ 88 val callerChooserTargets: List<ChooserTarget> = emptyList(), 89 90 /** 91 * Actions the user may perform. These are presented as separate affordances from the main list 92 * of choices. Selecting a choice is a terminal action which results in finishing. The item 93 * limit is [MAX_CHOOSER_ACTIONS]. This may be further constrained as appropriate. 94 */ 95 val chooserActions: List<ChooserAction> = emptyList(), 96 97 /** 98 * An action to start an Activity which for user updating of shared content. Selection is a 99 * terminal action, closing the current activity and launching the target of the action. 100 */ 101 val modifyShareAction: ChooserAction? = null, 102 103 /** 104 * When false the host activity will be [finished][android.app.Activity.finish] when stopped. 105 */ 106 @get:JvmName("shouldRetainInOnStop") val shouldRetainInOnStop: Boolean = false, 107 108 /** 109 * Intents which contain alternate representations of the content being shared. Any results from 110 * resolving these _alternate_ intents are included with the results of the primary intent as 111 * additional choices (e.g. share as image content vs. link to content). 112 */ 113 val additionalTargets: List<Intent> = emptyList(), 114 115 /** 116 * Alternate [extras][Intent.getExtras] to substitute when launching a selected app. 117 * 118 * For a given app (by package name), the Bundle describes what parameters to substitute when 119 * that app is selected. 120 * 121 * // TODO: Map<String, Bundle> 122 */ 123 val replacementExtras: Bundle? = null, 124 125 /** 126 * App-supplied choices to be presented first in the list. 127 * 128 * Custom labels and icons may be supplied using 129 * [LabeledIntent][android.content.pm.LabeledIntent]. 130 * 131 * Limit 2. 132 */ 133 val initialIntents: List<Intent> = emptyList(), 134 135 /** 136 * Provides for callers to be notified when a component is selected. 137 * 138 * The selection is reported in the Intent as [Intent.EXTRA_CHOSEN_COMPONENT] with the 139 * [ComponentName] of the item. 140 */ 141 val chosenComponentSender: IntentSender? = null, 142 143 /** 144 * Provides a mechanism for callers to post-process a target when a selection is made. 145 * 146 * The received intent will contain: 147 * * **EXTRA_INTENT** The chosen target 148 * * **EXTRA_ALTERNATE_INTENTS** Additional intents which also match the target 149 * * **EXTRA_RESULT_RECEIVER** A [ResultReceiver][android.os.ResultReceiver] providing a 150 * mechanism for the caller to return information. An updated intent to send must be included 151 * as [Intent.EXTRA_INTENT]. 152 */ 153 val refinementIntentSender: IntentSender? = null, 154 155 /** 156 * Contains the text content to share supplied by the source app. 157 * 158 * TODO: Constrain length? 159 */ 160 val sharedText: CharSequence? = null, 161 /** Contains title to the text content to share supplied by the source app. */ 162 val sharedTextTitle: CharSequence? = null, 163 164 /** 165 * Supplied to 166 * [ShortcutManager.getShareTargets][android.content.pm.ShortcutManager.getShareTargets] to 167 * query for matching shortcuts. Specifically, only the [dataTypes][IntentFilter.hasDataType] 168 * are considered for matching share shortcuts currently. 169 */ 170 val shareTargetFilter: IntentFilter? = null, 171 172 /** A URI for additional content */ 173 val additionalContentUri: Uri? = null, 174 175 /** Focused item index (from target intent's STREAM_EXTRA) */ 176 val focusedItemPosition: Int = 0, 177 178 /** Value for [Intent.EXTRA_CHOOSER_CONTENT_TYPE_HINT] on the incoming chooser intent. */ 179 val contentTypeHint: ContentTypeHint = ContentTypeHint.NONE, 180 181 /** 182 * Metadata to be shown to the user as a part of the sharesheet window. 183 * 184 * Specified by the [Intent.EXTRA_METADATA_TEXT] 185 */ 186 val metadataText: CharSequence? = null, 187 val interactiveSessionCallback: IChooserInteractiveSessionCallback? = null, 188 ) { 189 val referrerPackage = referrer?.takeIf { it.scheme == ANDROID_APP_SCHEME }?.authority 190 191 fun getReferrerFillInIntent(): Intent { 192 return Intent().apply { 193 referrerPackage?.also { pkg -> 194 putExtra(EXTRA_REFERRER, Uri.parse("$ANDROID_APP_SCHEME://$pkg")) 195 } 196 } 197 } 198 199 val payloadIntents = listOf(targetIntent) + additionalTargets 200 201 val callerAllowsTextToggle = 202 screenshotContextUrl() && "com.android.systemui".equals(referrerPackage) 203 } 204