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

Commit 422a634a authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Add CUJ Jank interactions for App Pair saving and launching

* Added finishCallback consumer to LauncherAccessibilityDelegate
to inform when adding an item to workspace was completed.
* The logic seemed to be dependent on the parameter
"focusForAccessibility", but all callers of that are currently
passing in true

Bug: 328646540
Test: https://paste.googleplex.com/6232597136408576
Newly added CUJs showing up when playing w/ device

Change-Id: Ia4944f8d23634bb92296938ea2d07a6babf6f77c
parent 7d553175
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1253,7 +1253,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                    if (findExactPairMatch) {
                        // We did not find the app pair we were looking for, so launch one.
                        recents.getSplitSelectController().getAppPairsController().launchAppPair(
                                (AppPairIcon) launchingIconView);
                                (AppPairIcon) launchingIconView, -1 /*cuj*/);
                    } else {
                        startItemInfoActivity(itemInfos.get(0));
                    }
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEAS
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;

import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.internal.jank.Cuj.CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_WORKSPACE;
import static com.android.launcher3.Flags.enablePredictiveBackGesture;
import static com.android.launcher3.Flags.enableUnfoldStateAnimation;
import static com.android.launcher3.LauncherConstants.SavedInstanceKeys.PENDING_SPLIT_SELECT_INFO;
@@ -1347,7 +1348,8 @@ public class QuickstepLauncher extends Launcher {
     * Launches two apps as an app pair.
     */
    public void launchAppPair(AppPairIcon appPairIcon) {
        mSplitSelectStateController.getAppPairsController().launchAppPair(appPairIcon);
        mSplitSelectStateController.getAppPairsController().launchAppPair(appPairIcon,
                CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_WORKSPACE);
    }

    public boolean canStartHomeSafely() {
+22 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.quickstep.util;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import static com.android.internal.jank.Cuj.CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_TASKBAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH;
import static com.android.launcher3.model.data.AppInfo.PACKAGE_KEY_COMPARATOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -40,6 +41,7 @@ import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.internal.jank.Cuj;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
@@ -62,6 +64,7 @@ import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;

import java.util.Arrays;
@@ -112,6 +115,7 @@ public class AppPairsController {
     * well on trampoline apps).
     */
    public void saveAppPair(GroupedTaskView gtv) {
        InteractionJankMonitorWrapper.begin(gtv, Cuj.CUJ_LAUNCHER_SAVE_APP_PAIR);
        TaskView.TaskIdAttributeContainer[] attributes = gtv.getTaskIdAttributeContainers();
        WorkspaceItemInfo recentsInfo1 = attributes[0].getItemInfo();
        WorkspaceItemInfo recentsInfo2 = attributes[1].getItemInfo();
@@ -168,7 +172,13 @@ public class AppPairsController {
                LauncherAccessibilityDelegate delegate =
                        Launcher.getLauncher(mContext).getAccessibilityDelegate();
                if (delegate != null) {
                    delegate.addToWorkspace(newAppPair, true);
                    delegate.addToWorkspace(newAppPair, true, (success) -> {
                        if (success) {
                            InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_SAVE_APP_PAIR);
                        } else {
                            InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_SAVE_APP_PAIR);
                        }
                    });
                    mStatsLogManager.logger().withItemInfo(newAppPair)
                            .log(StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_SAVE);
                }
@@ -179,12 +189,18 @@ public class AppPairsController {
    /**
     * Launches an app pair by searching the RecentsModel for running instances of each app, and
     * staging either those running instances or launching the apps as new Intents.
     *
     * @param cuj Should be an integer from {@link Cuj} or -1 if no CUJ needs to be logged for jank
     *            monitoring
     */
    public void launchAppPair(AppPairIcon appPairIcon) {
    public void launchAppPair(AppPairIcon appPairIcon, int cuj) {
        WorkspaceItemInfo app1 = appPairIcon.getInfo().contents.get(0);
        WorkspaceItemInfo app2 = appPairIcon.getInfo().contents.get(1);
        ComponentKey app1Key = new ComponentKey(app1.getTargetComponent(), app1.user);
        ComponentKey app2Key = new ComponentKey(app2.getTargetComponent(), app2.user);
        mSplitSelectStateController.setLaunchingCuj(cuj);
        InteractionJankMonitorWrapper.begin(appPairIcon, cuj);

        mSplitSelectStateController.findLastActiveTasksAndRunCallback(
                Arrays.asList(app1Key, app2Key),
                false /* findExactPairMatch */,
@@ -343,7 +359,8 @@ public class AppPairsController {
                                && !lastActiveTasksOfAppPair.contains(runningTaskId2)) {
                            // Neither A nor B are on screen, so just launch a new app pair
                            // normally.
                            launchAppPair(launchingIconView);
                            launchAppPair(launchingIconView,
                                    CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_TASKBAR);
                        } else {
                            // Exactly one app (A or B) is on-screen, so we have to launch the other
                            // on the appropriate side.
@@ -388,7 +405,8 @@ public class AppPairsController {

                        if (!task1IsOnScreen && !task2IsOnScreen) {
                            // Neither App A nor App B are on-screen, launch the app pair normally.
                            launchAppPair(launchingIconView);
                            launchAppPair(launchingIconView,
                                    CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_TASKBAR);
                        } else {
                            // Either A or B is on-screen, so launch the other on the appropriate
                            // side.
+16 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import com.android.quickstep.views.SplitInstructionsView;
import com.android.systemui.animation.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
import com.android.wm.shell.splitscreen.ISplitSelectListener;

@@ -151,6 +152,12 @@ public class SplitSelectStateController {
    /** True when the first selected split app is being launched in fullscreen. */
    private boolean mLaunchingFirstAppFullscreen;

    /**
     * Should be a constant from {@link com.android.internal.jank.Cuj} or -1, does not need to be
     * set for all launches.
     */
    private int mLaunchCuj = -1;

    private FloatingTaskView mFirstFloatingTaskView;
    private SplitInstructionsView mSplitInstructionsView;

@@ -707,6 +714,10 @@ public class SplitSelectStateController {
        return mSplitAnimationController;
    }

    public void setLaunchingCuj(int launchCuj) {
        mLaunchCuj = launchCuj;
    }

    /**
     * Requires Shell Transitions
     */
@@ -850,6 +861,11 @@ public class SplitSelectStateController {
        mSplitInstructionsView = null;
        mLaunchingFirstAppFullscreen = false;

        if (mLaunchCuj != -1) {
            InteractionJankMonitorWrapper.end(mLaunchCuj);
        }
        mLaunchCuj = -1;

        if (mSessionInstanceIds != null) {
            mStatsLogManager.logger()
                    .withInstanceId(mSessionInstanceIds.second)
+10 −10
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ class AppPairsControllerTest {
        whenever(mockTopTaskTracker.getCachedTopTask(any())).thenReturn(mockCachedTaskInfo)
        whenever(mockTask1.getKey()).thenReturn(mockTaskKey1)
        whenever(mockTask2.getKey()).thenReturn(mockTaskKey2)
        doNothing().whenever(spyAppPairsController).launchAppPair(any())
        doNothing().whenever(spyAppPairsController).launchAppPair(any(), any())
        doNothing()
            .whenever(spyAppPairsController)
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
@@ -210,7 +210,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchAppPair and launchToSide were never called
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, never())
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
    }
@@ -234,7 +234,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_BOTTOM_OR_RIGHT))
    }
@@ -258,7 +258,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_TOP_OR_LEFT))
    }
@@ -282,7 +282,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_BOTTOM_OR_RIGHT))
    }
@@ -306,7 +306,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_TOP_OR_LEFT))
    }
@@ -330,7 +330,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchAppPair was called
        verify(spyAppPairsController, times(1)).launchAppPair(any())
        verify(spyAppPairsController, times(1)).launchAppPair(any(), any())
        verify(spyAppPairsController, never())
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
    }
@@ -354,7 +354,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_BOTTOM_OR_RIGHT))
    }
@@ -378,7 +378,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchToSide was called with the correct arguments
        verify(spyAppPairsController, never()).launchAppPair(any())
        verify(spyAppPairsController, never()).launchAppPair(any(), any())
        verify(spyAppPairsController, times(1))
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), eq(STAGE_POSITION_TOP_OR_LEFT))
    }
@@ -402,7 +402,7 @@ class AppPairsControllerTest {
        callback.accept(arrayOf(mockTask1, mockTask2))

        // Verify that launchAppPair was called
        verify(spyAppPairsController, times(1)).launchAppPair(any())
        verify(spyAppPairsController, times(1)).launchAppPair(any(), any())
        verify(spyAppPairsController, never())
            .launchToSide(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
    }
Loading