From 9b9086cbe79eb0b97847eaf07319e1c626f2973b Mon Sep 17 00:00:00 2001 From: Justin Weir Date: Mon, 7 Aug 2023 21:47:11 -0400 Subject: [PATCH] Add LogBuffer that passively tracks touch handling in the shade Logs will passively observe calls to ViewGroup.onInterceptTouchEvent for all top level ViewGroups for each major section of the shade, e.g. QS, NSSL, Keyguard, Bouncer. Additionally, it will track touches on Views near the top of the shade's hierarchy like scrims and the long press detector. Bug: 288507023 Bug: 288505944 Test: updated and ran affected tests Test: manual verification of logs Change-Id: Ic3b94ae80b7cff462d3ae0af62d8466885fb684c --- .../keyguard/KeyguardSecurityContainer.java | 6 ++ .../android/keyguard/KeyguardStatusView.java | 7 ++ .../common/ui/view/LongPressHandlingView.kt | 5 ++ .../systemui/log/dagger/LogModule.java | 8 ++ .../systemui/log/dagger/ShadeTouchLog.java | 33 ++++++++ .../android/systemui/qs/QSContainerImpl.java | 7 ++ .../com/android/systemui/scrim/ScrimView.java | 12 +++ .../systemui/shade/NotificationPanelView.java | 5 ++ .../shade/NotificationShadeWindowView.java | 2 + ...NotificationShadeWindowViewController.java | 70 +++++++++++----- .../NotificationsQuickSettingsContainer.java | 7 ++ .../systemui/shade/ShadeControllerImpl.java | 6 ++ .../com/android/systemui/shade/ShadeLogger.kt | 46 ++++++++--- .../com/android/systemui/shade/TouchLogger.kt | 62 +++++++++++++++ .../systemui/statusbar/LightRevealScrim.kt | 8 ++ .../stack/NotificationStackScrollLayout.java | 6 ++ .../statusbar/phone/ScrimController.java | 3 + ...tificationShadeWindowViewControllerTest.kt | 79 ++++++++++--------- .../shade/NotificationShadeWindowViewTest.kt | 2 + .../systemui/shade/ShadeControllerImplTest.kt | 3 + .../phone/CentralSurfacesImplTest.java | 2 + 21 files changed, 307 insertions(+), 72 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/log/dagger/ShadeTouchLog.java create mode 100644 packages/SystemUI/src/com/android/systemui/shade/TouchLogger.kt diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 42a4e7202c824..42dceb82a9a70 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -100,6 +100,7 @@ import com.android.systemui.Gefingerpoken; import com.android.systemui.R; import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.shade.TouchLogger; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -665,6 +666,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return insets.inset(0, 0, 0, inset); } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev)); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 75852793c24d4..5774e42d24257 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -23,12 +23,14 @@ import android.graphics.Canvas; import android.os.Build; import android.os.Trace; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.widget.GridLayout; import com.android.systemui.R; +import com.android.systemui.shade.TouchLogger; import com.android.systemui.statusbar.CrossFadeHelper; import java.io.PrintWriter; @@ -110,6 +112,11 @@ public class KeyguardStatusView extends GridLayout { } } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev)); + } + public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardStatusView:"); pw.println(" mDarkAmount: " + mDarkAmount); diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt index 2dd98dcf41b6e..323070a848633 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt @@ -22,6 +22,7 @@ import android.content.Context import android.util.AttributeSet import android.view.MotionEvent import android.view.View +import com.android.systemui.shade.TouchLogger import kotlin.math.pow import kotlin.math.sqrt import kotlinx.coroutines.DisposableHandle @@ -83,6 +84,10 @@ class LongPressHandlingView( interactionHandler.isLongPressHandlingEnabled = isEnabled } + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + return TouchLogger.logDispatchTouch("long_press", event, super.dispatchTouchEvent(event)) + } + @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent?): Boolean { return interactionHandler.onTouchEvent(event?.toModel()) diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index cc1504a1df977..b6577f747f038 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -120,6 +120,14 @@ public class LogModule { return factory.create("ShadeLog", 500, false); } + /** Provides a logging buffer for Shade messages. */ + @Provides + @SysUISingleton + @ShadeTouchLog + public static LogBuffer provideShadeTouchLogBuffer(LogBufferFactory factory) { + return factory.create("ShadeTouchLog", 500, false); + } + /** Provides a logging buffer for all logs related to managing notification sections. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeTouchLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeTouchLog.java new file mode 100644 index 0000000000000..b13667e4822bd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeTouchLog.java @@ -0,0 +1,33 @@ +/* + * 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.log.dagger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.android.systemui.log.LogBuffer; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Qualifier; + +/** A {@link LogBuffer} for tracking touches in various shade child views. */ +@Qualifier +@Documented +@Retention(RUNTIME) +public @interface ShadeTouchLog { +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index 1afc885cb70d8..d2eac45754bd7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -23,12 +23,14 @@ import android.graphics.Canvas; import android.graphics.Path; import android.graphics.PointF; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.qs.customize.QSCustomizer; +import com.android.systemui.shade.TouchLogger; import com.android.systemui.util.LargeScreenUtils; import java.io.PrintWriter; @@ -128,6 +130,11 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { } } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch("QS", ev, super.dispatchTouchEvent(ev)); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java index fc89a9e637ec6..f4d19dc2691d2 100644 --- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java +++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java @@ -30,6 +30,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Looper; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import androidx.annotation.Nullable; @@ -38,6 +39,7 @@ import androidx.core.graphics.ColorUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor; +import com.android.systemui.shade.TouchLogger; import com.android.systemui.util.LargeScreenUtils; import java.util.concurrent.Executor; @@ -59,6 +61,7 @@ public class ScrimView extends View { private float mViewAlpha = 1.0f; private Drawable mDrawable; private PorterDuffColorFilter mColorFilter; + private String mScrimName; private int mTintColor; private boolean mBlendWithMainColor = true; private Runnable mChangeRunnable; @@ -336,6 +339,15 @@ public class ScrimView extends View { } } + public void setScrimName(String scrimName) { + mScrimName = scrimName; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch(mScrimName, ev, super.dispatchTouchEvent(ev)); + } + /** * The position of the bottom of the scrim, used for clipping. * @see #enableBottomEdgeConcave(boolean) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java index af3cc860df574..c501d88b77ce7 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java @@ -105,6 +105,11 @@ public final class NotificationPanelView extends FrameLayout { return mTouchHandler.onInterceptTouchEvent(event); } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch("NPV", ev, super.dispatchTouchEvent(ev)); + } + @Override public void dispatchConfigurationChanged(Configuration newConfig) { super.dispatchConfigurationChanged(newConfig); diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java index a9c4aebe7ed69..f9b4e671f373e 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java @@ -107,6 +107,8 @@ public class NotificationShadeWindowView extends WindowRootView { result = result != null ? result : super.dispatchTouchEvent(ev); + TouchLogger.logDispatchTouch(TAG, ev, result); + mInteractionEventHandler.dispatchTouchEventComplete(); return result; diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 5b5785e36ccc6..832a25bfbc414 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -91,6 +91,7 @@ public class NotificationShadeWindowViewController { private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; private final LockIconViewController mLockIconViewController; + private final ShadeLogger mShadeLogger; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final StatusBarWindowStateController mStatusBarWindowStateController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @@ -151,6 +152,7 @@ public class NotificationShadeWindowViewController { KeyguardUnlockAnimationController keyguardUnlockAnimationController, NotificationInsetsController notificationInsetsController, AmbientState ambientState, + ShadeLogger shadeLogger, PulsingGestureListener pulsingGestureListener, LockscreenHostedDreamGestureListener lockscreenHostedDreamGestureListener, KeyguardBouncerViewModel keyguardBouncerViewModel, @@ -176,6 +178,7 @@ public class NotificationShadeWindowViewController { mStatusBarWindowStateController = statusBarWindowStateController; mLockIconViewController = lockIconViewController; mBackActionInteractor = backActionInteractor; + mShadeLogger = shadeLogger; mLockIconViewController.init(); mService = centralSurfaces; mPowerInteractor = powerInteractor; @@ -223,6 +226,13 @@ public class NotificationShadeWindowViewController { return mView.findViewById(R.id.keyguard_message_area); } + private Boolean logDownDispatch(MotionEvent ev, String msg, Boolean result) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mShadeLogger.logShadeWindowDispatch(ev, msg, result); + } + return result; + } + /** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */ public void setupExpandedStatusBar() { mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller); @@ -237,8 +247,8 @@ public class NotificationShadeWindowViewController { @Override public Boolean handleDispatchTouchEvent(MotionEvent ev) { if (mStatusBarViewController == null) { // Fix for b/192490822 - Log.w(TAG, "Ignoring touch while statusBarView not yet set."); - return false; + return logDownDispatch(ev, + "Ignoring touch while statusBarView not yet set", false); } boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP; @@ -250,10 +260,9 @@ public class NotificationShadeWindowViewController { } // Reset manual touch dispatch state here but make sure the UP/CANCEL event still - // gets - // delivered. + // gets delivered. if (!isCancel && mService.shouldIgnoreTouch()) { - return false; + return logDownDispatch(ev, "touch ignored by CS", false); } if (isDown) { @@ -265,8 +274,11 @@ public class NotificationShadeWindowViewController { mTouchActive = false; mDownEvent = null; } - if (mTouchCancelled || mExpandAnimationRunning) { - return false; + if (mTouchCancelled) { + return logDownDispatch(ev, "touch cancelled", false); + } + if (mExpandAnimationRunning) { + return logDownDispatch(ev, "expand animation running", false); } if (mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { @@ -280,17 +292,17 @@ public class NotificationShadeWindowViewController { } if (mIsOcclusionTransitionRunning) { - return false; + return logDownDispatch(ev, "occlusion transition running", false); } mFalsingCollector.onTouchEvent(ev); mPulsingWakeupGestureHandler.onTouchEvent(ev); if (mDreamingWakeupGestureHandler != null && mDreamingWakeupGestureHandler.onTouchEvent(ev)) { - return true; + return logDownDispatch(ev, "dream wakeup gesture handled", true); } if (mStatusBarKeyguardViewManager.dispatchTouchEvent(ev)) { - return true; + return logDownDispatch(ev, "dispatched to Keyguard", true); } if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == View.VISIBLE) { @@ -298,7 +310,7 @@ public class NotificationShadeWindowViewController { // you can't touch anything other than the brightness slider while the mirror is // showing and the rest of the panel is transparent. if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { - return false; + return logDownDispatch(ev, "disallowed new pointer", false); } } if (isDown) { @@ -329,7 +341,9 @@ public class NotificationShadeWindowViewController { expandingBelowNotch = true; } if (expandingBelowNotch) { - return mStatusBarViewController.sendTouchToView(ev); + return logDownDispatch(ev, + "expand below notch. sending touch to status bar", + mStatusBarViewController.sendTouchToView(ev)); } if (!mIsTrackingBarGesture && isDown @@ -339,9 +353,10 @@ public class NotificationShadeWindowViewController { if (mStatusBarViewController.touchIsWithinView(x, y)) { if (mStatusBarWindowStateController.windowIsShowing()) { mIsTrackingBarGesture = true; - return mStatusBarViewController.sendTouchToView(ev); - } else { // it's hidden or hiding, don't send to notification shade. - return true; + return logDownDispatch(ev, "sending touch to status bar", + mStatusBarViewController.sendTouchToView(ev)); + } else { + return logDownDispatch(ev, "hidden or hiding", true); } } } else if (mIsTrackingBarGesture) { @@ -349,10 +364,10 @@ public class NotificationShadeWindowViewController { if (isUp || isCancel) { mIsTrackingBarGesture = false; } - return sendToStatusBar; + return logDownDispatch(ev, "sending bar gesture to status bar", + sendToStatusBar); } - - return null; + return logDownDispatch(ev, "no custom touch dispatch of down event", null); } @Override @@ -364,18 +379,26 @@ public class NotificationShadeWindowViewController { public boolean shouldInterceptTouchEvent(MotionEvent ev) { if (mStatusBarStateController.isDozing() && !mService.isPulsing() && !mDockManager.isDocked()) { - // Capture all touch events in always-on. + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mShadeLogger.d("NSWVC: capture all touch events in always-on"); + } return true; } if (mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(ev)) { // Don't allow touches to proceed to underlying views if alternate // bouncer is showing + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mShadeLogger.d("NSWVC: alt bouncer showing"); + } return true; } if (mLockIconViewController.onInterceptTouchEvent(ev)) { // immediately return true; don't send the touch to the drag down helper + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mShadeLogger.d("NSWVC: don't send touch to drag down helper"); + } return true; } @@ -383,7 +406,13 @@ public class NotificationShadeWindowViewController { && mDragDownHelper.isDragDownEnabled() && !mService.isBouncerShowing() && !mStatusBarStateController.isDozing()) { - return mDragDownHelper.onInterceptTouchEvent(ev); + boolean result = mDragDownHelper.onInterceptTouchEvent(ev); + if (result) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mShadeLogger.d("NSWVC: drag down helper intercepted"); + } + } + return result; } else { return false; } @@ -495,6 +524,7 @@ public class NotificationShadeWindowViewController { } public void cancelCurrentTouch() { + mShadeLogger.d("NSWVC: cancelling current touch"); if (mTouchActive) { final long now = mClock.uptimeMillis(); final MotionEvent event; diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java index 3b3df50f15206..a4e439b04fc01 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java @@ -22,6 +22,7 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.view.WindowInsets; @@ -182,6 +183,12 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout mIsMigratingNSSL = isMigrating; } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch("NotificationsQuickSettingsContainer", ev, + super.dispatchTouchEvent(ev)); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (mIsMigratingNSSL) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java index 22c638177a480..d7a3392104125 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java @@ -27,6 +27,8 @@ import android.view.WindowManagerGlobal; import com.android.systemui.assist.AssistManager; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.log.LogBuffer; +import com.android.systemui.log.dagger.ShadeTouchLog; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationPresenter; @@ -56,6 +58,7 @@ public final class ShadeControllerImpl implements ShadeController { private final CommandQueue mCommandQueue; private final Executor mMainExecutor; + private final LogBuffer mTouchLog; private final KeyguardStateController mKeyguardStateController; private final NotificationShadeWindowController mNotificationShadeWindowController; private final StatusBarStateController mStatusBarStateController; @@ -79,6 +82,7 @@ public final class ShadeControllerImpl implements ShadeController { public ShadeControllerImpl( CommandQueue commandQueue, @Main Executor mainExecutor, + @ShadeTouchLog LogBuffer touchLog, KeyguardStateController keyguardStateController, StatusBarStateController statusBarStateController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, @@ -92,6 +96,7 @@ public final class ShadeControllerImpl implements ShadeController { ) { mCommandQueue = commandQueue; mMainExecutor = mainExecutor; + mTouchLog = touchLog; mShadeViewControllerLazy = shadeViewControllerLazy; mStatusBarStateController = statusBarStateController; mStatusBarWindowController = statusBarWindowController; @@ -413,6 +418,7 @@ public final class ShadeControllerImpl implements ShadeController { @Override public void start() { + TouchLogger.logTouchesTo(mTouchLog); getShadeViewController().setTrackingStartedListener(this::runPostCollapseRunnables); getShadeViewController().setOpenCloseListener( new OpenCloseListener() { diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt index 1c30bddfe8596..c3ef925f4578a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt @@ -79,19 +79,39 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) { fun logMotionEvent(event: MotionEvent, message: String) { buffer.log( - TAG, - LogLevel.VERBOSE, - { - str1 = message - long1 = event.eventTime - long2 = event.downTime - int1 = event.action - int2 = event.classification - double1 = event.y.toDouble() - }, - { - "$str1: eventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2" - } + TAG, + LogLevel.VERBOSE, + { + str1 = message + long1 = event.eventTime + long2 = event.downTime + int1 = event.action + int2 = event.classification + }, + { + "$str1: eventTime=$long1,downTime=$long2,action=$int1,class=$int2" + } + ) + } + + /** Logs motion event dispatch results from NotificationShadeWindowViewController. */ + fun logShadeWindowDispatch(event: MotionEvent, message: String, result: Boolean?) { + buffer.log( + TAG, + LogLevel.VERBOSE, + { + str1 = message + long1 = event.eventTime + long2 = event.downTime + }, + { + val prefix = when (result) { + true -> "SHADE TOUCH REROUTED" + false -> "SHADE TOUCH BLOCKED" + null -> "SHADE TOUCH DISPATCHED" + } + "$prefix: eventTime=$long1,downTime=$long2, reason=$str1" + } ) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/TouchLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/TouchLogger.kt new file mode 100644 index 0000000000000..d96dc12f55495 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/TouchLogger.kt @@ -0,0 +1,62 @@ +package com.android.systemui.shade + +import android.view.MotionEvent +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel + +private const val TAG = "systemui.shade.touch" + +/** + * A logger for tracking touch dispatching in the shade view hierarchy. The purpose of this logger + * is to passively observe dispatchTouchEvent calls in order to see which subtrees of the shade are + * handling touches. Additionally, some touches may be passively observed for views near the top of + * the shade hierarchy that cannot intercept touches, i.e. scrims. The usage of static methods for + * logging is sub-optimal in many ways, but it was selected in this case to make usage of this + * non-function diagnostic code as low friction as possible. + */ +class TouchLogger { + companion object { + private var touchLogger: DispatchTouchLogger? = null + + @JvmStatic + fun logTouchesTo(buffer: LogBuffer) { + touchLogger = DispatchTouchLogger(buffer) + } + + @JvmStatic + fun logDispatchTouch(viewTag: String, ev: MotionEvent, result: Boolean): Boolean { + touchLogger?.logDispatchTouch(viewTag, ev, result) + return result + } + } +} + +/** Logs touches. */ +private class DispatchTouchLogger(private val buffer: LogBuffer) { + fun logDispatchTouch(viewTag: String, ev: MotionEvent, result: Boolean) { + // NOTE: never log position of touches for security purposes + buffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = viewTag + int1 = ev.action + long1 = ev.downTime + bool1 = result + }, + { "Touch: view=$str1, type=${typeToString(int1)}, downtime=$long1, result=$bool1" } + ) + } + + private fun typeToString(type: Int): String { + return when (type) { + MotionEvent.ACTION_DOWN -> "DOWN" + MotionEvent.ACTION_UP -> "UP" + MotionEvent.ACTION_MOVE -> "MOVE" + MotionEvent.ACTION_CANCEL -> "CANCEL" + MotionEvent.ACTION_POINTER_DOWN -> "POINTER_DOWN" + MotionEvent.ACTION_POINTER_UP -> "POINTER_UP" + else -> "OTHER" + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt index 823bb355a3075..5e449900248ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt @@ -14,9 +14,11 @@ import android.graphics.Shader import android.os.Trace import android.util.AttributeSet import android.util.MathUtils.lerp +import android.view.MotionEvent import android.view.View import android.view.animation.PathInterpolator import com.android.app.animation.Interpolators +import com.android.systemui.shade.TouchLogger import com.android.systemui.statusbar.LightRevealEffect.Companion.getPercentPastThreshold import com.android.systemui.util.getColorWithAlpha import com.android.systemui.util.leak.RotationUtils @@ -234,6 +236,8 @@ class PowerButtonReveal( } } +private const val TAG = "LightRevealScrim" + /** * Scrim view that partially reveals the content underneath it using a [RadialGradient] with a * transparent center. The center position, size, and stops of the gradient can be manipulated to @@ -447,6 +451,10 @@ constructor( canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), gradientPaint) } + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + return TouchLogger.logDispatchTouch(TAG, event, super.dispatchTouchEvent(event)) + } + private fun setPaintColorFilter() { gradientPaint.colorFilter = PorterDuffColorFilter( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index d71bc2fd64702..5e3a67ece4a5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -93,6 +93,7 @@ import com.android.systemui.flags.ViewRefactorFlag; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.shade.ShadeController; +import com.android.systemui.shade.TouchLogger; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.NotificationShelf; @@ -3480,6 +3481,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return super.onTouchEvent(ev); } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev)); + } + void dispatchDownEventToScroller(MotionEvent ev) { MotionEvent downEvent = MotionEvent.obtain(ev); downEvent.setAction(MotionEvent.ACTION_DOWN); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index e82ac59b67469..fc661384146c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -370,6 +370,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mScrimBehind = behindScrim; mScrimInFront = scrimInFront; updateThemeColors(); + mNotificationsScrim.setScrimName(getScrimName(mNotificationsScrim)); + mScrimBehind.setScrimName(getScrimName(mScrimBehind)); + mScrimInFront.setScrimName(getScrimName(mScrimInFront)); behindScrim.enableBottomEdgeConcave(mClipsQsScrim); mNotificationsScrim.enableRoundedCorners(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index 7b3e89dc00177..1edeeffe52174 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -95,7 +95,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController - @Mock private lateinit var shadeController: ShadeController + @Mock private lateinit var shadeLogger: ShadeLogger @Mock private lateinit var ambientState: AmbientState @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController @@ -150,44 +150,45 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { testScope = TestScope() underTest = NotificationShadeWindowViewController( - lockscreenShadeTransitionController, - FalsingCollectorFake(), - sysuiStatusBarStateController, - dockManager, - notificationShadeDepthController, - view, - notificationPanelViewController, - ShadeExpansionStateManager(), - stackScrollLayoutController, - statusBarKeyguardViewManager, - statusBarWindowStateController, - lockIconViewController, - centralSurfaces, - backActionInteractor, - powerInteractor, - notificationShadeWindowController, - unfoldTransitionProgressProvider, - keyguardUnlockAnimationController, - notificationInsetsController, - ambientState, - pulsingGestureListener, - mLockscreenHostedDreamGestureListener, - keyguardBouncerViewModel, - keyguardBouncerComponentFactory, - mock(KeyguardMessageAreaController.Factory::class.java), - keyguardTransitionInteractor, - primaryBouncerToGoneTransitionViewModel, - notificationExpansionRepository, - featureFlags, - FakeSystemClock(), - BouncerMessageInteractor( - FakeBouncerMessageRepository(), - mock(BouncerMessageFactory::class.java), - FakeUserRepository(), - CountDownTimerUtil(), - featureFlags - ), - BouncerLogger(logcatLogBuffer("BouncerLog")) + lockscreenShadeTransitionController, + FalsingCollectorFake(), + sysuiStatusBarStateController, + dockManager, + notificationShadeDepthController, + view, + notificationPanelViewController, + ShadeExpansionStateManager(), + stackScrollLayoutController, + statusBarKeyguardViewManager, + statusBarWindowStateController, + lockIconViewController, + centralSurfaces, + backActionInteractor, + powerInteractor, + notificationShadeWindowController, + unfoldTransitionProgressProvider, + keyguardUnlockAnimationController, + notificationInsetsController, + ambientState, + shadeLogger, + pulsingGestureListener, + mLockscreenHostedDreamGestureListener, + keyguardBouncerViewModel, + keyguardBouncerComponentFactory, + mock(KeyguardMessageAreaController.Factory::class.java), + keyguardTransitionInteractor, + primaryBouncerToGoneTransitionViewModel, + notificationExpansionRepository, + featureFlags, + FakeSystemClock(), + BouncerMessageInteractor( + FakeBouncerMessageRepository(), + mock(BouncerMessageFactory::class.java), + FakeUserRepository(), + CountDownTimerUtil(), + featureFlags + ), + BouncerLogger(logcatLogBuffer("BouncerLog")) ) underTest.setupExpandedStatusBar() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt index 5c3ce71e33d28..829184c4f05a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -105,6 +105,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { @Mock private lateinit var lockIconViewController: LockIconViewController @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController @Mock private lateinit var ambientState: AmbientState + @Mock private lateinit var shadeLogger: ShadeLogger @Mock private lateinit var pulsingGestureListener: PulsingGestureListener @Mock private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener @@ -179,6 +180,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { keyguardUnlockAnimationController, notificationInsetsController, ambientState, + shadeLogger, pulsingGestureListener, mLockscreenHostedDreamGestureListener, keyguardBouncerViewModel, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt index 52e0c9c9936bf..6a14a005b0f09 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt @@ -22,6 +22,7 @@ import android.view.WindowManager import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.assist.AssistManager +import com.android.systemui.log.LogBuffer import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.NotificationShadeWindowController @@ -59,6 +60,7 @@ class ShadeControllerImplTest : SysuiTestCase() { @Mock private lateinit var shadeViewController: ShadeViewController @Mock private lateinit var nswvc: NotificationShadeWindowViewController @Mock private lateinit var display: Display + @Mock private lateinit var touchLog: LogBuffer private lateinit var shadeController: ShadeControllerImpl @@ -71,6 +73,7 @@ class ShadeControllerImplTest : SysuiTestCase() { ShadeControllerImpl( commandQueue, FakeExecutor(FakeSystemClock()), + touchLog, keyguardStateController, statusBarStateController, statusBarKeyguardViewManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 61da90165c82e..39b2948794508 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -115,6 +115,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel; +import com.android.systemui.log.LogBuffer; import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.notetask.NoteTaskController; import com.android.systemui.plugins.ActivityStarter; @@ -441,6 +442,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mShadeController = spy(new ShadeControllerImpl( mCommandQueue, mMainExecutor, + mock(LogBuffer.class), mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,