Merge "Query and surface Quick Share chip before screenshot image compress/export. Update chip intent, once image URL is available after compress/export." into sc-dev

This commit is contained in:
Song Hu
2021-04-23 17:10:16 +00:00
committed by Android (Google) Code Review
6 changed files with 227 additions and 34 deletions

View File

@@ -81,6 +81,12 @@ public final class SystemUiDeviceConfigFlags {
public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
"screenshot_notification_smart_actions_timeout_ms";
/**
* (int) Timeout value in ms to get Quick Share actions for screenshot notification.
*/
public static final String SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS =
"screenshot_notification_quick_share_actions_timeout_ms";
// Flags related to Smart Suggestions - these are read in SmartReplyConstants.
/** (boolean) Whether to enable smart suggestions in notifications. */

View File

@@ -20,6 +20,8 @@ import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE;
import static com.android.systemui.screenshot.LogConfig.logTag;
import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.QUICK_SHARE_ACTION;
import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.REGULAR_SMART_ACTIONS;
import android.app.ActivityTaskManager;
import android.app.Notification;
@@ -74,6 +76,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private final ScreenshotSmartActions mScreenshotSmartActions;
private final ScreenshotController.SaveImageInBackgroundData mParams;
private final ScreenshotController.SavedImageData mImageData;
private final ScreenshotController.QuickShareData mQuickShareData;
private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
private String mScreenshotId;
@@ -90,6 +93,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mContext = context;
mScreenshotSmartActions = screenshotSmartActions;
mImageData = new ScreenshotController.SavedImageData();
mQuickShareData = new ScreenshotController.QuickShareData();
mSharedElementTransition = sharedElementTransition;
mImageExporter = exporter;
@@ -127,6 +131,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
Bitmap image = mParams.image;
mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId);
try {
if (mSmartActionsEnabled && mParams.mQuickShareActionsReadyListener != null) {
// Since Quick Share target recommendation does not rely on image URL, it is
// queried and surfaced before image compress/export. Action intent would not be
// used, because it does not contain image URL.
queryQuickShareAction(image, user);
}
// Call synchronously here since already on a background thread.
ListenableFuture<ImageExporter.Result> future =
mImageExporter.export(Runnable::run, requestId, image);
@@ -136,7 +147,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
CompletableFuture<List<Notification.Action>> smartActionsFuture =
mScreenshotSmartActions.getSmartActionsFuture(
mScreenshotId, uri, image, mSmartActionsProvider,
mScreenshotId, uri, image, mSmartActionsProvider, REGULAR_SMART_ACTIONS,
mSmartActionsEnabled, user);
List<Notification.Action> smartActions = new ArrayList<>();
@@ -148,7 +159,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
smartActions.addAll(buildSmartActions(
mScreenshotSmartActions.getSmartActions(
mScreenshotId, smartActionsFuture, timeoutMs,
mSmartActionsProvider),
mSmartActionsProvider, REGULAR_SMART_ACTIONS),
mContext));
}
@@ -157,6 +168,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
mImageData.quickShareAction = createQuickShareAction(mContext,
mQuickShareData.quickShareAction, uri);
mParams.mActionsReadyListener.onActionsReady(mImageData);
if (DEBUG_CALLBACK) {
@@ -173,6 +186,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
}
mParams.clearImage();
mImageData.reset();
mQuickShareData.reset();
mParams.mActionsReadyListener.onActionsReady(mImageData);
if (DEBUG_CALLBACK) {
Log.d(TAG, "Calling (Consumer<Uri>) finisher.accept(null)");
@@ -197,6 +211,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// params. The finisher is expected to always be called back, so just use the baked-in
// params from the ctor in any case.
mImageData.reset();
mQuickShareData.reset();
mParams.mActionsReadyListener.onActionsReady(mImageData);
if (DEBUG_CALLBACK) {
Log.d(TAG, "onCancelled, calling (Consumer<Uri>) finisher.accept(null)");
@@ -389,4 +404,74 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
.putExtra(ScreenshotController.EXTRA_ID, screenshotId)
.putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
}
/**
* Populate image uri into intent of Quick Share action.
*/
@VisibleForTesting
private Notification.Action createQuickShareAction(Context context, Notification.Action action,
Uri uri) {
if (action == null) {
return null;
}
// Populate image URI into Quick Share chip intent
Intent sharingIntent = action.actionIntent.getIntent();
sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
// Include URI in ClipData also, so that grantPermission picks it up.
// We don't use setData here because some apps interpret this as "to:".
ClipData clipdata = new ClipData(new ClipDescription("content",
new String[]{"image/png"}),
new ClipData.Item(uri));
sharingIntent.setClipData(clipdata);
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
PendingIntent updatedPendingIntent = PendingIntent.getActivity(
context, 0, sharingIntent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
// Proxy smart actions through {@link GlobalScreenshot.SmartActionsReceiver}
// for logging smart actions.
Bundle extras = action.getExtras();
String actionType = extras.getString(
ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
Intent intent = new Intent(context, SmartActionsReceiver.class)
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, updatedPendingIntent)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
mRandom.nextInt(),
intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
return new Notification.Action.Builder(action.getIcon(), action.title,
broadcastIntent).setContextual(true).addExtras(extras).build();
}
/**
* Query and surface Quick Share chip if it is available. Action intent would not be used,
* because it does not contain image URL which would be populated in {@link
* #createQuickShareAction(Context, Notification.Action, Uri)}
*/
private void queryQuickShareAction(Bitmap image, UserHandle user) {
CompletableFuture<List<Notification.Action>> quickShareActionsFuture =
mScreenshotSmartActions.getSmartActionsFuture(
mScreenshotId, null, image, mSmartActionsProvider,
QUICK_SHARE_ACTION,
mSmartActionsEnabled, user);
int timeoutMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS,
500);
List<Notification.Action> quickShareActions =
mScreenshotSmartActions.getSmartActions(
mScreenshotId, quickShareActionsFuture, timeoutMs,
mSmartActionsProvider, QUICK_SHARE_ACTION);
if (!quickShareActions.isEmpty()) {
mQuickShareData.quickShareAction = quickShareActions.get(0);
mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
}
}
}

View File

@@ -114,6 +114,7 @@ public class ScreenshotController {
public Bitmap image;
public Consumer<Uri> finisher;
public ScreenshotController.ActionsReadyListener mActionsReadyListener;
public ScreenshotController.QuickShareActionReadyListener mQuickShareActionsReadyListener;
void clearImage() {
image = null;
@@ -129,6 +130,7 @@ public class ScreenshotController {
public Supplier<ActionTransition> editTransition;
public Notification.Action deleteAction;
public List<Notification.Action> smartActions;
public Notification.Action quickShareAction;
/**
* POD for shared element transition.
@@ -148,6 +150,21 @@ public class ScreenshotController {
editTransition = null;
deleteAction = null;
smartActions = null;
quickShareAction = null;
}
}
/**
* Structure returned by the QueryQuickShareInBackgroundTask
*/
static class QuickShareData {
public Notification.Action quickShareAction;
/**
* Used to reset the return data on error
*/
public void reset() {
quickShareAction = null;
}
}
@@ -155,6 +172,10 @@ public class ScreenshotController {
void onActionsReady(ScreenshotController.SavedImageData imageData);
}
interface QuickShareActionReadyListener {
void onActionsReady(ScreenshotController.QuickShareData quickShareData);
}
// These strings are used for communicating the action invoked to
// ScreenshotNotificationSmartActionsProvider.
static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
@@ -519,7 +540,8 @@ public class ScreenshotController {
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady);
saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady,
this::showUiOnQuickShareActionReady);
// The window is focusable by default
setWindowFocusable(true);
@@ -664,20 +686,21 @@ public class ScreenshotController {
saveScreenshotInWorkerThread(
/* onComplete */ finisher,
/* actionsReadyListener */ imageData -> {
if (DEBUG_CALLBACK) {
Log.d(TAG, "returning URI to finisher (Consumer<URI>): " + imageData.uri);
}
finisher.accept(imageData.uri);
if (imageData.uri == null) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_save_text);
} else {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
mScreenshotHandler.post(() -> Toast.makeText(mContext,
R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
}
});
if (DEBUG_CALLBACK) {
Log.d(TAG, "returning URI to finisher (Consumer<URI>): " + imageData.uri);
}
finisher.accept(imageData.uri);
if (imageData.uri == null) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_save_text);
} else {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
mScreenshotHandler.post(() -> Toast.makeText(mContext,
R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
}
},
null);
}
/**
@@ -718,12 +741,15 @@ public class ScreenshotController {
* Creates a new worker thread and saves the screenshot to the media store.
*/
private void saveScreenshotInWorkerThread(Consumer<Uri> finisher,
@Nullable ScreenshotController.ActionsReadyListener actionsReadyListener) {
@Nullable ScreenshotController.ActionsReadyListener actionsReadyListener,
@Nullable ScreenshotController.QuickShareActionReadyListener
quickShareActionsReadyListener) {
ScreenshotController.SaveImageInBackgroundData
data = new ScreenshotController.SaveImageInBackgroundData();
data.image = mScreenBitmap;
data.finisher = finisher;
data.mActionsReadyListener = actionsReadyListener;
data.mQuickShareActionsReadyListener = quickShareActionsReadyListener;
if (mSaveInBgTask != null) {
// just log success/failure for the pre-existing screenshot
@@ -785,6 +811,30 @@ public class ScreenshotController {
}
}
/**
* Sets up the action shade and its entrance animation, once we get the Quick Share action data.
*/
private void showUiOnQuickShareActionReady(ScreenshotController.QuickShareData quickShareData) {
if (DEBUG_UI) {
Log.d(TAG, "Showing UI for Quick Share action");
}
if (quickShareData.quickShareAction != null) {
mScreenshotHandler.post(() -> {
if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mScreenshotView.addQuickShareChip(quickShareData.quickShareAction);
}
});
} else {
mScreenshotView.addQuickShareChip(quickShareData.quickShareAction);
}
});
}
}
/**
* Supplies the necessary bits for the shared element transition to share sheet.
* Note that once supplied, the action intent to share must be sent immediately after.

View File

@@ -60,11 +60,14 @@ public class ScreenshotSmartActions {
CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
String screenshotId, Uri screenshotUri, Bitmap image,
ScreenshotNotificationSmartActionsProvider smartActionsProvider,
ScreenshotSmartActionType actionType,
boolean smartActionsEnabled, UserHandle userHandle) {
if (DEBUG_ACTIONS) {
Log.d(TAG, String.format("getSmartActionsFuture id=%s, uri=%s, provider=%s, "
+ "smartActionsEnabled=%b, userHandle=%s", screenshotId, screenshotUri,
smartActionsProvider.getClass(), smartActionsEnabled, userHandle));
Log.d(TAG, String.format(
"getSmartActionsFuture id=%s, uri=%s, provider=%s, actionType=%s, "
+ "smartActionsEnabled=%b, userHandle=%s",
screenshotId, screenshotUri, smartActionsProvider.getClass(), actionType,
smartActionsEnabled, userHandle));
}
if (!smartActionsEnabled) {
if (DEBUG_ACTIONS) {
@@ -89,7 +92,7 @@ public class ScreenshotSmartActions {
? runningTask.topActivity
: new ComponentName("", "");
smartActionsFuture = smartActionsProvider.getActions(screenshotId, screenshotUri, image,
componentName, ScreenshotSmartActionType.REGULAR_SMART_ACTIONS, userHandle);
componentName, actionType, userHandle);
} catch (Throwable e) {
long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
@@ -107,19 +110,21 @@ public class ScreenshotSmartActions {
@VisibleForTesting
List<Notification.Action> getSmartActions(String screenshotId,
CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
ScreenshotNotificationSmartActionsProvider smartActionsProvider,
ScreenshotSmartActionType actionType) {
long startTimeMs = SystemClock.uptimeMillis();
if (DEBUG_ACTIONS) {
Log.d(TAG, String.format("getSmartActions id=%s, timeoutMs=%d, provider=%s",
screenshotId, timeoutMs, smartActionsProvider.getClass()));
Log.d(TAG,
String.format("getSmartActions id=%s, timeoutMs=%d, actionType=%s, provider=%s",
screenshotId, timeoutMs, actionType, smartActionsProvider.getClass()));
}
try {
List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
TimeUnit.MILLISECONDS);
long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
if (DEBUG_ACTIONS) {
Log.d(TAG, String.format("Got %d smart actions. Wait time: %d ms",
actions.size(), waitTimeMs));
Log.d(TAG, String.format("Got %d smart actions. Wait time: %d ms, actionType=%s",
actions.size(), waitTimeMs, actionType));
}
notifyScreenshotOp(screenshotId, smartActionsProvider,
ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
@@ -129,8 +134,9 @@ public class ScreenshotSmartActions {
} catch (Throwable e) {
long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
if (DEBUG_ACTIONS) {
Log.e(TAG, String.format("Error getting smart actions. Wait time: %d ms",
waitTimeMs), e);
Log.e(TAG, String.format(
"Error getting smart actions. Wait time: %d ms, actionType=%s",
waitTimeMs, actionType), e);
}
ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
(e instanceof TimeoutException)
@@ -165,7 +171,7 @@ public class ScreenshotSmartActions {
SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
context, THREAD_POOL_EXECUTOR, new Handler());
if (DEBUG_ACTIONS) {
Log.e(TAG, String.format("%s notifyAction: %s id=%s, isSmartAction=%b",
Log.d(TAG, String.format("%s notifyAction: %s id=%s, isSmartAction=%b",
provider.getClass(), action, screenshotId, isSmartAction));
}
provider.notifyAction(screenshotId, action, isSmartAction);

View File

@@ -137,6 +137,7 @@ public class ScreenshotView extends FrameLayout implements
private ScreenshotActionChip mShareChip;
private ScreenshotActionChip mEditChip;
private ScreenshotActionChip mScrollChip;
private ScreenshotActionChip mQuickShareChip;
private UiEventLogger mUiEventLogger;
private ScreenshotViewCallback mCallbacks;
@@ -151,7 +152,8 @@ public class ScreenshotView extends FrameLayout implements
private enum PendingInteraction {
PREVIEW,
EDIT,
SHARE
SHARE,
QUICK_SHARE
}
public ScreenshotView(Context context) {
@@ -505,6 +507,9 @@ public class ScreenshotView extends FrameLayout implements
mShareChip.setOnClickListener(v -> {
mShareChip.setIsPending(true);
mEditChip.setIsPending(false);
if (mQuickShareChip != null) {
mQuickShareChip.setIsPending(false);
}
mPendingInteraction = PendingInteraction.SHARE;
});
chips.add(mShareChip);
@@ -514,6 +519,9 @@ public class ScreenshotView extends FrameLayout implements
mEditChip.setOnClickListener(v -> {
mEditChip.setIsPending(true);
mShareChip.setIsPending(false);
if (mQuickShareChip != null) {
mQuickShareChip.setIsPending(false);
}
mPendingInteraction = PendingInteraction.EDIT;
});
chips.add(mEditChip);
@@ -521,6 +529,9 @@ public class ScreenshotView extends FrameLayout implements
mScreenshotPreview.setOnClickListener(v -> {
mShareChip.setIsPending(false);
mEditChip.setIsPending(false);
if (mQuickShareChip != null) {
mQuickShareChip.setIsPending(false);
}
mPendingInteraction = PendingInteraction.PREVIEW;
});
@@ -582,6 +593,13 @@ public class ScreenshotView extends FrameLayout implements
startSharedTransition(
imageData.editTransition.get());
});
if (mQuickShareChip != null) {
mQuickShareChip.setPendingIntent(imageData.quickShareAction.actionIntent,
() -> {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
animateDismissal();
});
}
if (mPendingInteraction != null) {
switch (mPendingInteraction) {
@@ -594,6 +612,9 @@ public class ScreenshotView extends FrameLayout implements
case EDIT:
mEditChip.callOnClick();
break;
case QUICK_SHARE:
mQuickShareChip.callOnClick();
break;
}
} else {
LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -615,6 +636,25 @@ public class ScreenshotView extends FrameLayout implements
}
}
void addQuickShareChip(Notification.Action quickShareAction) {
if (mPendingInteraction == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
mQuickShareChip = (ScreenshotActionChip) inflater.inflate(
R.layout.global_screenshot_action_chip, mActionsView, false);
mQuickShareChip.setText(quickShareAction.title);
mQuickShareChip.setIcon(quickShareAction.getIcon(), false);
mQuickShareChip.setOnClickListener(v -> {
mShareChip.setIsPending(false);
mEditChip.setIsPending(false);
mQuickShareChip.setIsPending(true);
mPendingInteraction = PendingInteraction.QUICK_SHARE;
});
mQuickShareChip.setAlpha(1);
mActionsView.addView(mQuickShareChip);
mSmartChips.add(mQuickShareChip);
}
}
boolean isDismissing() {
return (mDismissAnimation != null && mDismissAnimation.isRunning());
}
@@ -700,6 +740,7 @@ public class ScreenshotView extends FrameLayout implements
mActionsView.removeView(chip);
}
mSmartChips.clear();
mQuickShareChip = null;
setAlpha(1);
mDismissButton.setTranslationY(0);
mActionsContainer.setTranslationY(0);

View File

@@ -16,6 +16,8 @@
package com.android.systemui.screenshot;
import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.REGULAR_SMART_ACTIONS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -87,6 +89,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
CompletableFuture<List<Notification.Action>> smartActionsFuture =
mScreenshotSmartActions.getSmartActionsFuture(
"", Uri.parse("content://authority/data"), bitmap, smartActionsProvider,
REGULAR_SMART_ACTIONS,
true, UserHandle.of(UserHandle.myUserId()));
assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
@@ -104,7 +107,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
RuntimeException.class);
List<Notification.Action> actions = mScreenshotSmartActions.getSmartActions(
"", smartActionsFuture, timeoutMs, mSmartActionsProvider);
"", smartActionsFuture, timeoutMs, mSmartActionsProvider, REGULAR_SMART_ACTIONS);
assertEquals(Collections.emptyList(), actions);
}
@@ -127,6 +130,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
CompletableFuture<List<Notification.Action>> smartActionsFuture =
mScreenshotSmartActions.getSmartActionsFuture(
"", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider,
REGULAR_SMART_ACTIONS,
true, UserHandle.of(UserHandle.myUserId()));
verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any(), any());
assertNotNull(smartActionsFuture);
@@ -140,7 +144,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
mScreenshotSmartActions.getSmartActionsFuture(
"", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider, true,
"", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider,
REGULAR_SMART_ACTIONS, true,
UserHandle.of(UserHandle.myUserId()));
verify(mSmartActionsProvider, times(1)).getActions(
any(), any(), any(), any(), any(), any());
@@ -157,7 +162,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
mContext, null, mHandler);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
mScreenshotSmartActions.getSmartActionsFuture("", null, bitmap,
actionsProvider,
actionsProvider, REGULAR_SMART_ACTIONS,
true, UserHandle.of(UserHandle.myUserId()));
assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);