Disable input during Activity Transition.
Bug 19437530 While the actual Activity Transitions are running, input is stopped, except for the "back" button. Change-Id: I112e6252b9de05ece10a6267681fee5487e5ef6b
This commit is contained in:
@@ -3841,10 +3841,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mStartedActivity = true;
|
||||
}
|
||||
|
||||
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
|
||||
if (decor != null) {
|
||||
decor.cancelPendingInputEvents();
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
// TODO Consider clearing/flushing other event sources and events for child windows.
|
||||
} else {
|
||||
if (options != null) {
|
||||
@@ -3855,6 +3852,18 @@ public class Activity extends ContextThemeWrapper
|
||||
mParent.startActivityFromChild(this, intent, requestCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels pending inputs and if an Activity Transition is to be run, starts the transition.
|
||||
*
|
||||
* @param options The ActivityOptions bundle used to start an Activity.
|
||||
*/
|
||||
private void cancelInputsAndStartExitTransition(Bundle options) {
|
||||
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
|
||||
if (decor != null) {
|
||||
decor.cancelPendingInputEvents();
|
||||
}
|
||||
if (options != null && !isTopOfTask()) {
|
||||
mActivityTransitionState.startExitOutTransition(this, options);
|
||||
}
|
||||
@@ -3872,9 +3881,6 @@ public class Activity extends ContextThemeWrapper
|
||||
*/
|
||||
public void startActivityForResultAsUser(Intent intent, int requestCode,
|
||||
@Nullable Bundle options, UserHandle user) {
|
||||
if (options != null) {
|
||||
mActivityTransitionState.startExitOutTransition(this, options);
|
||||
}
|
||||
if (mParent != null) {
|
||||
throw new RuntimeException("Can't be called from a child");
|
||||
}
|
||||
@@ -3896,10 +3902,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mStartedActivity = true;
|
||||
}
|
||||
|
||||
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
|
||||
if (decor != null) {
|
||||
decor.cancelPendingInputEvents();
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3925,6 +3928,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mToken, mEmbeddedID, -1, ar.getResultCode(),
|
||||
ar.getResultData());
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3948,6 +3952,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mToken, mEmbeddedID, -1, ar.getResultCode(),
|
||||
ar.getResultData());
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4380,6 +4385,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mToken, child.mEmbeddedID, requestCode,
|
||||
ar.getResultCode(), ar.getResultData());
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4431,9 +4437,6 @@ public class Activity extends ContextThemeWrapper
|
||||
@Override
|
||||
public void startActivityForResult(
|
||||
String who, Intent intent, int requestCode, @Nullable Bundle options) {
|
||||
if (options != null) {
|
||||
mActivityTransitionState.startExitOutTransition(this, options);
|
||||
}
|
||||
Instrumentation.ActivityResult ar =
|
||||
mInstrumentation.execStartActivity(
|
||||
this, mMainThread.getApplicationThread(), mToken, who,
|
||||
@@ -4443,6 +4446,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mToken, who, requestCode,
|
||||
ar.getResultCode(), ar.getResultData());
|
||||
}
|
||||
cancelInputsAndStartExitTransition(options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroupOverlay;
|
||||
import android.view.ViewParent;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
@@ -187,11 +188,6 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
||||
*/
|
||||
public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
|
||||
|
||||
/**
|
||||
* Send the shared element positions.
|
||||
*/
|
||||
public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
|
||||
|
||||
private Window mWindow;
|
||||
final protected ArrayList<String> mAllSharedElementNames;
|
||||
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
|
||||
@@ -207,6 +203,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
||||
new ArrayList<GhostViewListeners>();
|
||||
private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
|
||||
private ArrayList<Matrix> mSharedElementParentMatrices;
|
||||
private boolean mSharedElementTransitionComplete;
|
||||
private boolean mViewsTransitionComplete;
|
||||
|
||||
public ActivityTransitionCoordinator(Window window,
|
||||
ArrayList<String> allSharedElementNames,
|
||||
@@ -219,6 +217,11 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
||||
}
|
||||
|
||||
protected void viewsReady(ArrayMap<String, View> sharedElements) {
|
||||
final View decor = getDecor();
|
||||
final ViewRootImpl viewRoot = decor == null ? null : decor.getViewRootImpl();
|
||||
if (viewRoot != null) {
|
||||
viewRoot.setPausedForTransition(true);
|
||||
}
|
||||
sharedElements.retainAll(mAllSharedElementNames);
|
||||
if (mListener != null) {
|
||||
mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
|
||||
@@ -878,6 +881,32 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isViewsTransitionComplete() {
|
||||
return mViewsTransitionComplete;
|
||||
}
|
||||
|
||||
protected void viewsTransitionComplete() {
|
||||
mViewsTransitionComplete = true;
|
||||
startInputWhenTransitionsComplete();
|
||||
}
|
||||
|
||||
protected void sharedElementTransitionComplete() {
|
||||
mSharedElementTransitionComplete = true;
|
||||
startInputWhenTransitionsComplete();
|
||||
}
|
||||
private void startInputWhenTransitionsComplete() {
|
||||
if (mViewsTransitionComplete && mSharedElementTransitionComplete) {
|
||||
final View decor = getDecor();
|
||||
if (decor != null) {
|
||||
final ViewRootImpl viewRoot = decor.getViewRootImpl();
|
||||
viewRoot.setPausedForTransition(false);
|
||||
}
|
||||
onTransitionsComplete();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onTransitionsComplete() {}
|
||||
|
||||
protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
|
||||
@Override
|
||||
public void onTransitionStart(Transition transition) {
|
||||
|
||||
@@ -55,8 +55,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
private boolean mWasOpaque;
|
||||
private boolean mAreViewsReady;
|
||||
private boolean mIsViewsTransitionStarted;
|
||||
private boolean mIsViewsTransitionComplete;
|
||||
private boolean mIsSharedElementTransitionComplete;
|
||||
private Transition mEnterViewsTransition;
|
||||
|
||||
public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
|
||||
@@ -456,7 +454,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
}
|
||||
}
|
||||
if (viewsTransition == null) {
|
||||
viewTransitionComplete();
|
||||
viewsTransitionComplete();
|
||||
} else {
|
||||
viewsTransition.forceVisibility(View.INVISIBLE, true);
|
||||
final ArrayList<View> transitioningViews = mTransitioningViews;
|
||||
@@ -474,7 +472,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
mEnterViewsTransition = null;
|
||||
transition.removeListener(this);
|
||||
viewTransitionComplete();
|
||||
viewsTransitionComplete();
|
||||
super.onTransitionEnd(transition);
|
||||
}
|
||||
});
|
||||
@@ -497,18 +495,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
return transition;
|
||||
}
|
||||
|
||||
private void viewTransitionComplete() {
|
||||
mIsViewsTransitionComplete = true;
|
||||
if (mIsSharedElementTransitionComplete) {
|
||||
moveSharedElementsFromOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
private void sharedElementTransitionComplete() {
|
||||
mIsSharedElementTransitionComplete = true;
|
||||
if (mIsViewsTransitionComplete) {
|
||||
moveSharedElementsFromOverlay();
|
||||
}
|
||||
@Override
|
||||
protected void onTransitionsComplete() {
|
||||
moveSharedElementsFromOverlay();
|
||||
}
|
||||
|
||||
private void sharedElementTransitionStarted() {
|
||||
|
||||
@@ -46,8 +46,6 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
private static final String TAG = "ExitTransitionCoordinator";
|
||||
private static final long MAX_WAIT_MS = 1000;
|
||||
|
||||
private boolean mExitComplete;
|
||||
|
||||
private Bundle mSharedElementBundle;
|
||||
|
||||
private boolean mExitNotified;
|
||||
@@ -165,7 +163,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
if (mExitComplete) {
|
||||
if (isViewsTransitionComplete()) {
|
||||
delayCancel();
|
||||
}
|
||||
}
|
||||
@@ -310,14 +308,14 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
viewsTransition = configureTransition(getViewsTransition(), true);
|
||||
}
|
||||
if (viewsTransition == null) {
|
||||
exitTransitionComplete();
|
||||
viewsTransitionComplete();
|
||||
} else {
|
||||
final ArrayList<View> transitioningViews = mTransitioningViews;
|
||||
viewsTransition.addListener(new ContinueTransitionListener() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
exitTransitionComplete();
|
||||
viewsTransitionComplete();
|
||||
if (mIsHidden && transitioningViews != null) {
|
||||
showViews(transitioningViews, true);
|
||||
}
|
||||
@@ -373,19 +371,15 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
private void exitTransitionComplete() {
|
||||
mExitComplete = true;
|
||||
notifyComplete();
|
||||
}
|
||||
|
||||
protected boolean isReadyToNotify() {
|
||||
return mSharedElementBundle != null && mResultReceiver != null && mIsBackgroundReady;
|
||||
}
|
||||
|
||||
private void sharedElementTransitionComplete() {
|
||||
@Override
|
||||
protected void sharedElementTransitionComplete() {
|
||||
mSharedElementBundle = mExitSharedElementBundle == null
|
||||
? captureSharedElementState() : captureExitSharedElementsState();
|
||||
notifyComplete();
|
||||
super.sharedElementTransitionComplete();
|
||||
}
|
||||
|
||||
private Bundle captureExitSharedElementsState() {
|
||||
@@ -405,6 +399,11 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionsComplete() {
|
||||
notifyComplete();
|
||||
}
|
||||
|
||||
protected void notifyComplete() {
|
||||
if (isReadyToNotify()) {
|
||||
if (!mSharedElementNotified) {
|
||||
@@ -433,7 +432,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
}
|
||||
|
||||
private void notifyExitComplete() {
|
||||
if (!mExitNotified && mExitComplete) {
|
||||
if (!mExitNotified && isViewsTransitionComplete()) {
|
||||
mExitNotified = true;
|
||||
mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null);
|
||||
mResultReceiver = null; // done talking
|
||||
|
||||
@@ -586,7 +586,7 @@ final class AccessibilityInteractionController {
|
||||
}
|
||||
}
|
||||
|
||||
private void perfromAccessibilityActionUiThread(Message message) {
|
||||
private void performAccessibilityActionUiThread(Message message) {
|
||||
final int flags = message.arg1;
|
||||
final int accessibilityViewId = message.arg2;
|
||||
|
||||
@@ -602,7 +602,8 @@ final class AccessibilityInteractionController {
|
||||
|
||||
boolean succeeded = false;
|
||||
try {
|
||||
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
|
||||
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null ||
|
||||
mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) {
|
||||
return;
|
||||
}
|
||||
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
|
||||
@@ -1146,7 +1147,7 @@ final class AccessibilityInteractionController {
|
||||
findAccessibilityNodeInfoByAccessibilityIdUiThread(message);
|
||||
} break;
|
||||
case MSG_PERFORM_ACCESSIBILITY_ACTION: {
|
||||
perfromAccessibilityActionUiThread(message);
|
||||
performAccessibilityActionUiThread(message);
|
||||
} break;
|
||||
case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID: {
|
||||
findAccessibilityNodeInfosByViewIdUiThread(message);
|
||||
|
||||
@@ -173,6 +173,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
// so the window should no longer be active.
|
||||
boolean mStopped = false;
|
||||
|
||||
// Set to true to stop input during an Activity Transition.
|
||||
boolean mPausedForTransition = false;
|
||||
|
||||
boolean mLastInCompatMode = false;
|
||||
|
||||
SurfaceHolder.Callback2 mSurfaceHolderCallback;
|
||||
@@ -977,15 +980,25 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return null;
|
||||
}
|
||||
|
||||
void setStopped(boolean stopped) {
|
||||
void setWindowStopped(boolean stopped) {
|
||||
if (mStopped != stopped) {
|
||||
mStopped = stopped;
|
||||
if (!stopped) {
|
||||
if (!mStopped) {
|
||||
scheduleTraversals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block the input events during an Activity Transition. The KEYCODE_BACK event is allowed
|
||||
* through to allow quick reversal of the Activity Transition.
|
||||
*
|
||||
* @param paused true to pause, false to resume.
|
||||
*/
|
||||
public void setPausedForTransition(boolean paused) {
|
||||
mPausedForTransition = paused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewParent getParent() {
|
||||
return null;
|
||||
@@ -3632,8 +3645,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if (mView == null || !mAdded) {
|
||||
Slog.w(TAG, "Dropping event due to root view being removed: " + q.mEvent);
|
||||
return true;
|
||||
} else if ((!mAttachInfo.mHasWindowFocus || mStopped)
|
||||
&& !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
|
||||
} else if ((!mAttachInfo.mHasWindowFocus
|
||||
&& !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
|
||||
|| (mPausedForTransition && !isBack(q.mEvent))) {
|
||||
// This is a focus event and the window doesn't currently have input focus or
|
||||
// has stopped. This could be an event that came back from the previous stage
|
||||
// but the window has lost focus or stopped in the meantime.
|
||||
@@ -3656,6 +3670,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mNext.dump(prefix, writer);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBack(InputEvent event) {
|
||||
if (event instanceof KeyEvent) {
|
||||
return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6223,7 +6245,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
@Override
|
||||
public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
|
||||
if (mView == null) {
|
||||
if (mView == null || mStopped || mPausedForTransition) {
|
||||
return false;
|
||||
}
|
||||
// Intercept accessibility focus events fired by virtual nodes to keep
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.app.ActivityManager;
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
@@ -552,7 +551,7 @@ public final class WindowManagerGlobal {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (token == null || mParams.get(i).token == token) {
|
||||
ViewRootImpl root = mRoots.get(i);
|
||||
root.setStopped(stopped);
|
||||
root.setWindowStopped(stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user