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

Commit 99cfd572 authored by Dhina17's avatar Dhina17 Committed by Garfield Tan
Browse files

WindowDecor: Pass correct displayId for back key event

TaskOperations object is being created with default display context
so it will provide the default display id only.
It causes that back button is not working on external displays.

Bug: 343265240
Test: Back button on simulated displays.
Test: atest DesktopModeWindowDecorViewModelTests
Change-Id: Ia4772e898dda20fb16ae85f2b2652a17924e9a7c
parent 9c0e43e5
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
        private final WindowContainerToken mTaskToken;
        private final DragPositioningCallback mDragPositioningCallback;
        private final DragDetector mDragDetector;
        private final int mDisplayId;

        private int mDragPointerId = -1;
        private boolean mIsDragging;
@@ -266,6 +267,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            mTaskToken = taskInfo.token;
            mDragPositioningCallback = dragPositioningCallback;
            mDragDetector = new DragDetector(this);
            mDisplayId = taskInfo.displayId;
        }

        @Override
@@ -274,7 +276,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
            if (id == R.id.close_window) {
                mTaskOperations.closeTask(mTaskToken);
            } else if (id == R.id.back_button) {
                mTaskOperations.injectBackKey();
                mTaskOperations.injectBackKey(mDisplayId);
            } else if (id == R.id.minimize_window) {
                mTaskOperations.minimizeTask(mTaskToken);
            } else if (id == R.id.maximize_window) {
+3 −1
Original line number Diff line number Diff line
@@ -386,6 +386,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        private final DragPositioningCallback mDragPositioningCallback;
        private final DragDetector mDragDetector;
        private final GestureDetector mGestureDetector;
        private final int mDisplayId;

        /**
         * Whether to pilfer the next motion event to send cancellations to the windows below.
@@ -407,6 +408,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            mDragPositioningCallback = dragPositioningCallback;
            mDragDetector = new DragDetector(this);
            mGestureDetector = new GestureDetector(mContext, this);
            mDisplayId = taskInfo.displayId;
            mCloseMaximizeWindowRunnable = () -> {
                final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
                if (decoration == null) return;
@@ -432,7 +434,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    mTaskOperations.closeTask(mTaskToken, wct);
                }
            } else if (id == R.id.back_button) {
                mTaskOperations.injectBackKey();
                mTaskOperations.injectBackKey(mDisplayId);
            } else if (id == R.id.caption_handle || id == R.id.open_menu_button) {
                if (!decoration.isHandleMenuActive()) {
                    moveTaskToFront(decoration.mTaskInfo);
+5 −5
Original line number Diff line number Diff line
@@ -52,19 +52,19 @@ class TaskOperations {
        mSyncQueue = syncQueue;
    }

    void injectBackKey() {
        sendBackEvent(KeyEvent.ACTION_DOWN);
        sendBackEvent(KeyEvent.ACTION_UP);
    void injectBackKey(int displayId) {
        sendBackEvent(KeyEvent.ACTION_DOWN, displayId);
        sendBackEvent(KeyEvent.ACTION_UP, displayId);
    }

    private void sendBackEvent(int action) {
    private void sendBackEvent(int action, int displayId) {
        final long when = SystemClock.uptimeMillis();
        final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK,
                0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD,
                0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                InputDevice.SOURCE_KEYBOARD);

        ev.setDisplayId(mContext.getDisplay().getDisplayId());
        ev.setDisplayId(displayId);
        if (!mContext.getSystemService(InputManager.class)
                .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
            Log.e(TAG, "Inject input event fail");
+41 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.Context
import android.graphics.Rect
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.hardware.input.InputManager
import android.os.Handler
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.RequiresFlagsEnabled
@@ -42,8 +43,10 @@ import android.view.InputChannel
import android.view.InputMonitor
import android.view.InsetsSource
import android.view.InsetsState
import android.view.KeyEvent
import android.view.SurfaceControl
import android.view.SurfaceView
import android.view.View
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
import androidx.test.filters.SmallTest
@@ -51,6 +54,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
@@ -61,6 +65,7 @@ import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.shared.DesktopModeStatus
import com.android.wm.shell.sysui.KeyguardChangeListener
import com.android.wm.shell.sysui.ShellCommandHandler
@@ -70,6 +75,7 @@ import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener
import java.util.Optional
import java.util.function.Supplier
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -278,6 +284,41 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        verify(mockInputMonitor, times(1)).dispose()
    }

    @Test
    fun testBackEventHasRightDisplayId() {
        val secondaryDisplay = createVirtualDisplay() ?: return
        val secondaryDisplayId = secondaryDisplay.display.displayId
        val task = createTask(
            displayId = secondaryDisplayId,
            windowingMode = WINDOWING_MODE_FREEFORM
        )
        val windowDecor = setUpMockDecorationForTask(task)

        onTaskOpening(task)
        val onClickListenerCaptor = argumentCaptor<View.OnClickListener>()
        verify(windowDecor).setCaptionListeners(
            onClickListenerCaptor.capture(), any(), any(), any())

        val onClickListener = onClickListenerCaptor.firstValue
        val view = mock(View::class.java)
        whenever(view.id).thenReturn(R.id.back_button)

        val inputManager = mock(InputManager::class.java)
        mContext.addMockSystemService(InputManager::class.java, inputManager)

        val freeformTaskTransitionStarter = mock(FreeformTaskTransitionStarter::class.java)
        desktopModeWindowDecorViewModel
                .setFreeformTaskTransitionStarter(freeformTaskTransitionStarter)

        onClickListener.onClick(view)

        val eventCaptor = argumentCaptor<KeyEvent>()
        verify(inputManager, times(2)).injectInputEvent(eventCaptor.capture(), anyInt())

        assertEquals(secondaryDisplayId, eventCaptor.firstValue.displayId)
        assertEquals(secondaryDisplayId, eventCaptor.secondValue.displayId)
    }

    @Test
    fun testCaptionIsNotCreatedWhenKeyguardIsVisible() {
        val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)