Merge "Add shared transitions from clipboard UI" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8b7d200a60
@@ -18,6 +18,7 @@ package com.android.systemui.clipboardoverlay;
|
||||
|
||||
import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
|
||||
|
||||
|
||||
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN;
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
|
||||
@@ -33,6 +34,7 @@ import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBO
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
|
||||
import static com.android.systemui.flags.Flags.CLIPBOARD_IMAGE_TIMEOUT;
|
||||
import static com.android.systemui.flags.Flags.CLIPBOARD_SHARED_TRANSITIONS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -47,6 +49,7 @@ import android.hardware.input.InputManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Log;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.InputMonitor;
|
||||
@@ -54,6 +57,7 @@ import android.view.MotionEvent;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
@@ -73,7 +77,8 @@ import javax.inject.Inject;
|
||||
/**
|
||||
* Controls state and UI for the overlay that appears when something is added to the clipboard
|
||||
*/
|
||||
public class ClipboardOverlayController implements ClipboardListener.ClipboardOverlay {
|
||||
public class ClipboardOverlayController implements ClipboardListener.ClipboardOverlay,
|
||||
ClipboardOverlayView.ClipboardOverlayCallbacks {
|
||||
private static final String TAG = "ClipboardOverlayCtrlr";
|
||||
|
||||
/** Constants for screenshot/copy deconflicting */
|
||||
@@ -92,6 +97,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final Executor mBgExecutor;
|
||||
private final ClipboardImageLoader mClipboardImageLoader;
|
||||
private final ClipboardTransitionExecutor mTransitionExecutor;
|
||||
|
||||
private final ClipboardOverlayView mView;
|
||||
|
||||
@@ -179,10 +185,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
ClipboardOverlayUtils clipboardUtils,
|
||||
@Background Executor bgExecutor,
|
||||
ClipboardImageLoader clipboardImageLoader,
|
||||
ClipboardTransitionExecutor transitionExecutor,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mContext = context;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mClipboardImageLoader = clipboardImageLoader;
|
||||
mTransitionExecutor = transitionExecutor;
|
||||
|
||||
mClipboardLogger = new ClipboardLogger(uiEventLogger);
|
||||
|
||||
@@ -200,7 +208,11 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
mClipboardUtils = clipboardUtils;
|
||||
mBgExecutor = bgExecutor;
|
||||
|
||||
mView.setCallbacks(mClipboardCallbacks);
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
mView.setCallbacks(this);
|
||||
} else {
|
||||
mView.setCallbacks(mClipboardCallbacks);
|
||||
}
|
||||
|
||||
mWindow.withWindowAttached(() -> {
|
||||
mWindow.setContentView(mView);
|
||||
@@ -209,16 +221,24 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
});
|
||||
|
||||
mTimeoutHandler.setOnTimeoutRunnable(() -> {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TIMED_OUT);
|
||||
animateOut();
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_TIMED_OUT);
|
||||
} else {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TIMED_OUT);
|
||||
animateOut();
|
||||
}
|
||||
});
|
||||
|
||||
mCloseDialogsReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
animateOut();
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
} else {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
animateOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -229,8 +249,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (SCREENSHOT_ACTION.equals(intent.getAction())) {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
animateOut();
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
} else {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
|
||||
animateOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -457,8 +481,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
remoteAction.ifPresent(action -> {
|
||||
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN);
|
||||
mView.post(() -> mView.setActionChip(action, () -> {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
|
||||
animateOut();
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_ACTION_TAPPED);
|
||||
} else {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
|
||||
animateOut();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -500,8 +528,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
if (!mView.isInTouchRegion(
|
||||
(int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
|
||||
animateOut();
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
|
||||
} else {
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
|
||||
animateOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,12 +583,16 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
mEnterAnimator.start();
|
||||
}
|
||||
|
||||
private void finish(ClipboardOverlayEvent event) {
|
||||
finish(event, null);
|
||||
}
|
||||
|
||||
private void animateOut() {
|
||||
if (mExitAnimator != null && mExitAnimator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
Animator anim = mView.getExitAnimation();
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
mExitAnimator = mView.getExitAnimation();
|
||||
mExitAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
private boolean mCancelled;
|
||||
|
||||
@Override
|
||||
@@ -573,8 +609,47 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
}
|
||||
}
|
||||
});
|
||||
mExitAnimator = anim;
|
||||
anim.start();
|
||||
mExitAnimator.start();
|
||||
}
|
||||
|
||||
private void finish(ClipboardOverlayEvent event, @Nullable Intent intent) {
|
||||
if (mExitAnimator != null && mExitAnimator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
mExitAnimator = mView.getExitAnimation();
|
||||
mExitAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
private boolean mCancelled;
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
super.onAnimationCancel(animation);
|
||||
mCancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
if (!mCancelled) {
|
||||
mClipboardLogger.logSessionComplete(event);
|
||||
if (intent != null) {
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
hideImmediate();
|
||||
}
|
||||
}
|
||||
});
|
||||
mExitAnimator.start();
|
||||
}
|
||||
|
||||
private void finishWithSharedTransition(ClipboardOverlayEvent event, Intent intent) {
|
||||
if (mExitAnimator != null && mExitAnimator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
mClipboardLogger.logSessionComplete(event);
|
||||
mExitAnimator = mView.getFadeOutAnimation();
|
||||
mExitAnimator.start();
|
||||
mTransitionExecutor.startSharedTransition(
|
||||
mWindow, mView.getPreview(), intent, this::hideImmediate);
|
||||
}
|
||||
|
||||
void hideImmediate() {
|
||||
@@ -613,6 +688,76 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
|
||||
mClipboardLogger.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismissButtonTapped() {
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteCopyButtonTapped() {
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
finish(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED,
|
||||
IntentCreator.getRemoteCopyIntent(mClipboardModel.getClipData(), mContext));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShareButtonTapped() {
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
if (mClipboardModel.getType() != ClipboardModel.Type.OTHER) {
|
||||
finishWithSharedTransition(CLIPBOARD_OVERLAY_SHARE_TAPPED,
|
||||
IntentCreator.getShareIntent(mClipboardModel.getClipData(), mContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewTapped() {
|
||||
if (mFeatureFlags.isEnabled(CLIPBOARD_SHARED_TRANSITIONS)) {
|
||||
switch (mClipboardModel.getType()) {
|
||||
case TEXT:
|
||||
finish(CLIPBOARD_OVERLAY_EDIT_TAPPED,
|
||||
IntentCreator.getTextEditorIntent(mContext));
|
||||
break;
|
||||
case IMAGE:
|
||||
finishWithSharedTransition(CLIPBOARD_OVERLAY_EDIT_TAPPED,
|
||||
IntentCreator.getImageEditIntent(mClipboardModel.getUri(), mContext));
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "Got preview tapped callback for non-editable type "
|
||||
+ mClipboardModel.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMinimizedViewTapped() {
|
||||
animateFromMinimized();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteraction() {
|
||||
if (!mClipboardModel.isRemote()) {
|
||||
mTimeoutHandler.resetTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeDismissInitiated(Animator animator) {
|
||||
if (mExitAnimator != null && mExitAnimator.isRunning()) {
|
||||
mExitAnimator.cancel();
|
||||
}
|
||||
mExitAnimator = animator;
|
||||
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismissComplete() {
|
||||
hideImmediate();
|
||||
}
|
||||
|
||||
static class ClipboardLogger {
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private String mClipSource;
|
||||
|
||||
@@ -254,6 +254,10 @@ public class ClipboardOverlayView extends DraggableConstraintLayout {
|
||||
});
|
||||
}
|
||||
|
||||
View getPreview() {
|
||||
return mClipboardPreview;
|
||||
}
|
||||
|
||||
void showImagePreview(@Nullable Bitmap thumbnail) {
|
||||
if (thumbnail == null) {
|
||||
mHiddenPreview.setText(mContext.getString(R.string.clipboard_text_hidden));
|
||||
@@ -368,6 +372,19 @@ public class ClipboardOverlayView extends DraggableConstraintLayout {
|
||||
return enterAnim;
|
||||
}
|
||||
|
||||
Animator getFadeOutAnimation() {
|
||||
ValueAnimator alphaAnim = ValueAnimator.ofFloat(1, 0);
|
||||
alphaAnim.addUpdateListener(animation -> {
|
||||
float alpha = (float) animation.getAnimatedValue();
|
||||
mActionContainer.setAlpha(alpha);
|
||||
mActionContainerBackground.setAlpha(alpha);
|
||||
mPreviewBorder.setAlpha(alpha);
|
||||
mDismissButton.setAlpha(alpha);
|
||||
});
|
||||
alphaAnim.setDuration(300);
|
||||
return alphaAnim;
|
||||
}
|
||||
|
||||
Animator getExitAnimation() {
|
||||
TimeInterpolator linearInterpolator = new LinearInterpolator();
|
||||
TimeInterpolator scaleInterpolator = new PathInterpolator(.3f, 0, 1f, 1f);
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.clipboardoverlay
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.app.ExitTransitionCoordinator
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.RemoteException
|
||||
import android.util.Log
|
||||
import android.util.Pair
|
||||
import android.view.IRemoteAnimationFinishedCallback
|
||||
import android.view.IRemoteAnimationRunner
|
||||
import android.view.RemoteAnimationAdapter
|
||||
import android.view.RemoteAnimationTarget
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManagerGlobal
|
||||
import com.android.internal.app.ChooserActivity
|
||||
import com.android.systemui.settings.DisplayTracker
|
||||
import javax.inject.Inject
|
||||
|
||||
class ClipboardTransitionExecutor
|
||||
@Inject
|
||||
constructor(val context: Context, val displayTracker: DisplayTracker) {
|
||||
fun startSharedTransition(window: Window, view: View, intent: Intent, onReady: Runnable) {
|
||||
val transition: Pair<ActivityOptions, ExitTransitionCoordinator> =
|
||||
ActivityOptions.startSharedElementAnimation(
|
||||
window,
|
||||
object : ExitTransitionCoordinator.ExitTransitionCallbacks {
|
||||
override fun isReturnTransitionAllowed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hideSharedElements() {
|
||||
onReady.run()
|
||||
}
|
||||
|
||||
override fun onFinish() {}
|
||||
},
|
||||
null,
|
||||
Pair.create(view, ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME)
|
||||
)
|
||||
transition.second.startExit()
|
||||
context.startActivity(intent, transition.first.toBundle())
|
||||
val runner = RemoteAnimationAdapter(NULL_ACTIVITY_TRANSITION, 0, 0)
|
||||
try {
|
||||
WindowManagerGlobal.getWindowManagerService()
|
||||
.overridePendingAppTransitionRemote(runner, displayTracker.defaultDisplayId)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error overriding clipboard app transition", e)
|
||||
}
|
||||
}
|
||||
|
||||
private val TAG: String = "ClipboardTransitionExec"
|
||||
|
||||
/**
|
||||
* This is effectively a no-op, but we need something non-null to pass in, in order to
|
||||
* successfully override the pending activity entrance animation.
|
||||
*/
|
||||
private val NULL_ACTIVITY_TRANSITION: IRemoteAnimationRunner.Stub =
|
||||
object : IRemoteAnimationRunner.Stub() {
|
||||
override fun onAnimationStart(
|
||||
transit: Int,
|
||||
apps: Array<RemoteAnimationTarget>,
|
||||
wallpapers: Array<RemoteAnimationTarget>,
|
||||
nonApps: Array<RemoteAnimationTarget>,
|
||||
finishedCallback: IRemoteAnimationFinishedCallback
|
||||
) {
|
||||
try {
|
||||
finishedCallback.onAnimationFinished()
|
||||
} catch (e: RemoteException) {
|
||||
Log.e(TAG, "Error finishing screenshot remote animation", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnimationCancelled() {}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBO
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHOWN_MINIMIZED;
|
||||
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
|
||||
import static com.android.systemui.flags.Flags.CLIPBOARD_IMAGE_TIMEOUT;
|
||||
import static com.android.systemui.flags.Flags.CLIPBOARD_SHARED_TRANSITIONS;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
@@ -93,12 +94,16 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private ClipboardImageLoader mClipboardImageLoader;
|
||||
@Mock
|
||||
private ClipboardTransitionExecutor mClipboardTransitionExecutor;
|
||||
@Mock
|
||||
private UiEventLogger mUiEventLogger;
|
||||
private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
|
||||
private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
|
||||
|
||||
@Mock
|
||||
private Animator mAnimator;
|
||||
private ArgumentCaptor<Animator.AnimatorListener> mAnimatorListenerCaptor =
|
||||
ArgumentCaptor.forClass(Animator.AnimatorListener.class);
|
||||
|
||||
private ClipData mSampleClipData;
|
||||
|
||||
@@ -117,6 +122,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
when(mClipboardOverlayView.getEnterAnimation()).thenReturn(mAnimator);
|
||||
when(mClipboardOverlayView.getExitAnimation()).thenReturn(mAnimator);
|
||||
when(mClipboardOverlayView.getFadeOutAnimation()).thenReturn(mAnimator);
|
||||
when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
|
||||
getImeInsets(new Rect(0, 0, 0, 0)));
|
||||
|
||||
@@ -124,7 +130,16 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
new ClipData.Item("Test Item"));
|
||||
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, true); // turned off for legacy tests
|
||||
mFeatureFlags.set(CLIPBOARD_SHARED_TRANSITIONS, true); // turned off for old tests
|
||||
}
|
||||
|
||||
/**
|
||||
* Needs to be done after setting flags for legacy tests, since the value of
|
||||
* CLIPBOARD_SHARED_TRANSITIONS is checked during construction. This can be moved back into
|
||||
* the setup method once CLIPBOARD_SHARED_TRANSITIONS is fully released and the tests where it
|
||||
* is false are removed.[
|
||||
*/
|
||||
private void initController() {
|
||||
mOverlayController = new ClipboardOverlayController(
|
||||
mContext,
|
||||
mClipboardOverlayView,
|
||||
@@ -136,6 +151,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
mClipboardUtils,
|
||||
mExecutor,
|
||||
mClipboardImageLoader,
|
||||
mClipboardTransitionExecutor,
|
||||
mUiEventLogger);
|
||||
verify(mClipboardOverlayView).setCallbacks(mOverlayCallbacksCaptor.capture());
|
||||
mCallbacks = mOverlayCallbacksCaptor.getValue();
|
||||
@@ -148,6 +164,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_invalidImageData_legacy() {
|
||||
initController();
|
||||
|
||||
ClipData clipData = new ClipData("", new String[]{"image/png"},
|
||||
new ClipData.Item(Uri.parse("")));
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
|
||||
@@ -161,6 +179,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_nonImageUri_legacy() {
|
||||
initController();
|
||||
|
||||
ClipData clipData = new ClipData("", new String[]{"resource/png"},
|
||||
new ClipData.Item(Uri.parse("")));
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
|
||||
@@ -175,6 +195,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void test_setClipData_textData_legacy() {
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
|
||||
initController();
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "abc");
|
||||
|
||||
verify(mClipboardOverlayView, times(1)).showTextPreview("Test Item", false);
|
||||
@@ -186,6 +208,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void test_setClipData_sensitiveTextData_legacy() {
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
|
||||
initController();
|
||||
|
||||
ClipDescription description = mSampleClipData.getDescription();
|
||||
PersistableBundle b = new PersistableBundle();
|
||||
b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
|
||||
@@ -202,6 +226,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
public void test_setClipData_repeatedCalls_legacy() {
|
||||
when(mAnimator.isRunning()).thenReturn(true);
|
||||
mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
|
||||
initController();
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
@@ -211,6 +236,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_invalidImageData() {
|
||||
initController();
|
||||
|
||||
ClipData clipData = new ClipData("", new String[]{"image/png"},
|
||||
new ClipData.Item(Uri.parse("")));
|
||||
|
||||
@@ -223,6 +250,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_nonImageUri() {
|
||||
initController();
|
||||
ClipData clipData = new ClipData("", new String[]{"resource/png"},
|
||||
new ClipData.Item(Uri.parse("")));
|
||||
|
||||
@@ -235,6 +263,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_textData() {
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "abc");
|
||||
|
||||
verify(mClipboardOverlayView, times(1)).showTextPreview("Test Item", false);
|
||||
@@ -245,6 +274,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_sensitiveTextData() {
|
||||
initController();
|
||||
ClipDescription description = mSampleClipData.getDescription();
|
||||
PersistableBundle b = new PersistableBundle();
|
||||
b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
|
||||
@@ -259,6 +289,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_setClipData_repeatedCalls() {
|
||||
initController();
|
||||
when(mAnimator.isRunning()).thenReturn(true);
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
@@ -268,7 +299,9 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_viewCallbacks_onShareTapped() {
|
||||
public void test_viewCallbacks_onShareTapped_sharedTransitionsOff() {
|
||||
mFeatureFlags.set(CLIPBOARD_SHARED_TRANSITIONS, false);
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
|
||||
mCallbacks.onShareButtonTapped();
|
||||
@@ -278,7 +311,22 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_viewCallbacks_onDismissTapped() {
|
||||
public void test_viewCallbacks_onShareTapped() {
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
|
||||
mCallbacks.onShareButtonTapped();
|
||||
verify(mAnimator).addListener(mAnimatorListenerCaptor.capture());
|
||||
mAnimatorListenerCaptor.getValue().onAnimationEnd(mAnimator);
|
||||
|
||||
verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_SHARE_TAPPED, 0, "");
|
||||
verify(mClipboardOverlayView, times(1)).getFadeOutAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_viewCallbacks_onDismissTapped_sharedTransitionsOff() {
|
||||
mFeatureFlags.set(CLIPBOARD_SHARED_TRANSITIONS, false);
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
@@ -287,8 +335,36 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
verify(mClipboardOverlayView, times(1)).getExitAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_viewCallbacks_onDismissTapped() {
|
||||
initController();
|
||||
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
verify(mAnimator).addListener(mAnimatorListenerCaptor.capture());
|
||||
mAnimatorListenerCaptor.getValue().onAnimationEnd(mAnimator);
|
||||
|
||||
// package name is null since we haven't actually set a source for this test
|
||||
verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, null);
|
||||
verify(mClipboardOverlayView, times(1)).getExitAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_multipleDismissals_dismissesOnce_sharedTransitionsOff() {
|
||||
mFeatureFlags.set(CLIPBOARD_SHARED_TRANSITIONS, false);
|
||||
initController();
|
||||
mCallbacks.onSwipeDismissInitiated(mAnimator);
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
mCallbacks.onSwipeDismissInitiated(mAnimator);
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
|
||||
verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_SWIPE_DISMISSED, 0, null);
|
||||
verify(mUiEventLogger, never()).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_multipleDismissals_dismissesOnce() {
|
||||
initController();
|
||||
|
||||
mCallbacks.onSwipeDismissInitiated(mAnimator);
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
mCallbacks.onSwipeDismissInitiated(mAnimator);
|
||||
@@ -300,6 +376,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_remoteCopy_withFlagOn() {
|
||||
initController();
|
||||
when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true);
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
@@ -309,6 +386,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_nonRemoteCopy() {
|
||||
initController();
|
||||
when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(false);
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
@@ -318,13 +396,16 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_logsUseLastClipSource() {
|
||||
mOverlayController.setClipData(mSampleClipData, "first.package");
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
mOverlayController.setClipData(mSampleClipData, "second.package");
|
||||
mCallbacks.onDismissButtonTapped();
|
||||
initController();
|
||||
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "first.package");
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "second.package");
|
||||
mOverlayController.setClipData(mSampleClipData, "first.package");
|
||||
mCallbacks.onShareButtonTapped();
|
||||
|
||||
mOverlayController.setClipData(mSampleClipData, "second.package");
|
||||
mCallbacks.onShareButtonTapped();
|
||||
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_SHARE_TAPPED, 0, "first.package");
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_SHARE_TAPPED, 0, "second.package");
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_SHOWN_EXPANDED, 0, "first.package");
|
||||
verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_SHOWN_EXPANDED, 0, "second.package");
|
||||
verifyNoMoreInteractions(mUiEventLogger);
|
||||
@@ -332,6 +413,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_logOnClipboardActionsShown() {
|
||||
initController();
|
||||
ClipData.Item item = mSampleClipData.getItemAt(0);
|
||||
item.setTextLinks(Mockito.mock(TextLinks.class));
|
||||
when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString()))
|
||||
@@ -357,6 +439,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_noInsets_showsExpanded() {
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
|
||||
verify(mClipboardOverlayView, never()).setMinimized(true);
|
||||
@@ -366,6 +449,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_insets_showsMinimized() {
|
||||
initController();
|
||||
when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
|
||||
getImeInsets(new Rect(0, 0, 0, 1)));
|
||||
mOverlayController.setClipData(mSampleClipData, "abc");
|
||||
@@ -389,6 +473,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void test_insetsChanged_minimizes() {
|
||||
initController();
|
||||
mOverlayController.setClipData(mSampleClipData, "");
|
||||
verify(mClipboardOverlayView, never()).setMinimized(true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user