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

Commit 8477226a authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Fix bug with rotating in the middle of split select staging animation

This patch fixes a bug where a user could cause a crash by rotating the device in the middle of the split staging animation.

The bug arose because:
1) Normally, when you rotate the device, reapplyState() is called to refresh the UI. This reloads the state, cancels any animations that happen to be running at the time, and generally works fine in most cases.
2) When animations are canceled within Overview, we also call RecentsView#reset() to clean up loose ends and prevent bugs.
3) Unlike other states, the split select state is unique because it is a transient state that holds the user's choices temporarily. If that information was cleared -- by reset() -- before it loads, it will crash.

Fixed by creating a new function in SplitScreenSelectState, onStateReapplied(), that is called when a reload is occurring. It makes sure that animations do not get canceled by calling end() to accelerate them to completion before the reloading occurs.

Fixes: 249819567
Test: Manual
Change-Id: I70c4651bcb5df81edd25f6e58e21520ebb391d01
parent 6d3658dd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -53,4 +53,9 @@ public class SplitScreenSelectState extends OverviewState {
            return SplitAnimationTimings.ABORT_DURATION;
        }
    }

    @Override
    public boolean shouldPreserveDataStateOnReapply() {
        return true;
    }
}
+0 −2
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
@@ -4624,7 +4623,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        return true;
    }

    /** TODO(b/181707736) More gracefully handle exiting split selection state */
    @SuppressLint("WrongCall")
    protected void resetFromSplitSelectionState() {
        if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
+8 −0
Original line number Diff line number Diff line
@@ -70,4 +70,12 @@ public interface BaseState<T extends BaseState> {
    default boolean showTaskThumbnailSplash() {
        return false;
    }

    /**
     * For this state, whether member variables and other forms of data state should be preserved
     * or wiped when the state is reapplied. (See {@link StateManager#reapplyState()})
     */
    default boolean shouldPreserveDataStateOnReapply() {
        return false;
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -184,6 +184,13 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
    public void reapplyState(boolean cancelCurrentAnimation) {
        boolean wasInAnimation = mConfig.currentAnimation != null;
        if (cancelCurrentAnimation) {
            // Animation canceling can trigger a cleanup routine, causing problems when we are in a
            // launcher state that relies on member variable data. So if we are in one of those
            // states, accelerate the current animation to its end point rather than canceling it
            // outright.
            if (mState.shouldPreserveDataStateOnReapply() && mConfig.currentAnimation != null) {
                mConfig.currentAnimation.end();
            }
            mAtomicAnimationFactory.cancelAllStateElementAnimation();
            cancelAnimation();
        }