Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d13251a7 authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Capture recent motion events used for falsing.

This spits out the last 20 motion events that the FalsingManager
uses into bug reports. It only records the data in eng/userdebug
builds.

This has been cleared with PWG over VC.

A tool to visualize this data in in progress.

Bug: 148084465
Test: manual
Change-Id: I3edf5dc8693a202ff0e31e737e912500a3e4363d
parent 998c6ad1
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -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);
+99 −9
Original line number Diff line number Diff line
@@ -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<String> RECENT_INFO_LOG =
            new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1);
    private static final Queue<DebugSwipeRecord> RECENT_SWIPES =
            new ArrayDeque<>(RECENT_SWIPE_LOG_SIZE + 1);

    private final List<FalsingClassifier> 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);

        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 r;
        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<XYDt> mRecentMotionEvents;

        DebugSwipeRecord(boolean isFalse, int interactionType,
                List<XYDt> 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;
        }
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -113,6 +113,10 @@ public class FalsingDataProvider {
        this.mInteractionType = interactionType;
    }

    public boolean isDirty() {
        return mDirty;
    }

    final int getInteractionType() {
        return mInteractionType;
    }
+5 −4
Original line number Diff line number Diff line
@@ -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;
    }

    /** */
+9 −4
Original line number Diff line number Diff line
@@ -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,