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

Commit 302cd6f8 authored by Miranda Kephart's avatar Miranda Kephart Committed by Android (Google) Code Review
Browse files

Merge "Add shared transitions from screenshot to markup"

parents 52e02921 0dab35d6
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -470,9 +470,6 @@ public class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
                || mSharedElementsHidden)) {
            finish();
        }
        if (!mIsReturning && mExitNotified) {
            mExitCallbacks = null; // don't need it anymore
        }
    }

    private void finish() {
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ public class ChooserActivity extends ResolverActivity implements
     * To be used for shared element transition into this activity.
     * @hide
     */
    public static final String FIRST_IMAGE_PREVIEW_TRANSITION_NAME = "chooser_preview_image_1";
    public static final String FIRST_IMAGE_PREVIEW_TRANSITION_NAME = "screenshot_preview_image";

    private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";

+48 −43
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -79,13 +79,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
    private final String mScreenshotId;
    private final boolean mSmartActionsEnabled;
    private final Random mRandom = new Random();
    private final Supplier<ShareTransition> mSharedElementTransition;
    private final Supplier<ActionTransition> mSharedElementTransition;
    private final ImageExporter mImageExporter;

    SaveImageInBackgroundTask(Context context, ImageExporter exporter,
            ScreenshotSmartActions screenshotSmartActions,
            ScreenshotController.SaveImageInBackgroundData data,
            Supplier<ShareTransition> sharedElementTransition) {
            Supplier<ActionTransition> sharedElementTransition) {
        mContext = context;
        mScreenshotSmartActions = screenshotSmartActions;
        mImageData = new ScreenshotController.SavedImageData();
@@ -150,7 +150,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            mImageData.uri = uri;
            mImageData.smartActions = smartActions;
            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
            mImageData.editAction = createEditAction(mContext, mContext.getResources(), uri);
            mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
            mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);

            mParams.mActionsReadyListener.onActionsReady(mImageData);
@@ -204,9 +204,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
     * Assumes that the action intent is sent immediately after being supplied.
     */
    @VisibleForTesting
    Supplier<ShareTransition> createShareAction(Context context, Resources r, Uri uri) {
    Supplier<ActionTransition> createShareAction(Context context, Resources r, Uri uri) {
        return () -> {
            ShareTransition transition = mSharedElementTransition.get();
            ActionTransition transition = mSharedElementTransition.get();

            // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
            // order to do some common work like dismissing the keyguard and sending
@@ -259,13 +259,15 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
                    Icon.createWithResource(r, R.drawable.ic_screenshot_share),
                    r.getString(com.android.internal.R.string.share), shareAction);

            transition.shareAction = shareActionBuilder.build();
            transition.action = shareActionBuilder.build();
            return transition;
        };
    }

    @VisibleForTesting
    Notification.Action createEditAction(Context context, Resources r, Uri uri) {
    Supplier<ActionTransition> createEditAction(Context context, Resources r, Uri uri) {
        return () -> {
            ActionTransition transition = mSharedElementTransition.get();
            // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
            // order to do some common work like dismissing the keyguard and sending
            // closeSystemWindows
@@ -282,8 +284,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
                editIntent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
            PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
                    context, 0, editIntent, PendingIntent.FLAG_IMMUTABLE,
                    transition.bundle, UserHandle.CURRENT);

            // Make sure pending intents for the system user are still unique across users
            // by setting the (otherwise unused) request code to the current user id.
@@ -304,7 +307,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
                    Icon.createWithResource(r, R.drawable.ic_screenshot_edit),
                    r.getString(com.android.internal.R.string.screenshot_edit), editAction);

        return editActionBuilder.build();
            transition.action = editActionBuilder.build();
            return transition;
        };
    }

    @VisibleForTesting
+21 −11
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
import com.android.systemui.util.DeviceConfigProxy;

import java.util.List;
@@ -115,17 +115,17 @@ public class ScreenshotController {
     */
    static class SavedImageData {
        public Uri uri;
        public Supplier<ShareTransition> shareTransition;
        public Notification.Action editAction;
        public Supplier<ActionTransition> shareTransition;
        public Supplier<ActionTransition> editTransition;
        public Notification.Action deleteAction;
        public List<Notification.Action> smartActions;

        /**
         * POD for shared element transition to share sheet.
         * POD for shared element transition.
         */
        static class ShareTransition {
        static class ActionTransition {
            public Bundle bundle;
            public Notification.Action shareAction;
            public Notification.Action action;
            public Runnable onCancelRunnable;
        }

@@ -135,7 +135,7 @@ public class ScreenshotController {
        public void reset() {
            uri = null;
            shareTransition = null;
            editAction = null;
            editTransition = null;
            deleteAction = null;
            smartActions = null;
        }
@@ -352,6 +352,10 @@ public class ScreenshotController {
        }
    }

    boolean isPendingSharedTransition() {
        return mScreenshotView.isPendingSharedTransition();
    }

    /**
     * Release the constructed window context.
     */
@@ -626,7 +630,7 @@ public class ScreenshotController {
        }

        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mImageExporter,
                mScreenshotSmartActions, data, getShareTransitionSupplier());
                mScreenshotSmartActions, data, getActionTransitionSupplier());
        mSaveInBgTask.execute();
    }

@@ -680,7 +684,7 @@ public class ScreenshotController {
     * 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.
     */
    private Supplier<ShareTransition> getShareTransitionSupplier() {
    private Supplier<ActionTransition> getActionTransitionSupplier() {
        return () -> {
            ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
                @Override
@@ -689,7 +693,13 @@ public class ScreenshotController {
                }

                @Override
                public void onFinish() { }
                public void hideSharedElements() {
                    resetScreenshotView();
                }

                @Override
                public void onFinish() {
                }
            };

            Pair<ActivityOptions, ExitTransitionCoordinator> transition =
@@ -698,7 +708,7 @@ public class ScreenshotController {
                                    ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
            transition.second.startExit();

            ShareTransition supply = new ShareTransition();
            ActionTransition supply = new ActionTransition();
            supply.bundle = transition.first.toBundle();
            supply.onCancelRunnable = () -> ActivityOptions.stopSharedElementAnimation(mWindow);
            return supply;
+52 −40
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ import android.widget.LinearLayout;

import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
import com.android.systemui.shared.system.QuickStepContract;

import java.util.ArrayList;
@@ -106,7 +106,6 @@ public class ScreenshotView extends FrameLayout implements
    private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
    private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
    private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
    private static final long SCREENSHOT_DISMISS_SHARE_OFFSET_MS = 300; // delay after share clicked
    private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
    private static final float ROUNDED_CORNER_RADIUS = .05f;
    private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
@@ -142,7 +141,7 @@ public class ScreenshotView extends FrameLayout implements
    private UiEventLogger mUiEventLogger;
    private ScreenshotViewCallback mCallbacks;
    private Animator mDismissAnimation;
    private boolean mIgnoreDismiss;
    private boolean mPendingSharedTransition;

    private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
    private PendingInteraction mPendingInteraction;
@@ -296,6 +295,10 @@ public class ScreenshotView extends FrameLayout implements
        requestFocus();
    }

    View getScreenshotPreview() {
        return mScreenshotPreview;
    }

    /**
     * Set up the logger and callback on dismissal.
     *
@@ -535,44 +538,22 @@ public class ScreenshotView extends FrameLayout implements
        });
        return animator;
    }
    protected View getScreenshotPreview() {
        return mScreenshotPreview;
    }

    void setChipIntents(ScreenshotController.SavedImageData imageData) {
        mShareChip.setOnClickListener(v -> {
            ShareTransition transition = imageData.shareTransition.get();
            try {
                mIgnoreDismiss = true;
                transition.shareAction.actionIntent.send();
            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);

                // Ensures that we delay dismissing until transition has started.
                postDelayed(() -> {
                    mIgnoreDismiss = false;
                    animateDismissal();
                }, SCREENSHOT_DISMISS_SHARE_OFFSET_MS);
            } catch (PendingIntent.CanceledException e) {
                mIgnoreDismiss = false;
                if (transition.onCancelRunnable != null) {
                    transition.onCancelRunnable.run();
                }
                Log.e(TAG, "Share intent cancelled", e);
            }
            startSharedTransition(
                    imageData.shareTransition.get());
        });
        mEditChip.setPendingIntent(imageData.editAction.actionIntent,
                () -> {
        mEditChip.setOnClickListener(v -> {
            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED);
                    animateDismissal();
            startSharedTransition(
                    imageData.editTransition.get());
        });
        mScreenshotPreview.setOnClickListener(v -> {
            try {
                imageData.editAction.actionIntent.send();
            } catch (PendingIntent.CanceledException e) {
                Log.e(TAG, "PendingIntent was cancelled", e);
            }
            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED);
            animateDismissal();
            startSharedTransition(
                    imageData.editTransition.get());
        });

        if (mPendingInteraction != null) {
@@ -611,14 +592,15 @@ public class ScreenshotView extends FrameLayout implements
        return (mDismissAnimation != null && mDismissAnimation.isRunning());
    }

    boolean isPendingSharedTransition() {
        return mPendingSharedTransition;
    }

    void animateDismissal() {
        animateDismissal(createScreenshotDismissAnimation());
        animateDismissal(createScreenshotTranslateDismissAnimation());
    }

    private void animateDismissal(Animator dismissAnimation) {
        if (mIgnoreDismiss) {
            return;
        }
        if (DEBUG_WINDOW) {
            Log.d(TAG, "removing OnComputeInternalInsetsListener");
        }
@@ -671,6 +653,7 @@ public class ScreenshotView extends FrameLayout implements
        getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
        // Clear any references to the bitmap
        mScreenshotPreview.setImageDrawable(null);
        mPendingSharedTransition = false;
        mActionsContainerBackground.setVisibility(View.GONE);
        mActionsContainer.setVisibility(View.GONE);
        mBackgroundProtection.setAlpha(0f);
@@ -698,7 +681,23 @@ public class ScreenshotView extends FrameLayout implements
        mScreenshotSelectorView.stop();
    }

    private AnimatorSet createScreenshotDismissAnimation() {
    private void startSharedTransition(ActionTransition transition) {
        try {
            mPendingSharedTransition = true;
            transition.action.actionIntent.send();

            // fade out non-preview UI
            createScreenshotFadeDismissAnimation().start();
        } catch (PendingIntent.CanceledException e) {
            mPendingSharedTransition = false;
            if (transition.onCancelRunnable != null) {
                transition.onCancelRunnable.run();
            }
            Log.e(TAG, "Intent cancelled", e);
        }
    }

    private AnimatorSet createScreenshotTranslateDismissAnimation() {
        ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
        alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS);
        alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS);
@@ -725,6 +724,19 @@ public class ScreenshotView extends FrameLayout implements
        return animSet;
    }

    private ValueAnimator createScreenshotFadeDismissAnimation() {
        ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
        alphaAnim.addUpdateListener(animation -> {
            float alpha = 1 - animation.getAnimatedFraction();
            mDismissButton.setAlpha(alpha);
            mActionsContainerBackground.setAlpha(alpha);
            mActionsContainer.setAlpha(alpha);
            mBackgroundProtection.setAlpha(alpha);
        });
        alphaAnim.setDuration(600);
        return alphaAnim;
    }

    /**
     * Create a drawable using the size of the bitmap and insets as the fractional inset parameters.
     */
Loading