diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 9ff338e8d5ab0..0d0bafe9ac3dd 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; @@ -658,6 +659,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 a6252a39ee8a8..26fe2f9e4403c 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 0261ee53a0ff3..1e5170ab1b6fb 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 d75190e7289a3..7e455ca896b55 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java @@ -192,6 +192,8 @@ public class NotificationShadeWindowView extends FrameLayout { 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 c7a7d97aff4f8..02360434344d7 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -92,6 +92,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; @@ -146,6 +147,7 @@ public class NotificationShadeWindowViewController { KeyguardUnlockAnimationController keyguardUnlockAnimationController, NotificationInsetsController notificationInsetsController, AmbientState ambientState, + ShadeLogger shadeLogger, PulsingGestureListener pulsingGestureListener, KeyguardBouncerViewModel keyguardBouncerViewModel, KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory, @@ -168,6 +170,7 @@ public class NotificationShadeWindowViewController { mStatusBarWindowStateController = statusBarWindowStateController; mLockIconViewController = lockIconViewController; mLockIconViewController.init(); + mShadeLogger = shadeLogger; mService = centralSurfaces; mNotificationShadeWindowController = controller; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; @@ -214,6 +217,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); @@ -225,8 +235,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; @@ -238,10 +248,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) { @@ -253,8 +262,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()) { @@ -268,13 +280,13 @@ public class NotificationShadeWindowViewController { } if (mIsOcclusionTransitionRunning) { - return false; + return logDownDispatch(ev, "occlusion transition running", false); } mFalsingCollector.onTouchEvent(ev); mPulsingWakeupGestureHandler.onTouchEvent(ev); if (mStatusBarKeyguardViewManager.dispatchTouchEvent(ev)) { - return true; + return logDownDispatch(ev, "dispatched to Keyguard", true); } if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == View.VISIBLE) { @@ -282,7 +294,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) { @@ -314,7 +326,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 @@ -324,9 +338,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) { @@ -334,10 +349,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 @@ -349,18 +364,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; } @@ -371,7 +394,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; } @@ -486,6 +515,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 e5b84bd86514f..600a026eebee4 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.WindowInsets; @@ -173,6 +174,12 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout super.dispatchDraw(canvas); } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return TouchLogger.logDispatchTouch("NotificationsQuickSettingsContainer", ev, + super.dispatchTouchEvent(ev)); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { int layoutIndex = mLayoutDrawingOrder.indexOf(child); diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java index d00dab6330146..3be24ba502a31 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java @@ -25,6 +25,8 @@ import android.view.WindowManagerGlobal; import com.android.systemui.assist.AssistManager; import com.android.systemui.dagger.SysUISingleton; +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; @@ -72,6 +74,7 @@ public final class ShadeControllerImpl implements ShadeController { @Inject public ShadeControllerImpl( CommandQueue commandQueue, + @ShadeTouchLog LogBuffer touchLog, KeyguardStateController keyguardStateController, StatusBarStateController statusBarStateController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, @@ -82,6 +85,7 @@ public final class ShadeControllerImpl implements ShadeController { Lazy gutsManager ) { mCommandQueue = commandQueue; + TouchLogger.logTouchesTo(touchLog); mStatusBarStateController = statusBarStateController; mStatusBarWindowController = statusBarWindowController; mGutsManager = gutsManager; diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt index 4fdd6e19cc4c4..40a9035bbe066 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..8aa2ee4dd9ea8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/TouchLogger.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade + +import android.view.MotionEvent +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.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 df6fe3d5e434e..3862f5f4004c5 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 @@ -92,6 +92,7 @@ import com.android.systemui.flags.Flags; 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; @@ -3457,6 +3458,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 c42a6dc5b6f2c..c0b5fdfb54364 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -360,6 +360,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 3995e71d24d41..7a41d7121dfa0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -89,6 +89,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @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 @@ -167,6 +168,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { keyguardUnlockAnimationController, notificationInsetsController, ambientState, + shadeLogger, pulsingGestureListener, keyguardBouncerViewModel, keyguardBouncerComponentFactory, 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 fe9574251ddb4..f87856b05dc4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -99,6 +99,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 keyguardBouncerViewModel: KeyguardBouncerViewModel @Mock private lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory @@ -179,6 +180,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { keyguardUnlockAnimationController, notificationInsetsController, ambientState, + shadeLogger, pulsingGestureListener, keyguardBouncerViewModel, keyguardBouncerComponentFactory, 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 77026308ad381..28a172894dd28 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.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor; 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; @@ -435,6 +436,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mShadeController = spy(new ShadeControllerImpl( mCommandQueue, + mock(LogBuffer.class), mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,