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

Commit 7b088c3e authored by Winson Chung's avatar Winson Chung
Browse files

Fixing occasional jump when launching certain apps from Recents.

- Removing code that cleared the pending options for an activity when it
  is fetched by the app.
- Only handle the first window-animation-started callback from the system
  when transitioning out of Recents.
- Add logic in Recents to disable toggling Recents while an activity
  transition has been requested (ie. activity started) and the transition
  actually starting. This prevents some cases where interleaving of the
  transition updates can occur while the app takes a long time to draw
  when it is resumed which could cause animation jumps and weirdness.

Bug: 37277853
Test: Launch between apps quickly, especially those with camera.

Change-Id: I7ff8a83539334a39b0ae049d267d1ab14a38e2f6
parent 37a9991b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31,4 +31,5 @@ oneway interface IRecentsSystemUserCallbacks {
    void sendRecentsDrawnEvent();
    void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
    void sendLaunchRecentsEvent();
    void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
}
+20 −0
Original line number Diff line number Diff line
@@ -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.
     */
+41 −4
Original line number Diff line number Diff line
@@ -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);
+7 −0
Original line number Diff line number Diff line
@@ -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));
    }
}
+31 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
Loading