Merge "Add unit test for EventReceiver class in CaptionWindowDecorViewModel" into tm-qpr-dev
This commit is contained in:
@@ -46,6 +46,7 @@ import android.window.WindowContainerTransaction;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.wm.shell.R;
|
import com.android.wm.shell.R;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.common.DisplayController;
|
import com.android.wm.shell.common.DisplayController;
|
||||||
@@ -56,7 +57,6 @@ import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
|||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View model for the window decoration with a caption and shadows. Works with
|
* View model for the window decoration with a caption and shadows. Works with
|
||||||
@@ -66,7 +66,6 @@ import java.util.function.Supplier;
|
|||||||
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||||
private static final String TAG = "CaptionViewModel";
|
private static final String TAG = "CaptionViewModel";
|
||||||
private final CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
|
private final CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
|
||||||
private final Supplier<InputManager> mInputManagerSupplier;
|
|
||||||
private final ActivityTaskManager mActivityTaskManager;
|
private final ActivityTaskManager mActivityTaskManager;
|
||||||
private final ShellTaskOrganizer mTaskOrganizer;
|
private final ShellTaskOrganizer mTaskOrganizer;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -82,7 +81,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
|
|
||||||
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
||||||
private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
|
private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
|
||||||
private EventReceiverFactory mEventReceiverFactory = new EventReceiverFactory();
|
private InputMonitorFactory mInputMonitorFactory;
|
||||||
|
|
||||||
public CaptionWindowDecorViewModel(
|
public CaptionWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
@@ -101,10 +100,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
syncQueue,
|
syncQueue,
|
||||||
desktopModeController,
|
desktopModeController,
|
||||||
new CaptionWindowDecoration.Factory(),
|
new CaptionWindowDecoration.Factory(),
|
||||||
InputManager::getInstance);
|
new InputMonitorFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CaptionWindowDecorViewModel(
|
@VisibleForTesting
|
||||||
|
CaptionWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
Handler mainHandler,
|
Handler mainHandler,
|
||||||
Choreographer mainChoreographer,
|
Choreographer mainChoreographer,
|
||||||
@@ -113,8 +113,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
SyncTransactionQueue syncQueue,
|
SyncTransactionQueue syncQueue,
|
||||||
Optional<DesktopModeController> desktopModeController,
|
Optional<DesktopModeController> desktopModeController,
|
||||||
CaptionWindowDecoration.Factory captionWindowDecorFactory,
|
CaptionWindowDecoration.Factory captionWindowDecorFactory,
|
||||||
Supplier<InputManager> inputManagerSupplier) {
|
InputMonitorFactory inputMonitorFactory) {
|
||||||
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mMainHandler = mainHandler;
|
mMainHandler = mainHandler;
|
||||||
mMainChoreographer = mainChoreographer;
|
mMainChoreographer = mainChoreographer;
|
||||||
@@ -125,11 +124,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
mDesktopModeController = desktopModeController;
|
mDesktopModeController = desktopModeController;
|
||||||
|
|
||||||
mCaptionWindowDecorFactory = captionWindowDecorFactory;
|
mCaptionWindowDecorFactory = captionWindowDecorFactory;
|
||||||
mInputManagerSupplier = inputManagerSupplier;
|
mInputMonitorFactory = inputMonitorFactory;
|
||||||
}
|
|
||||||
|
|
||||||
void setEventReceiverFactory(EventReceiverFactory eventReceiverFactory) {
|
|
||||||
mEventReceiverFactory = eventReceiverFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -205,7 +200,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
decoration.close();
|
decoration.close();
|
||||||
int displayId = taskInfo.displayId;
|
int displayId = taskInfo.displayId;
|
||||||
if (mEventReceiversByDisplay.contains(displayId)) {
|
if (mEventReceiversByDisplay.contains(displayId)) {
|
||||||
EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
|
|
||||||
removeTaskFromEventReceiver(displayId);
|
removeTaskFromEventReceiver(displayId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,12 +402,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventReceiverFactory {
|
|
||||||
EventReceiver create(InputMonitor inputMonitor, InputChannel channel, Looper looper) {
|
|
||||||
return new EventReceiver(inputMonitor, channel, looper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle MotionEvents relevant to focused task's caption that don't directly touch it
|
* Handle MotionEvents relevant to focused task's caption that don't directly touch it
|
||||||
*
|
*
|
||||||
@@ -500,11 +488,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createInputChannel(int displayId) {
|
private void createInputChannel(int displayId) {
|
||||||
InputManager inputManager = mInputManagerSupplier.get();
|
InputManager inputManager = InputManager.getInstance();
|
||||||
InputMonitor inputMonitor =
|
InputMonitor inputMonitor =
|
||||||
inputManager.monitorGestureInput("caption-touch", mContext.getDisplayId());
|
mInputMonitorFactory.create(inputManager, mContext);
|
||||||
EventReceiver eventReceiver = mEventReceiverFactory.create(
|
EventReceiver eventReceiver = new EventReceiver(inputMonitor,
|
||||||
inputMonitor, inputMonitor.getInputChannel(), Looper.myLooper());
|
inputMonitor.getInputChannel(), Looper.myLooper());
|
||||||
mEventReceiversByDisplay.put(displayId, eventReceiver);
|
mEventReceiversByDisplay.put(displayId, eventReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,4 +550,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
mWindowDecorByTaskId.get(taskId).closeHandleMenu();
|
mWindowDecorByTaskId.get(taskId).closeHandleMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class InputMonitorFactory {
|
||||||
|
InputMonitor create(InputManager inputManager, Context context) {
|
||||||
|
return inputManager.monitorGestureInput("caption-touch", context.getDisplayId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.anyInt;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
|
import android.hardware.display.DisplayManager;
|
||||||
|
import android.hardware.display.VirtualDisplay;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -37,9 +38,9 @@ import android.view.Display;
|
|||||||
import android.view.InputChannel;
|
import android.view.InputChannel;
|
||||||
import android.view.InputMonitor;
|
import android.view.InputMonitor;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.rule.GrantPermissionRule;
|
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.ShellTestCase;
|
import com.android.wm.shell.ShellTestCase;
|
||||||
@@ -55,37 +56,28 @@ import org.mockito.Mock;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/** Tests of {@link CaptionWindowDecorViewModel} */
|
/** Tests of {@link CaptionWindowDecorViewModel} */
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
||||||
@Mock private CaptionWindowDecoration mCaptionWindowDecoration;
|
|
||||||
|
|
||||||
|
private static final String TAG = "CaptionWindowDecorViewModelTests";
|
||||||
|
|
||||||
|
@Mock private CaptionWindowDecoration mCaptionWindowDecoration;
|
||||||
@Mock private CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
|
@Mock private CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
|
||||||
|
|
||||||
@Mock private Handler mMainHandler;
|
@Mock private Handler mMainHandler;
|
||||||
|
|
||||||
@Mock private Choreographer mMainChoreographer;
|
@Mock private Choreographer mMainChoreographer;
|
||||||
|
|
||||||
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
||||||
|
|
||||||
@Mock private DisplayController mDisplayController;
|
@Mock private DisplayController mDisplayController;
|
||||||
|
|
||||||
@Mock private SyncTransactionQueue mSyncQueue;
|
@Mock private SyncTransactionQueue mSyncQueue;
|
||||||
|
|
||||||
@Mock private DesktopModeController mDesktopModeController;
|
@Mock private DesktopModeController mDesktopModeController;
|
||||||
|
|
||||||
@Mock private InputMonitor mInputMonitor;
|
@Mock private InputMonitor mInputMonitor;
|
||||||
|
|
||||||
@Mock private InputChannel mInputChannel;
|
|
||||||
|
|
||||||
@Mock private CaptionWindowDecorViewModel.EventReceiverFactory mEventReceiverFactory;
|
|
||||||
|
|
||||||
@Mock private CaptionWindowDecorViewModel.EventReceiver mEventReceiver;
|
|
||||||
|
|
||||||
@Mock private InputManager mInputManager;
|
@Mock private InputManager mInputManager;
|
||||||
|
|
||||||
|
@Mock private CaptionWindowDecorViewModel.InputMonitorFactory mMockInputMonitorFactory;
|
||||||
private final List<InputManager> mMockInputManagers = new ArrayList<>();
|
private final List<InputManager> mMockInputManagers = new ArrayList<>();
|
||||||
|
|
||||||
private CaptionWindowDecorViewModel mCaptionWindowDecorViewModel;
|
private CaptionWindowDecorViewModel mCaptionWindowDecorViewModel;
|
||||||
@@ -104,30 +96,36 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
|||||||
mSyncQueue,
|
mSyncQueue,
|
||||||
Optional.of(mDesktopModeController),
|
Optional.of(mDesktopModeController),
|
||||||
mCaptionWindowDecorFactory,
|
mCaptionWindowDecorFactory,
|
||||||
new MockObjectSupplier<>(mMockInputManagers, () -> mock(InputManager.class)));
|
mMockInputMonitorFactory
|
||||||
mCaptionWindowDecorViewModel.setEventReceiverFactory(mEventReceiverFactory);
|
);
|
||||||
|
|
||||||
doReturn(mCaptionWindowDecoration)
|
doReturn(mCaptionWindowDecoration)
|
||||||
.when(mCaptionWindowDecorFactory)
|
.when(mCaptionWindowDecorFactory)
|
||||||
.create(any(), any(), any(), any(), any(), any(), any(), any());
|
.create(any(), any(), any(), any(), any(), any(), any(), any());
|
||||||
|
|
||||||
when(mInputManager.monitorGestureInput(any(), anyInt())).thenReturn(mInputMonitor);
|
when(mMockInputMonitorFactory.create(any(), any())).thenReturn(mInputMonitor);
|
||||||
when(mEventReceiverFactory.create(any(), any(), any())).thenReturn(mEventReceiver);
|
// InputChannel cannot be mocked because it passes to InputEventReceiver.
|
||||||
when(mInputMonitor.getInputChannel()).thenReturn(mInputChannel);
|
final InputChannel[] inputChannels = InputChannel.openInputChannelPair(TAG);
|
||||||
|
inputChannels[0].dispose();
|
||||||
|
when(mInputMonitor.getInputChannel()).thenReturn(inputChannels[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteCaptionOnChangeTransitionWhenNecessary() throws Exception {
|
public void testDeleteCaptionOnChangeTransitionWhenNecessary() throws Exception {
|
||||||
Looper.prepare();
|
|
||||||
final int taskId = 1;
|
final int taskId = 1;
|
||||||
final ActivityManager.RunningTaskInfo taskInfo =
|
final ActivityManager.RunningTaskInfo taskInfo =
|
||||||
createTaskInfo(taskId, WINDOWING_MODE_FREEFORM);
|
createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM);
|
||||||
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
||||||
|
runOnMainThread(() -> {
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
||||||
GrantPermissionRule.grant(android.Manifest.permission.MONITOR_INPUT);
|
|
||||||
|
|
||||||
mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT);
|
mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
|
||||||
|
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
|
||||||
|
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
|
||||||
|
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
});
|
||||||
verify(mCaptionWindowDecorFactory)
|
verify(mCaptionWindowDecorFactory)
|
||||||
.create(
|
.create(
|
||||||
mContext,
|
mContext,
|
||||||
@@ -138,10 +136,6 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
|||||||
mMainHandler,
|
mMainHandler,
|
||||||
mMainChoreographer,
|
mMainChoreographer,
|
||||||
mSyncQueue);
|
mSyncQueue);
|
||||||
|
|
||||||
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
|
|
||||||
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
|
|
||||||
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
|
||||||
verify(mCaptionWindowDecoration).close();
|
verify(mCaptionWindowDecoration).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,31 +143,21 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
|||||||
public void testCreateCaptionOnChangeTransitionWhenNecessary() throws Exception {
|
public void testCreateCaptionOnChangeTransitionWhenNecessary() throws Exception {
|
||||||
final int taskId = 1;
|
final int taskId = 1;
|
||||||
final ActivityManager.RunningTaskInfo taskInfo =
|
final ActivityManager.RunningTaskInfo taskInfo =
|
||||||
createTaskInfo(taskId, WINDOWING_MODE_UNDEFINED);
|
createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_UNDEFINED);
|
||||||
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
||||||
|
runOnMainThread(() -> {
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
||||||
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
|
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
|
||||||
|
|
||||||
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
|
||||||
verify(mCaptionWindowDecorFactory, never())
|
|
||||||
.create(
|
|
||||||
mContext,
|
|
||||||
mDisplayController,
|
|
||||||
mTaskOrganizer,
|
|
||||||
taskInfo,
|
|
||||||
surfaceControl,
|
|
||||||
mMainHandler,
|
|
||||||
mMainChoreographer,
|
|
||||||
mSyncQueue);
|
|
||||||
|
|
||||||
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
|
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
|
||||||
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
|
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
|
||||||
|
|
||||||
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
});
|
||||||
verify(mCaptionWindowDecorFactory)
|
verify(mCaptionWindowDecorFactory, times(1))
|
||||||
.create(
|
.create(
|
||||||
mContext,
|
mContext,
|
||||||
mDisplayController,
|
mDisplayController,
|
||||||
@@ -185,34 +169,79 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
|||||||
mSyncQueue);
|
mSyncQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
|
@Test
|
||||||
|
public void testCreateAndDisposeEventReceiver() throws Exception {
|
||||||
|
final int taskId = 1;
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo =
|
||||||
|
createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM);
|
||||||
|
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
|
||||||
|
runOnMainThread(() -> {
|
||||||
|
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
|
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
||||||
|
|
||||||
|
mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
|
||||||
|
mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo);
|
||||||
|
});
|
||||||
|
verify(mMockInputMonitorFactory).create(any(), any());
|
||||||
|
verify(mInputMonitor).dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEventReceiversOnMultipleDisplays() throws Exception {
|
||||||
|
runOnMainThread(() -> {
|
||||||
|
SurfaceView surfaceView = new SurfaceView(mContext);
|
||||||
|
final DisplayManager mDm = mContext.getSystemService(DisplayManager.class);
|
||||||
|
final VirtualDisplay secondaryDisplay = mDm.createVirtualDisplay(
|
||||||
|
"testEventReceiversOnMultipleDisplays", /*width=*/ 400, /*height=*/ 400,
|
||||||
|
/*densityDpi=*/ 320, surfaceView.getHolder().getSurface(),
|
||||||
|
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
|
||||||
|
int secondaryDisplayId = secondaryDisplay.getDisplay().getDisplayId();
|
||||||
|
|
||||||
|
final int taskId = 1;
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo =
|
||||||
|
createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM);
|
||||||
|
final ActivityManager.RunningTaskInfo secondTaskInfo =
|
||||||
|
createTaskInfo(taskId + 1, secondaryDisplayId, WINDOWING_MODE_FREEFORM);
|
||||||
|
final ActivityManager.RunningTaskInfo thirdTaskInfo =
|
||||||
|
createTaskInfo(taskId + 2, secondaryDisplayId, WINDOWING_MODE_FREEFORM);
|
||||||
|
|
||||||
|
SurfaceControl surfaceControl = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
|
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
||||||
|
|
||||||
|
mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT);
|
||||||
|
mCaptionWindowDecorViewModel.onTaskOpening(secondTaskInfo, surfaceControl,
|
||||||
|
startT, finishT);
|
||||||
|
mCaptionWindowDecorViewModel.onTaskOpening(thirdTaskInfo, surfaceControl,
|
||||||
|
startT, finishT);
|
||||||
|
mCaptionWindowDecorViewModel.destroyWindowDecoration(thirdTaskInfo);
|
||||||
|
mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo);
|
||||||
|
});
|
||||||
|
verify(mMockInputMonitorFactory, times(2)).create(any(), any());
|
||||||
|
verify(mInputMonitor, times(1)).dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runOnMainThread(Runnable r) throws Exception {
|
||||||
|
final Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
mainHandler.post(() -> {
|
||||||
|
r.run();
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
latch.await(20, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId,
|
||||||
|
int displayId, int windowingMode) {
|
||||||
ActivityManager.RunningTaskInfo taskInfo =
|
ActivityManager.RunningTaskInfo taskInfo =
|
||||||
new TestRunningTaskInfoBuilder()
|
new TestRunningTaskInfoBuilder()
|
||||||
.setDisplayId(Display.DEFAULT_DISPLAY)
|
.setDisplayId(displayId)
|
||||||
.setVisible(true)
|
.setVisible(true)
|
||||||
.build();
|
.build();
|
||||||
taskInfo.taskId = taskId;
|
taskInfo.taskId = taskId;
|
||||||
taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
|
taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
|
||||||
return taskInfo;
|
return taskInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MockObjectSupplier<T> implements Supplier<T> {
|
|
||||||
private final List<T> mObjects;
|
|
||||||
private final Supplier<T> mDefaultSupplier;
|
|
||||||
private int mNumOfCalls = 0;
|
|
||||||
|
|
||||||
private MockObjectSupplier(List<T> objects, Supplier<T> defaultSupplier) {
|
|
||||||
mObjects = objects;
|
|
||||||
mDefaultSupplier = defaultSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T get() {
|
|
||||||
final T mock =
|
|
||||||
mNumOfCalls < mObjects.size() ? mObjects.get(mNumOfCalls)
|
|
||||||
: mDefaultSupplier.get();
|
|
||||||
++mNumOfCalls;
|
|
||||||
return mock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user