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

Commit 6b92c6e5 authored by Winson's avatar Winson
Browse files

Adding fast alt-tab trigger to prevent full animation.

Change-Id: I3df7a99977d0c2687eea084a95a0953429e8ff47
parent 1b58561f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ package com.android.systemui.recents;
 */
public class Constants {

    // TODO: Move into RecentsMetrics
    public static class Metrics {
        // DO NOT MODIFY THE ORDER OF THESE METRICS
        public static final int DismissSourceKeyboard = 0;
@@ -28,6 +29,7 @@ public class Constants {
        public static final int DismissSourceHeaderButton = 2;
    }

    // TODO: Move into RecentsDebugFlags
    public static class DebugFlags {

        public static class App {
@@ -37,7 +39,7 @@ public class Constants {
            public static final boolean EnableTaskFiltering = false;
            // Enables dismiss-all
            public static final boolean EnableDismissAll = false;
            // Enables fast-toggling
            // Enables fast-toggling by just tapping on the recents button
            public static final boolean EnableFastToggleRecents = false;
            // Enables the thumbnail alpha on the front-most task
            public static final boolean EnableThumbnailAlphaOnFrontmost = false;
+106 −5
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
@@ -74,7 +75,12 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
    private final static String TAG = "RecentsImpl";
    private final static boolean DEBUG = false;

    private final static int sMinToggleDelay = 350;
    // The minimum amount of time between each recents button press that we will handle
    private final static int MIN_TOGGLE_DELAY_MS = 350;
    // The duration within which the user releasing the alt tab (from when they pressed alt tab)
    // that the fast alt-tab animation will run.  If the user's alt-tab takes longer than this
    // duration, then we will toggle recents after this duration.
    private final static int FAST_ALT_TAB_DELAY_MS = 225;

    public final static String RECENTS_PACKAGE = "com.android.systemui";
    public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
@@ -155,6 +161,14 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
    // Variables to keep track of if we need to start recents after binding
    boolean mTriggeredFromAltTab;
    long mLastToggleTime;
    DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() {
        @Override
        public void run() {
            // When this fires, then the user has not released alt-tab for at least
            // FAST_ALT_TAB_DELAY_MS milliseconds
            showRecents(mTriggeredFromAltTab);
        }
    });

    Bitmap mThumbnailTransitionBitmapCache;
    Task mThumbnailTransitionBitmapCacheKey;
@@ -238,6 +252,29 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
    @Override
    public void showRecents(boolean triggeredFromAltTab) {
        mTriggeredFromAltTab = triggeredFromAltTab;
        if (mFastAltTabTrigger.hasTriggered()) {
            // We are calling this from the doze trigger, so just fall through to show Recents
            mFastAltTabTrigger.resetTrigger();
        } else if (mFastAltTabTrigger.isDozing()) {
            // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
            // otherwise, this is an additional tab (alt-tab*), which means that we should trigger
            // immediately (fall through and disable the pending trigger)
            // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
            //       so we may actually additional signal to handle multiple quick tab cases.  The
            //       severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
            //       duration though
            if (!triggeredFromAltTab) {
                return;
            }
            mFastAltTabTrigger.stopDozing();
        } else {
            // Otherwise, the doze trigger is not running, and if this is an alt tab, we should
            // start the trigger and then wait for the hide (or for it to elapse)
            if (triggeredFromAltTab) {
                mFastAltTabTrigger.startDozing();
                return;
            }
        }

        try {
            // Check if the top task is in the home stack, and start the recents activity
@@ -255,6 +292,17 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
    @Override
    public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
        if (mBootCompleted) {
            if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
                // The user has released alt-tab before the trigger has run, so just show the next
                // task immediately
                showNextTask();

                // Cancel the fast alt-tab trigger
                mFastAltTabTrigger.stopDozing();
                mFastAltTabTrigger.resetTrigger();
                return;
            }

            // Defer to the activity to handle hiding recents, if it handles it, then it must still
            // be visible
            EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
@@ -264,6 +312,11 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub

    @Override
    public void toggleRecents() {
        // Skip this toggle if we are already waiting to trigger recents via alt-tab
        if (mFastAltTabTrigger.isDozing()) {
            return;
        }

        mTriggeredFromAltTab = false;

        try {
@@ -282,7 +335,7 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
                    // better than showing a janky screenshot).
                    // NOTE: Ideally, the screenshot mechanism would take the window transform into
                    // account
                    if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
                    if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
                        return;
                    }

@@ -295,7 +348,7 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
                // better than showing a janky screenshot).
                // NOTE: Ideally, the screenshot mechanism would take the window transform into
                // account
                if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
                if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
                    return;
                }

@@ -334,10 +387,58 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub
        // Do nothing
    }

    /**
     * Transitions to the next recent task in the stack.
     */
    public void showNextTask() {
        SystemServicesProxy ssp = Recents.getSystemServices();
        RecentsTaskLoader loader = Recents.getTaskLoader();
        RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
        loader.preloadTasks(plan, true /* isTopTaskHome */);
        TaskStack focusedStack = plan.getTaskStack();

        // Return early if there are no tasks in the focused stack
        if (focusedStack == null || focusedStack.getTaskCount() == 0) return;

        ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask();
        // Return early if there is no running task
        if (runningTask == null) return;
        // Return early if the running task is in the home stack (optimization)
        if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;

        // Find the task in the recents list
        ArrayList<Task> tasks = focusedStack.getTasks();
        Task toTask = null;
        ActivityOptions launchOpts = null;
        int taskCount = tasks.size();
        for (int i = taskCount - 1; i >= 1; i--) {
            Task task = tasks.get(i);
            if (task.key.id == runningTask.id) {
                toTask = tasks.get(i - 1);
                launchOpts = ActivityOptions.makeCustomAnimation(mContext,
                        R.anim.recents_launch_prev_affiliated_task_target,
                        R.anim.recents_launch_prev_affiliated_task_source);
                break;
            }
        }

        // Return early if there is no next task
        if (toTask == null) {
            ssp.startInPlaceAnimationOnFrontMostApplication(
                    ActivityOptions.makeCustomInPlaceAnimation(mContext,
                            R.anim.recents_launch_prev_affiliated_task_bounce));
            return;
        }

        // Launch the task
        ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
    }

    /**
     * Transitions to the next affiliated task.
     */
    public void showRelativeAffiliatedTask(boolean showNextTask) {
        // Return early if there is no focused stack
        SystemServicesProxy ssp = Recents.getSystemServices();
        int focusedStackId = ssp.getFocusedStack();
        RecentsTaskLoader loader = Recents.getTaskLoader();
        RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
        loader.preloadTasks(plan, true /* isTopTaskHome */);
+17 −8
Original line number Diff line number Diff line
@@ -29,44 +29,53 @@ public class DozeTrigger {
    boolean mIsDozing;
    boolean mHasTriggered;
    int mDozeDurationMilliseconds;
    Runnable mSleepRunnable;
    Runnable mOnSleepRunnable;

    // Sleep-runnable
    Runnable mDozeRunnable = new Runnable() {
        @Override
        public void run() {
            mSleepRunnable.run();
            mIsDozing = false;
            mHasTriggered = true;
            mOnSleepRunnable.run();
        }
    };

    public DozeTrigger(int dozeDurationMilliseconds, Runnable sleepRunnable) {
    public DozeTrigger(int dozeDurationMilliseconds, Runnable onSleepRunnable) {
        mHandler = new Handler();
        mDozeDurationMilliseconds = dozeDurationMilliseconds;
        mSleepRunnable = sleepRunnable;
        mOnSleepRunnable = onSleepRunnable;
    }

    /** Starts dozing. This also resets the trigger flag. */
    /**
     * Starts dozing and queues the onSleepRunnable to be called. This also resets the trigger flag.
     */
    public void startDozing() {
        forcePoke();
        mHasTriggered = false;
    }

    /** Stops dozing. */
    /**
     * Stops dozing and prevents the onSleepRunnable from being called.
     */
    public void stopDozing() {
        mHandler.removeCallbacks(mDozeRunnable);
        mIsDozing = false;
    }

    /** Poke this dozer to wake it up for a little bit, if it is dozing. */
    /**
     * Poke this dozer to wake it up if it is dozing, delaying the onSleepRunnable from being
     * called for a for the doze duration.
     */
    public void poke() {
        if (mIsDozing) {
            forcePoke();
        }
    }

    /** Poke this dozer to wake it up for a little bit. */
    /**
     * Poke this dozer to wake it up even if it is not currently dozing.
     */
    void forcePoke() {
        mHandler.removeCallbacks(mDozeRunnable);
        mHandler.postDelayed(mDozeRunnable, mDozeDurationMilliseconds);