Merge "Fix for ANRs due to InputMonitor" into tm-qpr-dev
This commit is contained in:
@@ -75,10 +75,10 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
private FreeformTaskTransitionStarter mTransitionStarter;
|
private FreeformTaskTransitionStarter mTransitionStarter;
|
||||||
private DesktopModeController mDesktopModeController;
|
private DesktopModeController mDesktopModeController;
|
||||||
private EventReceiver mEventReceiver;
|
|
||||||
private InputMonitor mInputMonitor;
|
|
||||||
private boolean mTransitionDragActive;
|
private boolean mTransitionDragActive;
|
||||||
|
|
||||||
|
private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
|
||||||
|
|
||||||
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 EventReceiverFactory mEventReceiverFactory = new EventReceiverFactory();
|
||||||
@@ -150,8 +150,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||||
|
|
||||||
if (decoration == null) return;
|
if (decoration == null) return;
|
||||||
|
|
||||||
|
int oldDisplayId = decoration.mDisplay.getDisplayId();
|
||||||
|
if (taskInfo.displayId != oldDisplayId) {
|
||||||
|
removeTaskFromEventReceiver(oldDisplayId);
|
||||||
|
incrementEventReceiverTasks(taskInfo.displayId);
|
||||||
|
}
|
||||||
|
|
||||||
decoration.relayout(taskInfo);
|
decoration.relayout(taskInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +202,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
if (decoration == null) return;
|
if (decoration == null) return;
|
||||||
|
|
||||||
decoration.close();
|
decoration.close();
|
||||||
|
int displayId = taskInfo.displayId;
|
||||||
|
if (mEventReceiversByDisplay.contains(displayId)) {
|
||||||
|
EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
|
||||||
|
removeTaskFromEventReceiver(displayId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CaptionTouchEventListener implements
|
private class CaptionTouchEventListener implements
|
||||||
@@ -329,8 +341,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
|
|
||||||
// InputEventReceiver to listen for touch input outside of caption bounds
|
// InputEventReceiver to listen for touch input outside of caption bounds
|
||||||
class EventReceiver extends InputEventReceiver {
|
class EventReceiver extends InputEventReceiver {
|
||||||
EventReceiver(InputChannel channel, Looper looper) {
|
private InputMonitor mInputMonitor;
|
||||||
|
private int mTasksOnDisplay;
|
||||||
|
EventReceiver(InputMonitor inputMonitor, InputChannel channel, Looper looper) {
|
||||||
super(channel, looper);
|
super(channel, looper);
|
||||||
|
mInputMonitor = inputMonitor;
|
||||||
|
mTasksOnDisplay = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -338,15 +354,62 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
boolean handled = false;
|
boolean handled = false;
|
||||||
if (event instanceof MotionEvent) {
|
if (event instanceof MotionEvent) {
|
||||||
handled = true;
|
handled = true;
|
||||||
CaptionWindowDecorViewModel.this.handleReceivedMotionEvent((MotionEvent) event);
|
CaptionWindowDecorViewModel.this
|
||||||
|
.handleReceivedMotionEvent((MotionEvent) event, mInputMonitor);
|
||||||
}
|
}
|
||||||
finishInputEvent(event, handled);
|
finishInputEvent(event, handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
if (mInputMonitor != null) {
|
||||||
|
mInputMonitor.dispose();
|
||||||
|
mInputMonitor = null;
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void incrementTaskNumber() {
|
||||||
|
mTasksOnDisplay++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decrementTaskNumber() {
|
||||||
|
mTasksOnDisplay--;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTasksOnDisplay() {
|
||||||
|
return mTasksOnDisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an EventReceiver exists on a particular display.
|
||||||
|
* If it does, increment its task count. Otherwise, create one for that display.
|
||||||
|
* @param displayId the display to check against
|
||||||
|
*/
|
||||||
|
private void incrementEventReceiverTasks(int displayId) {
|
||||||
|
if (mEventReceiversByDisplay.contains(displayId)) {
|
||||||
|
EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
|
||||||
|
eventReceiver.incrementTaskNumber();
|
||||||
|
} else {
|
||||||
|
createInputChannel(displayId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all tasks on this display are gone, we don't need to monitor its input.
|
||||||
|
private void removeTaskFromEventReceiver(int displayId) {
|
||||||
|
if (!mEventReceiversByDisplay.contains(displayId)) return;
|
||||||
|
EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
|
||||||
|
if (eventReceiver == null) return;
|
||||||
|
eventReceiver.decrementTaskNumber();
|
||||||
|
if (eventReceiver.getTasksOnDisplay() == 0) {
|
||||||
|
disposeInputChannel(displayId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventReceiverFactory {
|
class EventReceiverFactory {
|
||||||
EventReceiver create(InputChannel channel, Looper looper) {
|
EventReceiver create(InputMonitor inputMonitor, InputChannel channel, Looper looper) {
|
||||||
return new EventReceiver(channel, looper);
|
return new EventReceiver(inputMonitor, channel, looper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,14 +418,14 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
*
|
*
|
||||||
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
|
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
|
||||||
*/
|
*/
|
||||||
private void handleReceivedMotionEvent(MotionEvent ev) {
|
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
|
||||||
if (!DesktopModeStatus.isActive(mContext)) {
|
if (!DesktopModeStatus.isActive(mContext)) {
|
||||||
handleCaptionThroughStatusBar(ev);
|
handleCaptionThroughStatusBar(ev);
|
||||||
}
|
}
|
||||||
handleEventOutsideFocusedCaption(ev);
|
handleEventOutsideFocusedCaption(ev);
|
||||||
// Prevent status bar from reacting to a caption drag.
|
// Prevent status bar from reacting to a caption drag.
|
||||||
if (mTransitionDragActive && !DesktopModeStatus.isActive(mContext)) {
|
if (mTransitionDragActive && !DesktopModeStatus.isActive(mContext)) {
|
||||||
mInputMonitor.pilferPointers();
|
inputMonitor.pilferPointers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,6 +444,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform caption actions if not able to through normal means.
|
* Perform caption actions if not able to through normal means.
|
||||||
* Turn on desktop mode if handle is dragged below status bar.
|
* Turn on desktop mode if handle is dragged below status bar.
|
||||||
@@ -434,6 +498,22 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
return focusedDecor;
|
return focusedDecor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createInputChannel(int displayId) {
|
||||||
|
InputManager inputManager = mInputManagerSupplier.get();
|
||||||
|
InputMonitor inputMonitor =
|
||||||
|
inputManager.monitorGestureInput("caption-touch", mContext.getDisplayId());
|
||||||
|
EventReceiver eventReceiver = mEventReceiverFactory.create(
|
||||||
|
inputMonitor, inputMonitor.getInputChannel(), Looper.myLooper());
|
||||||
|
mEventReceiversByDisplay.put(displayId, eventReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disposeInputChannel(int displayId) {
|
||||||
|
EventReceiver eventReceiver = mEventReceiversByDisplay.removeReturnOld(displayId);
|
||||||
|
if (eventReceiver != null) {
|
||||||
|
eventReceiver.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
|
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
|
||||||
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
|
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
|
||||||
return DesktopModeStatus.IS_SUPPORTED
|
return DesktopModeStatus.IS_SUPPORTED
|
||||||
@@ -472,14 +552,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||||
windowDecoration.setDragResizeCallback(taskPositioner);
|
windowDecoration.setDragResizeCallback(taskPositioner);
|
||||||
windowDecoration.relayout(taskInfo, startT, finishT);
|
windowDecoration.relayout(taskInfo, startT, finishT);
|
||||||
if (mInputMonitor == null) {
|
incrementEventReceiverTasks(taskInfo.displayId);
|
||||||
InputManager inputManager = mInputManagerSupplier.get();
|
|
||||||
mInputMonitor =
|
|
||||||
inputManager.monitorGestureInput("caption-touch", mContext.getDisplayId());
|
|
||||||
mEventReceiver =
|
|
||||||
mEventReceiverFactory.create(
|
|
||||||
mInputMonitor.getInputChannel(), Looper.myLooper());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DragStartListenerImpl implements TaskPositioner.DragStartListener {
|
private class DragStartListenerImpl implements TaskPositioner.DragStartListener {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
|||||||
.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(mInputManager.monitorGestureInput(any(), anyInt())).thenReturn(mInputMonitor);
|
||||||
when(mEventReceiverFactory.create(any(), any())).thenReturn(mEventReceiver);
|
when(mEventReceiverFactory.create(any(), any(), any())).thenReturn(mEventReceiver);
|
||||||
when(mInputMonitor.getInputChannel()).thenReturn(mInputChannel);
|
when(mInputMonitor.getInputChannel()).thenReturn(mInputChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user