• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.systemui.screenshot
18 
19 import android.content.ClipData
20 import android.content.ClipDescription
21 import android.content.ComponentName
22 import android.content.ContentProvider
23 import android.content.Context
24 import android.content.Intent
25 import android.net.Uri
26 import android.os.UserHandle
27 import com.android.systemui.res.R
28 import com.android.systemui.screenshot.scroll.LongScreenshotActivity
29 
30 object ActionIntentCreator {
31     /** @return a chooser intent to share the given URI. */
createSharenull32     fun createShare(uri: Uri): Intent = createShare(uri, subject = null, text = null)
33 
34     /** @return a chooser intent to share the given URI with the optional provided subject. */
35     fun createShareWithSubject(uri: Uri, subject: String): Intent =
36         createShare(uri, subject = subject)
37 
38     /** @return a chooser intent to share the given URI with the optional provided extra text. */
39     fun createShareWithText(uri: Uri, extraText: String): Intent =
40         createShare(uri, text = extraText)
41 
42     private fun createShare(rawUri: Uri, subject: String? = null, text: String? = null): Intent {
43         val uri = uriWithoutUserId(rawUri)
44 
45         // Create a share intent, this will always go through the chooser activity first
46         // which should not trigger auto-enter PiP
47         val sharingIntent =
48             Intent(Intent.ACTION_SEND).apply {
49                 setDataAndType(uri, "image/png")
50                 putExtra(Intent.EXTRA_STREAM, uri)
51 
52                 // Include URI in ClipData also, so that grantPermission picks it up.
53                 // We don't use setData here because some apps interpret this as "to:".
54                 clipData =
55                     ClipData(
56                         ClipDescription("content", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)),
57                         ClipData.Item(uri)
58                     )
59 
60                 subject?.let { putExtra(Intent.EXTRA_SUBJECT, subject) }
61                 text?.let { putExtra(Intent.EXTRA_TEXT, text) }
62                 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
63                 addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
64             }
65 
66         return Intent.createChooser(sharingIntent, null)
67             .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
68             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
69             .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
70     }
71 
72     /**
73      * @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
74      *   available.
75      */
createEditnull76     fun createEdit(rawUri: Uri, context: Context): Intent {
77         val uri = uriWithoutUserId(rawUri)
78         val editIntent = Intent(Intent.ACTION_EDIT)
79 
80         val editor = context.getString(R.string.config_screenshotEditor)
81         if (editor.isNotEmpty()) {
82             editIntent.component = ComponentName.unflattenFromString(editor)
83         }
84 
85         return editIntent
86             .setDataAndType(uri, "image/png")
87             .putExtra(EXTRA_EDIT_SOURCE, EDIT_SOURCE_SCREENSHOT)
88             .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
89             .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
90             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
91             .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
92     }
93 
94     /** @return an Intent to start the LongScreenshotActivity */
createLongScreenshotIntentnull95     fun createLongScreenshotIntent(owner: UserHandle, context: Context): Intent {
96         return Intent(context, LongScreenshotActivity::class.java)
97             .putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE, owner)
98             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
99             .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
100             .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
101     }
102 
103     private const val EXTRA_EDIT_SOURCE = "edit_source"
104     private const val EDIT_SOURCE_SCREENSHOT = "screenshot"
105 }
106 
107 /**
108  * URIs here are passed only via Intent which are sent to the target user via Intent. Because of
109  * this, the userId component can be removed to prevent compatibility issues when an app attempts
110  * valid a URI containing a userId within the authority.
111  */
uriWithoutUserIdnull112 private fun uriWithoutUserId(uri: Uri): Uri {
113     return ContentProvider.getUriWithoutUserId(uri)
114 }
115