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

Commit 29c1e843 authored by Tracy Zhou's avatar Tracy Zhou Committed by Android (Google) Code Review
Browse files

Merge "Fix a memory leak" into sc-dev

parents f23ea3b0 773050d2
Loading
Loading
Loading
Loading
+7 −101
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static android.widget.Toast.LENGTH_SHORT;

import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -97,8 +96,8 @@ import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.InputProxyHandlerFactory;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.RectFSpringAnim;
@@ -113,12 +112,10 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.TaskInfoCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Consumer;

/**
@@ -255,7 +252,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
        mActivityInterface = gestureState.getActivityInterface();
        mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
        mInputConsumerProxy =
                new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler);
                new InputConsumerProxy(inputConsumer, () -> {
                    endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
                    endLauncherTransitionController();
                }, new InputProxyHandlerFactory(mActivityInterface, mGestureState));
        mTaskAnimationManager = taskAnimationManager;
        mTouchTimeMs = touchTimeMs;
        mContinuingLastGesture = continuingLastGesture;
@@ -783,19 +783,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
        handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
    }

    /**
     * Called to create a input proxy for the running task
     */
    @UiThread
    protected InputConsumer createNewInputProxyHandler() {
        endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
        endLauncherTransitionController();

        StatefulActivity activity = mActivityInterface.getCreatedActivity();
        return activity == null ? InputConsumer.NO_OP
                : new OverviewInputConsumer(mGestureState, activity, null, true);
    }

    private void endRunningWindowAnim(boolean cancel) {
        if (mRunningWindowAnim != null) {
            if (cancel) {
@@ -1338,6 +1325,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
            mInputConsumerProxy.destroy();
            mTaskAnimationManager.setLiveTileCleanUpHandler(null);
        }
        mInputConsumerProxy.unregisterCallback();
        endRunningWindowAnim(false /* cancel */);

        if (mGestureEndCallback != null) {
@@ -1502,36 +1490,13 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,

    protected abstract void finishRecentsControllerToHome(Runnable callback);

    private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() {
        @Override
        public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
                boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
            if (mRecentsView.getRunningTaskIndex() != -1
                    && mRecentsView.getRunningTaskId() == task.taskId
                    && mRecentsAnimationTargets.hasTask(task.taskId)) {
                launchOtherTaskInLiveTileMode(task.taskId, mRecentsAnimationTargets.apps);
            }
            ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
                    mLiveTileRestartListener);
        }
    };

    private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
        endLauncherTransitionController();
        mActivityInterface.onSwipeUpToRecentsComplete();
        mRecentsView.onSwipeUpAnimationSuccess();
        if (LIVE_TILE.get()) {
            mTaskAnimationManager.setLaunchOtherTaskInLiveTileModeHandler(
                    appearedTaskTarget -> {
                        RemoteAnimationTargetCompat[] apps = Arrays.copyOf(
                                mRecentsAnimationTargets.apps,
                                mRecentsAnimationTargets.apps.length + 1);
                        apps[apps.length - 1] = appearedTaskTarget;
                        launchOtherTaskInLiveTileMode(appearedTaskTarget.taskId, apps);
                    });
            mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy);
            ActivityManagerWrapper.getInstance().registerTaskStackListener(
                    mLiveTileRestartListener);
            mTaskAnimationManager.enableLiveTileRestartListener();
        }

        SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
@@ -1539,65 +1504,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
        reset();
    }

    private void launchOtherTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) {
        AnimatorSet anim = new AnimatorSet();
        TaskView taskView = mRecentsView.getTaskView(taskId);
        if (taskView == null || !mRecentsView.isTaskViewVisible(taskView)) {
            // TODO: Refine this animation.
            SurfaceTransactionApplier surfaceApplier =
                    new SurfaceTransactionApplier(mActivity.getDragLayer());
            ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
            appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
            appAnimator.setInterpolator(ACCEL_DEACCEL);
            appAnimator.addUpdateListener(new MultiValueUpdateListener() {
                @Override
                public void onUpdate(float percent) {
                    SurfaceParams.Builder builder = new SurfaceParams.Builder(
                            apps[apps.length - 1].leash);
                    Matrix matrix = new Matrix();
                    matrix.postScale(percent, percent);
                    matrix.postTranslate(mDp.widthPx * (1 - percent) / 2,
                            mDp.heightPx * (1 - percent) / 2);
                    builder.withAlpha(percent).withMatrix(matrix);
                    surfaceApplier.scheduleApply(builder.build());
                }
            });
            anim.play(appAnimator);
        } else {
            TaskViewUtils.composeRecentsLaunchAnimator(
                    anim, taskView, apps,
                    mRecentsAnimationTargets.wallpapers, true /* launcherClosing */,
                    mActivity.getStateManager(), mRecentsView,
                    mActivityInterface.getDepthController());
        }
        anim.addListener(new AnimatorListenerAdapter(){

            @Override
            public void onAnimationEnd(Animator animator) {
                cleanUp(false);
            }

            @Override
            public void onAnimationCancel(Animator animator) {
                cleanUp(true);
            }

            private void cleanUp(boolean canceled) {
                if (mRecentsAnimationController != null) {
                    mRecentsAnimationController.finish(false /* toRecents */,
                            null /* onFinishComplete */);
                    if (canceled) {
                        mRecentsAnimationController = null;
                    } else {
                        mActivityInterface.onLaunchTaskSuccess();
                    }
                    ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
                }
            }
        });
        anim.start();
    }

    private static boolean isNotInRecents(RemoteAnimationTargetCompat app) {
        return app.isNotInRecents
                || app.activityType == ACTIVITY_TYPE_HOME;
+0 −9
Original line number Diff line number Diff line
@@ -41,13 +41,4 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets {
    public boolean hasTargets() {
        return unfilteredApps.length != 0;
    }

    public boolean hasTask(int taskId) {
        for (RemoteAnimationTargetCompat target : unfilteredApps) {
            if (target.taskId == taskId) {
                return true;
            }
        }
        return false;
    }
}
+32 −17
Original line number Diff line number Diff line
@@ -17,10 +17,11 @@ package com.android.quickstep;

import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -31,13 +32,13 @@ import androidx.annotation.UiThread;

import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.RemoteTransitionCompat;

import java.util.function.Consumer;
import com.android.systemui.shared.system.TaskStackChangeListener;

public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
    public static final boolean ENABLE_SHELL_TRANSITIONS =
@@ -49,10 +50,24 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
    // Temporary until we can hook into gesture state events
    private GestureState mLastGestureState;
    private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
    private Consumer<RemoteAnimationTargetCompat> mLaunchOtherTaskHandler;
    private Runnable mLiveTileCleanUpHandler;
    private Context mCtx;

    private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() {
        @Override
        public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
                boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
            BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
            if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                    && activityInterface.getCreatedActivity() != null) {
                RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
                recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId);
                ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
                        mLiveTileRestartListener);
            }
        }
    };

    TaskAnimationManager(Context ctx) {
        mCtx = ctx;
    }
@@ -114,9 +129,14 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn

            @Override
            public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
                if (mLaunchOtherTaskHandler != null
                        && mLastGestureState.getEndTarget() == RECENTS) {
                    mLaunchOtherTaskHandler.accept(appearedTaskTarget);
                BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
                if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                        && activityInterface.getCreatedActivity() != null) {
                    RecentsView recentsView =
                            activityInterface.getCreatedActivity().getOverviewPanel();
                    RemoteAnimationTargetCompat[] apps = new RemoteAnimationTargetCompat[1];
                    apps[0] = appearedTaskTarget;
                    recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId, apps);
                    return;
                }
                if (mController != null) {
@@ -161,17 +181,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
        return mCallbacks;
    }

    /**
     * The passed-in handler is used to render side task launch animation in recents in live tile
     * mode.
     */
    public void setLaunchOtherTaskInLiveTileModeHandler(
            Consumer<RemoteAnimationTargetCompat> handler) {
        mLaunchOtherTaskHandler = handler;
    public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
        mLiveTileCleanUpHandler = cleanUpHandler;
    }

    public void setLiveTileCleanUpHandler(Runnable runnable) {
        mLiveTileCleanUpHandler = runnable;
    public void enableLiveTileRestartListener() {
        ActivityManagerWrapper.getInstance().registerTaskStackListener(mLiveTileRestartListener);
    }

    /**
@@ -215,6 +230,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
            mLiveTileCleanUpHandler.run();
            mLiveTileCleanUpHandler = null;
        }
        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mLiveTileRestartListener);

        // Release all the target leashes
        if (mTargets != null) {
@@ -231,7 +247,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
        mTargets = null;
        mLastGestureState = null;
        mLastAppearedTaskTarget = null;
        mLaunchOtherTaskHandler = null;
    }

    public void dump() {
+20 −8
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ public class InputConsumerProxy {
    private static final String TAG = "InputConsumerProxy";

    private final InputConsumerController mInputConsumerController;
    private final Supplier<InputConsumer> mConsumerSupplier;
    private Runnable mCallback;
    private Supplier<InputConsumer> mConsumerSupplier;

    // The consumer is created lazily on demand.
    private InputConsumer mInputConsumer;
@@ -48,8 +49,9 @@ public class InputConsumerProxy {
    private boolean mDestroyPending = false;

    public InputConsumerProxy(InputConsumerController inputConsumerController,
            Supplier<InputConsumer> consumerSupplier) {
            Runnable callback, Supplier<InputConsumer> consumerSupplier) {
        mInputConsumerController = inputConsumerController;
        mCallback = callback;
        mConsumerSupplier = consumerSupplier;
    }

@@ -64,9 +66,7 @@ public class InputConsumerProxy {
        if (ev instanceof MotionEvent) {
            onInputConsumerMotionEvent((MotionEvent) ev);
        } else if (ev instanceof KeyEvent) {
            if (mInputConsumer == null) {
                mInputConsumer = mConsumerSupplier.get();
            }
            initInputConsumerIfNeeded();
            mInputConsumer.onKeyEvent((KeyEvent) ev);
            return true;
        }
@@ -89,9 +89,7 @@ public class InputConsumerProxy {

        if (action == ACTION_DOWN) {
            mTouchInProgress = true;
            if (mInputConsumer == null) {
                mInputConsumer = mConsumerSupplier.get();
            }
            initInputConsumerIfNeeded();
        } else if (action == ACTION_CANCEL || action == ACTION_UP) {
            // Finish any pending actions
            mTouchInProgress = false;
@@ -115,4 +113,18 @@ public class InputConsumerProxy {
        mDestroyed = true;
        mInputConsumerController.setInputListener(null);
    }

    public void unregisterCallback() {
        mCallback = null;
    }

    private void initInputConsumerIfNeeded() {
        if (mInputConsumer == null) {
            if (mCallback != null) {
                mCallback.run();
            }
            mInputConsumer = mConsumerSupplier.get();
            mConsumerSupplier = null;
        }
    }
}
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.quickstep.util;

import androidx.annotation.UiThread;

import com.android.launcher3.statemanager.StatefulActivity;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;

import java.util.function.Supplier;

/**
 * A factory that creates a input consumer for
 *  {@link com.android.quickstep.util.InputConsumerProxy}.
 */
public class InputProxyHandlerFactory implements Supplier<InputConsumer> {

    private final BaseActivityInterface mActivityInterface;
    private final GestureState mGestureState;

    @UiThread
    public InputProxyHandlerFactory(BaseActivityInterface activityInterface,
            GestureState gestureState) {
        mActivityInterface = activityInterface;
        mGestureState = gestureState;
    }

    /**
     * Called to create a input proxy for the running task
     */
    @Override
    public InputConsumer get() {
        StatefulActivity activity = mActivityInterface.getCreatedActivity();
        return activity == null ? InputConsumer.NO_OP
                : new OverviewInputConsumer(mGestureState, activity, null, true);
    }
}
Loading