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,