diff options
13 files changed, 242 insertions, 62 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index 357eca37ba37..d2caefd3b552 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -398,6 +398,7 @@ public class BrightLineFalsingManager implements FalsingManager { || mAccessibilityManager.isTouchExplorationEnabled() || mDataProvider.isA11yAction() || mDataProvider.isFromTrackpad() + || mDataProvider.isFromKeyboard() || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED) && mDataProvider.isUnfolded()); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java index a79a654aedc2..76b228d4726a 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java @@ -16,6 +16,7 @@ package com.android.systemui.classifier; +import android.view.KeyEvent; import android.view.MotionEvent; /** @@ -50,6 +51,14 @@ public interface FalsingCollector { void onBouncerHidden(); /** + * Call this to record a KeyEvent in the {@link com.android.systemui.plugins.FalsingManager}. + * + * This may decide to only collect certain KeyEvents and ignore others. Do not assume all + * KeyEvents are collected. + */ + void onKeyEvent(KeyEvent ev); + + /** * Call this to record a MotionEvent in the {@link com.android.systemui.plugins.FalsingManager}. * * Be sure to call {@link #onMotionEventComplete()} after the rest of SystemUI is done with the diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java index d6b9a119e31c..dcd419512498 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java @@ -16,6 +16,7 @@ package com.android.systemui.classifier; +import android.view.KeyEvent; import android.view.MotionEvent; import javax.inject.Inject; @@ -23,6 +24,8 @@ import javax.inject.Inject; /** */ public class FalsingCollectorFake implements FalsingCollector { + public KeyEvent lastKeyEvent = null; + @Override public void init() { } @@ -70,6 +73,11 @@ public class FalsingCollectorFake implements FalsingCollector { } @Override + public void onKeyEvent(KeyEvent ev) { + lastKeyEvent = ev; + } + + @Override public void onTouchEvent(MotionEvent ev) { } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 4f4f3d0324b3..beaa170943fd 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -21,6 +21,7 @@ import static com.android.systemui.dock.DockManager.DockEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricSourceType; import android.util.Log; +import android.view.KeyEvent; import android.view.MotionEvent; import androidx.annotation.VisibleForTesting; @@ -49,7 +50,10 @@ import com.android.systemui.util.time.SystemClock; import dagger.Lazy; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import javax.inject.Inject; @@ -61,6 +65,14 @@ class FalsingCollectorImpl implements FalsingCollector { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final long GESTURE_PROCESSING_DELAY_MS = 100; + private final Set<Integer> mAcceptedKeycodes = new HashSet<>(Arrays.asList( + KeyEvent.KEYCODE_ENTER, + KeyEvent.KEYCODE_ESCAPE, + KeyEvent.KEYCODE_SHIFT_LEFT, + KeyEvent.KEYCODE_SHIFT_RIGHT, + KeyEvent.KEYCODE_SPACE + )); + private final FalsingDataProvider mFalsingDataProvider; private final FalsingManager mFalsingManager; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -279,6 +291,14 @@ class FalsingCollectorImpl implements FalsingCollector { } @Override + public void onKeyEvent(KeyEvent ev) { + // Only collect if it is an ACTION_UP action and is allow-listed + if (ev.getAction() == KeyEvent.ACTION_UP && mAcceptedKeycodes.contains(ev.getKeyCode())) { + mFalsingDataProvider.onKeyEvent(ev); + } + } + + @Override public void onTouchEvent(MotionEvent ev) { logDebug("REAL: onTouchEvent(" + ev.getActionMasked() + ")"); if (!mKeyguardStateController.isShowing()) { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt index c5d8c795853d..b289fa49d06c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt @@ -16,6 +16,7 @@ package com.android.systemui.classifier +import android.view.KeyEvent import android.view.MotionEvent import com.android.systemui.classifier.FalsingCollectorImpl.logDebug import com.android.systemui.dagger.SysUISingleton @@ -59,6 +60,10 @@ class FalsingCollectorNoOp @Inject constructor() : FalsingCollector { logDebug("NOOP: onBouncerHidden") } + override fun onKeyEvent(ev: KeyEvent) { + logDebug("NOOP: onKeyEvent(${ev.action}") + } + override fun onTouchEvent(ev: MotionEvent) { logDebug("NOOP: onTouchEvent(${ev.actionMasked})") } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 809d5b289cab..15017011134b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -20,6 +20,7 @@ import static com.android.systemui.classifier.FalsingModule.IS_FOLDABLE_DEVICE; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; import android.util.DisplayMetrics; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; @@ -41,6 +42,7 @@ import javax.inject.Named; public class FalsingDataProvider { private static final long MOTION_EVENT_AGE_MS = 1000; + private static final long KEY_EVENT_AGE_MS = 500; private static final long DROP_EVENT_THRESHOLD_MS = 50; private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI); @@ -56,8 +58,10 @@ public class FalsingDataProvider { private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>(); private final List<GestureFinalizedListener> mGestureFinalizedListeners = new ArrayList<>(); - private TimeLimitedMotionEventBuffer mRecentMotionEvents = - new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); + private TimeLimitedInputEventBuffer<MotionEvent> mRecentMotionEvents = + new TimeLimitedInputEventBuffer<>(MOTION_EVENT_AGE_MS); + private final TimeLimitedInputEventBuffer<KeyEvent> mRecentKeyEvents = + new TimeLimitedInputEventBuffer<>(KEY_EVENT_AGE_MS); private List<MotionEvent> mPriorMotionEvents = new ArrayList<>(); private boolean mDirty = true; @@ -89,6 +93,10 @@ public class FalsingDataProvider { FalsingClassifier.logInfo("width, height: " + getWidthPixels() + ", " + getHeightPixels()); } + void onKeyEvent(KeyEvent keyEvent) { + mRecentKeyEvents.add(keyEvent); + } + void onMotionEvent(MotionEvent motionEvent) { List<MotionEvent> motionEvents = unpackMotionEvent(motionEvent); FalsingClassifier.logVerbose("Unpacked into: " + motionEvents.size()); @@ -109,6 +117,10 @@ public class FalsingDataProvider { // previous ACTION_MOVE event and when it happens, it makes some classifiers fail. mDropLastEvent = shouldDropEvent(motionEvent); + if (!motionEvents.isEmpty() && !mRecentKeyEvents.isEmpty()) { + recycleAndClearRecentKeyEvents(); + } + mRecentMotionEvents.addAll(motionEvents); FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); @@ -141,7 +153,7 @@ public class FalsingDataProvider { mRecentMotionEvents.get(mRecentMotionEvents.size() - 1).getEventTime())); mPriorMotionEvents = mRecentMotionEvents; - mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); + mRecentMotionEvents = new TimeLimitedInputEventBuffer<>(MOTION_EVENT_AGE_MS); } mDropLastEvent = false; mA11YAction = false; @@ -261,6 +273,13 @@ public class FalsingDataProvider { return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY(); } + /** + * If it's a specific set of keys as collected from {@link FalsingCollector} + */ + public boolean isFromKeyboard() { + return !mRecentKeyEvents.isEmpty(); + } + public boolean isFromTrackpad() { if (mRecentMotionEvents.isEmpty()) { return false; @@ -318,6 +337,14 @@ public class FalsingDataProvider { } } + private void recycleAndClearRecentKeyEvents() { + for (KeyEvent ev : mRecentKeyEvents) { + ev.recycle(); + } + + mRecentKeyEvents.clear(); + } + private List<MotionEvent> unpackMotionEvent(MotionEvent motionEvent) { List<MotionEvent> motionEvents = new ArrayList<>(); List<PointerProperties> pointerPropertiesList = new ArrayList<>(); @@ -416,6 +443,8 @@ public class FalsingDataProvider { mRecentMotionEvents.clear(); + recycleAndClearRecentKeyEvents(); + mDirty = true; mSessionListeners.forEach(SessionListener::onSessionEnded); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedInputEventBuffer.java index 51aede79b581..7627ad19f650 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedInputEventBuffer.java @@ -16,7 +16,7 @@ package com.android.systemui.classifier; -import android.view.MotionEvent; +import android.view.InputEvent; import java.util.ArrayList; import java.util.Collection; @@ -25,31 +25,31 @@ import java.util.List; import java.util.ListIterator; /** - * Maintains an ordered list of the last N milliseconds of MotionEvents. + * Maintains an ordered list of the last N milliseconds of InputEvents. * * This class is simply a convenience class designed to look like a simple list, but that - * automatically discards old MotionEvents. It functions much like a queue - first in first out - + * automatically discards old InputEvents. It functions much like a queue - first in first out - * but does not have a fixed size like a circular buffer. */ -public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { +public class TimeLimitedInputEventBuffer<T extends InputEvent> implements List<T> { - private final List<MotionEvent> mMotionEvents; + private final List<T> mInputEvents; private final long mMaxAgeMs; - public TimeLimitedMotionEventBuffer(long maxAgeMs) { + public TimeLimitedInputEventBuffer(long maxAgeMs) { super(); mMaxAgeMs = maxAgeMs; - mMotionEvents = new ArrayList<>(); + mInputEvents = new ArrayList<>(); } private void ejectOldEvents() { - if (mMotionEvents.isEmpty()) { + if (mInputEvents.isEmpty()) { return; } - Iterator<MotionEvent> iter = listIterator(); - long mostRecentMs = mMotionEvents.get(mMotionEvents.size() - 1).getEventTime(); + Iterator<T> iter = listIterator(); + long mostRecentMs = mInputEvents.get(mInputEvents.size() - 1).getEventTime(); while (iter.hasNext()) { - MotionEvent ev = iter.next(); + T ev = iter.next(); if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) { iter.remove(); ev.recycle(); @@ -58,140 +58,140 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { } @Override - public void add(int index, MotionEvent element) { + public void add(int index, T element) { throw new UnsupportedOperationException(); } @Override - public MotionEvent remove(int index) { - return mMotionEvents.remove(index); + public T remove(int index) { + return mInputEvents.remove(index); } @Override public int indexOf(Object o) { - return mMotionEvents.indexOf(o); + return mInputEvents.indexOf(o); } @Override public int lastIndexOf(Object o) { - return mMotionEvents.lastIndexOf(o); + return mInputEvents.lastIndexOf(o); } @Override public int size() { - return mMotionEvents.size(); + return mInputEvents.size(); } @Override public boolean isEmpty() { - return mMotionEvents.isEmpty(); + return mInputEvents.isEmpty(); } @Override public boolean contains(Object o) { - return mMotionEvents.contains(o); + return mInputEvents.contains(o); } @Override - public Iterator<MotionEvent> iterator() { - return mMotionEvents.iterator(); + public Iterator<T> iterator() { + return mInputEvents.iterator(); } @Override public Object[] toArray() { - return mMotionEvents.toArray(); + return mInputEvents.toArray(); } @Override - public <T> T[] toArray(T[] a) { - return mMotionEvents.toArray(a); + public <T2> T2[] toArray(T2[] a) { + return mInputEvents.toArray(a); } @Override - public boolean add(MotionEvent element) { - boolean result = mMotionEvents.add(element); + public boolean add(T element) { + boolean result = mInputEvents.add(element); ejectOldEvents(); return result; } @Override public boolean remove(Object o) { - return mMotionEvents.remove(o); + return mInputEvents.remove(o); } @Override public boolean containsAll(Collection<?> c) { - return mMotionEvents.containsAll(c); + return mInputEvents.containsAll(c); } @Override - public boolean addAll(Collection<? extends MotionEvent> collection) { - boolean result = mMotionEvents.addAll(collection); + public boolean addAll(Collection<? extends T> collection) { + boolean result = mInputEvents.addAll(collection); ejectOldEvents(); return result; } @Override - public boolean addAll(int index, Collection<? extends MotionEvent> elements) { + public boolean addAll(int index, Collection<? extends T> elements) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { - return mMotionEvents.removeAll(c); + return mInputEvents.removeAll(c); } @Override public boolean retainAll(Collection<?> c) { - return mMotionEvents.retainAll(c); + return mInputEvents.retainAll(c); } @Override public void clear() { - mMotionEvents.clear(); + mInputEvents.clear(); } @Override public boolean equals(Object o) { - return mMotionEvents.equals(o); + return mInputEvents.equals(o); } @Override public int hashCode() { - return mMotionEvents.hashCode(); + return mInputEvents.hashCode(); } @Override - public MotionEvent get(int index) { - return mMotionEvents.get(index); + public T get(int index) { + return mInputEvents.get(index); } @Override - public MotionEvent set(int index, MotionEvent element) { + public T set(int index, T element) { throw new UnsupportedOperationException(); } @Override - public ListIterator<MotionEvent> listIterator() { + public ListIterator<T> listIterator() { return new Iter(0); } @Override - public ListIterator<MotionEvent> listIterator(int index) { + public ListIterator<T> listIterator(int index) { return new Iter(index); } @Override - public List<MotionEvent> subList(int fromIndex, int toIndex) { - return mMotionEvents.subList(fromIndex, toIndex); + public List<T> subList(int fromIndex, int toIndex) { + return mInputEvents.subList(fromIndex, toIndex); } - class Iter implements ListIterator<MotionEvent> { + class Iter implements ListIterator<T> { - private final ListIterator<MotionEvent> mIterator; + private final ListIterator<T> mIterator; Iter(int index) { - this.mIterator = mMotionEvents.listIterator(index); + this.mIterator = mInputEvents.listIterator(index); } @Override @@ -200,7 +200,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { } @Override - public MotionEvent next() { + public T next() { return mIterator.next(); } @@ -210,7 +210,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { } @Override - public MotionEvent previous() { + public T previous() { return mIterator.previous(); } @@ -230,12 +230,12 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { } @Override - public void set(MotionEvent motionEvent) { + public void set(T inputEvent) { throw new UnsupportedOperationException(); } @Override - public void add(MotionEvent element) { + public void add(T element) { throw new UnsupportedOperationException(); } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java index f9b4e671f373..903af61f2202 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java @@ -81,6 +81,8 @@ public class NotificationShadeWindowView extends WindowRootView { @Override public boolean dispatchKeyEvent(KeyEvent event) { + mInteractionEventHandler.collectKeyEvent(event); + if (mInteractionEventHandler.interceptMediaKey(event)) { return true; } @@ -301,6 +303,11 @@ public class NotificationShadeWindowView extends WindowRootView { boolean dispatchKeyEvent(KeyEvent event); boolean dispatchKeyEventPreIme(KeyEvent event); + + /** + * Collects the KeyEvent without intercepting it + */ + void collectKeyEvent(KeyEvent event); } /** diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 324dfdf32a3f..6ac81d226eee 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -563,6 +563,11 @@ public class NotificationShadeWindowViewController implements Dumpable { public boolean dispatchKeyEvent(KeyEvent event) { return mSysUIKeyEventHandler.dispatchKeyEvent(event); } + + @Override + public void collectKeyEvent(KeyEvent event) { + mFalsingCollector.onKeyEvent(event); + } }); mView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java index 45d20dcd9d11..8e5ddc79976f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.KeyEvent; import android.view.MotionEvent; import androidx.test.filters.SmallTest; @@ -202,6 +203,36 @@ public class FalsingCollectorImplTest extends SysuiTestCase { } @Test + public void testPassThroughEnterKeyEvent() { + KeyEvent enterDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, + 0, 0, 0, 0, 0, 0, 0, ""); + KeyEvent enterUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, + 0, 0, 0, 0, 0, 0, ""); + + mFalsingCollector.onKeyEvent(enterDown); + verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class)); + + mFalsingCollector.onKeyEvent(enterUp); + verify(mFalsingDataProvider, times(1)).onKeyEvent(enterUp); + } + + @Test + public void testAvoidAKeyEvent() { + // Arbitrarily chose the "A" key, as it is not currently allowlisted. If this key is + // allowlisted in the future, please choose another key that will not be collected. + KeyEvent aKeyDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, + 0, 0, 0, 0, 0, 0, 0, ""); + KeyEvent aKeyUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0, + 0, 0, 0, 0, 0, 0, ""); + + mFalsingCollector.onKeyEvent(aKeyDown); + verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class)); + + mFalsingCollector.onKeyEvent(aKeyUp); + verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class)); + } + + @Test public void testPassThroughGesture() { MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java index 0353f87ae9b4..057b0a158cab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; import android.testing.AndroidTestingRunner; import android.util.DisplayMetrics; +import android.view.KeyEvent; import android.view.MotionEvent; import androidx.test.filters.SmallTest; @@ -282,6 +283,22 @@ public class FalsingDataProviderTest extends ClassifierTest { } @Test + public void test_isFromKeyboard_disallowedKey_false() { + KeyEvent eventDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, + 0, 0, 0, 0, 0, 0, ""); + KeyEvent eventUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0, + 0, 0, 0, 0, 0, ""); + + //events have not come in yet + assertThat(mDataProvider.isFromKeyboard()).isFalse(); + + mDataProvider.onKeyEvent(eventDown); + mDataProvider.onKeyEvent(eventUp); + assertThat(mDataProvider.isFromKeyboard()).isTrue(); + mDataProvider.onSessionEnd(); + } + + @Test public void test_IsFromTrackpad() { MotionEvent motionEventOrigin = appendTrackpadDownEvent(0, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedMotionEventBufferTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedInputEventBufferTest.java index 901196f8bbba..ad7afa3c593f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedMotionEventBufferTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedInputEventBufferTest.java @@ -20,6 +20,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import android.testing.AndroidTestingRunner; +import android.view.InputEvent; +import android.view.KeyEvent; import android.view.MotionEvent; import androidx.test.filters.SmallTest; @@ -34,28 +36,28 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) -public class TimeLimitedMotionEventBufferTest extends SysuiTestCase { +public class TimeLimitedInputEventBufferTest extends SysuiTestCase { private static final long MAX_AGE_MS = 100; - private TimeLimitedMotionEventBuffer mBuffer; + private TimeLimitedInputEventBuffer<InputEvent> mBuffer; @Before public void setup() { MockitoAnnotations.initMocks(this); - mBuffer = new TimeLimitedMotionEventBuffer(MAX_AGE_MS); + mBuffer = new TimeLimitedInputEventBuffer<>(MAX_AGE_MS); } @After public void tearDown() { - for (MotionEvent motionEvent : mBuffer) { - motionEvent.recycle(); + for (InputEvent inputEvent : mBuffer) { + inputEvent.recycle(); } mBuffer.clear(); } @Test - public void testAllEventsRetained() { + public void testMotionEventAllEventsRetained() { MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0); MotionEvent eventC = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 0, 0, 0); @@ -70,7 +72,7 @@ public class TimeLimitedMotionEventBufferTest extends SysuiTestCase { } @Test - public void testOlderEventsRemoved() { + public void testMotionEventOlderEventsRemoved() { MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0); MotionEvent eventC = MotionEvent.obtain( @@ -89,4 +91,40 @@ public class TimeLimitedMotionEventBufferTest extends SysuiTestCase { assertThat(mBuffer.get(0), is(eventC)); assertThat(mBuffer.get(1), is(eventD)); } + + @Test + public void testKeyEventAllEventsRetained() { + KeyEvent eventA = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0, + 0, 0, 0, 0, 0, ""); + KeyEvent eventB = KeyEvent.obtain(0, 3, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0, 0, 0, 0, + 0, 0, 0, ""); + + mBuffer.add(eventA); + mBuffer.add(eventB); + + assertThat(mBuffer.size(), is(2)); + } + + @Test + public void testKeyEventOlderEventsRemoved() { + KeyEvent eventA = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0, + 0, 0, 0, 0, 0, ""); + KeyEvent eventB = KeyEvent.obtain(0, 1, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0, 0, 0, 0, + 0, 0, 0, ""); + KeyEvent eventC = KeyEvent.obtain(0, MAX_AGE_MS + 1, MotionEvent.ACTION_DOWN, + KeyEvent.KEYCODE_A, 0, 0, 0, 0, 0, 0, 0, ""); + KeyEvent eventD = KeyEvent.obtain(0, MAX_AGE_MS + 2, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, + 0, 0, 0, 0, 0, 0, 0, ""); + + mBuffer.add(eventA); + mBuffer.add(eventB); + assertThat(mBuffer.size(), is(2)); + + mBuffer.add(eventC); + mBuffer.add(eventD); + assertThat(mBuffer.size(), is(2)); + + assertThat(mBuffer.get(0), is(eventC)); + assertThat(mBuffer.get(1), is(eventD)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index dfbb699ed915..2c0a15dd4e5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -69,7 +69,6 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat -import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.emptyFlow @@ -87,6 +86,8 @@ import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import kotlin.test.assertEquals +import java.util.Optional import org.mockito.Mockito.`when` as whenever @OptIn(ExperimentalCoroutinesApi::class) @@ -138,6 +139,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { private val notificationLaunchAnimationInteractor = NotificationLaunchAnimationInteractor(notificationLaunchAnimationRepository) + private lateinit var falsingCollector: FalsingCollectorFake private lateinit var fakeClock: FakeSystemClock private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler> private lateinit var interactionEventHandler: InteractionEventHandler @@ -170,11 +172,12 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { mSetFlagsRule.enableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES) testScope = TestScope() + falsingCollector = FalsingCollectorFake() fakeClock = FakeSystemClock() underTest = NotificationShadeWindowViewController( lockscreenShadeTransitionController, - FalsingCollectorFake(), + falsingCollector, sysuiStatusBarStateController, dockManager, notificationShadeDepthController, @@ -566,6 +569,13 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { verify(sysUIKeyEventHandler).interceptMediaKey(keyEvent) } + @Test + fun forwardsCollectKeyEvent() { + val keyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A) + interactionEventHandler.collectKeyEvent(keyEvent) + assertEquals(keyEvent, falsingCollector.lastKeyEvent) + } + companion object { private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0) |