Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0482828c authored by Song Hu's avatar Song Hu Committed by Android (Google) Code Review
Browse files

Merge "Query and surface Quick Share chip before screenshot image...

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
parents 116e4c41 e55e544f
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,12 @@ public final class SystemUiDeviceConfigFlags {
    public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
    public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
            "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.
    // Flags related to Smart Suggestions - these are read in SmartReplyConstants.


    /** (boolean) Whether to enable smart suggestions in notifications. */
    /** (boolean) Whether to enable smart suggestions in notifications. */
+87 −2
Original line number Original line Diff line number Diff line
@@ -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_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE;
import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE;
import static com.android.systemui.screenshot.LogConfig.logTag;
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.ActivityTaskManager;
import android.app.Notification;
import android.app.Notification;
@@ -74,6 +76,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
    private final ScreenshotSmartActions mScreenshotSmartActions;
    private final ScreenshotSmartActions mScreenshotSmartActions;
    private final ScreenshotController.SaveImageInBackgroundData mParams;
    private final ScreenshotController.SaveImageInBackgroundData mParams;
    private final ScreenshotController.SavedImageData mImageData;
    private final ScreenshotController.SavedImageData mImageData;
    private final ScreenshotController.QuickShareData mQuickShareData;


    private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
    private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
    private String mScreenshotId;
    private String mScreenshotId;
@@ -90,6 +93,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
        mContext = context;
        mContext = context;
        mScreenshotSmartActions = screenshotSmartActions;
        mScreenshotSmartActions = screenshotSmartActions;
        mImageData = new ScreenshotController.SavedImageData();
        mImageData = new ScreenshotController.SavedImageData();
        mQuickShareData = new ScreenshotController.QuickShareData();
        mSharedElementTransition = sharedElementTransition;
        mSharedElementTransition = sharedElementTransition;
        mImageExporter = exporter;
        mImageExporter = exporter;


@@ -127,6 +131,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
        Bitmap image = mParams.image;
        Bitmap image = mParams.image;
        mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId);
        mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId);
        try {
        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.
            // Call synchronously here since already on a background thread.
            ListenableFuture<ImageExporter.Result> future =
            ListenableFuture<ImageExporter.Result> future =
                    mImageExporter.export(Runnable::run, requestId, image);
                    mImageExporter.export(Runnable::run, requestId, image);
@@ -136,7 +147,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {


            CompletableFuture<List<Notification.Action>> smartActionsFuture =
            CompletableFuture<List<Notification.Action>> smartActionsFuture =
                    mScreenshotSmartActions.getSmartActionsFuture(
                    mScreenshotSmartActions.getSmartActionsFuture(
                            mScreenshotId, uri, image, mSmartActionsProvider,
                            mScreenshotId, uri, image, mSmartActionsProvider, REGULAR_SMART_ACTIONS,
                            mSmartActionsEnabled, user);
                            mSmartActionsEnabled, user);


            List<Notification.Action> smartActions = new ArrayList<>();
            List<Notification.Action> smartActions = new ArrayList<>();
@@ -148,7 +159,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
                smartActions.addAll(buildSmartActions(
                smartActions.addAll(buildSmartActions(
                        mScreenshotSmartActions.getSmartActions(
                        mScreenshotSmartActions.getSmartActions(
                                mScreenshotId, smartActionsFuture, timeoutMs,
                                mScreenshotId, smartActionsFuture, timeoutMs,
                                mSmartActionsProvider),
                                mSmartActionsProvider, REGULAR_SMART_ACTIONS),
                        mContext));
                        mContext));
            }
            }


@@ -157,6 +168,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
            mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
            mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
            mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
            mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
            mImageData.quickShareAction = createQuickShareAction(mContext,
                    mQuickShareData.quickShareAction, uri);


            mParams.mActionsReadyListener.onActionsReady(mImageData);
            mParams.mActionsReadyListener.onActionsReady(mImageData);
            if (DEBUG_CALLBACK) {
            if (DEBUG_CALLBACK) {
@@ -173,6 +186,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            }
            }
            mParams.clearImage();
            mParams.clearImage();
            mImageData.reset();
            mImageData.reset();
            mQuickShareData.reset();
            mParams.mActionsReadyListener.onActionsReady(mImageData);
            mParams.mActionsReadyListener.onActionsReady(mImageData);
            if (DEBUG_CALLBACK) {
            if (DEBUG_CALLBACK) {
                Log.d(TAG, "Calling (Consumer<Uri>) finisher.accept(null)");
                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. The finisher is expected to always be called back, so just use the baked-in
        // params from the ctor in any case.
        // params from the ctor in any case.
        mImageData.reset();
        mImageData.reset();
        mQuickShareData.reset();
        mParams.mActionsReadyListener.onActionsReady(mImageData);
        mParams.mActionsReadyListener.onActionsReady(mImageData);
        if (DEBUG_CALLBACK) {
        if (DEBUG_CALLBACK) {
            Log.d(TAG, "onCancelled, calling (Consumer<Uri>) finisher.accept(null)");
            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_ID, screenshotId)
                .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
                .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);
        }
    }
}
}
+66 −16
Original line number Original line Diff line number Diff line
@@ -114,6 +114,7 @@ public class ScreenshotController {
        public Bitmap image;
        public Bitmap image;
        public Consumer<Uri> finisher;
        public Consumer<Uri> finisher;
        public ScreenshotController.ActionsReadyListener mActionsReadyListener;
        public ScreenshotController.ActionsReadyListener mActionsReadyListener;
        public ScreenshotController.QuickShareActionReadyListener mQuickShareActionsReadyListener;


        void clearImage() {
        void clearImage() {
            image = null;
            image = null;
@@ -129,6 +130,7 @@ public class ScreenshotController {
        public Supplier<ActionTransition> editTransition;
        public Supplier<ActionTransition> editTransition;
        public Notification.Action deleteAction;
        public Notification.Action deleteAction;
        public List<Notification.Action> smartActions;
        public List<Notification.Action> smartActions;
        public Notification.Action quickShareAction;


        /**
        /**
         * POD for shared element transition.
         * POD for shared element transition.
@@ -148,6 +150,21 @@ public class ScreenshotController {
            editTransition = null;
            editTransition = null;
            deleteAction = null;
            deleteAction = null;
            smartActions = 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);
        void onActionsReady(ScreenshotController.SavedImageData imageData);
    }
    }


    interface QuickShareActionReadyListener {
        void onActionsReady(ScreenshotController.QuickShareData quickShareData);
    }

    // These strings are used for communicating the action invoked to
    // These strings are used for communicating the action invoked to
    // ScreenshotNotificationSmartActionsProvider.
    // ScreenshotNotificationSmartActionsProvider.
    static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
    static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
@@ -519,7 +540,8 @@ public class ScreenshotController {
        mScreenBitmap.setHasAlpha(false);
        mScreenBitmap.setHasAlpha(false);
        mScreenBitmap.prepareToDraw();
        mScreenBitmap.prepareToDraw();


        saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady);
        saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady,
                this::showUiOnQuickShareActionReady);


        // The window is focusable by default
        // The window is focusable by default
        setWindowFocusable(true);
        setWindowFocusable(true);
@@ -677,7 +699,8 @@ public class ScreenshotController {
                        mScreenshotHandler.post(() -> Toast.makeText(mContext,
                        mScreenshotHandler.post(() -> Toast.makeText(mContext,
                                R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
                                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.
     * Creates a new worker thread and saves the screenshot to the media store.
     */
     */
    private void saveScreenshotInWorkerThread(Consumer<Uri> finisher,
    private void saveScreenshotInWorkerThread(Consumer<Uri> finisher,
            @Nullable ScreenshotController.ActionsReadyListener actionsReadyListener) {
            @Nullable ScreenshotController.ActionsReadyListener actionsReadyListener,
            @Nullable ScreenshotController.QuickShareActionReadyListener
                    quickShareActionsReadyListener) {
        ScreenshotController.SaveImageInBackgroundData
        ScreenshotController.SaveImageInBackgroundData
                data = new ScreenshotController.SaveImageInBackgroundData();
                data = new ScreenshotController.SaveImageInBackgroundData();
        data.image = mScreenBitmap;
        data.image = mScreenBitmap;
        data.finisher = finisher;
        data.finisher = finisher;
        data.mActionsReadyListener = actionsReadyListener;
        data.mActionsReadyListener = actionsReadyListener;
        data.mQuickShareActionsReadyListener = quickShareActionsReadyListener;


        if (mSaveInBgTask != null) {
        if (mSaveInBgTask != null) {
            // just log success/failure for the pre-existing screenshot
            // 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.
     * 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.
     * Note that once supplied, the action intent to share must be sent immediately after.
+18 −12
Original line number Original line Diff line number Diff line
@@ -60,11 +60,14 @@ public class ScreenshotSmartActions {
    CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
    CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
            String screenshotId, Uri screenshotUri, Bitmap image,
            String screenshotId, Uri screenshotUri, Bitmap image,
            ScreenshotNotificationSmartActionsProvider smartActionsProvider,
            ScreenshotNotificationSmartActionsProvider smartActionsProvider,
            ScreenshotSmartActionType actionType,
            boolean smartActionsEnabled, UserHandle userHandle) {
            boolean smartActionsEnabled, UserHandle userHandle) {
        if (DEBUG_ACTIONS) {
        if (DEBUG_ACTIONS) {
            Log.d(TAG, String.format("getSmartActionsFuture id=%s, uri=%s, provider=%s, "
            Log.d(TAG, String.format(
                            + "smartActionsEnabled=%b, userHandle=%s", screenshotId, screenshotUri,
                    "getSmartActionsFuture id=%s, uri=%s, provider=%s, actionType=%s, "
                    smartActionsProvider.getClass(), smartActionsEnabled, userHandle));
                            + "smartActionsEnabled=%b, userHandle=%s",
                    screenshotId, screenshotUri, smartActionsProvider.getClass(), actionType,
                    smartActionsEnabled, userHandle));
        }
        }
        if (!smartActionsEnabled) {
        if (!smartActionsEnabled) {
            if (DEBUG_ACTIONS) {
            if (DEBUG_ACTIONS) {
@@ -89,7 +92,7 @@ public class ScreenshotSmartActions {
                            ? runningTask.topActivity
                            ? runningTask.topActivity
                            : new ComponentName("", "");
                            : new ComponentName("", "");
            smartActionsFuture = smartActionsProvider.getActions(screenshotId, screenshotUri, image,
            smartActionsFuture = smartActionsProvider.getActions(screenshotId, screenshotUri, image,
                    componentName, ScreenshotSmartActionType.REGULAR_SMART_ACTIONS, userHandle);
                    componentName, actionType, userHandle);
        } catch (Throwable e) {
        } catch (Throwable e) {
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
            smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
@@ -107,19 +110,21 @@ public class ScreenshotSmartActions {
    @VisibleForTesting
    @VisibleForTesting
    List<Notification.Action> getSmartActions(String screenshotId,
    List<Notification.Action> getSmartActions(String screenshotId,
            CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
            CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
            ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
            ScreenshotNotificationSmartActionsProvider smartActionsProvider,
            ScreenshotSmartActionType actionType) {
        long startTimeMs = SystemClock.uptimeMillis();
        long startTimeMs = SystemClock.uptimeMillis();
        if (DEBUG_ACTIONS) {
        if (DEBUG_ACTIONS) {
            Log.d(TAG, String.format("getSmartActions id=%s, timeoutMs=%d, provider=%s",
            Log.d(TAG,
                    screenshotId, timeoutMs, smartActionsProvider.getClass()));
                    String.format("getSmartActions id=%s, timeoutMs=%d, actionType=%s, provider=%s",
                            screenshotId, timeoutMs, actionType, smartActionsProvider.getClass()));
        }
        }
        try {
        try {
            List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
            List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
                    TimeUnit.MILLISECONDS);
                    TimeUnit.MILLISECONDS);
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            if (DEBUG_ACTIONS) {
            if (DEBUG_ACTIONS) {
                Log.d(TAG, String.format("Got %d smart actions. Wait time: %d ms",
                Log.d(TAG, String.format("Got %d smart actions. Wait time: %d ms, actionType=%s",
                        actions.size(), waitTimeMs));
                        actions.size(), waitTimeMs, actionType));
            }
            }
            notifyScreenshotOp(screenshotId, smartActionsProvider,
            notifyScreenshotOp(screenshotId, smartActionsProvider,
                    ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
                    ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
@@ -129,8 +134,9 @@ public class ScreenshotSmartActions {
        } catch (Throwable e) {
        } catch (Throwable e) {
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
            if (DEBUG_ACTIONS) {
            if (DEBUG_ACTIONS) {
                Log.e(TAG, String.format("Error getting smart actions. Wait time: %d ms",
                Log.e(TAG, String.format(
                        waitTimeMs), e);
                        "Error getting smart actions. Wait time: %d ms, actionType=%s",
                        waitTimeMs, actionType), e);
            }
            }
            ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
            ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
                    (e instanceof TimeoutException)
                    (e instanceof TimeoutException)
@@ -165,7 +171,7 @@ public class ScreenshotSmartActions {
                    SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
                    SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
                            context, THREAD_POOL_EXECUTOR, new Handler());
                            context, THREAD_POOL_EXECUTOR, new Handler());
            if (DEBUG_ACTIONS) {
            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.getClass(), action, screenshotId, isSmartAction));
            }
            }
            provider.notifyAction(screenshotId, action, isSmartAction);
            provider.notifyAction(screenshotId, action, isSmartAction);
+42 −1
Original line number Original line Diff line number Diff line
@@ -137,6 +137,7 @@ public class ScreenshotView extends FrameLayout implements
    private ScreenshotActionChip mShareChip;
    private ScreenshotActionChip mShareChip;
    private ScreenshotActionChip mEditChip;
    private ScreenshotActionChip mEditChip;
    private ScreenshotActionChip mScrollChip;
    private ScreenshotActionChip mScrollChip;
    private ScreenshotActionChip mQuickShareChip;


    private UiEventLogger mUiEventLogger;
    private UiEventLogger mUiEventLogger;
    private ScreenshotViewCallback mCallbacks;
    private ScreenshotViewCallback mCallbacks;
@@ -151,7 +152,8 @@ public class ScreenshotView extends FrameLayout implements
    private enum PendingInteraction {
    private enum PendingInteraction {
        PREVIEW,
        PREVIEW,
        EDIT,
        EDIT,
        SHARE
        SHARE,
        QUICK_SHARE
    }
    }


    public ScreenshotView(Context context) {
    public ScreenshotView(Context context) {
@@ -505,6 +507,9 @@ public class ScreenshotView extends FrameLayout implements
        mShareChip.setOnClickListener(v -> {
        mShareChip.setOnClickListener(v -> {
            mShareChip.setIsPending(true);
            mShareChip.setIsPending(true);
            mEditChip.setIsPending(false);
            mEditChip.setIsPending(false);
            if (mQuickShareChip != null) {
                mQuickShareChip.setIsPending(false);
            }
            mPendingInteraction = PendingInteraction.SHARE;
            mPendingInteraction = PendingInteraction.SHARE;
        });
        });
        chips.add(mShareChip);
        chips.add(mShareChip);
@@ -514,6 +519,9 @@ public class ScreenshotView extends FrameLayout implements
        mEditChip.setOnClickListener(v -> {
        mEditChip.setOnClickListener(v -> {
            mEditChip.setIsPending(true);
            mEditChip.setIsPending(true);
            mShareChip.setIsPending(false);
            mShareChip.setIsPending(false);
            if (mQuickShareChip != null) {
                mQuickShareChip.setIsPending(false);
            }
            mPendingInteraction = PendingInteraction.EDIT;
            mPendingInteraction = PendingInteraction.EDIT;
        });
        });
        chips.add(mEditChip);
        chips.add(mEditChip);
@@ -521,6 +529,9 @@ public class ScreenshotView extends FrameLayout implements
        mScreenshotPreview.setOnClickListener(v -> {
        mScreenshotPreview.setOnClickListener(v -> {
            mShareChip.setIsPending(false);
            mShareChip.setIsPending(false);
            mEditChip.setIsPending(false);
            mEditChip.setIsPending(false);
            if (mQuickShareChip != null) {
                mQuickShareChip.setIsPending(false);
            }
            mPendingInteraction = PendingInteraction.PREVIEW;
            mPendingInteraction = PendingInteraction.PREVIEW;
        });
        });


@@ -582,6 +593,13 @@ public class ScreenshotView extends FrameLayout implements
            startSharedTransition(
            startSharedTransition(
                    imageData.editTransition.get());
                    imageData.editTransition.get());
        });
        });
        if (mQuickShareChip != null) {
            mQuickShareChip.setPendingIntent(imageData.quickShareAction.actionIntent,
                    () -> {
                        mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
                        animateDismissal();
                    });
        }


        if (mPendingInteraction != null) {
        if (mPendingInteraction != null) {
            switch (mPendingInteraction) {
            switch (mPendingInteraction) {
@@ -594,6 +612,9 @@ public class ScreenshotView extends FrameLayout implements
                case EDIT:
                case EDIT:
                    mEditChip.callOnClick();
                    mEditChip.callOnClick();
                    break;
                    break;
                case QUICK_SHARE:
                    mQuickShareChip.callOnClick();
                    break;
            }
            }
        } else {
        } else {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            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() {
    boolean isDismissing() {
        return (mDismissAnimation != null && mDismissAnimation.isRunning());
        return (mDismissAnimation != null && mDismissAnimation.isRunning());
    }
    }
@@ -700,6 +740,7 @@ public class ScreenshotView extends FrameLayout implements
            mActionsView.removeView(chip);
            mActionsView.removeView(chip);
        }
        }
        mSmartChips.clear();
        mSmartChips.clear();
        mQuickShareChip = null;
        setAlpha(1);
        setAlpha(1);
        mDismissButton.setTranslationY(0);
        mDismissButton.setTranslationY(0);
        mActionsContainer.setTranslationY(0);
        mActionsContainer.setTranslationY(0);
Loading