Merge "Add falsing protection to the pulsing state" into tm-qpr-dev
This commit is contained in:
@@ -102,6 +102,12 @@ public interface FalsingManager {
|
|||||||
*/
|
*/
|
||||||
boolean isFalseDoubleTap();
|
boolean isFalseDoubleTap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the last proximity event reported NEAR. May be used to short circuit motion events
|
||||||
|
* that require the proximity sensor is not covered.
|
||||||
|
*/
|
||||||
|
boolean isProximityNear();
|
||||||
|
|
||||||
boolean isClassifierEnabled();
|
boolean isClassifierEnabled();
|
||||||
|
|
||||||
boolean shouldEnforceBouncer();
|
boolean shouldEnforceBouncer();
|
||||||
|
|||||||
@@ -80,12 +80,14 @@ public class BrightLineFalsingManager implements FalsingManager {
|
|||||||
private final Collection<FalsingClassifier> mClassifiers;
|
private final Collection<FalsingClassifier> mClassifiers;
|
||||||
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
|
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
|
||||||
private List<FalsingTapListener> mFalsingTapListeners = new ArrayList<>();
|
private List<FalsingTapListener> mFalsingTapListeners = new ArrayList<>();
|
||||||
|
private ProximityEvent mLastProximityEvent;
|
||||||
|
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
|
|
||||||
private final SessionListener mSessionListener = new SessionListener() {
|
private final SessionListener mSessionListener = new SessionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSessionEnded() {
|
public void onSessionEnded() {
|
||||||
|
mLastProximityEvent = null;
|
||||||
mClassifiers.forEach(FalsingClassifier::onSessionEnded);
|
mClassifiers.forEach(FalsingClassifier::onSessionEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +338,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|
|||||||
public void onProximityEvent(ProximityEvent proximityEvent) {
|
public void onProximityEvent(ProximityEvent proximityEvent) {
|
||||||
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
|
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
|
||||||
// make these calls.
|
// make these calls.
|
||||||
|
mLastProximityEvent = proximityEvent;
|
||||||
mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent));
|
mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,6 +350,11 @@ public class BrightLineFalsingManager implements FalsingManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isProximityNear() {
|
||||||
|
return mLastProximityEvent != null && mLastProximityEvent.getCovered();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUnlockingDisabled() {
|
public boolean isUnlockingDisabled() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ import javax.inject.Inject;
|
|||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class FalsingCollectorImpl implements FalsingCollector {
|
class FalsingCollectorImpl implements FalsingCollector {
|
||||||
|
|
||||||
private static final boolean DEBUG = false;
|
private static final String TAG = "FalsingCollector";
|
||||||
private static final String TAG = "FalsingManager";
|
private static final String PROXIMITY_SENSOR_TAG = "FalsingCollector";
|
||||||
private static final String PROXIMITY_SENSOR_TAG = "FalsingManager";
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
private static final long GESTURE_PROCESSING_DELAY_MS = 100;
|
private static final long GESTURE_PROCESSING_DELAY_MS = 100;
|
||||||
|
|
||||||
private final FalsingDataProvider mFalsingDataProvider;
|
private final FalsingDataProvider mFalsingDataProvider;
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
|
|||||||
return mInternalFalsingManager.isFalseDoubleTap();
|
return mInternalFalsingManager.isFalseDoubleTap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isProximityNear() {
|
||||||
|
return mInternalFalsingManager.isProximityNear();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isClassifierEnabled() {
|
public boolean isClassifierEnabled() {
|
||||||
return mInternalFalsingManager.isClassifierEnabled();
|
return mInternalFalsingManager.isClassifierEnabled();
|
||||||
|
|||||||
@@ -17,12 +17,9 @@
|
|||||||
package com.android.systemui.shade;
|
package com.android.systemui.shade;
|
||||||
|
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
import android.hardware.display.AmbientDisplayConfiguration;
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.session.MediaSessionLegacyHelper;
|
import android.media.session.MediaSessionLegacyHelper;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
@@ -52,7 +49,6 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
|||||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
||||||
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
|
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
|
||||||
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
|
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
|
||||||
import com.android.systemui.tuner.TunerService;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -66,7 +62,6 @@ import javax.inject.Inject;
|
|||||||
public class NotificationShadeWindowViewController {
|
public class NotificationShadeWindowViewController {
|
||||||
private static final String TAG = "NotifShadeWindowVC";
|
private static final String TAG = "NotifShadeWindowVC";
|
||||||
private final FalsingCollector mFalsingCollector;
|
private final FalsingCollector mFalsingCollector;
|
||||||
private final TunerService mTunerService;
|
|
||||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||||
private final NotificationShadeWindowView mView;
|
private final NotificationShadeWindowView mView;
|
||||||
private final NotificationShadeDepthController mDepthController;
|
private final NotificationShadeDepthController mDepthController;
|
||||||
@@ -77,6 +72,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
private final StatusBarWindowStateController mStatusBarWindowStateController;
|
private final StatusBarWindowStateController mStatusBarWindowStateController;
|
||||||
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
private final AmbientState mAmbientState;
|
private final AmbientState mAmbientState;
|
||||||
|
private final PulsingGestureListener mPulsingGestureListener;
|
||||||
|
|
||||||
private GestureDetector mGestureDetector;
|
private GestureDetector mGestureDetector;
|
||||||
private View mBrightnessMirror;
|
private View mBrightnessMirror;
|
||||||
@@ -88,8 +84,6 @@ public class NotificationShadeWindowViewController {
|
|||||||
private final CentralSurfaces mService;
|
private final CentralSurfaces mService;
|
||||||
private final NotificationShadeWindowController mNotificationShadeWindowController;
|
private final NotificationShadeWindowController mNotificationShadeWindowController;
|
||||||
private DragDownHelper mDragDownHelper;
|
private DragDownHelper mDragDownHelper;
|
||||||
private boolean mDoubleTapEnabled;
|
|
||||||
private boolean mSingleTapEnabled;
|
|
||||||
private boolean mExpandingBelowNotch;
|
private boolean mExpandingBelowNotch;
|
||||||
private final DockManager mDockManager;
|
private final DockManager mDockManager;
|
||||||
private final NotificationPanelViewController mNotificationPanelViewController;
|
private final NotificationPanelViewController mNotificationPanelViewController;
|
||||||
@@ -102,7 +96,6 @@ public class NotificationShadeWindowViewController {
|
|||||||
public NotificationShadeWindowViewController(
|
public NotificationShadeWindowViewController(
|
||||||
LockscreenShadeTransitionController transitionController,
|
LockscreenShadeTransitionController transitionController,
|
||||||
FalsingCollector falsingCollector,
|
FalsingCollector falsingCollector,
|
||||||
TunerService tunerService,
|
|
||||||
SysuiStatusBarStateController statusBarStateController,
|
SysuiStatusBarStateController statusBarStateController,
|
||||||
DockManager dockManager,
|
DockManager dockManager,
|
||||||
NotificationShadeDepthController depthController,
|
NotificationShadeDepthController depthController,
|
||||||
@@ -117,10 +110,11 @@ public class NotificationShadeWindowViewController {
|
|||||||
CentralSurfaces centralSurfaces,
|
CentralSurfaces centralSurfaces,
|
||||||
NotificationShadeWindowController controller,
|
NotificationShadeWindowController controller,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
AmbientState ambientState) {
|
AmbientState ambientState,
|
||||||
|
PulsingGestureListener pulsingGestureListener
|
||||||
|
) {
|
||||||
mLockscreenShadeTransitionController = transitionController;
|
mLockscreenShadeTransitionController = transitionController;
|
||||||
mFalsingCollector = falsingCollector;
|
mFalsingCollector = falsingCollector;
|
||||||
mTunerService = tunerService;
|
|
||||||
mStatusBarStateController = statusBarStateController;
|
mStatusBarStateController = statusBarStateController;
|
||||||
mView = notificationShadeWindowView;
|
mView = notificationShadeWindowView;
|
||||||
mDockManager = dockManager;
|
mDockManager = dockManager;
|
||||||
@@ -136,6 +130,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
mNotificationShadeWindowController = controller;
|
mNotificationShadeWindowController = controller;
|
||||||
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
|
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
|
||||||
mAmbientState = ambientState;
|
mAmbientState = ambientState;
|
||||||
|
mPulsingGestureListener = pulsingGestureListener;
|
||||||
|
|
||||||
// This view is not part of the newly inflated expanded status bar.
|
// This view is not part of the newly inflated expanded status bar.
|
||||||
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
|
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
|
||||||
@@ -151,46 +146,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
|
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
|
||||||
public void setupExpandedStatusBar() {
|
public void setupExpandedStatusBar() {
|
||||||
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
|
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
|
||||||
|
mGestureDetector = new GestureDetector(mView.getContext(), mPulsingGestureListener);
|
||||||
TunerService.Tunable tunable = (key, newValue) -> {
|
|
||||||
AmbientDisplayConfiguration configuration =
|
|
||||||
new AmbientDisplayConfiguration(mView.getContext());
|
|
||||||
switch (key) {
|
|
||||||
case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
|
|
||||||
mDoubleTapEnabled = configuration.doubleTapGestureEnabled(
|
|
||||||
UserHandle.USER_CURRENT);
|
|
||||||
break;
|
|
||||||
case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
|
|
||||||
mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mTunerService.addTunable(tunable,
|
|
||||||
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
|
|
||||||
Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
|
|
||||||
|
|
||||||
GestureDetector.SimpleOnGestureListener gestureListener =
|
|
||||||
new GestureDetector.SimpleOnGestureListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
|
||||||
if (mSingleTapEnabled && !mDockManager.isDocked()) {
|
|
||||||
mService.wakeUpIfDozing(
|
|
||||||
SystemClock.uptimeMillis(), mView, "SINGLE_TAP");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDoubleTap(MotionEvent e) {
|
|
||||||
if (mDoubleTapEnabled || mSingleTapEnabled) {
|
|
||||||
mService.wakeUpIfDozing(
|
|
||||||
SystemClock.uptimeMillis(), mView, "DOUBLE_TAP");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mGestureDetector = new GestureDetector(mView.getContext(), gestureListener);
|
|
||||||
|
|
||||||
mLowLightClockController.ifPresent(controller -> controller.attachLowLightClockView(mView));
|
mLowLightClockController.ifPresent(controller -> controller.attachLowLightClockView(mView));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.shade
|
||||||
|
|
||||||
|
import android.hardware.display.AmbientDisplayConfiguration
|
||||||
|
import android.os.SystemClock
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import com.android.systemui.Dumpable
|
||||||
|
import com.android.systemui.dock.DockManager
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.plugins.FalsingManager
|
||||||
|
import com.android.systemui.statusbar.phone.CentralSurfaces
|
||||||
|
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
|
||||||
|
import com.android.systemui.tuner.TunerService
|
||||||
|
import com.android.systemui.tuner.TunerService.Tunable
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If tap and/or double tap to wake is enabled, this gestureListener will wake the display on
|
||||||
|
* tap/double tap when the device is pulsing (AoD 2). Taps are gated by the proximity sensor and
|
||||||
|
* falsing manager.
|
||||||
|
*
|
||||||
|
* Touches go through the [NotificationShadeWindowViewController] when the device is pulsing.
|
||||||
|
* Otherwise, if the device is dozing and NOT pulsing, wake-ups are handled by
|
||||||
|
* [com.android.systemui.doze.DozeSensors].
|
||||||
|
*/
|
||||||
|
@CentralSurfacesComponent.CentralSurfacesScope
|
||||||
|
class PulsingGestureListener @Inject constructor(
|
||||||
|
private val notificationShadeWindowView: NotificationShadeWindowView,
|
||||||
|
private val falsingManager: FalsingManager,
|
||||||
|
private val dockManager: DockManager,
|
||||||
|
private val centralSurfaces: CentralSurfaces,
|
||||||
|
private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
|
||||||
|
tunerService: TunerService,
|
||||||
|
dumpManager: DumpManager
|
||||||
|
) : GestureDetector.SimpleOnGestureListener(), Dumpable {
|
||||||
|
private var doubleTapEnabled = false
|
||||||
|
private var singleTapEnabled = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
val tunable = Tunable { key: String?, _: String? ->
|
||||||
|
when (key) {
|
||||||
|
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE ->
|
||||||
|
doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled(
|
||||||
|
UserHandle.USER_CURRENT)
|
||||||
|
Settings.Secure.DOZE_TAP_SCREEN_GESTURE ->
|
||||||
|
singleTapEnabled = ambientDisplayConfiguration.tapGestureEnabled(
|
||||||
|
UserHandle.USER_CURRENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tunerService.addTunable(tunable,
|
||||||
|
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
|
||||||
|
Settings.Secure.DOZE_TAP_SCREEN_GESTURE)
|
||||||
|
|
||||||
|
dumpManager.registerDumpable(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||||
|
if (singleTapEnabled &&
|
||||||
|
!dockManager.isDocked &&
|
||||||
|
!falsingManager.isProximityNear &&
|
||||||
|
!falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)
|
||||||
|
) {
|
||||||
|
centralSurfaces.wakeUpIfDozing(
|
||||||
|
SystemClock.uptimeMillis(),
|
||||||
|
notificationShadeWindowView,
|
||||||
|
"PULSING_SINGLE_TAP")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDoubleTap(e: MotionEvent): Boolean {
|
||||||
|
if ((doubleTapEnabled || singleTapEnabled) &&
|
||||||
|
!falsingManager.isProximityNear &&
|
||||||
|
!falsingManager.isFalseDoubleTap
|
||||||
|
) {
|
||||||
|
centralSurfaces.wakeUpIfDozing(
|
||||||
|
SystemClock.uptimeMillis(),
|
||||||
|
notificationShadeWindowView,
|
||||||
|
"PULSING_DOUBLE_TAP")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
||||||
|
pw.println("singleTapEnabled=$singleTapEnabled")
|
||||||
|
pw.println("doubleTapEnabled=$doubleTapEnabled")
|
||||||
|
pw.println("isDocked=${dockManager.isDocked}")
|
||||||
|
pw.println("isProxCovered=${falsingManager.isProximityNear}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.logging.testing.FakeMetricsLogger;
|
import com.android.internal.logging.testing.FakeMetricsLogger;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -111,5 +112,51 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
|||||||
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
|
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsProxNear_noProxEvents_defaultsToFalse() {
|
||||||
|
assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsProxNear_receivesNearEvent() {
|
||||||
|
mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
|
||||||
|
@Override
|
||||||
|
public boolean getCovered() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimestampNs() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertThat(mBrightLineFalsingManager.isProximityNear()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsProxNear_receivesNearAndThenFarEvent() {
|
||||||
|
mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
|
||||||
|
@Override
|
||||||
|
public boolean getCovered() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimestampNs() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
|
||||||
|
@Override
|
||||||
|
public boolean getCovered() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimestampNs() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,19 +26,18 @@ import com.android.systemui.classifier.FalsingCollectorFake
|
|||||||
import com.android.systemui.dock.DockManager
|
import com.android.systemui.dock.DockManager
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
||||||
import com.android.systemui.lowlightclock.LowLightClockController
|
import com.android.systemui.lowlightclock.LowLightClockController
|
||||||
|
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController
|
import com.android.systemui.statusbar.NotificationShadeDepthController
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController
|
import com.android.systemui.statusbar.NotificationShadeWindowController
|
||||||
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
import com.android.systemui.statusbar.notification.stack.AmbientState
|
import com.android.systemui.statusbar.notification.stack.AmbientState
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||||
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
|
||||||
import com.android.systemui.statusbar.phone.CentralSurfaces
|
import com.android.systemui.statusbar.phone.CentralSurfaces
|
||||||
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
|
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
|
||||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
||||||
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
|
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
|
||||||
import com.android.systemui.statusbar.window.StatusBarWindowStateController
|
import com.android.systemui.statusbar.window.StatusBarWindowStateController
|
||||||
import com.android.systemui.tuner.TunerService
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -60,8 +59,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var view: NotificationShadeWindowView
|
private lateinit var view: NotificationShadeWindowView
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var tunserService: TunerService
|
|
||||||
@Mock
|
|
||||||
private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
|
private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var centralSurfaces: CentralSurfaces
|
private lateinit var centralSurfaces: CentralSurfaces
|
||||||
@@ -91,6 +88,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var lowLightClockController: LowLightClockController
|
private lateinit var lowLightClockController: LowLightClockController
|
||||||
|
@Mock
|
||||||
|
private lateinit var pulsingGestureListener: PulsingGestureListener
|
||||||
|
|
||||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||||
private lateinit var interactionEventHandler: InteractionEventHandler
|
private lateinit var interactionEventHandler: InteractionEventHandler
|
||||||
@@ -105,7 +104,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
underTest = NotificationShadeWindowViewController(
|
underTest = NotificationShadeWindowViewController(
|
||||||
lockscreenShadeTransitionController,
|
lockscreenShadeTransitionController,
|
||||||
FalsingCollectorFake(),
|
FalsingCollectorFake(),
|
||||||
tunserService,
|
|
||||||
sysuiStatusBarStateController,
|
sysuiStatusBarStateController,
|
||||||
dockManager,
|
dockManager,
|
||||||
notificationShadeDepthController,
|
notificationShadeDepthController,
|
||||||
@@ -120,7 +118,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
centralSurfaces,
|
centralSurfaces,
|
||||||
notificationShadeWindowController,
|
notificationShadeWindowController,
|
||||||
keyguardUnlockAnimationController,
|
keyguardUnlockAnimationController,
|
||||||
ambientState
|
ambientState,
|
||||||
|
pulsingGestureListener
|
||||||
)
|
)
|
||||||
underTest.setupExpandedStatusBar()
|
underTest.setupExpandedStatusBar()
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
@Mock private LowLightClockController mLowLightClockController;
|
@Mock private LowLightClockController mLowLightClockController;
|
||||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
@Mock private AmbientState mAmbientState;
|
@Mock private AmbientState mAmbientState;
|
||||||
|
@Mock private PulsingGestureListener mPulsingGestureListener;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
||||||
mInteractionEventHandlerCaptor;
|
mInteractionEventHandlerCaptor;
|
||||||
@@ -110,7 +111,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
mController = new NotificationShadeWindowViewController(
|
mController = new NotificationShadeWindowViewController(
|
||||||
mLockscreenShadeTransitionController,
|
mLockscreenShadeTransitionController,
|
||||||
new FalsingCollectorFake(),
|
new FalsingCollectorFake(),
|
||||||
mTunerService,
|
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mDockManager,
|
mDockManager,
|
||||||
mNotificationShadeDepthController,
|
mNotificationShadeDepthController,
|
||||||
@@ -125,7 +125,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
mCentralSurfaces,
|
mCentralSurfaces,
|
||||||
mNotificationShadeWindowController,
|
mNotificationShadeWindowController,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mAmbientState);
|
mAmbientState,
|
||||||
|
mPulsingGestureListener
|
||||||
|
);
|
||||||
mController.setupExpandedStatusBar();
|
mController.setupExpandedStatusBar();
|
||||||
mController.setDragDownHelper(mDragDownHelper);
|
mController.setDragDownHelper(mDragDownHelper);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.shade
|
||||||
|
|
||||||
|
import android.hardware.display.AmbientDisplayConfiguration
|
||||||
|
import android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE
|
||||||
|
import android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.dock.DockManager
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.plugins.FalsingManager
|
||||||
|
import com.android.systemui.statusbar.phone.CentralSurfaces
|
||||||
|
import com.android.systemui.tuner.TunerService
|
||||||
|
import com.android.systemui.tuner.TunerService.Tunable
|
||||||
|
import com.android.systemui.util.mockito.eq
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.ArgumentMatchers.anyLong
|
||||||
|
import org.mockito.ArgumentMatchers.anyObject
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@RunWithLooper(setAsMainLooper = true)
|
||||||
|
@SmallTest
|
||||||
|
class PulsingGestureListenerTest : SysuiTestCase() {
|
||||||
|
@Mock
|
||||||
|
private lateinit var view: NotificationShadeWindowView
|
||||||
|
@Mock
|
||||||
|
private lateinit var centralSurfaces: CentralSurfaces
|
||||||
|
@Mock
|
||||||
|
private lateinit var dockManager: DockManager
|
||||||
|
@Mock
|
||||||
|
private lateinit var falsingManager: FalsingManager
|
||||||
|
@Mock
|
||||||
|
private lateinit var ambientDisplayConfiguration: AmbientDisplayConfiguration
|
||||||
|
@Mock
|
||||||
|
private lateinit var tunerService: TunerService
|
||||||
|
@Mock
|
||||||
|
private lateinit var dumpManager: DumpManager
|
||||||
|
|
||||||
|
private lateinit var tunableCaptor: ArgumentCaptor<Tunable>
|
||||||
|
private lateinit var underTest: PulsingGestureListener
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
underTest = PulsingGestureListener(
|
||||||
|
view,
|
||||||
|
falsingManager,
|
||||||
|
dockManager,
|
||||||
|
centralSurfaces,
|
||||||
|
ambientDisplayConfiguration,
|
||||||
|
tunerService,
|
||||||
|
dumpManager
|
||||||
|
)
|
||||||
|
whenever(dockManager.isDocked).thenReturn(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_singleTapEnabled() {
|
||||||
|
// GIVEN tap is enabled, prox not covered
|
||||||
|
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isProximityNear).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN the falsing manager does NOT think the tap is a false tap
|
||||||
|
whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
|
||||||
|
|
||||||
|
// WHEN there's a tap
|
||||||
|
underTest.onSingleTapConfirmed(downEv)
|
||||||
|
|
||||||
|
// THEN wake up device if dozing
|
||||||
|
verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_doubleTapEnabled() {
|
||||||
|
// GIVEN double tap is enabled, prox not covered
|
||||||
|
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isProximityNear).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN the falsing manager does NOT think the tap is a false tap
|
||||||
|
whenever(falsingManager.isFalseDoubleTap).thenReturn(false)
|
||||||
|
|
||||||
|
// WHEN there's a double tap
|
||||||
|
underTest.onDoubleTap(downEv)
|
||||||
|
|
||||||
|
// THEN wake up device if dozing
|
||||||
|
verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_singleTapEnabled_falsing() {
|
||||||
|
// GIVEN tap is enabled, prox not covered
|
||||||
|
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isProximityNear).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN the falsing manager thinks the tap is a false tap
|
||||||
|
whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true)
|
||||||
|
|
||||||
|
// WHEN there's a tap
|
||||||
|
underTest.onSingleTapConfirmed(downEv)
|
||||||
|
|
||||||
|
// THEN the device doesn't wake up
|
||||||
|
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_doubleTapEnabled_falsing() {
|
||||||
|
// GIVEN double tap is enabled, prox not covered
|
||||||
|
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isProximityNear).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN the falsing manager thinks the tap is a false tap
|
||||||
|
whenever(falsingManager.isFalseDoubleTap).thenReturn(true)
|
||||||
|
|
||||||
|
// WHEN there's a tap
|
||||||
|
underTest.onDoubleTap(downEv)
|
||||||
|
|
||||||
|
// THEN the device doesn't wake up
|
||||||
|
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_singleTapEnabled_proxCovered() {
|
||||||
|
// GIVEN tap is enabled, not a false tap based on classifiers
|
||||||
|
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN prox is covered
|
||||||
|
whenever(falsingManager.isProximityNear()).thenReturn(true)
|
||||||
|
|
||||||
|
// WHEN there's a tap
|
||||||
|
underTest.onSingleTapConfirmed(downEv)
|
||||||
|
|
||||||
|
// THEN the device doesn't wake up
|
||||||
|
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGestureDetector_doubleTapEnabled_proxCovered() {
|
||||||
|
// GIVEN double tap is enabled, not a false tap based on classifiers
|
||||||
|
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
|
||||||
|
updateSettings()
|
||||||
|
whenever(falsingManager.isFalseDoubleTap).thenReturn(false)
|
||||||
|
|
||||||
|
// GIVEN prox is covered
|
||||||
|
whenever(falsingManager.isProximityNear()).thenReturn(true)
|
||||||
|
|
||||||
|
// WHEN there's a tap
|
||||||
|
underTest.onDoubleTap(downEv)
|
||||||
|
|
||||||
|
// THEN the device doesn't wake up
|
||||||
|
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSettings() {
|
||||||
|
tunableCaptor = ArgumentCaptor.forClass(Tunable::class.java)
|
||||||
|
verify(tunerService).addTunable(
|
||||||
|
tunableCaptor.capture(),
|
||||||
|
eq(DOZE_DOUBLE_TAP_GESTURE),
|
||||||
|
eq(DOZE_TAP_SCREEN_GESTURE))
|
||||||
|
tunableCaptor.value.onTuningChanged(DOZE_DOUBLE_TAP_GESTURE, "")
|
||||||
|
tunableCaptor.value.onTuningChanged(DOZE_TAP_SCREEN_GESTURE, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||||
@@ -40,6 +40,7 @@ public class FalsingManagerFake implements FalsingManager {
|
|||||||
private boolean mIsReportingEnabled;
|
private boolean mIsReportingEnabled;
|
||||||
private boolean mIsFalseRobustTap;
|
private boolean mIsFalseRobustTap;
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
|
private boolean mIsProximityNear;
|
||||||
|
|
||||||
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
|
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
|
||||||
private final List<FalsingTapListener> mTapListeners = new ArrayList<>();
|
private final List<FalsingTapListener> mTapListeners = new ArrayList<>();
|
||||||
@@ -82,6 +83,10 @@ public class FalsingManagerFake implements FalsingManager {
|
|||||||
mIsFalseDoubleTap = falseDoubleTap;
|
mIsFalseDoubleTap = falseDoubleTap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsProximityNear(boolean proxNear) {
|
||||||
|
mIsProximityNear = proxNear;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSimpleTap() {
|
public boolean isSimpleTap() {
|
||||||
checkDestroyed();
|
checkDestroyed();
|
||||||
@@ -100,6 +105,11 @@ public class FalsingManagerFake implements FalsingManager {
|
|||||||
return mIsFalseDoubleTap;
|
return mIsFalseDoubleTap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isProximityNear() {
|
||||||
|
return mIsProximityNear;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void setIsClassifierEnabled(boolean isClassifierEnabled) {
|
public void setIsClassifierEnabled(boolean isClassifierEnabled) {
|
||||||
mIsClassifierEnabled = isClassifierEnabled;
|
mIsClassifierEnabled = isClassifierEnabled;
|
||||||
|
|||||||
Reference in New Issue
Block a user