diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt index 99dd6b6cd6730..670c1fa45e5ca 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt @@ -49,8 +49,11 @@ import kotlin.math.floor * When the HWC of the device supports Composition.DISPLAY_DECORATION, we use this layer to draw * screen decorations. */ -class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDecorationSupport) : - DisplayCutoutBaseView(context) { +class ScreenDecorHwcLayer( + context: Context, + displayDecorationSupport: DisplayDecorationSupport, + private val debug: Boolean, +) : DisplayCutoutBaseView(context) { val colorMode: Int private val useInvertedAlphaColor: Boolean private val color: Int @@ -74,7 +77,7 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec throw IllegalArgumentException("Attempting to use unsupported mode " + "${PixelFormat.formatToString(displayDecorationSupport.format)}") } - if (DEBUG_COLOR) { + if (debug) { color = Color.GREEN bgColor = Color.TRANSPARENT colorMode = ActivityInfo.COLOR_MODE_DEFAULT @@ -106,7 +109,7 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec override fun onAttachedToWindow() { super.onAttachedToWindow() parent.requestTransparentRegion(this) - if (!DEBUG_COLOR) { + if (!debug) { viewRootImpl.setDisplayDecoration(true) } @@ -143,12 +146,12 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec override fun gatherTransparentRegion(region: Region?): Boolean { region?.let { calculateTransparentRect() - if (DEBUG_COLOR) { + if (debug) { // Since we're going to draw a rectangle where the layer would // normally be transparent, treat the transparent region as // empty. We still want this method to be called, though, so // that it calculates the transparent rect at the right time - // to match !DEBUG_COLOR. + // to match ![debug] region.setEmpty() } else { region.op(transparentRect, Region.Op.INTERSECT) @@ -421,8 +424,4 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec ipw.println("roundedCornerBottomSize=$roundedCornerBottomSize") ipw.decreaseIndent() } - - companion object { - private val DEBUG_COLOR = ScreenDecorations.DEBUG_COLOR - } } diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 0b8d8563802d9..29f7a5e42778a 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -104,7 +104,7 @@ import javax.inject.Inject; */ @SysUISingleton public class ScreenDecorations implements CoreStartable, Dumpable { - private static final boolean DEBUG = false; + private static final boolean DEBUG_LOGGING = false; private static final String TAG = "ScreenDecorations"; // Provide a way for factory to disable ScreenDecorations to run the Display tests. @@ -112,7 +112,8 @@ public class ScreenDecorations implements CoreStartable, Dumpable { SystemProperties.getBoolean("debug.disable_screen_decorations", false); private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = SystemProperties.getBoolean("debug.screenshot_rounded_corners", false); - static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS; + private boolean mDebug = DEBUG_SCREENSHOT_ROUNDED_CORNERS; + private int mDebugColor = Color.RED; private static final int[] DISPLAY_CUTOUT_IDS = { R.id.display_cutout, @@ -357,6 +358,26 @@ public class ScreenDecorations implements CoreStartable, Dumpable { mAuthController.addCallback(mAuthControllerCallback); } + /** + * Change the value of {@link ScreenDecorations#mDebug}. This operation is heavyweight, since + * it requires essentially re-init-ing this screen decorations process with the debug + * information taken into account. + */ + private void setDebug(boolean debug) { + if (mDebug == debug) { + return; + } + + mExecutor.execute(() -> { + // Re-trigger all of the screen decorations setup here so that the debug values + // can be picked up + removeAllOverlays(); + removeHwcOverlay(); + startOnScreenDecorationsThread(); + updateColorInversionDefault(); + }); + } + private boolean isPrivacyDotEnabled() { return mDotFactory.getHasProviders(); } @@ -436,15 +457,12 @@ public class ScreenDecorations implements CoreStartable, Dumpable { // - we are trying to redraw. This because WM resized our window and told us to. // - the config change has been dispatched, so WM is no longer deferring layout. mPendingConfigChange = true; - if (DEBUG) { - if (mRotation != newRotation) { - Log.i(TAG, "Rotation changed, deferring " + newRotation - + ", staying at " + mRotation); - } - if (displayModeChanged(mDisplayMode, newDisplayMode)) { - Log.i(TAG, "Resolution changed, deferring " + newDisplayMode - + ", staying at " + mDisplayMode); - } + if (mRotation != newRotation) { + mLogger.logRotationChangeDeferred(mRotation, newRotation); + } + if (displayModeChanged(mDisplayMode, newDisplayMode)) { + mLogger.logDisplayModeChanged( + newDisplayMode.getModeId(), mDisplayMode.getModeId()); } if (mOverlays != null) { @@ -757,7 +775,8 @@ public class ScreenDecorations implements CoreStartable, Dumpable { } mScreenDecorHwcWindow = (ViewGroup) LayoutInflater.from(mContext).inflate( R.layout.screen_decor_hwc_layer, null); - mScreenDecorHwcLayer = new ScreenDecorHwcLayer(mContext, mHwcScreenDecorationSupport); + mScreenDecorHwcLayer = + new ScreenDecorHwcLayer(mContext, mHwcScreenDecorationSupport, mDebug); mScreenDecorHwcWindow.addView(mScreenDecorHwcLayer, new FrameLayout.LayoutParams( MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START)); mWindowManager.addView(mScreenDecorHwcWindow, getHwcWindowLayoutParams()); @@ -805,7 +824,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable { lp.height = MATCH_PARENT; lp.setTitle("ScreenDecorHwcOverlay"); lp.gravity = Gravity.TOP | Gravity.START; - if (!DEBUG_COLOR) { + if (!mDebug) { lp.setColorMode(ActivityInfo.COLOR_MODE_A8); } return lp; @@ -913,19 +932,40 @@ public class ScreenDecorations implements CoreStartable, Dumpable { new UserTracker.Callback() { @Override public void onUserChanged(int newUser, @NonNull Context userContext) { - if (DEBUG) { - Log.d(TAG, "UserSwitched newUserId=" + newUser); - } + mLogger.logUserSwitched(newUser); // update color inversion setting to the new user mColorInversionSetting.setUserId(newUser); updateColorInversion(mColorInversionSetting.getValue()); } }; + /** + * Use the current value of {@link ScreenDecorations#mColorInversionSetting} and passes it + * to {@link ScreenDecorations#updateColorInversion} + */ + private void updateColorInversionDefault() { + int inversion = 0; + if (mColorInversionSetting != null) { + inversion = mColorInversionSetting.getValue(); + } + + updateColorInversion(inversion); + } + + /** + * Update the tint color of screen decoration assets. Defaults to Color.BLACK. In the case of + * a color inversion being set, use Color.WHITE (which inverts to black). + * + * When {@link ScreenDecorations#mDebug} is {@code true}, this value is updated to use + * {@link ScreenDecorations#mDebugColor}, and does not handle inversion. + * + * @param colorsInvertedValue if non-zero, assume that colors are inverted, and use Color.WHITE + * for screen decoration tint + */ private void updateColorInversion(int colorsInvertedValue) { mTintColor = colorsInvertedValue != 0 ? Color.WHITE : Color.BLACK; - if (DEBUG_COLOR) { - mTintColor = Color.RED; + if (mDebug) { + mTintColor = mDebugColor; } updateOverlayProviderViews(new Integer[] { @@ -966,7 +1006,9 @@ public class ScreenDecorations implements CoreStartable, Dumpable { int oldRotation = mRotation; mPendingConfigChange = false; updateConfiguration(); - if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation); + if (oldRotation != mRotation) { + mLogger.logRotationChanged(oldRotation, mRotation); + } setupDecorations(); if (mOverlays != null) { // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(), @@ -1199,7 +1241,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable { paint.setColor(mColor); paint.setStyle(Paint.Style.FILL); - if (DEBUG) { + if (DEBUG_LOGGING) { getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG, getWindowTitleByPos(pos) + " drawn in rot " + mRotation)); } @@ -1392,7 +1434,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable { mView.getViewTreeObserver().removeOnPreDrawListener(this); if (mTargetRotation == mRotation && !displayModeChanged(mDisplayMode, mTargetDisplayMode)) { - if (DEBUG) { + if (DEBUG_LOGGING) { final String title = mPosition < 0 ? "ScreenDecorHwcLayer" : getWindowTitleByPos(mPosition); Log.i(TAG, title + " already in target rot " @@ -1408,7 +1450,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable { // This changes the window attributes - we need to restart the traversal for them to // take effect. updateConfiguration(); - if (DEBUG) { + if (DEBUG_LOGGING) { final String title = mPosition < 0 ? "ScreenDecorHwcLayer" : getWindowTitleByPos(mPosition); Log.i(TAG, title @@ -1443,7 +1485,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable { final Display.Mode displayMode = mDisplayInfo.getMode(); if ((displayRotation != mRotation || displayModeChanged(mDisplayMode, displayMode)) && !mPendingConfigChange) { - if (DEBUG) { + if (DEBUG_LOGGING) { if (displayRotation != mRotation) { Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot " + displayRotation + ". Restarting draw"); diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt index f7277842c0265..27301e92eca22 100644 --- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt @@ -21,9 +21,9 @@ import android.graphics.Rect import android.graphics.RectF import androidx.core.graphics.toRectF import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.DEBUG import com.android.systemui.log.LogLevel.ERROR +import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.dagger.ScreenDecorationsLog import com.google.errorprone.annotations.CompileTimeConstant import javax.inject.Inject @@ -164,4 +164,49 @@ constructor( fun cameraProtectionEvent(@CompileTimeConstant cameraProtectionEvent: String) { logBuffer.log(TAG, DEBUG, cameraProtectionEvent) } + + fun logRotationChangeDeferred(currentRot: Int, newRot: Int) { + logBuffer.log( + TAG, + INFO, + { + int1 = currentRot + int2 = newRot + }, + { "Rotation changed, deferring $int2, staying at $int2" }, + ) + } + + fun logRotationChanged(oldRot: Int, newRot: Int) { + logBuffer.log( + TAG, + INFO, + { + int1 = oldRot + int2 = newRot + }, + { "Rotation changed from $int1 to $int2" } + ) + } + + fun logDisplayModeChanged(currentMode: Int, newMode: Int) { + logBuffer.log( + TAG, + INFO, + { + int1 = currentMode + int2 = newMode + }, + { "Resolution changed, deferring mode change to $int2, staying at $int1" }, + ) + } + + fun logUserSwitched(newUser: Int) { + logBuffer.log( + TAG, + DEBUG, + { int1 = newUser }, + { "UserSwitched newUserId=$int1. Updating color inversion setting" }, + ) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt index 8207fa6958f33..d500b5aebcbfd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt @@ -74,7 +74,8 @@ class ScreenDecorHwcLayerTest : SysuiTestCase() { val decorationSupport = DisplayDecorationSupport() decorationSupport.format = PixelFormat.R_8 - decorHwcLayer = Mockito.spy(ScreenDecorHwcLayer(mContext, decorationSupport)) + decorHwcLayer = + Mockito.spy(ScreenDecorHwcLayer(mContext, decorationSupport, /* debug */ false)) whenever(decorHwcLayer.width).thenReturn(displayWidth) whenever(decorHwcLayer.height).thenReturn(displayHeight) whenever(decorHwcLayer.context).thenReturn(mockContext)