summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Miranda Kephart <mkephart@google.com> 2024-04-04 14:07:23 -0400
committer Matt Casey <mrcasey@google.com> 2024-04-08 13:37:37 +0000
commit431c56498bf12d4d704c29f001e99d4d4f49dd77 (patch)
tree05e263a9304905fc56d15f5368f12f7bd5b7a813
parentf1e70448a03ae78cf3cbb22c1bd329714b720779 (diff)
Create ScreenshotResult class to simplify null checks
Bug: 329659738 Test: atest DefaultScreenshotActionsProviderTest Flag: ACONFIG com.android.systemui.screenshot_shelf_ui DEVELOPMENT Change-Id: I0fced77866375aa3d9fc447343884c96a9c6a936 Merged-In: I0fced77866375aa3d9fc447343884c96a9c6a936
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt136
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt20
6 files changed, 109 insertions, 122 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
index 60c44309fb07..6b0178336a72 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
@@ -23,21 +23,17 @@ import android.app.PendingIntent
import android.app.assist.AssistContent
import android.content.Context
import android.content.Intent
-import android.os.Process
import android.os.UserHandle
-import android.provider.DeviceConfig
import android.util.Log
import android.util.Pair
import androidx.appcompat.content.res.AppCompatResources
import com.android.app.tracing.coroutines.launch
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.res.R
import com.android.systemui.screenshot.ActionIntentCreator.createEdit
import com.android.systemui.screenshot.ActionIntentCreator.createShareWithSubject
-import com.android.systemui.screenshot.ScreenshotController.SavedImageData
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED
@@ -47,8 +43,6 @@ import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import java.text.DateFormat
-import java.util.Date
import kotlinx.coroutines.CoroutineScope
/**
@@ -56,7 +50,7 @@ import kotlinx.coroutines.CoroutineScope
* implementation.
*/
interface ScreenshotActionsProvider {
- fun setCompletedScreenshot(result: SavedImageData)
+ fun setCompletedScreenshot(result: ScreenshotSavedResult)
fun isPendingSharedTransition(): Boolean
fun onAssistContentAvailable(assistContent: AssistContent) {}
@@ -85,8 +79,8 @@ constructor(
@Assisted val windowTransition: () -> Pair<ActivityOptions, ExitTransitionCoordinator>,
@Assisted val requestDismissal: () -> Unit,
) : ScreenshotActionsProvider {
- private var pendingAction: ((SavedImageData) -> Unit)? = null
- private var result: SavedImageData? = null
+ private var pendingAction: ((ScreenshotSavedResult) -> Unit)? = null
+ private var result: ScreenshotSavedResult? = null
private var isPendingSharedTransition = false
init {
@@ -94,7 +88,7 @@ constructor(
debugLog(LogConfig.DEBUG_ACTIONS) { "Preview tapped" }
uiEventLogger.log(SCREENSHOT_PREVIEW_TAPPED, 0, request.packageNameString)
onDeferrableActionTapped { result ->
- startSharedTransition(createEdit(result.uri, context), true)
+ startSharedTransition(createEdit(result.uri, context), result.user, true)
}
}
viewModel.addAction(
@@ -106,7 +100,7 @@ constructor(
debugLog(LogConfig.DEBUG_ACTIONS) { "Edit tapped" }
uiEventLogger.log(SCREENSHOT_EDIT_TAPPED, 0, request.packageNameString)
onDeferrableActionTapped { result ->
- startSharedTransition(createEdit(result.uri, context), true)
+ startSharedTransition(createEdit(result.uri, context), result.user, true)
}
}
)
@@ -119,74 +113,58 @@ constructor(
debugLog(LogConfig.DEBUG_ACTIONS) { "Share tapped" }
uiEventLogger.log(SCREENSHOT_SHARE_TAPPED, 0, request.packageNameString)
onDeferrableActionTapped { result ->
- startSharedTransition(createShareWithSubject(result.uri, result.subject), false)
+ startSharedTransition(
+ createShareWithSubject(result.uri, result.subject),
+ result.user,
+ false
+ )
}
}
)
- if (smartActionsEnabled(request.userHandle ?: Process.myUserHandle())) {
- smartActionsProvider.requestQuickShare(request, requestId) { quickShare ->
- if (!quickShare.actionIntent.isImmutable) {
- viewModel.addAction(
- ActionButtonViewModel(
- quickShare.getIcon().loadDrawable(context),
- quickShare.title,
- quickShare.title,
- ) {
- debugLog(LogConfig.DEBUG_ACTIONS) { "Quickshare tapped" }
- onDeferrableActionTapped { result ->
- uiEventLogger.log(
- SCREENSHOT_SMART_ACTION_TAPPED,
- 0,
- request.packageNameString
- )
- sendPendingIntent(
- smartActionsProvider
- .wrapIntent(
- quickShare,
- result.uri,
- result.subject,
- requestId
- )
- .actionIntent
- )
- }
+ smartActionsProvider.requestQuickShare(request, requestId) { quickShare ->
+ if (!quickShare.actionIntent.isImmutable) {
+ viewModel.addAction(
+ ActionButtonViewModel(
+ quickShare.getIcon().loadDrawable(context),
+ quickShare.title,
+ quickShare.title
+ ) {
+ debugLog(LogConfig.DEBUG_ACTIONS) { "Quickshare tapped" }
+ onDeferrableActionTapped { result ->
+ uiEventLogger.log(
+ SCREENSHOT_SMART_ACTION_TAPPED,
+ 0,
+ request.packageNameString
+ )
+ sendPendingIntent(
+ smartActionsProvider
+ .wrapIntent(quickShare, result.uri, result.subject, requestId)
+ .actionIntent
+ )
}
- )
- } else {
- Log.w(TAG, "Received immutable quick share pending intent; ignoring")
- }
+ }
+ )
+ } else {
+ Log.w(TAG, "Received immutable quick share pending intent; ignoring")
}
}
}
- override fun setCompletedScreenshot(result: SavedImageData) {
+ override fun setCompletedScreenshot(result: ScreenshotSavedResult) {
if (this.result != null) {
Log.e(TAG, "Got a second completed screenshot for existing request!")
return
}
- if (result.uri == null || result.owner == null || result.imageTime == null) {
- Log.e(TAG, "Invalid result provided!")
- return
- }
- if (result.subject == null) {
- result.subject = getSubjectString(result.imageTime)
- }
this.result = result
pendingAction?.invoke(result)
- if (smartActionsEnabled(result.owner)) {
- smartActionsProvider.requestSmartActions(request, requestId, result) { smartActions ->
- viewModel.addActions(
- smartActions.map {
- ActionButtonViewModel(
- it.getIcon().loadDrawable(context),
- it.title,
- it.title,
- ) {
- sendPendingIntent(it.actionIntent)
- }
+ smartActionsProvider.requestSmartActions(request, requestId, result) { smartActions ->
+ viewModel.addActions(
+ smartActions.map {
+ ActionButtonViewModel(it.getIcon().loadDrawable(context), it.title, it.title) {
+ sendPendingIntent(it.actionIntent)
}
- )
- }
+ }
+ )
}
}
@@ -194,17 +172,15 @@ constructor(
return isPendingSharedTransition
}
- private fun onDeferrableActionTapped(onResult: (SavedImageData) -> Unit) {
+ private fun onDeferrableActionTapped(onResult: (ScreenshotSavedResult) -> Unit) {
result?.let { onResult.invoke(it) } ?: run { pendingAction = onResult }
}
- private fun startSharedTransition(intent: Intent, overrideTransition: Boolean) {
- val user =
- result?.owner
- ?: run {
- Log.wtf(TAG, "User handle not provided in screenshot result! Result: $result")
- return
- }
+ private fun startSharedTransition(
+ intent: Intent,
+ user: UserHandle,
+ overrideTransition: Boolean
+ ) {
isPendingSharedTransition = true
applicationScope.launch("$TAG#launchIntentAsync") {
actionExecutor.launchIntent(intent, windowTransition.invoke(), user, overrideTransition)
@@ -225,21 +201,6 @@ constructor(
}
}
- private fun smartActionsEnabled(user: UserHandle): Boolean {
- val savingToOtherUser = user != Process.myUserHandle()
- return !savingToOtherUser &&
- DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS,
- true
- )
- }
-
- private fun getSubjectString(imageTime: Long): String {
- val subjectDate = DateFormat.getDateTimeInstance().format(Date(imageTime))
- return String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate)
- }
-
@AssistedFactory
interface Factory : ScreenshotActionsProvider.Factory {
override fun create(
@@ -252,6 +213,5 @@ constructor(
companion object {
private const val TAG = "ScreenshotActionsProvider"
- private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 1e513b200ac4..20098873c36c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -942,7 +942,7 @@ public class ScreenshotController {
private void saveScreenshotInBackground(
ScreenshotData screenshot, UUID requestId, Consumer<Uri> finisher) {
ListenableFuture<ImageExporter.Result> future = mImageExporter.export(mBgExecutor,
- requestId, screenshot.getBitmap(), screenshot.getUserHandle(), mDisplayId);
+ requestId, screenshot.getBitmap(), screenshot.getUserOrDefault(), mDisplayId);
future.addListener(() -> {
try {
ImageExporter.Result result = future.get();
@@ -950,12 +950,8 @@ public class ScreenshotController {
logScreenshotResultStatus(result.uri, screenshot.getUserHandle());
mScreenshotHandler.resetTimeout();
if (result.uri != null) {
- final SavedImageData savedImageData = new SavedImageData();
- savedImageData.uri = result.uri;
- savedImageData.owner = screenshot.getUserHandle();
- savedImageData.imageTime = result.timestamp;
- mActionsProvider.setCompletedScreenshot(savedImageData);
- mViewProxy.setChipIntents(savedImageData);
+ mActionsProvider.setCompletedScreenshot(new ScreenshotSavedResult(
+ result.uri, screenshot.getUserOrDefault(), result.timestamp));
}
if (DEBUG_CALLBACK) {
Log.d(TAG, "finished background processing, Calling (Consumer<Uri>) "
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
index 92e933a9557b..4fdd90bdcded 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
@@ -5,6 +5,7 @@ import android.graphics.Bitmap
import android.graphics.Insets
import android.graphics.Rect
import android.net.Uri
+import android.os.Process
import android.os.UserHandle
import android.view.Display
import android.view.WindowManager.ScreenshotSource
@@ -31,6 +32,10 @@ data class ScreenshotData(
val packageNameString: String
get() = if (topComponent == null) "" else topComponent!!.packageName
+ fun getUserOrDefault(): UserHandle {
+ return userHandle ?: Process.myUserHandle()
+ }
+
companion object {
@JvmStatic
fun fromRequest(request: ScreenshotRequest, displayId: Int = Display.DEFAULT_DISPLAY) =
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt
new file mode 100644
index 000000000000..5b6e7ac3e4e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 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.systemui.screenshot
+
+import android.net.Uri
+import android.os.UserHandle
+import java.text.DateFormat
+import java.util.Date
+
+/**
+ * Represents a saved screenshot, with the uri and user it was saved to as well as the time it was
+ * saved.
+ */
+data class ScreenshotSavedResult(val uri: Uri, val user: UserHandle, val imageTime: Long) {
+ val subject: String
+
+ init {
+ val subjectDate = DateFormat.getDateTimeInstance().format(Date(imageTime))
+ subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate)
+ }
+
+ companion object {
+ private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt
index 2eaff8654a9e..9a50bab469bb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt
@@ -65,10 +65,9 @@ constructor(
onAction: (Notification.Action) -> Unit
) {
val bitmap = data.bitmap ?: return
- val user = data.userHandle ?: return
val component = data.topComponent ?: ComponentName("", "")
- requestQuickShareAction(id, bitmap, component, user) { quickShareAction ->
- onAction(quickShareAction)
+ requestQuickShareAction(id, bitmap, component, data.getUserOrDefault()) { quickShare ->
+ onAction(quickShare)
}
}
@@ -83,14 +82,19 @@ constructor(
fun requestSmartActions(
data: ScreenshotData,
id: String,
- result: ScreenshotController.SavedImageData,
+ result: ScreenshotSavedResult,
onActions: (List<Notification.Action>) -> Unit
) {
val bitmap = data.bitmap ?: return
- val user = data.userHandle ?: return
- val uri = result.uri ?: return
val component = data.topComponent ?: ComponentName("", "")
- requestSmartActions(id, bitmap, component, user, uri, REGULAR_SMART_ACTIONS) { actions ->
+ requestSmartActions(
+ id,
+ bitmap,
+ component,
+ data.getUserOrDefault(),
+ result.uri,
+ REGULAR_SMART_ACTIONS
+ ) { actions ->
onActions(actions)
}
}
@@ -197,7 +201,7 @@ constructor(
onActions(listOf())
return
}
- var smartActionsFuture: CompletableFuture<List<Notification.Action>>
+ val smartActionsFuture: CompletableFuture<List<Notification.Action>>
val startTimeMs = SystemClock.uptimeMillis()
try {
smartActionsFuture =
@@ -266,6 +270,7 @@ constructor(
Log.e(TAG, "Error in notifyScreenshotOp: ", e)
}
}
+
private fun isSmartActionsEnabled(user: UserHandle): Boolean {
// Smart actions don't yet work for cross-user saves.
val savingToOtherUser = user !== Process.myUserHandle()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
index 4a5cf57e6fa8..7226b1de022d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
@@ -67,14 +67,7 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() {
private val requestDismissal = mock<() -> Unit>()
private val request = ScreenshotData.forTesting()
- private val invalidResult = ScreenshotController.SavedImageData()
- private val validResult =
- ScreenshotController.SavedImageData().apply {
- uri = Uri.EMPTY
- owner = UserHandle.OWNER
- subject = "Test"
- imageTime = 0
- }
+ private val validResult = ScreenshotSavedResult(Uri.EMPTY, android.os.Process.myUserHandle(), 0)
private lateinit var viewModel: ScreenshotViewModel
private lateinit var actionsProvider: ScreenshotActionsProvider
@@ -109,17 +102,6 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() {
}
@Test
- fun actionAccessed_withInvalidResult_doesNothing() {
- actionsProvider = createActionsProvider()
-
- actionsProvider.setCompletedScreenshot(invalidResult)
- viewModel.previewAction.value!!.invoke()
- viewModel.actions.value[1].onClicked!!.invoke()
-
- verifyNoMoreInteractions(actionIntentExecutor)
- }
-
- @Test
@Ignore("b/332526567")
fun actionAccessed_withResult_launchesIntent() = runTest {
actionsProvider = createActionsProvider()