Merge "Wakeup display on taps before entering true AoD" into tm-qpr-dev am: 88deb41710

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19969291

Change-Id: Ic1292b3d54747918e1b9c8745c1bb03d64a7d1ff
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Beverly Tai
2022-09-16 13:14:00 +00:00
committed by Automerger Merge Worker
10 changed files with 97 additions and 47 deletions

View File

@@ -147,10 +147,10 @@ public interface FalsingManager {
}
/**
* Listener that is alerted when a double tap is required to confirm a single tap.
* Listener that is alerted when an additional tap is required to confirm a single tap.
**/
interface FalsingTapListener {
void onDoubleTapRequired();
void onAdditionalTapRequired();
}
/** Passed to {@link FalsingManager#onProximityEvent}. */

View File

@@ -291,7 +291,7 @@ public class BrightLineFalsingManager implements FalsingManager {
FalsingClassifier.Result.falsed(
0, getClass().getSimpleName(), "bad history"));
logDebug("False Single Tap: true (bad history)");
mFalsingTapListeners.forEach(FalsingTapListener::onDoubleTapRequired);
mFalsingTapListeners.forEach(FalsingTapListener::onAdditionalTapRequired);
return true;
} else {
mPriorResults = getPassedResult(0.1);
@@ -321,7 +321,7 @@ public class BrightLineFalsingManager implements FalsingManager {
mHistoryTracker.falseBelief(),
mHistoryTracker.falseConfidence());
mPriorResults = Collections.singleton(result);
logDebug("False Double Tap: " + result.isFalse());
logDebug("False Double Tap: " + result.isFalse() + " reason=" + result.getReason());
return result.isFalse();
}

View File

@@ -303,9 +303,7 @@ class FalsingCollectorImpl implements FalsingCollector {
@Override
public void onTouchEvent(MotionEvent ev) {
if (!mKeyguardStateController.isShowing()
|| (mStatusBarStateController.isDozing()
&& !mStatusBarStateController.isPulsing())) {
if (!mKeyguardStateController.isShowing()) {
avoidGesture();
return;
}

View File

@@ -33,6 +33,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.android.systemui.statusbar.VibratorHelper.TOUCH_VIBRATION_ATTRIBUTES;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD;
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
@@ -62,6 +63,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.Process;
import android.os.Trace;
import android.os.UserManager;
import android.os.VibrationEffect;
@@ -236,6 +238,9 @@ public final class NotificationPanelViewController extends PanelViewController {
private static final boolean SPEW_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
private static final boolean DEBUG_DRAWABLE = false;
private static final VibrationEffect ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_STRENGTH_MEDIUM, false);
/**
* The parallax amount of the quick settings translation when dragging down the panel
*/
@@ -682,14 +687,22 @@ public final class NotificationPanelViewController extends PanelViewController {
private final FalsingTapListener mFalsingTapListener = new FalsingTapListener() {
@Override
public void onDoubleTapRequired() {
public void onAdditionalTapRequired() {
if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
mTapAgainViewController.show();
} else {
mKeyguardIndicationController.showTransientIndication(
R.string.notification_tap_again);
}
mVibratorHelper.vibrate(VibrationEffect.EFFECT_STRENGTH_MEDIUM);
if (!mStatusBarStateController.isDozing()) {
mVibratorHelper.vibrate(
Process.myUid(),
mView.getContext().getPackageName(),
ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT,
"falsing-additional-tap-required",
TOUCH_VIBRATION_ATTRIBUTES);
}
}
};

View File

@@ -73,7 +73,7 @@ public class NotificationShadeWindowViewController {
private final AmbientState mAmbientState;
private final PulsingGestureListener mPulsingGestureListener;
private GestureDetector mGestureDetector;
private GestureDetector mPulsingWakeupGestureHandler;
private View mBrightnessMirror;
private boolean mTouchActive;
private boolean mTouchCancelled;
@@ -149,7 +149,8 @@ public class NotificationShadeWindowViewController {
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
public void setupExpandedStatusBar() {
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
mGestureDetector = new GestureDetector(mView.getContext(), mPulsingGestureListener);
mPulsingWakeupGestureHandler = new GestureDetector(mView.getContext(),
mPulsingGestureListener);
mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {
@Override
@@ -196,7 +197,7 @@ public class NotificationShadeWindowViewController {
}
mFalsingCollector.onTouchEvent(ev);
mGestureDetector.onTouchEvent(ev);
mPulsingWakeupGestureHandler.onTouchEvent(ev);
mStatusBarKeyguardViewManager.onTouch(ev);
if (mBrightnessMirror != null
&& mBrightnessMirror.getVisibility() == View.VISIBLE) {

View File

@@ -26,6 +26,7 @@ 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.plugins.FalsingManager.LOW_PENALTY
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
@@ -36,12 +37,12 @@ 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.
* tap/double tap when the device is pulsing (AoD2) or transitioning to AoD. 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].
* Touches go through the [NotificationShadeWindowViewController] when the device is dozing but the
* screen is still ON and not in the true AoD display state. When the device is in the true AoD
* display state, wake-ups are handled by [com.android.systemui.doze.DozeSensors].
*/
@CentralSurfacesComponent.CentralSurfacesScope
class PulsingGestureListener @Inject constructor(
@@ -75,12 +76,12 @@ class PulsingGestureListener @Inject constructor(
dumpManager.registerDumpable(this)
}
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
if (statusBarStateController.isPulsing &&
override fun onSingleTapUp(e: MotionEvent): Boolean {
if (statusBarStateController.isDozing &&
singleTapEnabled &&
!dockManager.isDocked &&
!falsingManager.isProximityNear &&
!falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)
!falsingManager.isFalseTap(LOW_PENALTY)
) {
centralSurfaces.wakeUpIfDozing(
SystemClock.uptimeMillis(),
@@ -91,8 +92,15 @@ class PulsingGestureListener @Inject constructor(
return false
}
override fun onDoubleTap(e: MotionEvent): Boolean {
if (statusBarStateController.isPulsing &&
/**
* Receives [MotionEvent.ACTION_DOWN], [MotionEvent.ACTION_MOVE], and [MotionEvent.ACTION_UP]
* motion events for a double tap.
*/
override fun onDoubleTapEvent(e: MotionEvent): Boolean {
// React to the [MotionEvent.ACTION_UP] event after double tap is detected. Falsing
// checks MUST be on the ACTION_UP event.
if (e.actionMasked == MotionEvent.ACTION_UP &&
statusBarStateController.isDozing &&
(doubleTapEnabled || singleTapEnabled) &&
!falsingManager.isProximityNear &&
!falsingManager.isFalseDoubleTap

View File

@@ -38,7 +38,7 @@ import javax.inject.Inject;
public class VibratorHelper {
private final Vibrator mVibrator;
private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
public static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
private final Executor mExecutor;

View File

@@ -229,7 +229,10 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
}
@Test
public void testAvoidDozingNotPulsing() {
public void testGestureWhenDozing() {
// We check the FalsingManager for taps during the transition to AoD (dozing=true,
// pulsing=false), so the FalsingCollector needs to continue to analyze events that occur
// while the device is dozing.
MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
@@ -239,13 +242,13 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
mFalsingCollector.onTouchEvent(down);
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
// Up event would normally flush the up event, but doesn't.
// Up event flushes
mFalsingCollector.onTouchEvent(up);
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
verify(mFalsingDataProvider, times(2)).onMotionEvent(any(MotionEvent.class));
}
@Test
public void testAvoidDozingButPulsing() {
public void testGestureWhenPulsing() {
MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);

View File

@@ -1022,7 +1022,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
FalsingManager.FalsingTapListener listener = getFalsingTapListener();
mStatusBarStateController.setState(KEYGUARD);
listener.onDoubleTapRequired();
listener.onAdditionalTapRequired();
verify(mKeyguardIndicationController).showTransientIndication(anyInt());
}
@@ -1032,7 +1032,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
FalsingManager.FalsingTapListener listener = getFalsingTapListener();
mStatusBarStateController.setState(SHADE_LOCKED);
listener.onDoubleTapRequired();
listener.onAdditionalTapRequired();
verify(mTapAgainViewController).show();
}

View File

@@ -89,7 +89,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
@Test
fun testGestureDetector_singleTapEnabled() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN tap is enabled, prox not covered
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
@@ -100,7 +100,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
// WHEN there's a tap
underTest.onSingleTapConfirmed(downEv)
underTest.onSingleTapUp(upEv)
// THEN wake up device if dozing
verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
@@ -108,7 +108,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
@Test
fun testGestureDetector_doubleTapEnabled() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN double tap is enabled, prox not covered
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
@@ -119,15 +119,27 @@ class PulsingGestureListenerTest : SysuiTestCase() {
whenever(falsingManager.isFalseDoubleTap).thenReturn(false)
// WHEN there's a double tap
underTest.onDoubleTap(downEv)
underTest.onDoubleTapEvent(upEv)
// THEN wake up device if dozing
verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
}
@Test
fun testGestureDetector_doubleTapEnabled_onDownEvent_noFalsingCheck() {
// GIVEN tap is enabled
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
// WHEN there's a double tap on DOWN event
underTest.onDoubleTapEvent(downEv)
// THEN don't check the falsing manager, should only be checked on the UP event
verify(falsingManager, never()).isFalseDoubleTap()
}
@Test
fun testGestureDetector_singleTapEnabled_falsing() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN tap is enabled, prox not covered
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
@@ -138,29 +150,43 @@ class PulsingGestureListenerTest : SysuiTestCase() {
whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true)
// WHEN there's a tap
underTest.onSingleTapConfirmed(downEv)
underTest.onSingleTapUp(upEv)
// THEN the device doesn't wake up
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
}
@Test
fun testGestureDetector_notPulsing_noFalsingCheck() {
whenever(statusBarStateController.isPulsing).thenReturn(false)
fun testSingleTap_notDozing_noFalsingCheck() {
whenever(statusBarStateController.isDozing).thenReturn(false)
// GIVEN tap is enabled, prox not covered
// GIVEN tap is enabled
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
// WHEN there's a tap
underTest.onSingleTapConfirmed(downEv)
underTest.onSingleTapUp(upEv)
// THEN the falsing manager never gets a call (because the device wasn't pulsing
// THEN the falsing manager never gets a call (because the device wasn't dozing
// during the tap)
verify(falsingManager, never()).isFalseTap(anyInt())
}
@Test
fun testDoubleTap_notDozing_noFalsingCheck() {
whenever(statusBarStateController.isDozing).thenReturn(false)
// GIVEN tap is enabled
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
// WHEN there's a tap
underTest.onDoubleTapEvent(upEv)
// THEN the falsing manager never gets a call (because the device wasn't dozing
// during the tap)
verify(falsingManager, never()).isFalseTap(anyInt())
}
@Test
fun testGestureDetector_doubleTapEnabled_falsing() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN double tap is enabled, prox not covered
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
@@ -170,8 +196,8 @@ class PulsingGestureListenerTest : SysuiTestCase() {
// GIVEN the falsing manager thinks the tap is a false tap
whenever(falsingManager.isFalseDoubleTap).thenReturn(true)
// WHEN there's a tap
underTest.onDoubleTap(downEv)
// WHEN there's a double tap ACTION_UP event
underTest.onDoubleTapEvent(upEv)
// THEN the device doesn't wake up
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
@@ -179,7 +205,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
@Test
fun testGestureDetector_singleTapEnabled_proxCovered() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN tap is enabled, not a false tap based on classifiers
whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
@@ -190,7 +216,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
whenever(falsingManager.isProximityNear()).thenReturn(true)
// WHEN there's a tap
underTest.onSingleTapConfirmed(downEv)
underTest.onSingleTapUp(upEv)
// THEN the device doesn't wake up
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
@@ -198,7 +224,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
@Test
fun testGestureDetector_doubleTapEnabled_proxCovered() {
whenever(statusBarStateController.isPulsing).thenReturn(true)
whenever(statusBarStateController.isDozing).thenReturn(true)
// GIVEN double tap is enabled, not a false tap based on classifiers
whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
@@ -209,7 +235,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
whenever(falsingManager.isProximityNear()).thenReturn(true)
// WHEN there's a tap
underTest.onDoubleTap(downEv)
underTest.onDoubleTapEvent(upEv)
// THEN the device doesn't wake up
verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
@@ -227,3 +253,4 @@ class PulsingGestureListenerTest : SysuiTestCase() {
}
private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
private val upEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)