diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index b2131e72be56d..056ead2108f1f 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -25,9 +25,12 @@ import android.provider.DeviceConfig; import android.util.DisplayMetrics; import android.view.MotionEvent; +import androidx.annotation.NonNull; + import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.Dependency; +import com.android.systemui.DumpController; +import com.android.systemui.Dumpable; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.classifier.brightline.FalsingDataProvider; import com.android.systemui.dagger.qualifiers.Main; @@ -40,6 +43,7 @@ import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.sensors.ProximitySensor; +import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.concurrent.Executor; @@ -52,7 +56,7 @@ import javax.inject.Singleton; * {@link FalsingManagerImpl} is used when a Plugin is not loaded. */ @Singleton -public class FalsingManagerProxy implements FalsingManager { +public class FalsingManagerProxy implements FalsingManager, Dumpable { private static final String PROXIMITY_SENSOR_TAG = "FalsingManager"; @@ -63,16 +67,20 @@ public class FalsingManagerProxy implements FalsingManager { private final DeviceConfigProxy mDeviceConfig; private boolean mBrightlineEnabled; private final DockManager mDockManager; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private Executor mUiBgExecutor; @Inject FalsingManagerProxy(Context context, PluginManager pluginManager, @Main Executor executor, DisplayMetrics displayMetrics, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfig, DockManager dockManager, + KeyguardUpdateMonitor keyguardUpdateMonitor, + DumpController dumpController, @UiBackground Executor uiBgExecutor) { mDisplayMetrics = displayMetrics; mProximitySensor = proximitySensor; mDockManager = dockManager; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; mUiBgExecutor = uiBgExecutor; mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME); @@ -101,6 +109,8 @@ public class FalsingManagerProxy implements FalsingManager { }; pluginManager.addPluginListener(mPluginListener, FalsingPlugin.class); + + dumpController.registerDumpable("FalsingManager", this); } private void onDeviceConfigPropertiesChanged(Context context, String namespace) { @@ -130,7 +140,7 @@ public class FalsingManagerProxy implements FalsingManager { } else { mInternalFalsingManager = new BrightLineFalsingManager( new FalsingDataProvider(mDisplayMetrics), - Dependency.get(KeyguardUpdateMonitor.class), + mKeyguardUpdateMonitor, mProximitySensor, mDeviceConfig, mDockManager @@ -321,6 +331,11 @@ public class FalsingManagerProxy implements FalsingManager { mInternalFalsingManager.onTouchEvent(ev, width, height); } + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + mInternalFalsingManager.dump(pw); + } + @Override public void dump(PrintWriter pw) { mInternalFalsingManager.dump(pw); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index b2e61a2564d32..992a4cc7ca6ad 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -21,6 +21,7 @@ import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS import android.hardware.biometrics.BiometricSourceType; import android.net.Uri; +import android.os.Build; import android.util.Log; import android.view.MotionEvent; @@ -40,15 +41,19 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Queue; +import java.util.StringJoiner; +import java.util.stream.Collectors; /** * FalsingManager designed to make clear why a touch was rejected. */ public class BrightLineFalsingManager implements FalsingManager { - static final boolean DEBUG = false; private static final String TAG = "FalsingManager"; - private static final int RECENT_INFO_LOG_SIZE = 20; + static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private static final int RECENT_INFO_LOG_SIZE = 40; + private static final int RECENT_SWIPE_LOG_SIZE = 20; private final FalsingDataProvider mDataProvider; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -62,6 +67,8 @@ public class BrightLineFalsingManager implements FalsingManager { private boolean mJustUnlockedWithFace; private static final Queue RECENT_INFO_LOG = new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1); + private static final Queue RECENT_SWIPES = + new ArrayDeque<>(RECENT_SWIPE_LOG_SIZE + 1); private final List mClassifiers; @@ -78,6 +85,7 @@ public class BrightLineFalsingManager implements FalsingManager { } } }; + private boolean mPreviousResult = false; public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider, KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor, @@ -148,7 +156,11 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseTouch() { - boolean r = !mJustUnlockedWithFace && !mDockManager.isDocked() + if (!mDataProvider.isDirty()) { + return mPreviousResult; + } + + mPreviousResult = !mJustUnlockedWithFace && !mDockManager.isDocked() && mClassifiers.stream().anyMatch(falsingClassifier -> { boolean result = falsingClassifier.isFalseTouch(); if (result) { @@ -167,9 +179,26 @@ public class BrightLineFalsingManager implements FalsingManager { return result; }); - logDebug("Is false touch? " + r); + logDebug("Is false touch? " + mPreviousResult); - return r; + if (Build.IS_ENG || Build.IS_USERDEBUG) { + // Copy motion events, as the passed in list gets emptied out elsewhere in the code. + RECENT_SWIPES.add(new DebugSwipeRecord( + mPreviousResult, + mDataProvider.getInteractionType(), + mDataProvider.getRecentMotionEvents().stream().map( + motionEvent -> new XYDt( + (int) motionEvent.getX(), + (int) motionEvent.getY(), + (int) (motionEvent.getEventTime() - motionEvent.getDownTime()))) + .collect(Collectors.toList()))); + while (RECENT_SWIPES.size() > RECENT_INFO_LOG_SIZE) { + DebugSwipeRecord record = RECENT_SWIPES.remove(); + } + + } + + return mPreviousResult; } @Override @@ -212,7 +241,6 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onNotificatonStartDraggingDown() { updateInteractionType(Classifier.NOTIFICATION_DRAG_DOWN); - } @Override @@ -348,15 +376,35 @@ public class BrightLineFalsingManager implements FalsingManager { public void dump(PrintWriter pw) { IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); ipw.println("BRIGHTLINE FALSING MANAGER"); - ipw.print("classifierEnabled="); pw.println(isClassifierEnabled() ? 1 : 0); - ipw.print("mJustUnlockedWithFace="); pw.println(mJustUnlockedWithFace ? 1 : 0); - ipw.print("isDocked="); pw.println(mDockManager.isDocked() ? 1 : 0); + ipw.print("classifierEnabled="); + ipw.println(isClassifierEnabled() ? 1 : 0); + ipw.print("mJustUnlockedWithFace="); + ipw.println(mJustUnlockedWithFace ? 1 : 0); + ipw.print("isDocked="); + ipw.println(mDockManager.isDocked() ? 1 : 0); + ipw.print("width="); + ipw.println(mDataProvider.getWidthPixels()); + ipw.print("height="); + ipw.println(mDataProvider.getHeightPixels()); + ipw.println(); + if (RECENT_SWIPES.size() != 0) { + ipw.println("Recent swipes:"); + ipw.increaseIndent(); + for (DebugSwipeRecord record : RECENT_SWIPES) { + ipw.println(record.getString()); + ipw.println(); + } + ipw.decreaseIndent(); + } else { + ipw.println("No recent swipes"); + } ipw.println(); ipw.println("Recent falsing info:"); ipw.increaseIndent(); for (String msg : RECENT_INFO_LOG) { ipw.println(msg); } + ipw.println(); } @Override @@ -386,4 +434,46 @@ public class BrightLineFalsingManager implements FalsingManager { static void logError(String msg) { Log.e(TAG, msg); } + + private static class DebugSwipeRecord { + private static final byte VERSION = 1; // opaque version number indicating format of data. + private final boolean mIsFalse; + private final int mInteractionType; + private final List mRecentMotionEvents; + + DebugSwipeRecord(boolean isFalse, int interactionType, + List recentMotionEvents) { + mIsFalse = isFalse; + mInteractionType = interactionType; + mRecentMotionEvents = recentMotionEvents; + } + + String getString() { + StringJoiner sj = new StringJoiner(","); + sj.add(Integer.toString(VERSION)) + .add(mIsFalse ? "1" : "0") + .add(Integer.toString(mInteractionType)); + for (XYDt event : mRecentMotionEvents) { + sj.add(event.toString()); + } + return sj.toString(); + } + } + + private static class XYDt { + private final int mX; + private final int mY; + private final int mDT; + + XYDt(int x, int y, int dT) { + mX = x; + mY = y; + mDT = dT; + } + + @Override + public String toString() { + return mX + "," + mY + "," + mDT; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java index 8b11ceb34ea09..5494c644c22cf 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java @@ -113,6 +113,10 @@ public class FalsingDataProvider { this.mInteractionType = interactionType; } + public boolean isDirty() { + return mDirty; + } + final int getInteractionType() { return mInteractionType; } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 0ec739fecaa72..5810eae72663e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -28,6 +28,7 @@ import android.os.ServiceManager; import android.util.DisplayMetrics; import android.view.IWindowManager; import android.view.LayoutInflater; +import android.view.WindowManager; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.NotificationMessagingUtil; @@ -98,10 +99,10 @@ public class DependencyProvider { @Singleton @Provides - // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used - // anywhere it is needed. - public DisplayMetrics provideDisplayMetrics() { - return new DisplayMetrics(); + public DisplayMetrics provideDisplayMetrics(Context context, WindowManager windowManager) { + DisplayMetrics displayMetrics = new DisplayMetrics(); + context.getDisplay().getMetrics(displayMetrics); + return displayMetrics; } /** */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java index 25efd320e5540..7fb711f2af501 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java @@ -28,6 +28,7 @@ import android.util.DisplayMetrics; import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.dock.DockManager; @@ -53,6 +54,8 @@ public class FalsingManagerProxyTest extends SysuiTestCase { PluginManager mPluginManager; @Mock(stubOnly = true) ProximitySensor mProximitySensor; + @Mock(stubOnly = true) + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private FalsingManagerProxy mProxy; private DeviceConfigProxy mDeviceConfig; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @@ -63,7 +66,6 @@ public class FalsingManagerProxyTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - mDependency.injectMockDependency(KeyguardUpdateMonitor.class); mDeviceConfig = new DeviceConfigProxyFake(); mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false); @@ -79,7 +81,8 @@ public class FalsingManagerProxyTest extends SysuiTestCase { @Test public void test_brightLineFalsingManagerDisabled() { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, - mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor); + mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, + new DumpController(), mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); } @@ -89,14 +92,16 @@ public class FalsingManagerProxyTest extends SysuiTestCase { BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false); mExecutor.runAllReady(); mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, - mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor); + mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, + new DumpController(), mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); } @Test public void test_brightLineFalsingManagerToggled() throws InterruptedException { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, - mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor); + mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, + new DumpController(), mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,