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

Commit 3f948e3f authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Adding state manager to fallback recents activity

Bug: 156398988
Change-Id: Id0a106ef888ade5223940ac8243108c39b4d6b98
parent 7dcd4d6e
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides.states;

import android.content.Context;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -54,11 +55,7 @@ public class BackgroundAppState extends OverviewState {

    @Override
    public float[] getOverviewScaleAndOffset(Launcher launcher) {
        return new float[] {getOverviewScale(launcher), NO_OFFSET};
    }

    private float getOverviewScale(Launcher launcher) {
        return ((RecentsView) launcher.getOverviewPanel()).getMaxScaleForFullScreen();
        return getOverviewScaleAndOffsetForBackgroundState(launcher);
    }

    @Override
@@ -88,4 +85,11 @@ public class BackgroundAppState extends OverviewState {
    protected float getDepthUnchecked(Context context) {
        return 1f;
    }

    public static float[] getOverviewScaleAndOffsetForBackgroundState(
            BaseDraggingActivity activity) {
        return new float[] {
                ((RecentsView) activity.getOverviewPanel()).getMaxScaleForFullScreen(),
                NO_OFFSET};
    }
}
+13 −9
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -49,22 +50,25 @@ public class OverviewModalTaskState extends OverviewState {

    @Override
    public float[] getOverviewScaleAndOffset(Launcher launcher) {
        Resources res = launcher.getBaseContext().getResources();
        return getOverviewScaleAndOffsetForModalState(launcher);
    }

    @Override
    public float getOverviewModalness() {
        return 1.0f;
    }

    public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) {
        Resources res = activity.getResources();

        Rect out = new Rect();
        launcher.<RecentsView>getOverviewPanel().getTaskSize(out);
        activity.<RecentsView>getOverviewPanel().getTaskSize(out);
        int taskHeight = out.height();

        float topMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
        float bottomMargin = res.getDimension(R.dimen.overview_actions_top_margin);
        float newHeight = taskHeight + topMargin + bottomMargin;
        float scale = newHeight / taskHeight;

        return new float[] {scale, 0};
    }

    @Override
    public float getOverviewModalness() {
        return 1.0f;
        return new float[] {scale, NO_OFFSET};
    }
}
+16 −20
Original line number Diff line number Diff line
@@ -15,14 +15,15 @@
 */
package com.android.quickstep;

import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.fallback.FallbackRecentsView.ZOOM_PROGRESS;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;

@@ -30,6 +31,7 @@ import androidx.annotation.Nullable;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ActivityInitListener;
@@ -89,15 +91,13 @@ public final class FallbackActivityInterface implements
    public AnimationFactory prepareRecentsUI(
            boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
        RecentsActivity activity = getCreatedActivity();
        if (activityVisible) {
        if (activity == null) {
            return (transitionLength) -> { };
        }

        activity.getStateManager().goToState(BACKGROUND_APP);
        FallbackRecentsView rv = activity.getOverviewPanel();
        rv.setContentAlpha(0);
        rv.getClearAllButton().setVisibilityAlpha(0);
        rv.setDisallowScrollToClearAll(true);
        rv.setInOverviewState(false);

        return new AnimationFactory() {

@@ -115,23 +115,19 @@ public final class FallbackActivityInterface implements

            @Override
            public void createActivityInterface(long transitionLength) {
                AnimatorSet animatorSet = new AnimatorSet();
                PendingAnimation pa = new PendingAnimation(transitionLength * 2);

                if (isAnimatingToRecents) {
                    ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
                    anim.setDuration(transitionLength).setInterpolator(LINEAR);
                    animatorSet.play(anim);
                    pa.addFloat(rv, CONTENT_ALPHA, 0, 1, LINEAR);
                }

                ObjectAnimator anim = ObjectAnimator.ofFloat(rv, ZOOM_PROGRESS, 1, 0);
                anim.setDuration(transitionLength).setInterpolator(LINEAR);
                animatorSet.play(anim);

                AnimatorPlaybackController controller =
                        AnimatorPlaybackController.wrap(animatorSet, transitionLength);
                pa.addFloat(rv, SCALE_PROPERTY, rv.getMaxScaleForFullScreen(), 1, LINEAR);
                pa.addFloat(rv, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
                AnimatorPlaybackController controller = pa.createPlaybackController();

                // Since we are changing the start position of the UI, reapply the state, at the end
                controller.setEndAction(() ->
                        rv.setInOverviewState(controller.getInterpolatedProgress() > 0.5));
                controller.setEndAction(() -> activity.getStateManager().goToState(
                        controller.getInterpolatedProgress() > 0.5 ? DEFAULT : BACKGROUND_APP));
                callback.accept(controller);
            }
        };
@@ -147,7 +143,7 @@ public final class FallbackActivityInterface implements
    @Nullable
    @Override
    public RecentsActivity getCreatedActivity() {
        return BaseRecentsActivity.ACTIVITY_TRACKER.getCreatedActivity();
        return RecentsActivity.ACTIVITY_TRACKER.getCreatedActivity();
    }

    @Nullable
+48 −4
Original line number Diff line number Diff line
@@ -37,10 +37,12 @@ import android.os.Bundle;
import android.util.ArrayMap;
import android.view.MotionEvent;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.ObjectWrapper;
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RectFSpringAnim;
@@ -103,6 +105,12 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
    private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
    private RunningWindowAnim mFinishAnimation;

    // Used to control Recents components throughout the swipe gesture.
    private AnimatorPlaybackController mLauncherTransitionController;
    private boolean mHasLauncherTransitionControllerStarted;

    private AnimationFactory mAnimationFactory = (t) -> { };

    public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
            GestureState gestureState, InputConsumerController inputConsumer,
            boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
@@ -165,10 +173,6 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
        mRecentsView = mActivity.getOverviewPanel();
        mRecentsView.setOnPageTransitionEndCallback(null);
        linkRecentsViewScroll();
        mRecentsView.setDisallowScrollToClearAll(true);
        mRecentsView.getClearAllButton().setVisibilityAlpha(0);
        mRecentsView.setZoomProgress(1);

        if (!mContinuingLastGesture) {
            if (mRunningOverHome) {
                mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
@@ -178,9 +182,48 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
        }
        mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
        mDeviceState.enableMultipleRegions(false);

        mAnimationFactory = mActivityInterface.prepareRecentsUI(alreadyOnHome,
                this::onAnimatorPlaybackControllerCreated);
        mAnimationFactory.createActivityInterface(mTransitionDragLength);
        return true;
    }

    @Override
    protected void initTransitionEndpoints(DeviceProfile dp) {
        super.initTransitionEndpoints(dp);
        if (canCreateNewOrUpdateExistingLauncherTransitionController()) {
            mAnimationFactory.createActivityInterface(mTransitionDragLength);
        }
    }

    private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
        mLauncherTransitionController = anim;
        mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
        mLauncherTransitionController.dispatchOnStart();
        updateLauncherTransitionProgress();
    }

    private void updateLauncherTransitionProgress() {
        if (mLauncherTransitionController == null
                || !canCreateNewOrUpdateExistingLauncherTransitionController()) {
            return;
        }
        // Normalize the progress to 0 to 1, as the animation controller will clamp it to that
        // anyway. The controller mimics the drag length factor by applying it to its interpolators.
        float progress = mCurrentShift.value / mDragLengthFactor;
        mLauncherTransitionController.setPlayFraction(progress);
    }

    /**
     * We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
     * (it has its own animation) or if we're already animating the current controller.
     * @return Whether we can create the launcher controller or update its progress.
     */
    private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
        return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
    }

    @Override
    protected boolean moveWindowWithRecentsScroll() {
        return mInQuickSwitchMode;
@@ -260,6 +303,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
        }

        applyWindowTransform();
        updateLauncherTransitionProgress();
    }

    @Override
+156 −26
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.quickstep;

import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;

import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY;
@@ -29,21 +32,32 @@ import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.view.View;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsStateController;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityOptionsCompat;
@@ -51,26 +65,40 @@ import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;

import java.io.FileDescriptor;
import java.io.PrintWriter;

/**
 * A recents activity that shows the recently launched tasks as swipable task cards.
 * See {@link com.android.quickstep.views.RecentsView}.
 */
public final class RecentsActivity extends BaseRecentsActivity {
public final class RecentsActivity extends StatefulActivity<RecentsState> {

    public static final String EXTRA_THUMBNAIL = "thumbnailData";
    public static final String EXTRA_TASK_ID = "taskID";
    public static final ActivityTracker<RecentsActivity> ACTIVITY_TRACKER =
            new ActivityTracker<>();

    private Handler mUiHandler = new Handler(Looper.getMainLooper());
    private RecentsRootView mRecentsRootView;
    private FallbackRecentsView mFallbackRecentsView;
    private OverviewActionsView mActionsView;

    @Override
    private Configuration mOldConfig;

    private StateManager<RecentsState> mStateManager;

    /**
     * Init drag layer and overview panel views.
     */
    protected void initViews() {
        setContentView(R.layout.fallback_recents_activity);
        mRecentsRootView = findViewById(R.id.drag_layer);
        mFallbackRecentsView = findViewById(R.id.overview_panel);
        mActionsView = findViewById(R.id.overview_actions_view);

        mRecentsRootView.recreateControllers();
        mFallbackRecentsView.init(findViewById(R.id.overview_actions_view));
        mFallbackRecentsView.init(mActionsView);
    }

    @Override
@@ -103,25 +131,38 @@ public final class RecentsActivity extends BaseRecentsActivity {
        intent.removeExtra(EXTRA_TASK_ID);
        intent.removeExtra(EXTRA_THUMBNAIL);
        super.onNewIntent(intent);
        ACTIVITY_TRACKER.handleNewIntent(this, intent);
    }

    @Override
    /**
         * Logic for when device configuration changes (rotation, screen size change, multi-window,
         * etc.)
         */
    protected void onHandleConfigChanged() {
        super.onHandleConfigChanged();
        mRecentsRootView.recreateControllers();
    }
        mUserEventDispatcher = null;
        initDeviceProfile();

    @Override
    protected void reapplyUi() {
        mRecentsRootView.dispatchInsets();
        AbstractFloatingView.closeOpenViews(this, true,
                AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
        dispatchDeviceProfileChanged();

        reapplyUi();
        mRecentsRootView.recreateControllers();
    }

    @Override
    /**
     * Generate the device profile to use in this activity.
     * @return device profile
     */
    protected DeviceProfile createDeviceProfile() {
        DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
        DeviceProfile dp1 = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);

        // In case we are reusing IDP, create a copy so that we don't conflict with Launcher
        // activity.
        return (mRecentsRootView != null) && isInMultiWindowMode()
                ? dp.getMultiWindowProfile(this, getMultiWindowDisplaySize())
                : super.createDeviceProfile();
                : dp1.copy(this);
    }

    @Override
@@ -139,6 +180,10 @@ public final class RecentsActivity extends BaseRecentsActivity {
        return (T) mFallbackRecentsView;
    }

    public OverviewActionsView getActionsView() {
        return mActionsView;
    }

    @Override
    public void returnToHomescreen() {
        super.returnToHomescreen();
@@ -160,12 +205,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
                    RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
                AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
                        wallpaperTargets);
                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mFallbackRecentsView.resetViewUI();
                    }
                });
                anim.addListener(resetStateListener());
                result.setAnimation(anim, RecentsActivity.this);
            }
        };
@@ -193,12 +233,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
                    .createAdjacentPageAnimForTaskLaunch(taskView);
            adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
            adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
            adjacentAnimation.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mFallbackRecentsView.resetTaskVisuals();
                }
            });
            adjacentAnimation.addListener(resetStateListener());
            target.play(adjacentAnimation);
        }
        return target;
@@ -210,13 +245,14 @@ public final class RecentsActivity extends BaseRecentsActivity {
        // onActivityStart callback.
        mFallbackRecentsView.setContentAlpha(1);
        super.onStart();
        mFallbackRecentsView.resetTaskVisuals();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mFallbackRecentsView.reset();

        // Workaround for b/78520668, explicitly trim memory once UI is hidden
        onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
    }

    @Override
@@ -228,4 +264,98 @@ public final class RecentsActivity extends BaseRecentsActivity {
    public void onTaskLaunched() {
        mFallbackRecentsView.resetTaskVisuals();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mStateManager = new StateManager<>(this, RecentsState.DEFAULT);

        mOldConfig = new Configuration(getResources().getConfiguration());
        initDeviceProfile();
        initViews();

        getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
                Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
        ACTIVITY_TRACKER.handleCreate(this);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        int diff = newConfig.diff(mOldConfig);
        if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
            onHandleConfigChanged();
        }
        mOldConfig.setTo(newConfig);
        super.onConfigurationChanged(newConfig);
    }

    /**
     * Initialize/update the device profile.
     */
    private void initDeviceProfile() {
        mDeviceProfile = createDeviceProfile();
        onDeviceProfileInitiated();
    }

    @Override
    public void onEnterAnimationComplete() {
        super.onEnterAnimationComplete();
        // After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
        // as a part of quickstep, so that high-res thumbnails can load the next time we enter
        // overview
        RecentsModel.INSTANCE.get(this).getThumbnailCache()
                .getHighResLoadingState().setVisible(true);
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        RecentsModel.INSTANCE.get(this).onTrimMemory(level);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ACTIVITY_TRACKER.onActivityDestroyed(this);
    }

    @Override
    public void onBackPressed() {
        // TODO: Launch the task we came from
        startHome();
    }

    public void startHome() {
        startActivity(new Intent(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_HOME)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    }

    @Override
    protected StateHandler<RecentsState>[] createStateHandlers() {
        return new StateHandler[] { new FallbackRecentsStateController(this) };
    }

    @Override
    public StateManager<RecentsState> getStateManager() {
        return mStateManager;
    }

    @Override
    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        super.dump(prefix, fd, writer, args);
        writer.println(prefix + "Misc:");
        dumpMisc(prefix + "\t", writer);
    }

    private AnimatorListenerAdapter resetStateListener() {
        return new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mFallbackRecentsView.resetTaskVisuals();
                mStateManager.reapplyState();
            }
        };
    }
}
Loading