Reset the features in A11yInputFilter per display

The A11yInputFilter is an input filter for implementing many
accessibility features on multi-display. When any display is
added or removed, all features of all displays would be reset
now.

To avoid server side bad user experience, we should only reset
the features and the event stream state based on the changed
display which is added or removed.

Bug: 187996964
Test: a11y CTS & unit tests
Change-Id: I39ae59e12690240adbb0e81338dcb4c736a92197
This commit is contained in:
Jacky Kao
2021-06-10 09:23:20 +08:00
parent 1c61b6dcfc
commit e6014fc060
3 changed files with 315 additions and 129 deletions

View File

@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY
import android.accessibilityservice.AccessibilityTrace; import android.accessibilityservice.AccessibilityTrace;
import android.annotation.MainThread; import android.annotation.MainThread;
import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.graphics.Region; import android.graphics.Region;
import android.os.PowerManager; import android.os.PowerManager;
@@ -44,7 +45,10 @@ import com.android.server.accessibility.magnification.WindowMagnificationGesture
import com.android.server.accessibility.magnification.WindowMagnificationPromptController; import com.android.server.accessibility.magnification.WindowMagnificationPromptController;
import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.StringJoiner;
/** /**
* This class is an input filter for implementing accessibility features such * This class is an input filter for implementing accessibility features such
@@ -172,9 +176,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
private int mEnabledFeatures; private int mEnabledFeatures;
private EventStreamState mMouseStreamState; private final SparseArray<EventStreamState> mMouseStreamStates = new SparseArray<>(0);
private EventStreamState mTouchScreenStreamState; private final SparseArray<EventStreamState> mTouchScreenStreamStates = new SparseArray<>(0);
private EventStreamState mKeyboardStreamState; private EventStreamState mKeyboardStreamState;
@@ -212,10 +216,17 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
super.onUninstalled(); super.onUninstalled();
} }
void onDisplayChanged() { void onDisplayAdded(@NonNull Display display) {
if (mInstalled) { if (mInstalled) {
disableFeatures(); resetStreamStateForDisplay(display.getDisplayId());
enableFeatures(); enableFeaturesForDisplay(display);
}
}
void onDisplayRemoved(int displayId) {
if (mInstalled) {
disableFeaturesForDisplay(displayId);
resetStreamStateForDisplay(displayId);
} }
} }
@@ -243,16 +254,17 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
return; return;
} }
int eventSource = event.getSource(); final int eventSource = event.getSource();
final int displayId = event.getDisplayId();
if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) { if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
state.reset(); state.reset();
clearEventsForAllEventHandlers(eventSource); clearEventStreamHandler(displayId, eventSource);
super.onInputEvent(event, policyFlags); super.onInputEvent(event, policyFlags);
return; return;
} }
if (state.updateInputSource(event.getSource())) { if (state.updateInputSource(event.getSource())) {
clearEventsForAllEventHandlers(eventSource); clearEventStreamHandler(displayId, eventSource);
} }
if (!state.inputSourceValid()) { if (!state.inputSourceValid()) {
@@ -281,35 +293,39 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
*/ */
private EventStreamState getEventStreamState(InputEvent event) { private EventStreamState getEventStreamState(InputEvent event) {
if (event instanceof MotionEvent) { if (event instanceof MotionEvent) {
if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { final int displayId = event.getDisplayId();
if (mTouchScreenStreamState == null) {
mTouchScreenStreamState = new TouchScreenEventStreamState(); if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
} EventStreamState touchScreenStreamState = mTouchScreenStreamStates.get(displayId);
return mTouchScreenStreamState; if (touchScreenStreamState == null) {
} touchScreenStreamState = new TouchScreenEventStreamState();
if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { mTouchScreenStreamStates.put(displayId, touchScreenStreamState);
if (mMouseStreamState == null) { }
mMouseStreamState = new MouseEventStreamState(); return touchScreenStreamState;
} }
return mMouseStreamState; if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
} EventStreamState mouseStreamState = mMouseStreamStates.get(displayId);
if (mouseStreamState == null) {
mouseStreamState = new MouseEventStreamState();
mMouseStreamStates.put(displayId, mouseStreamState);
}
return mouseStreamState;
}
} else if (event instanceof KeyEvent) { } else if (event instanceof KeyEvent) {
if (event.isFromSource(InputDevice.SOURCE_KEYBOARD)) { if (event.isFromSource(InputDevice.SOURCE_KEYBOARD)) {
if (mKeyboardStreamState == null) { if (mKeyboardStreamState == null) {
mKeyboardStreamState = new KeyboardEventStreamState(); mKeyboardStreamState = new KeyboardEventStreamState();
} }
return mKeyboardStreamState; return mKeyboardStreamState;
} }
} }
return null; return null;
} }
private void clearEventsForAllEventHandlers(int eventSource) { private void clearEventStreamHandler(int displayId, int eventSource) {
for (int i = 0; i < mEventHandler.size(); i++) { final EventStreamTransformation eventHandler = mEventHandler.get(displayId);
final EventStreamTransformation eventHandler = mEventHandler.valueAt(i); if (eventHandler != null) {
if (eventHandler != null) { eventHandler.clearEvents(eventSource);
eventHandler.clearEvents(eventSource);
}
} }
} }
@@ -425,56 +441,69 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
private void enableFeatures() { private void enableFeatures() {
if (DEBUG) Slog.i(TAG, "enableFeatures()"); if (DEBUG) Slog.i(TAG, "enableFeatures()");
resetStreamState(); resetAllStreamState();
final ArrayList<Display> displaysList = mAms.getValidDisplayList(); final ArrayList<Display> displaysList = mAms.getValidDisplayList();
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
mAutoclickController = new AutoclickController(
mContext, mUserId, mAms.getTraceManager());
addFirstEventHandlerForAllDisplays(displaysList, mAutoclickController);
}
for (int i = displaysList.size() - 1; i >= 0; i--) { for (int i = displaysList.size() - 1; i >= 0; i--) {
final int displayId = displaysList.get(i).getDisplayId(); enableFeaturesForDisplay(displaysList.get(i));
final Context displayContext = mContext.createDisplayContext(displaysList.get(i)); }
enableDisplayIndependentFeatures();
}
if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) { private void enableFeaturesForDisplay(Display display) {
TouchExplorer explorer = new TouchExplorer(displayContext, mAms); if (DEBUG) {
if ((mEnabledFeatures & FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0) { Slog.i(TAG, "enableFeaturesForDisplay() : display Id = " + display.getDisplayId());
explorer.setServiceHandlesDoubleTap(true);
}
if ((mEnabledFeatures & FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0) {
explorer.setMultiFingerGesturesEnabled(true);
}
if ((mEnabledFeatures & FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0) {
explorer.setTwoFingerPassthroughEnabled(true);
}
if ((mEnabledFeatures & FLAG_SEND_MOTION_EVENTS) != 0) {
explorer.setSendMotionEventsEnabled(true);
}
addFirstEventHandler(displayId, explorer);
mTouchExplorer.put(displayId, explorer);
}
if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
|| ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0)
|| ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0)) {
final MagnificationGestureHandler magnificationGestureHandler =
createMagnificationGestureHandler(displayId,
displayContext);
addFirstEventHandler(displayId, magnificationGestureHandler);
mMagnificationGestureHandler.put(displayId, magnificationGestureHandler);
}
if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
MotionEventInjector injector = new MotionEventInjector(
mContext.getMainLooper(), mAms.getTraceManager());
addFirstEventHandler(displayId, injector);
mMotionEventInjectors.put(displayId, injector);
}
} }
final Context displayContext = mContext.createDisplayContext(display);
final int displayId = display.getDisplayId();
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
if (mAutoclickController == null) {
mAutoclickController = new AutoclickController(
mContext, mUserId, mAms.getTraceManager());
}
addFirstEventHandler(displayId, mAutoclickController);
}
if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
TouchExplorer explorer = new TouchExplorer(displayContext, mAms);
if ((mEnabledFeatures & FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0) {
explorer.setServiceHandlesDoubleTap(true);
}
if ((mEnabledFeatures & FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0) {
explorer.setMultiFingerGesturesEnabled(true);
}
if ((mEnabledFeatures & FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0) {
explorer.setTwoFingerPassthroughEnabled(true);
}
if ((mEnabledFeatures & FLAG_SEND_MOTION_EVENTS) != 0) {
explorer.setSendMotionEventsEnabled(true);
}
addFirstEventHandler(displayId, explorer);
mTouchExplorer.put(displayId, explorer);
}
if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
|| ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0)
|| ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0)) {
final MagnificationGestureHandler magnificationGestureHandler =
createMagnificationGestureHandler(displayId,
displayContext);
addFirstEventHandler(displayId, magnificationGestureHandler);
mMagnificationGestureHandler.put(displayId, magnificationGestureHandler);
}
if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
MotionEventInjector injector = new MotionEventInjector(
mContext.getMainLooper(), mAms.getTraceManager());
addFirstEventHandler(displayId, injector);
mMotionEventInjectors.put(displayId, injector);
}
}
private void enableDisplayIndependentFeatures() {
if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) { if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
mAms.setMotionEventInjectors(mMotionEventInjectors); mAms.setMotionEventInjectors(mMotionEventInjectors);
} }
@@ -507,55 +536,57 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
mEventHandler.put(displayId, eventHandler); mEventHandler.put(displayId, eventHandler);
} }
/** private void disableFeatures() {
* Adds an event handler to the event handler chain for all displays. The handler is added at final ArrayList<Display> displaysList = mAms.getValidDisplayList();
* the beginning of the chain.
* for (int i = displaysList.size() - 1; i >= 0; i--) {
* @param displayList The list of displays disableFeaturesForDisplay(displaysList.get(i).getDisplayId());
* @param handler The handler to be added to the event handlers list. }
*/ mAms.setMotionEventInjectors(null);
private void addFirstEventHandlerForAllDisplays(ArrayList<Display> displayList, disableDisplayIndependentFeatures();
EventStreamTransformation handler) {
for (int i = 0; i < displayList.size(); i++) { resetAllStreamState();
final int displayId = displayList.get(i).getDisplayId(); }
addFirstEventHandler(displayId, handler);
private void disableFeaturesForDisplay(int displayId) {
if (DEBUG) {
Slog.i(TAG, "disableFeaturesForDisplay() : display Id = " + displayId);
}
final MotionEventInjector injector = mMotionEventInjectors.get(displayId);
if (injector != null) {
injector.onDestroy();
mMotionEventInjectors.remove(displayId);
}
final TouchExplorer explorer = mTouchExplorer.get(displayId);
if (explorer != null) {
explorer.onDestroy();
mTouchExplorer.remove(displayId);
}
final MagnificationGestureHandler handler = mMagnificationGestureHandler.get(displayId);
if (handler != null) {
handler.onDestroy();
mMagnificationGestureHandler.remove(displayId);
}
final EventStreamTransformation eventStreamTransformation = mEventHandler.get(displayId);
if (eventStreamTransformation != null) {
mEventHandler.remove(displayId);
} }
} }
private void disableFeatures() { private void disableDisplayIndependentFeatures() {
for (int i = mMotionEventInjectors.size() - 1; i >= 0; i--) {
final MotionEventInjector injector = mMotionEventInjectors.valueAt(i);
if (injector != null) {
injector.onDestroy();
}
}
mAms.setMotionEventInjectors(null);
mMotionEventInjectors.clear();
if (mAutoclickController != null) { if (mAutoclickController != null) {
mAutoclickController.onDestroy(); mAutoclickController.onDestroy();
mAutoclickController = null; mAutoclickController = null;
} }
for (int i = mTouchExplorer.size() - 1; i >= 0; i--) {
final TouchExplorer explorer = mTouchExplorer.valueAt(i);
if (explorer != null) {
explorer.onDestroy();
}
}
mTouchExplorer.clear();
for (int i = mMagnificationGestureHandler.size() - 1; i >= 0; i--) {
final MagnificationGestureHandler handler = mMagnificationGestureHandler.valueAt(i);
if (handler != null) {
handler.onDestroy();
}
}
mMagnificationGestureHandler.clear();
if (mKeyboardInterceptor != null) { if (mKeyboardInterceptor != null) {
mKeyboardInterceptor.onDestroy(); mKeyboardInterceptor.onDestroy();
mKeyboardInterceptor = null; mKeyboardInterceptor = null;
} }
mEventHandler.clear();
resetStreamState();
} }
private MagnificationGestureHandler createMagnificationGestureHandler( private MagnificationGestureHandler createMagnificationGestureHandler(
@@ -584,18 +615,32 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
return magnificationGestureHandler; return magnificationGestureHandler;
} }
void resetStreamState() { void resetAllStreamState() {
if (mTouchScreenStreamState != null) { final ArrayList<Display> displaysList = mAms.getValidDisplayList();
mTouchScreenStreamState.reset();
} for (int i = displaysList.size() - 1; i >= 0; i--) {
if (mMouseStreamState != null) { resetStreamStateForDisplay(displaysList.get(i).getDisplayId());
mMouseStreamState.reset();
} }
if (mKeyboardStreamState != null) { if (mKeyboardStreamState != null) {
mKeyboardStreamState.reset(); mKeyboardStreamState.reset();
} }
} }
void resetStreamStateForDisplay(int displayId) {
final EventStreamState touchScreenStreamState = mTouchScreenStreamStates.get(displayId);
if (touchScreenStreamState != null) {
touchScreenStreamState.reset();
mTouchScreenStreamStates.remove(displayId);
}
final EventStreamState mouseStreamState = mMouseStreamStates.get(displayId);
if (mouseStreamState != null) {
mouseStreamState.reset();
mMouseStreamStates.remove(displayId);
}
}
@Override @Override
public void onDestroy() { public void onDestroy() {
/* ignore */ /* ignore */
@@ -846,4 +891,45 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
mTouchExplorer.get(displayId).setTouchExplorationPassthroughRegion(region); mTouchExplorer.get(displayId).setTouchExplorationPassthroughRegion(region);
} }
} }
/**
* Dumps all {@link AccessibilityInputFilter}s here.
*/
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (mEventHandler == null) {
return;
}
pw.append("A11yInputFilter Info : ");
pw.println();
final ArrayList<Display> displaysList = mAms.getValidDisplayList();
for (int i = 0; i < displaysList.size(); i++) {
final int displayId = displaysList.get(i).getDisplayId();
EventStreamTransformation next = mEventHandler.get(displayId);
if (next != null) {
pw.append("Enabled features of Display [");
pw.append(Integer.toString(displayId));
pw.append("] = ");
final StringJoiner joiner = new StringJoiner(",", "[", "]");
while (next != null) {
if (next instanceof MagnificationGestureHandler) {
joiner.add("MagnificationGesture");
} else if (next instanceof KeyboardInterceptor) {
joiner.add("KeyboardInterceptor");
} else if (next instanceof TouchExplorer) {
joiner.add("TouchExplorer");
} else if (next instanceof AutoclickController) {
joiner.add("AutoclickController");
} else if (next instanceof MotionEventInjector) {
joiner.add("MotionEventInjector");
}
next = next.getNext();
}
pw.append(joiner.toString());
}
pw.println();
}
}
} }

View File

@@ -3340,6 +3340,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
pw.println(); pw.println();
} }
mA11yWindowManager.dump(fd, pw, args); mA11yWindowManager.dump(fd, pw, args);
if (mHasInputFilter && mInputFilter != null) {
mInputFilter.dump(fd, pw, args);
}
pw.println("Global client list info:{"); pw.println("Global client list info:{");
mGlobalClients.dump(pw, " Client list "); mGlobalClients.dump(pw, " Client list ");
pw.println(" Registered clients:{"); pw.println(" Registered clients:{");
@@ -3587,7 +3590,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
synchronized (mLock) { synchronized (mLock) {
mDisplaysList.add(display); mDisplaysList.add(display);
if (mInputFilter != null) { if (mInputFilter != null) {
mInputFilter.onDisplayChanged(); mInputFilter.onDisplayAdded(display);
} }
AccessibilityUserState userState = getCurrentUserStateLocked(); AccessibilityUserState userState = getCurrentUserStateLocked();
if (displayId != Display.DEFAULT_DISPLAY) { if (displayId != Display.DEFAULT_DISPLAY) {
@@ -3609,7 +3612,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return; return;
} }
if (mInputFilter != null) { if (mInputFilter != null) {
mInputFilter.onDisplayChanged(); mInputFilter.onDisplayRemoved(displayId);
} }
AccessibilityUserState userState = getCurrentUserStateLocked(); AccessibilityUserState userState = getCurrentUserStateLocked();
if (displayId != Display.DEFAULT_DISPLAY) { if (displayId != Display.DEFAULT_DISPLAY) {

View File

@@ -29,6 +29,7 @@ import static com.android.server.accessibility.AccessibilityInputFilter.FLAG_FEA
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -176,7 +177,7 @@ public class AccessibilityInputFilterTest {
} }
@Test @Test
public void testEventHandler_shouldChangeAfterOnDisplayChanged() { public void testEventHandler_shouldIncreaseAndHaveCorrectOrderAfterOnDisplayAdded() {
prepareLooper(); prepareLooper();
// Check if there is only one mEventHandler when there is one default display. // Check if there is only one mEventHandler when there is one default display.
@@ -184,13 +185,51 @@ public class AccessibilityInputFilterTest {
assertEquals(1, mEventHandler.size()); assertEquals(1, mEventHandler.size());
// Check if it has correct numbers of mEventHandler for corresponding displays. // Check if it has correct numbers of mEventHandler for corresponding displays.
setDisplayCount(4); setDisplayCount(2);
mA11yInputFilter.onDisplayChanged(); mA11yInputFilter.onDisplayAdded(mDisplayList.get(SECOND_DISPLAY));
assertEquals(4, mEventHandler.size()); assertEquals(2, mEventHandler.size());
EventStreamTransformation next = mEventHandler.get(SECOND_DISPLAY);
assertNotNull(next);
// Start from index 1 because KeyboardInterceptor only exists in EventHandler for
// DEFAULT_DISPLAY.
for (int i = 1; next != null; i++) {
assertEquals(next.getClass(), mExpectedEventHandlerTypes[i]);
next = next.getNext();
}
}
@Test
public void testEventHandler_shouldDecreaseAfterOnDisplayRemoved() {
prepareLooper();
setDisplayCount(2); setDisplayCount(2);
mA11yInputFilter.onDisplayChanged(); mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
assertEquals(2, mEventHandler.size()); assertEquals(2, mEventHandler.size());
// Check if it has correct numbers of mEventHandler for corresponding displays.
mA11yInputFilter.onDisplayRemoved(SECOND_DISPLAY);
assertEquals(1, mEventHandler.size());
EventStreamTransformation eventHandler = mEventHandler.get(SECOND_DISPLAY);
assertNull(eventHandler);
}
@Test
public void testEventHandler_shouldNoChangedInOtherDisplayAfterOnDisplayRemoved() {
prepareLooper();
setDisplayCount(2);
mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
EventStreamTransformation eventHandlerBeforeDisplayRemoved =
mEventHandler.get(DEFAULT_DISPLAY);
mA11yInputFilter.onDisplayRemoved(SECOND_DISPLAY);
EventStreamTransformation eventHandlerAfterDisplayRemoved =
mEventHandler.get(DEFAULT_DISPLAY);
assertEquals(eventHandlerBeforeDisplayRemoved, eventHandlerAfterDisplayRemoved);
} }
@Test @Test
@@ -240,7 +279,7 @@ public class AccessibilityInputFilterTest {
} }
@Test @Test
public void testInputEvent_shouldClearEventsForAllEventHandlers() { public void testInputEvent_shouldClearEventsForDisplayEventHandlers() {
prepareLooper(); prepareLooper();
mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures); mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
@@ -253,12 +292,70 @@ public class AccessibilityInputFilterTest {
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN)); send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
assertEquals(2, mCaptor1.mEvents.size()); assertEquals(2, mCaptor1.mEvents.size());
// InputEvent with different input source should trigger clearEvents() for each // InputEvent with different input source to the same display should trigger
// EventStreamTransformation in EventHandler. // clearEvents() for the EventHandler in this display.
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_MOUSE)); send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_MOUSE));
assertEquals(1, mCaptor1.mEvents.size()); assertEquals(1, mCaptor1.mEvents.size());
} }
@Test
public void testInputEvent_shouldNotClearEventsForOtherDisplayEventHandlers() {
prepareLooper();
setDisplayCount(2);
mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
assertEquals(2, mEventHandler.size());
mCaptor1 = new EventCaptor();
mCaptor2 = new EventCaptor();
mEventHandler.put(DEFAULT_DISPLAY, mCaptor1);
mEventHandler.put(SECOND_DISPLAY, mCaptor2);
// InputEvent with different displayId should be dispatched to corresponding EventHandler.
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
send(downEvent(SECOND_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
// InputEvent with different input source should not trigger clearEvents() for
// the EventHandler in the other display.
send(downEvent(SECOND_DISPLAY, InputDevice.SOURCE_MOUSE));
assertEquals(2, mCaptor1.mEvents.size());
}
@Test
public void testInputEvent_shouldNotClearEventsForOtherDisplayAfterOnDisplayAdded() {
prepareLooper();
mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
mCaptor1 = new EventCaptor();
mEventHandler.put(DEFAULT_DISPLAY, mCaptor1);
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
assertEquals(2, mCaptor1.mEvents.size());
setDisplayCount(2);
mA11yInputFilter.onDisplayAdded(mDisplayList.get(SECOND_DISPLAY));
assertEquals(2, mCaptor1.mEvents.size());
}
@Test
public void testInputEvent_shouldNotClearEventsForOtherDisplayAfterOnDisplayRemoved() {
prepareLooper();
setDisplayCount(2);
mA11yInputFilter.setUserAndEnabledFeatures(0, mFeatures);
mCaptor1 = new EventCaptor();
mEventHandler.put(DEFAULT_DISPLAY, mCaptor1);
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
send(downEvent(DEFAULT_DISPLAY, InputDevice.SOURCE_TOUCHSCREEN));
assertEquals(2, mCaptor1.mEvents.size());
mA11yInputFilter.onDisplayRemoved(SECOND_DISPLAY);
assertEquals(2, mCaptor1.mEvents.size());
}
@Test @Test
public void testEnabledFeatures_windowMagnificationMode_expectedMagnificationGestureHandler() { public void testEnabledFeatures_windowMagnificationMode_expectedMagnificationGestureHandler() {
prepareLooper(); prepareLooper();