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

Commit 34f9f07e authored by Daniel Akinola's avatar Daniel Akinola Committed by Android (Google) Code Review
Browse files

Merge "Logging a11y actions in desktop windowing" into main

parents 97a6505b ed4de351
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -167,7 +167,35 @@ class DesktopModeUiEventLogger(
        @UiEvent(doc = "Exit desktop mode education tooltip on the app header menu is clicked")
        EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_CLICKED(2104),
        @UiEvent(doc = "Exit desktop mode education tooltip is dismissed by the user")
        EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED(2105);
        EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED(2105),
        @UiEvent(doc = "A11y service opened app handle menu by selecting handle from fullscreen")
        A11Y_APP_HANDLE_MENU_OPENED(2156),
        @UiEvent(doc = "A11y service opened app handle menu through Switch Access actions menu ")
        A11Y_SYSTEM_ACTION_APP_HANDLE_MENU(2157),
        @UiEvent(doc = "A11y service selected desktop mode from app handle menu")
        A11Y_APP_HANDLE_MENU_DESKTOP_VIEW(2158),
        @UiEvent(doc = "A11y service selected fullscreen mode from app handle menu")
        A11Y_APP_HANDLE_MENU_FULLSCREEN(2159),
        @UiEvent(doc = "A11y service selected split screen mode from app handle menu")
        A11Y_APP_HANDLE_MENU_SPLIT_SCREEN(2160),
        @UiEvent(doc = "A11y service selected maximize/restore button from app header")
        A11Y_APP_WINDOW_MAXIMIZE_RESTORE_BUTTON(2161),
        @UiEvent(doc = "A11y service selected minimize button from app header")
        A11Y_APP_WINDOW_MINIMIZE_BUTTON(2162),
        @UiEvent(doc = "A11y service selected close button from app header")
        A11Y_APP_WINDOW_CLOSE_BUTTON(2163),
        @UiEvent(doc = "A11y service selected maximize button from app header maximize menu")
        A11Y_MAXIMIZE_MENU_MAXIMIZE(2164),
        @UiEvent(doc = "A11y service selected resize left button from app header maximize menu")
        A11Y_MAXIMIZE_MENU_RESIZE_LEFT(2165),
        @UiEvent(doc = "A11y service selected resize right button from app header maximize menu")
        A11Y_MAXIMIZE_MENU_RESIZE_RIGHT(2166),
        @UiEvent(doc = "A11y service triggered a11y action to maximize/restore app window")
        A11Y_ACTION_MAXIMIZE_RESTORE(2167),
        @UiEvent(doc = "A11y service triggered a11y action to resize app window left")
        A11Y_ACTION_RESIZE_LEFT(2168),
        @UiEvent(doc = "A11y service triggered a11y action to resize app window right")
        A11Y_ACTION_RESIZE_RIGHT(2169);

        override fun getId(): Int = mId
    }
+1 −0
Original line number Diff line number Diff line
@@ -1802,6 +1802,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        mMultiInstanceHelper,
                        mWindowDecorCaptionHandleRepository,
                        mDesktopModeEventLogger,
                        mDesktopModeUiEventLogger,
                        mDesktopModeCompatPolicy);
        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);

+15 −6
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ 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.DesktopModeUiEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeUtils;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
@@ -211,6 +212,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private final MultiInstanceHelper mMultiInstanceHelper;
    private final WindowDecorCaptionHandleRepository mWindowDecorCaptionHandleRepository;
    private final DesktopUserRepositories mDesktopUserRepositories;
    private final DesktopModeUiEventLogger mDesktopModeUiEventLogger;
    private boolean mIsRecentsTransitionRunning = false;
    private boolean mIsDragging = false;
    private Runnable mLoadAppInfoRunnable;
@@ -243,6 +245,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            MultiInstanceHelper multiInstanceHelper,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopModeUiEventLogger desktopModeUiEventLogger,
            DesktopModeCompatPolicy desktopModeCompatPolicy) {
        this (context, userContext, displayController, taskResourceLoader, splitScreenController,
                desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler,
@@ -257,7 +260,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                DefaultMaximizeMenuFactory.INSTANCE,
                DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper,
                windowDecorCaptionHandleRepository, desktopModeEventLogger,
                desktopModeCompatPolicy);
                desktopModeUiEventLogger, desktopModeCompatPolicy);
    }

    DesktopModeWindowDecoration(
@@ -294,6 +297,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            MultiInstanceHelper multiInstanceHelper,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopModeUiEventLogger desktopModeUiEventLogger,
            DesktopModeCompatPolicy desktopModeCompatPolicy) {
        super(context, userContext, displayController, taskOrganizer, taskInfo,
                taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
@@ -321,6 +325,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        mTaskResourceLoader = taskResourceLoader;
        mTaskResourceLoader.onWindowDecorCreated(taskInfo);
        mDesktopModeCompatPolicy = desktopModeCompatPolicy;
        mDesktopModeUiEventLogger = desktopModeUiEventLogger;
    }

    /**
@@ -895,10 +900,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                    mOnCaptionTouchListener,
                    mOnCaptionButtonClickListener,
                    mWindowManagerWrapper,
                    mHandler
                    mHandler,
                    mDesktopModeUiEventLogger
            );
        } else if (mRelayoutParams.mLayoutResId
                == R.layout.desktop_mode_app_header) {
        } else if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_header) {
            return mAppHeaderViewHolderFactory.create(
                    mResult.mRootView,
                    mOnCaptionTouchListener,
@@ -908,7 +913,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                    mOnLeftSnapClickListener,
                    mOnRightSnapClickListener,
                    mOnMaximizeOrRestoreClickListener,
                    mOnMaximizeHoverListener);
                    mOnMaximizeHoverListener,
                    mDesktopModeUiEventLogger);
        }
        throw new IllegalArgumentException("Unexpected layout resource id");
    }
@@ -1372,7 +1378,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        mMaximizeMenu = mMaximizeMenuFactory.create(mSyncQueue, mRootTaskDisplayAreaOrganizer,
                mDisplayController, mTaskInfo, mContext,
                (width, height) -> calculateMaximizeMenuPosition(width, height),
                mSurfaceControlTransactionSupplier);
                mSurfaceControlTransactionSupplier, mDesktopModeUiEventLogger);

        mMaximizeMenu.show(
                /* isTaskInImmersiveMode= */
@@ -1488,6 +1494,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                shouldShowRestartButton,
                isBrowserApp,
                isBrowserApp ? getAppLink() : getBrowserLink(),
                mDesktopModeUiEventLogger,
                mResult.mCaptionWidth,
                mResult.mCaptionHeight,
                mResult.mCaptionX,
@@ -1973,6 +1980,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                MultiInstanceHelper multiInstanceHelper,
                WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
                DesktopModeEventLogger desktopModeEventLogger,
                DesktopModeUiEventLogger desktopModeUiEventLogger,
                DesktopModeCompatPolicy desktopModeCompatPolicy) {
            return new DesktopModeWindowDecoration(
                    context,
@@ -2000,6 +2008,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                    multiInstanceHelper,
                    windowDecorCaptionHandleRepository,
                    desktopModeEventLogger,
                    desktopModeUiEventLogger,
                    desktopModeCompatPolicy);
        }
    }
+51 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.graphics.Bitmap
import android.graphics.Point
import android.graphics.PointF
import android.graphics.Rect
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.MotionEvent.ACTION_OUTSIDE
@@ -35,6 +36,7 @@ import android.view.SurfaceControl
import android.view.View
import android.view.WindowInsets.Type.systemBars
import android.view.WindowManager
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.Space
@@ -49,6 +51,10 @@ import androidx.core.view.isGone
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.ContextUtils.isRtl
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_APP_HANDLE_MENU_DESKTOP_VIEW
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_APP_HANDLE_MENU_FULLSCREEN
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_APP_HANDLE_MENU_SPLIT_SCREEN
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
@@ -97,6 +103,7 @@ class HandleMenu(
    private val shouldShowRestartButton: Boolean,
    private val isBrowserApp: Boolean,
    private val openInAppOrBrowserIntent: Intent?,
    private val desktopModeUiEventLogger: DesktopModeUiEventLogger,
    private val captionWidth: Int,
    private val captionHeight: Int,
    captionX: Int,
@@ -208,6 +215,7 @@ class HandleMenu(
    ) {
        val handleMenuView = HandleMenuView(
            context = context,
            desktopModeUiEventLogger = desktopModeUiEventLogger,
            menuWidth = menuWidth,
            captionHeight = captionHeight,
            shouldShowWindowingPill = shouldShowWindowingPill,
@@ -475,6 +483,7 @@ class HandleMenu(
    @SuppressLint("ClickableViewAccessibility")
    class HandleMenuView(
        private val context: Context,
        private val desktopModeUiEventLogger: DesktopModeUiEventLogger,
        menuWidth: Int,
        captionHeight: Int,
        private val shouldShowWindowingPill: Boolean,
@@ -615,6 +624,45 @@ class HandleMenu(
                return@setOnTouchListener true
            }

            desktopBtn.accessibilityDelegate = object : View.AccessibilityDelegate() {
                override fun performAccessibilityAction(
                    host: View,
                    action: Int,
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_APP_HANDLE_MENU_DESKTOP_VIEW)
                    }
                    return super.performAccessibilityAction(host, action, args)
                }
            }

            fullscreenBtn.accessibilityDelegate = object : View.AccessibilityDelegate() {
                override fun performAccessibilityAction(
                    host: View,
                    action: Int,
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_APP_HANDLE_MENU_FULLSCREEN)
                    }
                    return super.performAccessibilityAction(host, action, args)
                }
            }

            splitscreenBtn.accessibilityDelegate = object : View.AccessibilityDelegate() {
                override fun performAccessibilityAction(
                    host: View,
                    action: Int,
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_APP_HANDLE_MENU_SPLIT_SCREEN)
                    }
                    return super.performAccessibilityAction(host, action, args)
                }
            }

            with(context) {
                // Update a11y announcement out to say "double tap to enter Fullscreen"
                ViewCompat.replaceAccessibilityAction(
@@ -917,6 +965,7 @@ interface HandleMenuFactory {
        shouldShowRestartButton: Boolean,
        isBrowserApp: Boolean,
        openInAppOrBrowserIntent: Intent?,
        desktopModeUiEventLogger: DesktopModeUiEventLogger,
        captionWidth: Int,
        captionHeight: Int,
        captionX: Int,
@@ -942,6 +991,7 @@ object DefaultHandleMenuFactory : HandleMenuFactory {
        shouldShowRestartButton: Boolean,
        isBrowserApp: Boolean,
        openInAppOrBrowserIntent: Intent?,
        desktopModeUiEventLogger: DesktopModeUiEventLogger,
        captionWidth: Int,
        captionHeight: Int,
        captionX: Int,
@@ -963,6 +1013,7 @@ object DefaultHandleMenuFactory : HandleMenuFactory {
            shouldShowRestartButton,
            isBrowserApp,
            openInAppOrBrowserIntent,
            desktopModeUiEventLogger,
            captionWidth,
            captionHeight,
            captionX,
+43 −46
Original line number Diff line number Diff line
@@ -60,14 +60,16 @@ import android.window.TaskConstants
import androidx.compose.material3.ColorScheme
import androidx.compose.ui.graphics.toArgb
import androidx.core.animation.addListener
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_MAXIMIZE_MENU_MAXIMIZE
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_MAXIMIZE_MENU_RESIZE_LEFT
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_MAXIMIZE_MENU_RESIZE_RIGHT
import com.android.wm.shell.desktopmode.isTaskMaximized
import com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.wm.shell.shared.animation.Interpolators.FAST_OUT_LINEAR_IN
@@ -91,7 +93,8 @@ class MaximizeMenu(
    private val taskInfo: RunningTaskInfo,
    private val decorWindowContext: Context,
    private val positionSupplier: (Int, Int) -> Point,
        private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() }
    private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() },
    private val desktopModeUiEventLogger: DesktopModeUiEventLogger
) {
    private var maximizeMenu: AdditionalViewHostViewContainer? = null
    private var maximizeMenuView: MaximizeMenuView? = null
@@ -132,7 +135,7 @@ class MaximizeMenu(
            onLeftSnapClickListener = onLeftSnapClickListener,
            onRightSnapClickListener = onRightSnapClickListener,
            onHoverListener = onHoverListener,
            onOutsideTouchListener = onOutsideTouchListener
            onOutsideTouchListener = onOutsideTouchListener,
        )
        maximizeMenuView?.let { view ->
            view.animateOpenMenu(onEnd = {
@@ -167,7 +170,7 @@ class MaximizeMenu(
        onLeftSnapClickListener: () -> Unit,
        onRightSnapClickListener: () -> Unit,
        onHoverListener: (Boolean) -> Unit,
        onOutsideTouchListener: () -> Unit
        onOutsideTouchListener: () -> Unit,
    ) {
        val t = transactionSupplier.get()
        val builder = SurfaceControl.Builder()
@@ -186,6 +189,7 @@ class MaximizeMenu(
                "MaximizeMenu")
        maximizeMenuView = MaximizeMenuView(
            context = decorWindowContext,
            desktopModeUiEventLogger = desktopModeUiEventLogger,
            sizeToggleDirection = getSizeToggleDirection(),
            immersiveConfig = if (showImmersiveOption) {
                MaximizeMenuView.ImmersiveConfig.Visible(
@@ -265,6 +269,7 @@ class MaximizeMenu(
     */
    class MaximizeMenuView(
        context: Context,
        private val desktopModeUiEventLogger: DesktopModeUiEventLogger,
        private val sizeToggleDirection: SizeToggleDirection,
        immersiveConfig: ImmersiveConfig,
        showSnapOptions: Boolean,
@@ -425,7 +430,10 @@ class MaximizeMenu(
                ) {

                    super.onInitializeAccessibilityNodeInfo(host, info)
                    info.addAction(AccessibilityAction.ACTION_CLICK)
                    info.addAction(AccessibilityAction(
                        AccessibilityAction.ACTION_CLICK.id,
                        context.getString(R.string.maximize_menu_talkback_action_maximize_restore_text)
                    ))
                    host.isClickable = true
                }

@@ -435,6 +443,7 @@ class MaximizeMenu(
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_MAXIMIZE_MENU_MAXIMIZE)
                        onMaximizeClickListener?.invoke()
                    }
                    return super.performAccessibilityAction(host, action, args)
@@ -447,7 +456,10 @@ class MaximizeMenu(
                    info: AccessibilityNodeInfo
                ) {
                    super.onInitializeAccessibilityNodeInfo(host, info)
                    info.addAction(AccessibilityAction.ACTION_CLICK)
                    info.addAction(AccessibilityAction(
                        AccessibilityAction.ACTION_CLICK.id,
                        context.getString(R.string.maximize_menu_talkback_action_snap_left_text)
                    ))
                    host.isClickable = true
                }

@@ -457,6 +469,7 @@ class MaximizeMenu(
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_MAXIMIZE_MENU_RESIZE_LEFT)
                        onLeftSnapClickListener?.invoke()
                    }
                    return super.performAccessibilityAction(host, action, args)
@@ -469,7 +482,10 @@ class MaximizeMenu(
                    info: AccessibilityNodeInfo
                ) {
                    super.onInitializeAccessibilityNodeInfo(host, info)
                    info.addAction(AccessibilityAction.ACTION_CLICK)
                    info.addAction(AccessibilityAction(
                        AccessibilityAction.ACTION_CLICK.id,
                        context.getString(R.string.maximize_menu_talkback_action_snap_right_text)
                    ))
                    host.isClickable = true
                }

@@ -479,35 +495,13 @@ class MaximizeMenu(
                    args: Bundle?
                ): Boolean {
                    if (action == AccessibilityAction.ACTION_CLICK.id) {
                        desktopModeUiEventLogger.log(taskInfo, A11Y_MAXIMIZE_MENU_RESIZE_RIGHT)
                        onRightSnapClickListener?.invoke()
                    }
                    return super.performAccessibilityAction(host, action, args)
                }
            }

            with(context.resources) {
                ViewCompat.replaceAccessibilityAction(
                    snapLeftButton,
                    AccessibilityActionCompat.ACTION_CLICK,
                    getString(R.string.maximize_menu_talkback_action_snap_left_text),
                    null
                )

                ViewCompat.replaceAccessibilityAction(
                    snapRightButton,
                    AccessibilityActionCompat.ACTION_CLICK,
                    getString(R.string.maximize_menu_talkback_action_snap_right_text),
                    null
                )

                ViewCompat.replaceAccessibilityAction(
                    sizeToggleButton,
                    AccessibilityActionCompat.ACTION_CLICK,
                    getString(R.string.maximize_menu_talkback_action_maximize_restore_text),
                    null
                )
            }

            // Maximize/restore button.
            val sizeToggleBtnTextId = if (sizeToggleDirection == SizeToggleDirection.RESTORE)
                R.string.desktop_mode_maximize_menu_restore_button_text
@@ -793,14 +787,14 @@ class MaximizeMenu(

        /** Measure width of the root view of this menu. */
        fun measureWidth(): Int {
            rootView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
            return rootView.getMeasuredWidth()
            rootView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
            return rootView.measuredWidth
        }

        /** Measure height of the root view of this menu. */
        fun measureHeight(): Int {
            rootView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
            return rootView.getMeasuredHeight()
            rootView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
            return rootView.measuredHeight
        }

        private fun deactivateSnapOptions() {
@@ -1048,7 +1042,8 @@ interface MaximizeMenuFactory {
        taskInfo: RunningTaskInfo,
        decorWindowContext: Context,
        positionSupplier: (Int, Int) -> Point,
        transactionSupplier: Supplier<Transaction>
        transactionSupplier: Supplier<Transaction>,
        desktopModeUiEventLogger: DesktopModeUiEventLogger,
    ): MaximizeMenu
}

@@ -1061,7 +1056,8 @@ object DefaultMaximizeMenuFactory : MaximizeMenuFactory {
        taskInfo: RunningTaskInfo,
        decorWindowContext: Context,
        positionSupplier: (Int, Int) -> Point,
        transactionSupplier: Supplier<Transaction>
        transactionSupplier: Supplier<Transaction>,
        desktopModeUiEventLogger: DesktopModeUiEventLogger,
    ): MaximizeMenu {
        return MaximizeMenu(
            syncQueue,
@@ -1070,7 +1066,8 @@ object DefaultMaximizeMenuFactory : MaximizeMenuFactory {
            taskInfo,
            decorWindowContext,
            positionSupplier,
            transactionSupplier
            transactionSupplier,
            desktopModeUiEventLogger
        )
    }
}
Loading