diff options
| author | 2024-10-22 09:37:47 +0000 | |
|---|---|---|
| committer | 2024-10-22 09:37:47 +0000 | |
| commit | a1923cc340f45a2b4276920f7c1b1057b3013726 (patch) | |
| tree | df69b6d4471100b666ca6773eee3cec10cec0d00 | |
| parent | 44bf6e08babecdf1edbf4d3f9ee7cbf2a4ba71c8 (diff) | |
Add log resize start and end on all resize triggers.
Fixes: 373592364
Test: atest DesktopModeEventLoggerTest
Flag: com.android.window.flags.enable_resizing_metrics
Change-Id: If01e0cf026bdb5d242ed372c5e21c5c5fcb49868
15 files changed, 522 insertions, 96 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 427df1784506..4c2588984500 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -267,7 +267,8 @@ public abstract class WMShellModule { AppHandleEducationController appHandleEducationController, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler, - FocusTransitionObserver focusTransitionObserver) { + FocusTransitionObserver focusTransitionObserver, + DesktopModeEventLogger desktopModeEventLogger) { if (DesktopModeStatus.canEnterDesktopMode(context)) { return new DesktopModeWindowDecorViewModel( context, @@ -295,7 +296,8 @@ public abstract class WMShellModule { appHandleEducationController, windowDecorCaptionHandleRepository, desktopActivityOrientationHandler, - focusTransitionObserver); + focusTransitionObserver, + desktopModeEventLogger); } return new CaptionWindowDecorViewModel( context, @@ -647,7 +649,8 @@ public abstract class WMShellModule { Optional<RecentTasksController> recentTasksController, InteractionJankMonitor interactionJankMonitor, InputManager inputManager, - FocusTransitionObserver focusTransitionObserver) { + FocusTransitionObserver focusTransitionObserver, + DesktopModeEventLogger desktopModeEventLogger) { return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController, displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, dragAndDropController, transitions, keyguardManager, @@ -659,7 +662,8 @@ public abstract class WMShellModule { desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter, recentTasksController.orElse(null), interactionJankMonitor, mainHandler, - inputManager, focusTransitionObserver); + inputManager, focusTransitionObserver, + desktopModeEventLogger); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt index 8ebe503a3816..255ca6e2511f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt @@ -16,11 +16,20 @@ package com.android.wm.shell.desktopmode +import android.app.ActivityManager.RunningTaskInfo +import android.util.Size +import android.view.InputDevice.SOURCE_MOUSE +import android.view.InputDevice.SOURCE_TOUCHSCREEN +import android.view.MotionEvent +import android.view.MotionEvent.TOOL_TYPE_FINGER +import android.view.MotionEvent.TOOL_TYPE_MOUSE +import android.view.MotionEvent.TOOL_TYPE_STYLUS import com.android.internal.annotations.VisibleForTesting import com.android.internal.protolog.ProtoLog import com.android.internal.util.FrameworkStatsLog import com.android.window.flags.Flags import com.android.wm.shell.EventLogTags +import com.android.wm.shell.common.DisplayController import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import java.security.SecureRandom import java.util.Random @@ -176,7 +185,13 @@ class DesktopModeEventLogger { * Logs that a task resize event is starting with [taskSizeUpdate] within a Desktop mode * session. */ - fun logTaskResizingStarted(taskSizeUpdate: TaskSizeUpdate) { + fun logTaskResizingStarted( + resizeTrigger: ResizeTrigger, + motionEvent: MotionEvent?, + taskInfo: RunningTaskInfo, + displayController: DisplayController? = null, + displayLayoutSize: Size? = null, + ) { if (!Flags.enableResizingMetrics()) return val sessionId = currentSessionId.get() @@ -188,11 +203,19 @@ class DesktopModeEventLogger { return } + val taskSizeUpdate = createTaskSizeUpdate( + resizeTrigger, + motionEvent, + taskInfo, + displayController = displayController, + displayLayoutSize = displayLayoutSize, + ) + ProtoLog.v( WM_SHELL_DESKTOP_MODE, - "DesktopModeLogger: Logging task resize is starting, session: %s taskId: %s", + "DesktopModeLogger: Logging task resize is starting, session: %s, taskSizeUpdate: %s", sessionId, - taskSizeUpdate.instanceId + taskSizeUpdate ) logTaskSizeUpdated( FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE, @@ -203,7 +226,15 @@ class DesktopModeEventLogger { /** * Logs that a task resize event is ending with [taskSizeUpdate] within a Desktop mode session. */ - fun logTaskResizingEnded(taskSizeUpdate: TaskSizeUpdate) { + fun logTaskResizingEnded( + resizeTrigger: ResizeTrigger, + motionEvent: MotionEvent?, + taskInfo: RunningTaskInfo, + taskHeight: Int? = null, + taskWidth: Int? = null, + displayController: DisplayController? = null, + displayLayoutSize: Size? = null, + ) { if (!Flags.enableResizingMetrics()) return val sessionId = currentSessionId.get() @@ -215,18 +246,61 @@ class DesktopModeEventLogger { return } + val taskSizeUpdate = createTaskSizeUpdate( + resizeTrigger, + motionEvent, + taskInfo, + taskHeight, + taskWidth, + displayController, + displayLayoutSize, + ) + ProtoLog.v( WM_SHELL_DESKTOP_MODE, - "DesktopModeLogger: Logging task resize is ending, session: %s taskId: %s", + "DesktopModeLogger: Logging task resize is ending, session: %s, taskSizeUpdate: %s", sessionId, - taskSizeUpdate.instanceId + taskSizeUpdate ) + logTaskSizeUpdated( FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE, sessionId, taskSizeUpdate ) } + private fun createTaskSizeUpdate( + resizeTrigger: ResizeTrigger, + motionEvent: MotionEvent?, + taskInfo: RunningTaskInfo, + taskHeight: Int? = null, + taskWidth: Int? = null, + displayController: DisplayController? = null, + displayLayoutSize: Size? = null, + ): TaskSizeUpdate { + val taskBounds = taskInfo.configuration.windowConfiguration.bounds + + val height = taskHeight ?: taskBounds.height() + val width = taskWidth ?: taskBounds.width() + + val displaySize = when { + displayLayoutSize != null -> displayLayoutSize.height * displayLayoutSize.width + displayController != null -> displayController.getDisplayLayout(taskInfo.displayId) + ?.let { it.height() * it.width() } + else -> null + } + + return TaskSizeUpdate( + resizeTrigger, + getInputMethodFromMotionEvent(motionEvent), + taskInfo.taskId, + taskInfo.effectiveUid, + height, + width, + displaySize, + ) + } + fun logTaskInfoStateInit() { logTaskUpdate( FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INIT_STATSD, @@ -238,7 +312,8 @@ class DesktopModeEventLogger { taskHeight = 0, taskWidth = 0, taskX = 0, - taskY = 0) + taskY = 0 + ) ) } @@ -314,7 +389,7 @@ class DesktopModeEventLogger { /* task_width */ taskSizeUpdate.taskWidth, /* display_area */ - taskSizeUpdate.displayArea + taskSizeUpdate.displayArea ?: -1 ) } @@ -364,9 +439,24 @@ class DesktopModeEventLogger { val uid: Int, val taskHeight: Int, val taskWidth: Int, - val displayArea: Int, + val displayArea: Int?, ) + private fun getInputMethodFromMotionEvent(e: MotionEvent?): InputMethod { + if (e == null) return InputMethod.UNKNOWN_INPUT_METHOD + + val toolType = e.getToolType( + e.findPointerIndex(e.getPointerId(0)) + ) + return when { + toolType == TOOL_TYPE_STYLUS -> InputMethod.STYLUS + toolType == TOOL_TYPE_MOUSE -> InputMethod.MOUSE + toolType == TOOL_TYPE_FINGER && e.source == SOURCE_MOUSE -> InputMethod.TOUCHPAD + toolType == TOOL_TYPE_FINGER && e.source == SOURCE_TOUCHSCREEN -> InputMethod.TOUCH + else -> InputMethod.UNKNOWN_INPUT_METHOD + } + } + // Default value used when the task was not minimized. @VisibleForTesting const val UNSET_MINIMIZE_REASON = @@ -499,6 +589,10 @@ class DesktopModeEventLogger { FrameworkStatsLog .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_RIGHT_MENU_RESIZE_TRIGGER ), + MAXIMIZE_MENU( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__MAXIMIZE_MENU_RESIZE_TRIGGER + ), } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index b505bee469fe..69776cd4740a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -46,6 +46,7 @@ import android.util.Size import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.KeyEvent +import android.view.MotionEvent import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE @@ -125,7 +126,7 @@ import java.io.PrintWriter import java.util.Optional import java.util.concurrent.Executor import java.util.function.Consumer - +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger /** Handles moving tasks in and out of desktop */ class DesktopTasksController( private val context: Context, @@ -158,6 +159,7 @@ class DesktopTasksController( @ShellMainThread private val handler: Handler, private val inputManager: InputManager, private val focusTransitionObserver: FocusTransitionObserver, + private val desktopModeEventLogger: DesktopModeEventLogger, ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler, @@ -747,7 +749,11 @@ class DesktopTasksController( * bounds) and a free floating state (either the last saved bounds if available or the default * bounds otherwise). */ - fun toggleDesktopTaskSize(taskInfo: RunningTaskInfo) { + fun toggleDesktopTaskSize( + taskInfo: RunningTaskInfo, + resizeTrigger: ResizeTrigger, + motionEvent: MotionEvent?, + ) { val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val stableBounds = Rect().apply { displayLayout.getStableBounds(this) } @@ -794,7 +800,10 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) - + desktopModeEventLogger.logTaskResizingEnded( + resizeTrigger, motionEvent, taskInfo, destinationBounds.height(), + destinationBounds.width(), displayController + ) toggleResizeDesktopTaskTransitionHandler.startTransition(wct) } @@ -884,9 +893,19 @@ class DesktopTasksController( taskInfo: RunningTaskInfo, taskSurface: SurfaceControl, currentDragBounds: Rect, - position: SnapPosition + position: SnapPosition, + resizeTrigger: ResizeTrigger, + motionEvent: MotionEvent?, ) { val destinationBounds = getSnapBounds(taskInfo, position) + desktopModeEventLogger.logTaskResizingEnded( + resizeTrigger, + motionEvent, + taskInfo, + destinationBounds.height(), + destinationBounds.width(), + displayController, + ) if (destinationBounds == taskInfo.configuration.windowConfiguration.bounds) { // Handle the case where we attempt to snap resize when already snap resized: the task // position won't need to change but we want to animate the surface going back to the @@ -915,7 +934,8 @@ class DesktopTasksController( position: SnapPosition, taskSurface: SurfaceControl, currentDragBounds: Rect, - dragStartBounds: Rect + dragStartBounds: Rect, + motionEvent: MotionEvent, ) { releaseVisualIndicator() if (!taskInfo.isResizeable && DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE.isTrue()) { @@ -932,10 +952,25 @@ class DesktopTasksController( isResizable = taskInfo.isResizeable, ) } else { + val resizeTrigger = if (position == SnapPosition.LEFT) { + ResizeTrigger.DRAG_LEFT + } else { + ResizeTrigger.DRAG_RIGHT + } + desktopModeEventLogger.logTaskResizingStarted( + resizeTrigger, motionEvent, taskInfo, displayController + ) interactionJankMonitor.begin( taskSurface, context, handler, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_resizable" ) - snapToHalfScreen(taskInfo, taskSurface, currentDragBounds, position) + snapToHalfScreen( + taskInfo, + taskSurface, + currentDragBounds, + position, + resizeTrigger, + motionEvent, + ) } } @@ -1735,6 +1770,7 @@ class DesktopTasksController( currentDragBounds: Rect, validDragArea: Rect, dragStartBounds: Rect, + motionEvent: MotionEvent, ) { if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) { return @@ -1755,12 +1791,22 @@ class DesktopTasksController( } IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { handleSnapResizingTask( - taskInfo, SnapPosition.LEFT, taskSurface, currentDragBounds, dragStartBounds + taskInfo, + SnapPosition.LEFT, + taskSurface, + currentDragBounds, + dragStartBounds, + motionEvent, ) } IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { handleSnapResizingTask( - taskInfo, SnapPosition.RIGHT, taskSurface, currentDragBounds, dragStartBounds + taskInfo, + SnapPosition.RIGHT, + taskSurface, + currentDragBounds, + dragStartBounds, + motionEvent, ) } IndicatorType.NO_INDICATOR -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java index 509cb85c96cd..fde01eefee17 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java @@ -274,6 +274,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL closeDragResizeListener(); mDragResizeListener = new DragResizeInputListener( mContext, + mTaskInfo, mHandler, mChoreographer, mDisplay.getDisplayId(), diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index a06b4a2e09d4..a775cbc6c9f3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -32,6 +32,7 @@ import static android.view.WindowInsets.Type.statusBars; import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU; import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing; +import static com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR; @@ -103,6 +104,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; @@ -221,6 +223,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, }; private final TaskPositionerFactory mTaskPositionerFactory; private final FocusTransitionObserver mFocusTransitionObserver; + private final DesktopModeEventLogger mDesktopModeEventLogger; public DesktopModeWindowDecorViewModel( Context context, @@ -248,7 +251,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, AppHandleEducationController appHandleEducationController, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, - FocusTransitionObserver focusTransitionObserver) { + FocusTransitionObserver focusTransitionObserver, + DesktopModeEventLogger desktopModeEventLogger) { this( context, shellExecutor, @@ -281,7 +285,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, new TaskPositionerFactory(), - focusTransitionObserver); + focusTransitionObserver, + desktopModeEventLogger); } @VisibleForTesting @@ -317,7 +322,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, TaskPositionerFactory taskPositionerFactory, - FocusTransitionObserver focusTransitionObserver) { + FocusTransitionObserver focusTransitionObserver, + DesktopModeEventLogger desktopModeEventLogger) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; @@ -378,6 +384,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, }; mTaskPositionerFactory = taskPositionerFactory; mFocusTransitionObserver = focusTransitionObserver; + mDesktopModeEventLogger = desktopModeEventLogger; shellInit.addInitCallback(this::onInit, this); } @@ -547,15 +554,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, >= MANAGE_WINDOWS_MINIMUM_INSTANCES); } - private void onMaximizeOrRestore(int taskId, String source) { + private void onMaximizeOrRestore(int taskId, String source, ResizeTrigger resizeTrigger, + MotionEvent motionEvent) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); if (decoration == null) { return; } + mDesktopModeEventLogger.logTaskResizingStarted(resizeTrigger, motionEvent, + decoration.mTaskInfo, + mDisplayController, /* displayLayoutSize= */ null); mInteractionJankMonitor.begin( decoration.mTaskSurface, mContext, mMainHandler, Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source); - mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo); + mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo, resizeTrigger, + motionEvent); decoration.closeHandleMenu(); decoration.closeMaximizeMenu(); } @@ -568,7 +580,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mDesktopTasksController.toggleDesktopTaskFullImmersiveState(decoration.mTaskInfo); } - private void onSnapResize(int taskId, boolean left) { + private void onSnapResize(int taskId, boolean left, MotionEvent motionEvent) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); if (decoration == null) { return; @@ -579,13 +591,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, Toast.makeText(mContext, R.string.desktop_mode_non_resizable_snap_text, Toast.LENGTH_SHORT).show(); } else { + ResizeTrigger resizeTrigger = + left ? ResizeTrigger.SNAP_LEFT_MENU : ResizeTrigger.SNAP_RIGHT_MENU; + mDesktopModeEventLogger.logTaskResizingStarted(resizeTrigger, motionEvent, + decoration.mTaskInfo, + mDisplayController, /* displayLayoutSize= */ null); mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, mMainHandler, Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE, "maximize_menu_resizable"); mDesktopTasksController.snapToHalfScreen( decoration.mTaskInfo, decoration.mTaskSurface, decoration.mTaskInfo.configuration.windowConfiguration.getBounds(), - left ? SnapPosition.LEFT : SnapPosition.RIGHT); + left ? SnapPosition.LEFT : SnapPosition.RIGHT, + resizeTrigger, + motionEvent); } decoration.closeHandleMenu(); @@ -737,6 +756,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private boolean mTouchscreenInUse; private boolean mHasLongClicked; private int mDragPointerId = -1; + private MotionEvent mMotionEvent; private DesktopModeTouchEventListener( RunningTaskInfo taskInfo, @@ -798,7 +818,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } else { // Full immersive is disabled or task doesn't request/support it, so just // toggle between maximize/restore states. - onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button"); + onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button", + ResizeTrigger.MAXIMIZE_BUTTON, mMotionEvent); } } else if (id == R.id.minimize_window) { mDesktopTasksController.minimizeTask(decoration.mTaskInfo); @@ -807,6 +828,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, @Override public boolean onTouch(View v, MotionEvent e) { + mMotionEvent = e; final int id = v.getId(); final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); if ((e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN) { @@ -897,6 +919,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, */ @Override public boolean onGenericMotion(View v, MotionEvent ev) { + mMotionEvent = ev; final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); final int id = v.getId(); if (ev.getAction() == ACTION_HOVER_ENTER && id == R.id.maximize_window) { @@ -1040,7 +1063,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, taskInfo, decoration.mTaskSurface, position, new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)), newTaskBounds, decoration.calculateValidDragArea(), - new Rect(mOnDragStartInitialBounds)); + new Rect(mOnDragStartInitialBounds), e); if (touchingButton && !mHasLongClicked) { // We need the input event to not be consumed here to end the ripple // effect on the touched button. We will reset drag state in the ensuing @@ -1087,7 +1110,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, // Disallow double-tap to resize when in full immersive. return false; } - onMaximizeOrRestore(mTaskId, "double_tap"); + onMaximizeOrRestore(mTaskId, "double_tap", ResizeTrigger.DOUBLE_TAP_APP_HEADER, e); return true; } } @@ -1484,7 +1507,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mGenericLinksParser, mAssistContentRequester, mMultiInstanceHelper, - mWindowDecorCaptionHandleRepository); + mWindowDecorCaptionHandleRepository, + mDesktopModeEventLogger); mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration); final TaskPositioner taskPositioner = mTaskPositionerFactory.create( @@ -1501,15 +1525,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, final DesktopModeTouchEventListener touchEventListener = new DesktopModeTouchEventListener(taskInfo, taskPositioner); windowDecoration.setOnMaximizeOrRestoreClickListener(() -> { - onMaximizeOrRestore(taskInfo.taskId, "maximize_menu"); + onMaximizeOrRestore(taskInfo.taskId, "maximize_menu", ResizeTrigger.MAXIMIZE_MENU, + touchEventListener.mMotionEvent); return Unit.INSTANCE; }); windowDecoration.setOnLeftSnapClickListener(() -> { - onSnapResize(taskInfo.taskId, true /* isLeft */); + onSnapResize(taskInfo.taskId, /* isLeft= */ true, touchEventListener.mMotionEvent); return Unit.INSTANCE; }); windowDecoration.setOnRightSnapClickListener(() -> { - onSnapResize(taskInfo.taskId, false /* isLeft */); + onSnapResize(taskInfo.taskId, /* isLeft= */ false, touchEventListener.mMotionEvent); return Unit.INSTANCE; }); windowDecoration.setOnToDesktopClickListener(desktopModeTransitionSource -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 6eb20b9e3ae5..d94f3a9a70c6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -94,6 +94,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.CaptionState; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; @@ -216,7 +217,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin AppToWebGenericLinksParser genericLinksParser, AssistContentRequester assistContentRequester, MultiInstanceHelper multiInstanceHelper, - WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) { + WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, + DesktopModeEventLogger desktopModeEventLogger) { this (context, userContext, displayController, splitScreenController, desktopRepository, taskOrganizer, taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue, appHeaderViewHolderFactory, rootTaskDisplayAreaOrganizer, genericLinksParser, @@ -227,7 +229,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin new SurfaceControlViewHostFactory() {}, DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper, - windowDecorCaptionHandleRepository); + windowDecorCaptionHandleRepository, desktopModeEventLogger); } DesktopModeWindowDecoration( @@ -256,11 +258,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin MaximizeMenuFactory maximizeMenuFactory, HandleMenuFactory handleMenuFactory, MultiInstanceHelper multiInstanceHelper, - WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) { + WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, + DesktopModeEventLogger desktopModeEventLogger) { super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, - surfaceControlViewHostFactory); + surfaceControlViewHostFactory, desktopModeEventLogger); mSplitScreenController = splitScreenController; mHandler = handler; mBgExecutor = bgExecutor; @@ -605,6 +608,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Trace.beginSection("DesktopModeWindowDecoration#relayout-DragResizeInputListener"); mDragResizeListener = new DragResizeInputListener( mContext, + mTaskInfo, mHandler, mChoreographer, mDisplay.getDisplayId(), @@ -612,7 +616,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mDragPositioningCallback, mSurfaceControlBuilderSupplier, mSurfaceControlTransactionSupplier, - mDisplayController); + mDisplayController, + mDesktopModeEventLogger); Trace.endSection(); } @@ -1700,7 +1705,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin AppToWebGenericLinksParser genericLinksParser, AssistContentRequester assistContentRequester, MultiInstanceHelper multiInstanceHelper, - WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) { + WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, + DesktopModeEventLogger desktopModeEventLogger) { return new DesktopModeWindowDecoration( context, userContext, @@ -1719,7 +1725,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin genericLinksParser, assistContentRequester, multiInstanceHelper, - windowDecorCaptionHandleRepository); + windowDecorCaptionHandleRepository, + desktopModeEventLogger); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java index 4ff394e2b1a9..420409705b05 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java @@ -29,10 +29,12 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP; +import static com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEventFromTouchscreen; import android.annotation.NonNull; +import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; @@ -59,6 +61,7 @@ import android.window.InputTransferToken; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import java.util.function.Consumer; import java.util.function.Supplier; @@ -83,14 +86,17 @@ class DragResizeInputListener implements AutoCloseable { private final TaskResizeInputEventReceiver mInputEventReceiver; private final Context mContext; + private final RunningTaskInfo mTaskInfo; private final SurfaceControl mInputSinkSurface; private final IBinder mSinkClientToken; private final InputChannel mSinkInputChannel; private final DisplayController mDisplayController; + private final DesktopModeEventLogger mDesktopModeEventLogger; private final Region mTouchRegion = new Region(); DragResizeInputListener( Context context, + RunningTaskInfo taskInfo, Handler handler, Choreographer choreographer, int displayId, @@ -98,12 +104,15 @@ class DragResizeInputListener implements AutoCloseable { DragPositioningCallback callback, Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier, Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier, - DisplayController displayController) { + DisplayController displayController, + DesktopModeEventLogger desktopModeEventLogger) { mContext = context; + mTaskInfo = taskInfo; mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier; mDisplayId = displayId; mDecorationSurface = decorationSurface; mDisplayController = displayController; + mDesktopModeEventLogger = desktopModeEventLogger; mClientToken = new Binder(); final InputTransferToken inputTransferToken = new InputTransferToken(); mInputChannel = new InputChannel(); @@ -125,11 +134,12 @@ class DragResizeInputListener implements AutoCloseable { e.rethrowFromSystemServer(); } - mInputEventReceiver = new TaskResizeInputEventReceiver(context, mInputChannel, callback, + mInputEventReceiver = new TaskResizeInputEventReceiver(context, mTaskInfo, mInputChannel, + callback, handler, choreographer, () -> { final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId); return new Size(layout.width(), layout.height()); - }, this::updateSinkInputChannel); + }, this::updateSinkInputChannel, mDesktopModeEventLogger); mInputEventReceiver.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop()); mInputSinkSurface = surfaceControlBuilderSupplier.get() @@ -163,6 +173,22 @@ class DragResizeInputListener implements AutoCloseable { } } + DragResizeInputListener( + Context context, + RunningTaskInfo taskInfo, + Handler handler, + Choreographer choreographer, + int displayId, + SurfaceControl decorationSurface, + DragPositioningCallback callback, + Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier, + Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier, + DisplayController displayController) { + this(context, taskInfo, handler, choreographer, displayId, decorationSurface, callback, + surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, displayController, + new DesktopModeEventLogger()); + } + /** * Updates the geometry (the touch region) of this drag resize handler. * @@ -274,6 +300,7 @@ class DragResizeInputListener implements AutoCloseable { private static class TaskResizeInputEventReceiver extends InputEventReceiver implements DragDetector.MotionEventHandler { @NonNull private final Context mContext; + @NonNull private final RunningTaskInfo mTaskInfo; private final InputManager mInputManager; @NonNull private final InputChannel mInputChannel; @NonNull private final DragPositioningCallback mCallback; @@ -282,6 +309,7 @@ class DragResizeInputListener implements AutoCloseable { @NonNull private final DragDetector mDragDetector; @NonNull private final Supplier<Size> mDisplayLayoutSizeSupplier; @NonNull private final Consumer<Region> mTouchRegionConsumer; + @NonNull private final DesktopModeEventLogger mDesktopModeEventLogger; private final Rect mTmpRect = new Rect(); private boolean mConsumeBatchEventScheduled; private DragResizeWindowGeometry mDragResizeWindowGeometry; @@ -293,15 +321,24 @@ class DragResizeInputListener implements AutoCloseable { // resize events. For example, if multiple fingers are touching the screen, then each one // has a separate pointer id, but we only accept drag input from one. private int mDragPointerId = -1; + // The type of resizing that is currently being done. Used to track the same resize trigger + // on start and end of the resizing action. + private ResizeTrigger mResizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER; + // The last MotionEvent on ACTION_DOWN, used to track the input tool type and source for + // logging the start and end of the resizing action. + private MotionEvent mLastMotionEventOnDown; private TaskResizeInputEventReceiver(@NonNull Context context, + @NonNull RunningTaskInfo taskInfo, @NonNull InputChannel inputChannel, @NonNull DragPositioningCallback callback, @NonNull Handler handler, @NonNull Choreographer choreographer, @NonNull Supplier<Size> displayLayoutSizeSupplier, - @NonNull Consumer<Region> touchRegionConsumer) { + @NonNull Consumer<Region> touchRegionConsumer, + @NonNull DesktopModeEventLogger desktopModeEventLogger) { super(inputChannel, handler.getLooper()); mContext = context; + mTaskInfo = taskInfo; mInputManager = context.getSystemService(InputManager.class); mInputChannel = inputChannel; mCallback = callback; @@ -322,6 +359,7 @@ class DragResizeInputListener implements AutoCloseable { ViewConfiguration.get(mContext).getScaledTouchSlop()); mDisplayLayoutSizeSupplier = displayLayoutSizeSupplier; mTouchRegionConsumer = touchRegionConsumer; + mDesktopModeEventLogger = desktopModeEventLogger; } /** @@ -395,6 +433,7 @@ class DragResizeInputListener implements AutoCloseable { @Override public boolean handleMotionEvent(View v, MotionEvent e) { boolean result = false; + // Check if this is a touch event vs mouse event. // Touch events are tracked in four corners. Other events are tracked in resize edges. switch (e.getActionMasked()) { @@ -416,6 +455,13 @@ class DragResizeInputListener implements AutoCloseable { "%s: Handling action down, update ctrlType to %d", TAG, ctrlType); mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType, rawX, rawY); + mLastMotionEventOnDown = e; + mResizeTrigger = (ctrlType == CTRL_TYPE_BOTTOM || ctrlType == CTRL_TYPE_TOP + || ctrlType == CTRL_TYPE_RIGHT || ctrlType == CTRL_TYPE_LEFT) + ? ResizeTrigger.EDGE : ResizeTrigger.CORNER; + mDesktopModeEventLogger.logTaskResizingStarted(mResizeTrigger, + e, mTaskInfo, /* displayController= */ null, + /* displayLayoutSize= */ mDisplayLayoutSizeSupplier.get()); // Increase the input sink region to cover the whole screen; this is to // prevent input and focus from going to other tasks during a drag resize. updateInputSinkRegionForDrag(mDragStartTaskBounds); @@ -464,6 +510,12 @@ class DragResizeInputListener implements AutoCloseable { if (taskBounds.equals(mDragStartTaskBounds)) { mTouchRegionConsumer.accept(mTouchRegion); } + + mDesktopModeEventLogger.logTaskResizingEnded(mResizeTrigger, + mLastMotionEventOnDown, mTaskInfo, taskBounds.height(), + taskBounds.width(), + /* displayController= */ null, + /* displayLayoutSize= */ mDisplayLayoutSizeSupplier.get()); } mShouldHandleEvents = false; mDragPointerId = -1; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java index 33d1c260cb84..844ceb304bde 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java @@ -181,7 +181,7 @@ final class DragResizeWindowGeometry { } private boolean isInEdgeResizeBounds(float x, float y) { - return calculateEdgeResizeCtrlType(x, y) != 0; + return calculateEdgeResizeCtrlType(x, y) != CTRL_TYPE_UNDEFINED; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 6b3b357f2f7b..34cc0986c83f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -58,6 +58,7 @@ import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams.OccludingCaptionElement; import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer; @@ -111,6 +112,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> final Context mContext; final @NonNull Context mUserContext; final @NonNull DisplayController mDisplayController; + final @NonNull DesktopModeEventLogger mDesktopModeEventLogger; final ShellTaskOrganizer mTaskOrganizer; final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier; final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier; @@ -163,7 +165,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> this(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, SurfaceControl.Builder::new, SurfaceControl.Transaction::new, WindowContainerTransaction::new, SurfaceControl::new, - new SurfaceControlViewHostFactory() {}); + new SurfaceControlViewHostFactory() {}, new DesktopModeEventLogger()); } WindowDecoration( @@ -177,13 +179,16 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier, Supplier<WindowContainerTransaction> windowContainerTransactionSupplier, Supplier<SurfaceControl> surfaceControlSupplier, - SurfaceControlViewHostFactory surfaceControlViewHostFactory) { + SurfaceControlViewHostFactory surfaceControlViewHostFactory, + @NonNull DesktopModeEventLogger desktopModeEventLogger + ) { mContext = context; mUserContext = userContext; mDisplayController = displayController; mTaskOrganizer = taskOrganizer; mTaskInfo = taskInfo; mTaskSurface = cloneSurfaceControl(taskSurface, surfaceControlSupplier); + mDesktopModeEventLogger = desktopModeEventLogger; mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier; mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier; mWindowContainerTransactionSupplier = windowContainerTransactionSupplier; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java index e6bd05b82be9..f935ac76bbeb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java @@ -40,6 +40,8 @@ public final class TestRunningTaskInfoBuilder { private WindowContainerToken mToken = createMockWCToken(); private int mParentTaskId = INVALID_TASK_ID; + private int mUid = INVALID_TASK_ID; + private int mTaskId = INVALID_TASK_ID; private Intent mBaseIntent = new Intent(); private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD; private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED; @@ -73,6 +75,18 @@ public final class TestRunningTaskInfoBuilder { return this; } + /** Sets the task info's effective UID. */ + public TestRunningTaskInfoBuilder setUid(int uid) { + mUid = uid; + return this; + } + + /** Sets the task info's UID. */ + public TestRunningTaskInfoBuilder setTaskId(int taskId) { + mTaskId = taskId; + return this; + } + /** * Set {@link ActivityManager.RunningTaskInfo#baseIntent} for the task info, by default * an empty intent is assigned @@ -132,7 +146,8 @@ public final class TestRunningTaskInfoBuilder { public ActivityManager.RunningTaskInfo build() { final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); - info.taskId = sNextTaskId++; + info.taskId = (mTaskId == INVALID_TASK_ID) ? sNextTaskId++ : mTaskId; + info.effectiveUid = mUid; info.baseIntent = mBaseIntent; info.parentTaskId = mParentTaskId; info.displayId = mDisplayId; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt index 0825b6b0d7be..2a82e6e4f7b8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt @@ -16,9 +16,12 @@ package com.android.wm.shell.desktopmode +import android.app.ActivityManager.RunningTaskInfo +import android.graphics.Rect import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations +import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker import com.android.dx.mockito.inline.extended.ExtendedMockito.verify import com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions @@ -27,6 +30,9 @@ import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.window.flags.Flags import com.android.wm.shell.EventLogTags import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.TestRunningTaskInfoBuilder +import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod @@ -39,9 +45,13 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_M import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason import com.google.common.truth.Truth.assertThat +import org.junit.Before import org.junit.Rule import org.junit.Test +import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever /** * Tests for [DesktopModeEventLogger]. @@ -49,6 +59,8 @@ import org.mockito.kotlin.eq class DesktopModeEventLoggerTest : ShellTestCase() { private val desktopModeEventLogger = DesktopModeEventLogger() + val displayController = mock<DisplayController>() + val displayLayout = mock<DisplayLayout>() @JvmField @Rule(order = 0) @@ -60,6 +72,13 @@ class DesktopModeEventLoggerTest : ShellTestCase() { @Rule(order = 1) val setFlagsRule = SetFlagsRule() + @Before + fun setUp() { + doReturn(displayLayout).whenever(displayController).getDisplayLayout(anyInt()) + doReturn(DISPLAY_WIDTH).whenever(displayLayout).width() + doReturn(DISPLAY_HEIGHT).whenever(displayLayout).height() + } + @Test fun logSessionEnter_logsEnterReasonWithNewSessionId() { desktopModeEventLogger.logSessionEnter(EnterReason.KEYBOARD_SHORTCUT_ENTER) @@ -467,7 +486,8 @@ class DesktopModeEventLoggerTest : ShellTestCase() { @Test fun logTaskResizingStarted_noOngoingSession_doesNotLog() { - desktopModeEventLogger.logTaskResizingStarted(TASK_SIZE_UPDATE) + desktopModeEventLogger.logTaskResizingStarted(ResizeTrigger.CORNER, + null, createTaskInfo()) verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java)) verifyZeroInteractions(staticMockMarker(EventLogTags::class.java)) @@ -478,13 +498,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() { fun logTaskResizingStarted_logsTaskSizeUpdatedWithStartResizingStage() { val sessionId = startDesktopModeSession() - desktopModeEventLogger.logTaskResizingStarted(TASK_SIZE_UPDATE) + desktopModeEventLogger.logTaskResizingStarted(ResizeTrigger.CORNER, + null, createTaskInfo(), displayController) verify { FrameworkStatsLog.write( eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED), /* resize_trigger */ - eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER), + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER), /* resizing_stage */ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE), /* input_method */ @@ -500,7 +521,7 @@ class DesktopModeEventLoggerTest : ShellTestCase() { /* task_width */ eq(TASK_SIZE_UPDATE.taskWidth), /* display_area */ - eq(TASK_SIZE_UPDATE.displayArea), + eq(DISPLAY_AREA), ) } verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java)) @@ -508,7 +529,8 @@ class DesktopModeEventLoggerTest : ShellTestCase() { @Test fun logTaskResizingEnded_noOngoingSession_doesNotLog() { - desktopModeEventLogger.logTaskResizingEnded(TASK_SIZE_UPDATE) + desktopModeEventLogger.logTaskResizingEnded(ResizeTrigger.CORNER, + null, createTaskInfo()) verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java)) verifyZeroInteractions(staticMockMarker(EventLogTags::class.java)) @@ -519,13 +541,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() { fun logTaskResizingEnded_logsTaskSizeUpdatedWithEndResizingStage() { val sessionId = startDesktopModeSession() - desktopModeEventLogger.logTaskResizingEnded(TASK_SIZE_UPDATE) + desktopModeEventLogger.logTaskResizingEnded(ResizeTrigger.CORNER, + null, createTaskInfo(), displayController = displayController) verify { FrameworkStatsLog.write( eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED), /* resize_trigger */ - eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER), + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER), /* resizing_stage */ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE), /* input_method */ @@ -541,7 +564,7 @@ class DesktopModeEventLoggerTest : ShellTestCase() { /* task_width */ eq(TASK_SIZE_UPDATE.taskWidth), /* display_area */ - eq(TASK_SIZE_UPDATE.displayArea), + eq(DISPLAY_AREA), ) } verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java)) @@ -585,8 +608,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() { } } + private fun createTaskInfo(): RunningTaskInfo { + return TestRunningTaskInfoBuilder().setTaskId(TASK_ID) + .setUid(TASK_UID) + .setBounds(Rect(TASK_X, TASK_Y, TASK_WIDTH, TASK_HEIGHT)) + .build() + } + private companion object { - private const val sessionId = 1 private const val TASK_ID = 1 private const val TASK_UID = 1 private const val TASK_X = 0 @@ -594,7 +623,9 @@ class DesktopModeEventLoggerTest : ShellTestCase() { private const val TASK_HEIGHT = 100 private const val TASK_WIDTH = 100 private const val TASK_COUNT = 1 - private const val DISPLAY_AREA = 1000 + private const val DISPLAY_WIDTH = 500 + private const val DISPLAY_HEIGHT = 500 + private const val DISPLAY_AREA = DISPLAY_HEIGHT * DISPLAY_WIDTH private val TASK_UPDATE = TaskUpdate( TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 55b44ac935ea..61943568e7d4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -54,6 +54,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.Gravity import android.view.KeyEvent +import android.view.MotionEvent import android.view.SurfaceControl import android.view.WindowInsets import android.view.WindowManager @@ -99,6 +100,7 @@ import com.android.wm.shell.common.LaunchAdjacentController import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTasksController.TaskbarDesktopTaskListener import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask @@ -214,9 +216,11 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock private lateinit var taskbarDesktopTaskListener: TaskbarDesktopTaskListener @Mock private lateinit var freeformTaskTransitionStarter: FreeformTaskTransitionStarter @Mock private lateinit var mockHandler: Handler + @Mock private lateinit var desktopModeEventLogger: DesktopModeEventLogger @Mock lateinit var persistentRepository: DesktopPersistentRepository @Mock private lateinit var mockInputManager: InputManager @Mock private lateinit var mockFocusTransitionObserver: FocusTransitionObserver + @Mock lateinit var motionEvent: MotionEvent private lateinit var mockitoSession: StaticMockitoSession private lateinit var controller: DesktopTasksController @@ -329,6 +333,7 @@ class DesktopTasksControllerTest : ShellTestCase() { mockHandler, mockInputManager, mockFocusTransitionObserver, + desktopModeEventLogger, ) } @@ -357,9 +362,17 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java) - controller.toggleDesktopTaskSize(task1) - verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) + controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task1, + STABLE_BOUNDS.height(), + STABLE_BOUNDS.width(), + displayController + ) assertThat(argumentCaptor.value).isTrue() } @@ -376,9 +389,17 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask(bounds = stableBounds, active = true) val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java) - controller.toggleDesktopTaskSize(task1) - verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) + controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task1, + 0, + 0, + displayController + ) assertThat(argumentCaptor.value).isFalse() } @@ -2860,7 +2881,8 @@ class DesktopTasksControllerTest : ShellTestCase() { PointF(200f, -200f), /* inputCoordinate */ Rect(100, -100, 500, 1000), /* currentDragBounds */ Rect(0, 50, 2000, 2000), /* validDragArea */ - Rect() /* dragStartBounds */ ) + Rect() /* dragStartBounds */, + motionEvent) val rectAfterEnd = Rect(100, 50, 500, 1150) verify(transitions) .startTransition( @@ -2895,7 +2917,8 @@ class DesktopTasksControllerTest : ShellTestCase() { PointF(200f, 300f), /* inputCoordinate */ currentDragBounds, /* currentDragBounds */ Rect(0, 50, 2000, 2000) /* validDragArea */, - Rect() /* dragStartBounds */) + Rect() /* dragStartBounds */, + motionEvent) verify(transitions) @@ -3142,10 +3165,19 @@ class DesktopTasksControllerTest : ShellTestCase() { val bounds = Rect(0, 0, 100, 100) val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds) - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + // Assert bounds set to stable bounds val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(STABLE_BOUNDS) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + STABLE_BOUNDS.height(), + STABLE_BOUNDS.width(), + displayController + ) } @Test @@ -3164,10 +3196,18 @@ class DesktopTasksControllerTest : ShellTestCase() { STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom ) - controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT) + controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT, ResizeTrigger.SNAP_LEFT_MENU, motionEvent) // Assert bounds set to stable bounds val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds) assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.SNAP_LEFT_MENU, + motionEvent, + task, + expectedBounds.height(), + expectedBounds.width(), + displayController + ) } @Test @@ -3187,7 +3227,7 @@ class DesktopTasksControllerTest : ShellTestCase() { // Attempt to snap left again val currentDragBounds = Rect(bounds).apply { offset(-100, 0) } - controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT) + controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT, ResizeTrigger.SNAP_LEFT_MENU, motionEvent) // Assert that task is NOT updated via WCT verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any()) @@ -3200,6 +3240,14 @@ class DesktopTasksControllerTest : ShellTestCase() { eq(bounds), eq(true) ) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.SNAP_LEFT_MENU, + motionEvent, + task, + bounds.height(), + bounds.width(), + displayController + ) } @Test @@ -3210,12 +3258,22 @@ class DesktopTasksControllerTest : ShellTestCase() { } val preDragBounds = Rect(100, 100, 400, 500) val currentDragBounds = Rect(0, 100, 300, 500) + val expectedBounds = + Rect(STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom) controller.handleSnapResizingTask( - task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds) + task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds, motionEvent + ) val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds) assertThat(findBoundsChange(wct, task)).isEqualTo( - Rect(STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom)) + expectedBounds + ) + verify(desktopModeEventLogger, times(1)).logTaskResizingStarted( + ResizeTrigger.DRAG_LEFT, + motionEvent, + task, + displayController + ) } @Test @@ -3228,7 +3286,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val currentDragBounds = Rect(0, 100, 300, 500) controller.handleSnapResizingTask( - task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds) + task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds, motionEvent) verify(mReturnToDragStartAnimator).start( eq(task.taskId), eq(mockSurface), @@ -3236,6 +3294,13 @@ class DesktopTasksControllerTest : ShellTestCase() { eq(preDragBounds), eq(false) ) + verify(desktopModeEventLogger, never()).logTaskResizingStarted( + any(), + any(), + any(), + any(), + any() + ) } @Test @@ -3254,10 +3319,19 @@ class DesktopTasksControllerTest : ShellTestCase() { // Bounds should be 1000 x 500, vertically centered in the 1000 x 1000 stable bounds val expectedBounds = Rect(STABLE_BOUNDS.left, 250, STABLE_BOUNDS.right, 750) - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + // Assert bounds set to stable bounds val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + expectedBounds.height(), + expectedBounds.width(), + displayController + ) } @Test @@ -3265,8 +3339,12 @@ class DesktopTasksControllerTest : ShellTestCase() { val bounds = Rect(0, 0, 100, 100) val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds) - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds) + verify(desktopModeEventLogger, never()).logTaskResizingEnded( + any(), any(), any(), any(), + any(), any(), any() + ) } @Test @@ -3275,15 +3353,23 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize) // Maximize - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS) // Restore - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + boundsBeforeMaximize.height(), + boundsBeforeMaximize.width(), + displayController + ) } @Test @@ -3294,16 +3380,24 @@ class DesktopTasksControllerTest : ShellTestCase() { } // Maximize - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS.left, boundsBeforeMaximize.top, STABLE_BOUNDS.right, boundsBeforeMaximize.bottom) // Restore - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + boundsBeforeMaximize.height(), + boundsBeforeMaximize.width(), + displayController + ) } @Test @@ -3314,16 +3408,24 @@ class DesktopTasksControllerTest : ShellTestCase() { } // Maximize - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) task.configuration.windowConfiguration.bounds.set(boundsBeforeMaximize.left, STABLE_BOUNDS.top, boundsBeforeMaximize.right, STABLE_BOUNDS.bottom) // Restore - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + boundsBeforeMaximize.height(), + boundsBeforeMaximize.width(), + displayController + ) } @Test @@ -3332,14 +3434,22 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize) // Maximize - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS) // Restore - controller.toggleDesktopTaskSize(task) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) // Assert last bounds before maximize removed after use assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull() + verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( + ResizeTrigger.MAXIMIZE_BUTTON, + motionEvent, + task, + boundsBeforeMaximize.height(), + boundsBeforeMaximize.width(), + displayController + ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index 175fbd2396e3..1839b8a367fe 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -87,6 +87,8 @@ import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler +import com.android.wm.shell.desktopmode.DesktopModeEventLogger +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition @@ -194,7 +196,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @Mock private lateinit var mockAppHandleEducationController: AppHandleEducationController @Mock private lateinit var mockFocusTransitionObserver: FocusTransitionObserver @Mock private lateinit var mockCaptionHandleRepository: WindowDecorCaptionHandleRepository + @Mock private lateinit var motionEvent: MotionEvent + @Mock lateinit var displayController: DisplayController + @Mock lateinit var displayLayout: DisplayLayout private lateinit var spyContext: TestableContext + private lateinit var desktopModeEventLogger: DesktopModeEventLogger private val transactionFactory = Supplier<SurfaceControl.Transaction> { SurfaceControl.Transaction() @@ -224,6 +230,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { shellInit = ShellInit(mockShellExecutor) windowDecorByTaskIdSpy.clear() spyContext.addMockSystemService(InputManager::class.java, mockInputManager) + desktopModeEventLogger = mock<DesktopModeEventLogger>() desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel( spyContext, mockShellExecutor, @@ -256,7 +263,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { mockCaptionHandleRepository, Optional.of(mockActivityOrientationChangeHandler), mockTaskPositionerFactory, - mockFocusTransitionObserver + mockFocusTransitionObserver, + desktopModeEventLogger ) desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController) whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout) @@ -299,6 +307,10 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { argumentCaptor<DesktopModeKeyguardChangeListener>() verify(mockShellController).addKeyguardChangeListener(keyguardChangedCaptor.capture()) desktopModeOnKeyguardChangedListener = keyguardChangedCaptor.firstValue + whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout) + whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> + (i.arguments.first() as Rect).set(STABLE_BOUNDS) + } } @After @@ -612,7 +624,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { maxOrRestoreListenerCaptor.value.invoke() - verify(mockDesktopTasksController).toggleDesktopTaskSize(decor.mTaskInfo) + verify(mockDesktopTasksController).toggleDesktopTaskSize( + decor.mTaskInfo, + ResizeTrigger.MAXIMIZE_MENU, + null + ) } @Test @@ -647,7 +663,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { eq(decor.mTaskInfo), taskSurfaceCaptor.capture(), eq(currentBounds), - eq(SnapPosition.LEFT) + eq(SnapPosition.LEFT), + eq(ResizeTrigger.SNAP_LEFT_MENU), + eq(null) ) assertEquals(taskSurfaceCaptor.firstValue, decor.mTaskSurface) } @@ -685,7 +703,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { eq(decor.mTaskInfo), taskSurfaceCaptor.capture(), eq(currentBounds), - eq(SnapPosition.LEFT) + eq(SnapPosition.LEFT), + eq(ResizeTrigger.SNAP_LEFT_MENU), + eq(null) ) assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue) } @@ -704,7 +724,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { onLeftSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT)) + .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT), + eq(ResizeTrigger.MAXIMIZE_BUTTON), + eq(null)) verify(mockToast).show() } @@ -725,7 +747,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { eq(decor.mTaskInfo), taskSurfaceCaptor.capture(), eq(currentBounds), - eq(SnapPosition.RIGHT) + eq(SnapPosition.RIGHT), + eq(ResizeTrigger.SNAP_RIGHT_MENU), + eq(null) ) assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue) } @@ -763,7 +787,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { eq(decor.mTaskInfo), taskSurfaceCaptor.capture(), eq(currentBounds), - eq(SnapPosition.RIGHT) + eq(SnapPosition.RIGHT), + eq(ResizeTrigger.SNAP_RIGHT_MENU), + eq(null) ) assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue) } @@ -782,7 +808,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { onRightSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT)) + .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT), + eq(ResizeTrigger.MAXIMIZE_BUTTON), + eq(null)) verify(mockToast).show() } @@ -1247,7 +1275,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { onClickListenerCaptor.value.onClick(view) verify(mockDesktopTasksController) - .toggleDesktopTaskSize(decor.mTaskInfo) + .toggleDesktopTaskSize(decor.mTaskInfo, ResizeTrigger.MAXIMIZE_BUTTON, null) } private fun createOpenTaskDecoration( @@ -1337,7 +1365,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { whenever( mockDesktopModeWindowDecorFactory.create( any(), any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(), - any(), any(), any(), any(), any(), any(), any()) + any(), any(), any(), any(), any(), any(), any(), any()) ).thenReturn(decoration) decoration.mTaskInfo = task whenever(decoration.user).thenReturn(mockUserHandle) @@ -1378,5 +1406,6 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { private const val TAG = "DesktopModeWindowDecorViewModelTests" private val STABLE_INSETS = Rect(0, 100, 0, 0) private val INITIAL_BOUNDS = Rect(0, 0, 100, 100) + private val STABLE_BOUNDS = Rect(0, 0, 1000, 1000) } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java index 320887212f54..0afb6c10b549 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java @@ -106,6 +106,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.CaptionState; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; @@ -210,6 +211,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private MultiInstanceHelper mMockMultiInstanceHelper; @Mock private WindowDecorCaptionHandleRepository mMockCaptionHandleRepository; + @Mock + private DesktopModeEventLogger mDesktopModeEventLogger; @Captor private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener; @Captor @@ -1400,7 +1403,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(mMockWindowManager), mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory, - mMockMultiInstanceHelper, mMockCaptionHandleRepository); + mMockMultiInstanceHelper, mMockCaptionHandleRepository, mDesktopModeEventLogger); windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener, mMockTouchEventListener, mMockTouchEventListener); windowDecor.setExclusionRegionListener(mMockExclusionRegionListener); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index fb17ae93030d..cb7fadee9822 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -83,6 +83,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.tests.R; import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer; @@ -138,6 +139,8 @@ public class WindowDecorationTests extends ShellTestCase { private SurfaceSyncGroup mMockSurfaceSyncGroup; @Mock private SurfaceControl mMockTaskSurface; + @Mock + private DesktopModeEventLogger mDesktopModeEventLogger; private final List<SurfaceControl.Transaction> mMockSurfaceControlTransactions = new ArrayList<>(); @@ -1014,7 +1017,7 @@ public class WindowDecorationTests extends ShellTestCase { new MockObjectSupplier<>(mMockSurfaceControlTransactions, () -> mock(SurfaceControl.Transaction.class)), () -> mMockWindowContainerTransaction, () -> mMockTaskSurface, - mMockSurfaceControlViewHostFactory); + mMockSurfaceControlViewHostFactory, mDesktopModeEventLogger); } private class MockObjectSupplier<T> implements Supplier<T> { @@ -1054,11 +1057,12 @@ public class WindowDecorationTests extends ShellTestCase { Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier, Supplier<WindowContainerTransaction> windowContainerTransactionSupplier, Supplier<SurfaceControl> surfaceControlSupplier, - SurfaceControlViewHostFactory surfaceControlViewHostFactory) { + SurfaceControlViewHostFactory surfaceControlViewHostFactory, + DesktopModeEventLogger desktopModeEventLogger) { super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, - surfaceControlViewHostFactory); + surfaceControlViewHostFactory, desktopModeEventLogger); } @Override |