• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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