diff options
7 files changed, 145 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl index 1240e055d25a..cc7798e8721b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl @@ -31,4 +31,5 @@ oneway interface IRecentsSystemUserCallbacks { void sendRecentsDrawnEvent(); void sendDockingTopTaskEvent(int dragMode, in Rect initialRect); void sendLaunchRecentsEvent(); + void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index a5c994ec9761..1657bfa55bf6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -57,6 +57,7 @@ import com.android.systemui.recents.events.activity.DockedTopTaskEvent; import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; +import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent; import com.android.systemui.recents.events.component.ShowUserToastEvent; import com.android.systemui.recents.events.ui.RecentsDrawnEvent; import com.android.systemui.recents.misc.SystemServicesProxy; @@ -711,6 +712,25 @@ public class Recents extends SystemUI } } + public final void onBusEvent(SetWaitingForTransitionStartEvent event) { + int processUser = sSystemServicesProxy.getProcessUser(); + if (sSystemServicesProxy.isSystemUser(processUser)) { + mImpl.setWaitingForTransitionStart(event.waitingForTransitionStart); + } else { + postToSystemUser(new Runnable() { + @Override + public void run() { + try { + mUserToSystemCallbacks.setWaitingForTransitionStartEvent( + event.waitingForTransitionStart); + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } + } + }); + } + } + /** * Attempts to register with the system user. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 7cd93bba9b0b..86e93fdd63ad 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -24,12 +24,11 @@ import static android.view.View.MeasureSpec; import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityOptions; +import android.app.ActivityOptions.OnAnimationStartedListener; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.graphics.RectF; @@ -208,6 +207,20 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener protected static RecentsTaskLoadPlan sInstanceLoadPlan; // Stores the last pinned task time protected static long sLastPipTime = -1; + // Stores whether we are waiting for a transition to/from recents to start. During this time, + // we disallow the user from manually toggling recents until the transition has started. + private static boolean mWaitingForTransitionStart = false; + // Stores whether or not the user toggled while we were waiting for a transition to/from + // recents. In this case, we defer the toggle state until then and apply it immediately after. + private static boolean mToggleFollowingTransitionStart = true; + + private ActivityOptions.OnAnimationStartedListener mResetToggleFlagListener = + new OnAnimationStartedListener() { + @Override + public void onAnimationStarted() { + setWaitingForTransitionStart(false); + } + }; protected Context mContext; protected Handler mHandler; @@ -365,6 +378,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener return; } + if (mWaitingForTransitionStart) { + mToggleFollowingTransitionStart = true; + return; + } + mDraggingInRecents = false; mLaunchedWhileDocking = false; mTriggeredFromAltTab = false; @@ -638,6 +656,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } } + public void setWaitingForTransitionStart(boolean waitingForTransitionStart) { + if (mWaitingForTransitionStart == waitingForTransitionStart) { + return; + } + + mWaitingForTransitionStart = waitingForTransitionStart; + if (!waitingForTransitionStart && mToggleFollowingTransitionStart) { + toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET); + } + mToggleFollowingTransitionStart = false; + } + /** * Returns the preloaded load plan and invalidates it. */ @@ -865,8 +895,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()]; specs.toArray(specsArray); + return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, - specsArray, mHandler, null, this), null); + specsArray, mHandler, mResetToggleFlagListener, this), null); } else { // Update the destination rect Task toTask = new Task(); @@ -884,8 +915,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener return Lists.newArrayList(new AppTransitionAnimationSpec( toTask.key.id, thumbnail, rect)); }); + return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext, - mHandler, future.getFuture(), null, false /* scaleUp */), future); + mHandler, future.getFuture(), mResetToggleFlagListener, false /* scaleUp */), + future); } } @@ -991,6 +1024,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener launchState.launchedToTaskId = runningTaskId; launchState.launchedWithAltTab = mTriggeredFromAltTab; + // Disable toggling of recents between starting the activity and it is visible and the app + // has started its transition into recents. + setWaitingForTransitionStart(useThumbnailTransition); + // Preload the icon (this will be a null-op if we have preloaded the icon already in // preloadRecents()) preloadIcon(runningTaskId); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java index 3921a20cffd1..1285626015d2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java @@ -29,6 +29,7 @@ import com.android.systemui.EventLogTags; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.DockedTopTaskEvent; import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; +import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent; import com.android.systemui.recents.events.ui.RecentsDrawnEvent; import com.android.systemui.recents.misc.ForegroundThread; @@ -105,4 +106,10 @@ public class RecentsSystemUser extends IRecentsSystemUserCallbacks.Stub { public void sendLaunchRecentsEvent() throws RemoteException { EventBus.getDefault().post(new RecentsActivityStartingEvent()); } + + @Override + public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) { + EventBus.getDefault().post(new SetWaitingForTransitionStartEvent( + waitingForTransitionStart)); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java new file mode 100644 index 000000000000..d9cf5fbf645d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 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.recents.events.component; + +import com.android.systemui.recents.events.EventBus; + +/** + * This is sent when we are setting/resetting the flag to wait for the transition to start. + */ +public class SetWaitingForTransitionStartEvent extends EventBus.Event { + + public final boolean waitingForTransitionStart; + + public SetWaitingForTransitionStartEvent(boolean waitingForTransitionStart) { + this.waitingForTransitionStart = waitingForTransitionStart; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index ce40f202d519..127822aec6df 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -54,6 +54,7 @@ import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent; import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent; import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent; import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; +import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; @@ -117,31 +118,58 @@ public class RecentsTransitionHelper { final Rect windowRect = Recents.getSystemServices().getWindowRect(); transitionFuture = getAppTransitionFuture( () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect)); - animStartedListener = () -> { - // If we are launching into another task, cancel the previous task's - // window transition - EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task)); - EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent()); - stackView.cancelAllTaskViewAnimations(); - - if (screenPinningRequested) { - // Request screen pinning after the animation runs - mStartScreenPinningRunnable.taskId = task.key.id; - mHandler.postDelayed(mStartScreenPinningRunnable, 350); + animStartedListener = new OnAnimationStartedListener() { + private boolean mHandled; + + @Override + public void onAnimationStarted() { + if (mHandled) { + return; + } + mHandled = true; + + // If we are launching into another task, cancel the previous task's + // window transition + EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task)); + EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent()); + stackView.cancelAllTaskViewAnimations(); + + if (screenPinningRequested) { + // Request screen pinning after the animation runs + mStartScreenPinningRunnable.taskId = task.key.id; + mHandler.postDelayed(mStartScreenPinningRunnable, 350); + } + + // Reset the state where we are waiting for the transition to start + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); } }; } else { // This is only the case if the task is not on screen (scrolled offscreen for example) transitionFuture = null; - animStartedListener = () -> { - // If we are launching into another task, cancel the previous task's - // window transition - EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task)); - EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent()); - stackView.cancelAllTaskViewAnimations(); + animStartedListener = new OnAnimationStartedListener() { + private boolean mHandled; + + @Override + public void onAnimationStarted() { + if (mHandled) { + return; + } + mHandled = true; + + // If we are launching into another task, cancel the previous task's + // window transition + EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task)); + EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent()); + stackView.cancelAllTaskViewAnimations(); + + // Reset the state where we are waiting for the transition to start + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); + } }; } + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(true)); final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext, mHandler, transitionFuture != null ? transitionFuture.future : null, animStartedListener, true /* scaleUp */); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bcad2fc09602..161bf9adce30 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -13323,7 +13323,6 @@ public class ActivityManagerService extends IActivityManager.Stub final ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r != null) { final ActivityOptions activityOptions = r.pendingOptions; - r.pendingOptions = null; return activityOptions == null ? null : activityOptions.toBundle(); } return null; |