summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVCDownEventState.kt143
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java6
4 files changed, 205 insertions, 18 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVCDownEventState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVCDownEventState.kt
new file mode 100644
index 000000000000..06235071734e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVCDownEventState.kt
@@ -0,0 +1,143 @@
+/*
+ * 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.statusbar.phone
+
+import android.view.MotionEvent
+import com.android.internal.util.RingBuffer
+import com.android.systemui.dump.DumpsysTableLogger
+import com.android.systemui.dump.Row
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+/** Container for storing information about [MotionEvent.ACTION_DOWN] on
+ * [NotificationPanelViewController].
+ *
+ * This will be used in a dump to log the latest recorded down events.
+ *
+ * @see NotificationPanelViewController.initDownStates
+ */
+class NPVCDownEventState private constructor(
+ private var timeStamp: Long = 0,
+ private var x: Float = 0f,
+ private var y: Float = 0f,
+ private var qsTouchAboveFalsingThreshold: Boolean = false,
+ private var dozing: Boolean = false,
+ private var collapsed: Boolean = false,
+ private var canCollapseOnQQS: Boolean = false,
+ private var listenForHeadsUp: Boolean = false,
+ private var allowExpandForSmallExpansion: Boolean = false,
+ private var touchSlopExceededBeforeDown: Boolean = false,
+ private var lastEventSynthesized: Boolean = false
+) {
+
+ /**
+ * List of [String] to be used as a [Row] with [DumpsysTableLogger].
+ */
+ val asStringList: List<String> by lazy {
+ listOf(
+ DATE_FORMAT.format(timeStamp),
+ x.toString(),
+ y.toString(),
+ qsTouchAboveFalsingThreshold.toString(),
+ dozing.toString(),
+ collapsed.toString(),
+ canCollapseOnQQS.toString(),
+ listenForHeadsUp.toString(),
+ allowExpandForSmallExpansion.toString(),
+ touchSlopExceededBeforeDown.toString(),
+ lastEventSynthesized.toString()
+ )
+ }
+
+ /**
+ * [RingBuffer] to store [NPVCDownEventState]. After the buffer is full, it will recycle old
+ * events.
+ *
+ * Do not use [append] to add new elements. Instead use [insert], as it will recycle if
+ * necessary.
+ */
+ class Buffer(
+ capacity: Int
+ ) : RingBuffer<NPVCDownEventState>(NPVCDownEventState::class.java, capacity) {
+ override fun append(t: NPVCDownEventState?) {
+ throw UnsupportedOperationException("Not supported, use insert instead")
+ }
+
+ override fun createNewItem(): NPVCDownEventState {
+ return NPVCDownEventState()
+ }
+
+ /**
+ * Insert a new element in the buffer.
+ */
+ fun insert(
+ timeStamp: Long,
+ x: Float,
+ y: Float,
+ qsTouchAboveFalsingThreshold: Boolean,
+ dozing: Boolean,
+ collapsed: Boolean,
+ canCollapseOnQQS: Boolean,
+ listenForHeadsUp: Boolean,
+ allowExpandForSmallExpansion: Boolean,
+ touchSlopExceededBeforeDown: Boolean,
+ lastEventSynthesized: Boolean
+ ) {
+ nextSlot.apply {
+ this.timeStamp = timeStamp
+ this.x = x
+ this.y = y
+ this.qsTouchAboveFalsingThreshold = qsTouchAboveFalsingThreshold
+ this.dozing = dozing
+ this.collapsed = collapsed
+ this.canCollapseOnQQS = canCollapseOnQQS
+ this.listenForHeadsUp = listenForHeadsUp
+ this.allowExpandForSmallExpansion = allowExpandForSmallExpansion
+ this.touchSlopExceededBeforeDown = touchSlopExceededBeforeDown
+ this.lastEventSynthesized = lastEventSynthesized
+ }
+ }
+
+ /**
+ * Returns the content of the buffer (sorted from latest to newest).
+ *
+ * @see NPVCDownEventState.asStringList
+ */
+ fun toList(): List<Row> {
+ return toArray().map { it.asStringList }
+ }
+ }
+
+ companion object {
+ /**
+ * Headers for dumping a table using [DumpsysTableLogger].
+ */
+ @JvmField
+ val TABLE_HEADERS = listOf(
+ "Timestamp",
+ "X",
+ "Y",
+ "QSTouchAboveFalsingThreshold",
+ "Dozing",
+ "Collapsed",
+ "CanCollapseOnQQS",
+ "ListenForHeadsUp",
+ "AllowExpandForSmallExpansion",
+ "TouchSlopExceededBeforeDown",
+ "LastEventSynthesized"
+ )
+ }
+}
+
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index b5789fb9c634..985df423d744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -36,6 +36,7 @@ import static com.android.systemui.statusbar.notification.stack.StackStateAnimat
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN;
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPENING;
+import static com.android.systemui.util.DumpUtilsKt.asIndenting;
import static java.lang.Float.isNaN;
@@ -65,13 +66,13 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
-import android.os.SystemClock;
import android.os.Trace;
import android.os.UserManager;
import android.os.VibrationEffect;
import android.provider.Settings;
import android.transition.ChangeBounds;
import android.transition.TransitionManager;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.view.LayoutInflater;
@@ -121,6 +122,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpsysTableLogger;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -193,6 +195,7 @@ import com.android.systemui.util.LargeScreenUtils;
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.Utils;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.wm.shell.animation.FlingAnimationUtils;
@@ -212,7 +215,7 @@ import javax.inject.Provider;
@CentralSurfacesComponent.CentralSurfacesScope
public class NotificationPanelViewController extends PanelViewController {
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
* The parallax amount of the quick settings translation when dragging down the panel
@@ -279,6 +282,8 @@ public class NotificationPanelViewController extends PanelViewController {
*/
private static final int MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER = 300;
+ private static final int MAX_DOWN_EVENT_BUFFER_SIZE = 50;
+
private static final String COUNTER_PANEL_OPEN = "panel_open";
private static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
@@ -653,6 +658,8 @@ public class NotificationPanelViewController extends PanelViewController {
private final NotificationListContainer mNotificationListContainer;
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+ private final NPVCDownEventState.Buffer mLastDownEvents;
+
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
@@ -755,7 +762,8 @@ public class NotificationPanelViewController extends PanelViewController {
PanelEventsEmitter panelEventsEmitter,
NotificationStackSizeCalculator notificationStackSizeCalculator,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
- ShadeTransitionController shadeTransitionController) {
+ ShadeTransitionController shadeTransitionController,
+ SystemClock systemClock) {
super(view,
falsingManager,
dozeLog,
@@ -771,7 +779,8 @@ public class NotificationPanelViewController extends PanelViewController {
panelExpansionStateManager,
ambientState,
interactionJankMonitor,
- keyguardUnlockAnimationController);
+ keyguardUnlockAnimationController,
+ systemClock);
mView = view;
mVibratorHelper = vibratorHelper;
mKeyguardMediaController = keyguardMediaController;
@@ -860,6 +869,7 @@ public class NotificationPanelViewController extends PanelViewController {
mScreenOffAnimationController = screenOffAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mRemoteInputManager = remoteInputManager;
+ mLastDownEvents = new NPVCDownEventState.Buffer(MAX_DOWN_EVENT_BUFFER_SIZE);
int currentMode = navigationModeController.addListener(
mode -> mIsGestureNavigation = QuickStepContract.isGesturalMode(mode));
@@ -1709,6 +1719,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
private boolean onQsIntercept(MotionEvent event) {
+ if (DEBUG) Log.d(TAG, "onQsIntercept");
int pointerIndex = event.findPointerIndex(mTrackingPointer);
if (pointerIndex < 0) {
pointerIndex = 0;
@@ -1763,6 +1774,7 @@ public class NotificationPanelViewController extends PanelViewController {
if ((h > getTouchSlop(event) || (h < -getTouchSlop(event) && mQsExpanded))
&& Math.abs(h) > Math.abs(x - mInitialTouchX)
&& shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, h)) {
+ if (DEBUG) Log.d(TAG, "onQsIntercept - start tracking expansion");
mView.getParent().requestDisallowInterceptTouchEvent(true);
mQsTracking = true;
traceQsJank(true /* startTracing */, false /* wasCancelled */);
@@ -1832,6 +1844,19 @@ public class NotificationPanelViewController extends PanelViewController {
// down but not synthesized motion event.
mLastEventSynthesizedDown = false;
}
+ mLastDownEvents.insert(
+ mSystemClock.currentTimeMillis(),
+ mDownX,
+ mDownY,
+ mQsTouchAboveFalsingThreshold,
+ mDozingOnDown,
+ mCollapsedOnDown,
+ mIsPanelCollapseOnQQS,
+ mListenForHeadsUp,
+ mAllowExpandForSmallExpansion,
+ mTouchSlopExceededBeforeDown,
+ mLastEventSynthesizedDown
+ );
} else {
// not down event at all.
mLastEventSynthesizedDown = false;
@@ -1925,7 +1950,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (mAllowExpandForSmallExpansion) {
// When we get a touch that came over from launcher, the velocity isn't always correct
// Let's err on expanding if the gesture has been reasonably slow
- long timeSinceDown = SystemClock.uptimeMillis() - mDownTime;
+ long timeSinceDown = mSystemClock.uptimeMillis() - mDownTime;
return timeSinceDown <= MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER;
}
return false;
@@ -1952,8 +1977,8 @@ public class NotificationPanelViewController extends PanelViewController {
mConflictingQsExpansionGesture = true;
onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = event.getX();
- mInitialTouchX = event.getY();
+ mInitialTouchY = event.getY();
+ mInitialTouchX = event.getX();
}
if (!isFullyCollapsed()) {
handleQsDown(event);
@@ -2026,12 +2051,13 @@ public class NotificationPanelViewController extends PanelViewController {
private void handleQsDown(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && shouldQuickSettingsIntercept(
event.getX(), event.getY(), -1)) {
+ if (DEBUG) Log.d(TAG, "handleQsDown");
mFalsingCollector.onQsDown();
mQsTracking = true;
onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = event.getX();
- mInitialTouchX = event.getY();
+ mInitialTouchY = event.getY();
+ mInitialTouchX = event.getX();
// If we interrupt an expansion gesture here, make sure to update the state correctly.
notifyExpandingFinished();
@@ -2139,6 +2165,7 @@ public class NotificationPanelViewController extends PanelViewController {
break;
case MotionEvent.ACTION_MOVE:
+ if (DEBUG) Log.d(TAG, "onQSTouch move");
setQsExpansion(h + mInitialHeightOnTouch);
if (h >= getFalsingThreshold()) {
mQsTouchAboveFalsingThreshold = true;
@@ -3872,10 +3899,18 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void dump(PrintWriter pw, String[] args) {
super.dump(pw, args);
- pw.println(" gestureExclusionRect: " + calculateGestureExclusionRect()
- + " applyQSClippingImmediately: top(" + mQsClipTop + ") bottom(" + mQsClipBottom
- + ") qsVisible(" + mQsVisible
- );
+ IndentingPrintWriter ipw = asIndenting(pw);
+ ipw.increaseIndent();
+ ipw.println("gestureExclusionRect:" + calculateGestureExclusionRect());
+ ipw.println("applyQSClippingImmediately: top(" + mQsClipTop + ") bottom(" + mQsClipBottom
+ + ")");
+ ipw.println("qsVisible:" + mQsVisible);
+ new DumpsysTableLogger(
+ TAG,
+ NPVCDownEventState.TABLE_HEADERS,
+ mLastDownEvents.toList()
+ ).printTableData(ipw);
+ ipw.decreaseIndent();
if (mKeyguardStatusBarViewController != null) {
mKeyguardStatusBarViewController.dump(pw, args);
}
@@ -4042,6 +4077,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
if (!isFullyCollapsed() && onQsIntercept(event)) {
+ if (DEBUG) Log.d(TAG, "onQsIntercept true");
return true;
}
return super.onInterceptTouchEvent(event);
@@ -4112,6 +4148,7 @@ public class NotificationPanelViewController extends PanelViewController {
handled |= mHeadsUpTouchHelper.onTouchEvent(event);
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
+ if (DEBUG) Log.d(TAG, "handleQsTouch true");
return true;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 6637394e2b2a..7ab944dc013e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -32,7 +32,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.os.SystemClock;
import android.os.VibrationEffect;
import android.util.Log;
import android.util.MathUtils;
@@ -63,6 +62,7 @@ import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.PrintWriter;
@@ -194,6 +194,7 @@ public abstract class PanelViewController {
private final PanelExpansionStateManager mPanelExpansionStateManager;
private final TouchHandler mTouchHandler;
private final InteractionJankMonitor mInteractionJankMonitor;
+ protected final SystemClock mSystemClock;
protected abstract void onExpandingFinished();
@@ -237,7 +238,8 @@ public abstract class PanelViewController {
PanelExpansionStateManager panelExpansionStateManager,
AmbientState ambientState,
InteractionJankMonitor interactionJankMonitor,
- KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
+ KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+ SystemClock systemClock) {
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
@@ -297,6 +299,7 @@ public abstract class PanelViewController {
mVibrateOnOpening = mResources.getBoolean(R.bool.config_vibrateOnIconAnimation);
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
mInteractionJankMonitor = interactionJankMonitor;
+ mSystemClock = systemClock;
}
protected void loadDimens() {
@@ -1228,7 +1231,7 @@ public abstract class PanelViewController {
mCentralSurfaces.userActivity();
mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
mMinExpandHeight = 0.0f;
- mDownTime = SystemClock.uptimeMillis();
+ mDownTime = mSystemClock.uptimeMillis();
if (mAnimatingOnDown && mClosing && !mHintAnimationRunning) {
cancelHeightAnimator();
mTouchSlopExceeded = true;
@@ -1341,7 +1344,7 @@ public abstract class PanelViewController {
mHasLayoutedSinceDown = false;
mUpdateFlingOnLayout = false;
mMotionAborted = false;
- mDownTime = SystemClock.uptimeMillis();
+ mDownTime = mSystemClock.uptimeMillis();
mTouchAboveFalsingThreshold = false;
mCollapsedAndHeadsUpOnDown =
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 6997b3e4bd70..94e6b9a12a93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -139,6 +139,7 @@ import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.wm.shell.animation.FlingAnimationUtils;
@@ -357,10 +358,12 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
private Handler mMainHandler;
private final PanelExpansionStateManager mPanelExpansionStateManager =
new PanelExpansionStateManager();
+ private SystemClock mSystemClock;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mSystemClock = new FakeSystemClock();
mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
mInteractionJankMonitor);
@@ -533,7 +536,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mPanelEventsEmitter,
mNotificationStackSizeCalculator,
mUnlockedScreenOffAnimationController,
- mShadeTransitionController);
+ mShadeTransitionController,
+ mSystemClock);
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,
() -> {},