Adding ColorUpdateLogger to track color updates so that we demonstrate the root cause of our theme bugs
Bug: 294347738
Test: dumpsysui ColorUpdateLogger
Change-Id: I4879dd28a8d88b3ee6fc1f09c9029eb653bfa460
Flag: ACONFIG com.android.systemui.notification_color_update_logger DEVELOPMENT
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 2c285c8..2240843 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -29,6 +29,13 @@
}
flag {
+ name: "notification_color_update_logger"
+ namespace: "systemui"
+ description: "Enabled debug logging and dumping of notification color updates."
+ bug: "294347738"
+}
+
+flag {
name: "notifications_footer_view_refactor"
namespace: "systemui"
description: "Enables the refactored version of the footer view in the notification shade "
@@ -452,4 +459,3 @@
purpose: PURPOSE_BUGFIX
}
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0e0f152..6155348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import static com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress;
+import static com.android.systemui.util.ColorUtilKt.hexColorString;
import android.content.Context;
import android.content.res.Configuration;
@@ -42,6 +43,7 @@
import com.android.systemui.flags.RefactorFlag;
import com.android.systemui.res.R;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -187,8 +189,8 @@
@Override
public String toString() {
- return "NotificationShelf"
- + "(hideBackground=" + mHideBackground
+ return super.toString()
+ + " (hideBackground=" + mHideBackground
+ " notGoneIndex=" + mNotGoneIndex
+ " hasItemsInStableShelf=" + mHasItemsInStableShelf
+ " interactive=" + mInteractive
@@ -368,6 +370,17 @@
&& isYInView(localY, slop, top, bottom);
}
+ @Override
+ public void updateBackgroundColors() {
+ super.updateBackgroundColors();
+ ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();
+ if (colorUpdateLogger != null) {
+ colorUpdateLogger.logEvent("Shelf.updateBackgroundColors()",
+ "normalBgColor=" + hexColorString(getNormalBgColor())
+ + " background=" + mBackgroundNormal.toDumpString());
+ }
+ }
+
/**
* Update the shelf appearance based on the other notifications around it. This transforms
* the icons from the notification area into the shelf.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt
new file mode 100644
index 0000000..c8f996a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt
@@ -0,0 +1,153 @@
+/*
+ * 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.statusbar.notification
+
+import android.icu.text.SimpleDateFormat
+import android.util.IndentingPrintWriter
+import com.android.systemui.Dumpable
+import com.android.systemui.Flags.notificationColorUpdateLogger
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.util.Compile
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.printCollection
+import com.android.systemui.util.withIncreasedIndent
+import com.google.errorprone.annotations.CompileTimeConstant
+import java.io.PrintWriter
+import java.util.Locale
+import java.util.SortedSet
+import java.util.TreeSet
+import javax.inject.Inject
+
+@SysUISingleton
+class ColorUpdateLogger
+@Inject
+constructor(
+ val featureFlags: FeatureFlagsClassic,
+ dumpManager: DumpManager,
+) : Dumpable {
+
+ inline val isEnabled
+ get() = Compile.IS_DEBUG && notificationColorUpdateLogger()
+ private val frames: MutableList<Frame> = mutableListOf()
+
+ init {
+ dumpManager.registerDumpable(this)
+ if (isEnabled) {
+ instance = this
+ }
+ }
+
+ @JvmOverloads
+ fun logTriggerEvent(@CompileTimeConstant type: String, extra: String? = null) {
+ if (!isEnabled) return
+ val event = Event(type = type, extraValue = extra)
+ val didAppend = frames.lastOrNull()?.tryAddTrigger(event) == true
+ if (!didAppend) {
+ frames.add(Frame(event))
+ if (frames.size > maxFrames) frames.removeFirst()
+ }
+ }
+
+ @JvmOverloads
+ fun logEvent(@CompileTimeConstant type: String, extra: String? = null) {
+ if (!isEnabled) return
+ val frame = frames.lastOrNull() ?: return
+ frame.events.add(Event(type = type, extraValue = extra))
+ frame.trim()
+ }
+
+ @JvmOverloads
+ fun logNotificationEvent(
+ @CompileTimeConstant type: String,
+ key: String,
+ extra: String? = null
+ ) {
+ if (!isEnabled) return
+ val frame = frames.lastOrNull() ?: return
+ frame.events.add(Event(type = type, extraValue = extra, notificationKey = key))
+ frame.trim()
+ }
+
+ override fun dump(pwOrig: PrintWriter, args: Array<out String>) {
+ val pw = pwOrig.asIndenting()
+ pw.println("enabled: $isEnabled")
+ pw.printCollection("frames", frames) { it.dump(pw) }
+ }
+
+ private class Frame(event: Event) {
+ val startTime: Long = event.time
+ val events: MutableList<Event> = mutableListOf(event)
+ val triggers: SortedSet<String> = TreeSet<String>().apply { add(event.type) }
+ var trimmedEvents: Int = 0
+
+ fun tryAddTrigger(newEvent: Event): Boolean {
+ if (newEvent.time < startTime) return false
+ if (newEvent.time - startTime > triggerStartsNewFrameAge) return false
+ if (newEvent.type in triggers) return false
+ triggers.add(newEvent.type)
+ events.add(newEvent)
+ trim()
+ return true
+ }
+
+ fun trim() {
+ if (events.size > maxEventsPerFrame) {
+ events.removeFirst()
+ trimmedEvents++
+ }
+ }
+
+ fun dump(pw: IndentingPrintWriter) {
+ pw.println("Frame")
+ pw.withIncreasedIndent {
+ pw.println("startTime: ${timeString(startTime)}")
+ pw.printCollection("triggers", triggers)
+ pw.println("trimmedEvents: $trimmedEvents")
+ pw.printCollection("events", events) { it.dump(pw) }
+ }
+ }
+ }
+
+ private class Event(
+ @CompileTimeConstant val type: String,
+ val extraValue: String? = null,
+ val notificationKey: String? = null,
+ ) {
+ val time: Long = System.currentTimeMillis()
+
+ fun dump(pw: IndentingPrintWriter) {
+ pw.append(timeString(time)).append(": ").append(type)
+ extraValue?.let { pw.append(" ").append(it) }
+ notificationKey?.let { pw.append(" ---- ").append(logKey(it)) }
+ pw.println()
+ }
+ }
+
+ private companion object {
+ @JvmStatic
+ var instance: ColorUpdateLogger? = null
+ private set
+ private const val maxFrames = 5
+ private const val maxEventsPerFrame = 250
+ private const val triggerStartsNewFrameAge = 5000
+
+ private val dateFormat = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
+ private fun timeString(time: Long): String = dateFormat.format(time)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
index 3809ea0..b8a9594 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -23,6 +23,7 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
+import com.android.systemui.statusbar.notification.ColorUpdateLogger
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.row.NotificationGutsManager
@@ -41,7 +42,8 @@
private val mConfigurationController: ConfigurationController,
private val mLockscreenUserManager: NotificationLockscreenUserManager,
private val mGutsManager: NotificationGutsManager,
- private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor
+ private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val colorUpdateLogger: ColorUpdateLogger,
) : Coordinator, ConfigurationController.ConfigurationListener {
private var mIsSwitchingUser = false
@@ -51,11 +53,13 @@
private val mKeyguardUpdateCallback = object : KeyguardUpdateMonitorCallback() {
override fun onUserSwitching(userId: Int) {
+ colorUpdateLogger.logTriggerEvent("VCC.mKeyguardUpdateCallback.onUserSwitching()")
log { "ViewConfigCoordinator.onUserSwitching(userId=$userId)" }
mIsSwitchingUser = true
}
override fun onUserSwitchComplete(userId: Int) {
+ colorUpdateLogger.logTriggerEvent("VCC.mKeyguardUpdateCallback.onUserSwitchComplete()")
log { "ViewConfigCoordinator.onUserSwitchComplete(userId=$userId)" }
mIsSwitchingUser = false
applyChangesOnUserSwitched()
@@ -64,6 +68,7 @@
private val mUserChangedListener = object : UserChangedListener {
override fun onUserChanged(userId: Int) {
+ colorUpdateLogger.logTriggerEvent("VCC.mUserChangedListener.onUserChanged()")
log { "ViewConfigCoordinator.onUserChanged(userId=$userId)" }
applyChangesOnUserSwitched()
}
@@ -77,6 +82,7 @@
}
override fun onDensityOrFontScaleChanged() {
+ colorUpdateLogger.logTriggerEvent("VCC.onDensityOrFontScaleChanged()")
log {
val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser
"ViewConfigCoordinator.onDensityOrFontScaleChanged()" +
@@ -93,6 +99,7 @@
}
override fun onUiModeChanged() {
+ colorUpdateLogger.logTriggerEvent("VCC.onUiModeChanged()")
log {
val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser
"ViewConfigCoordinator.onUiModeChanged()" +
@@ -107,10 +114,12 @@
}
override fun onThemeChanged() {
+ colorUpdateLogger.logTriggerEvent("VCC.onThemeChanged()")
onDensityOrFontScaleChanged()
}
private fun applyChangesOnUserSwitched() {
+ colorUpdateLogger.logEvent("VCC.applyChangesOnUserSwitched()")
if (mReinflateNotificationsOnUserSwitched) {
updateNotificationsOnDensityOrFontScaleChanged()
mReinflateNotificationsOnUserSwitched = false
@@ -122,6 +131,8 @@
}
private fun updateNotificationsOnUiModeChanged() {
+ colorUpdateLogger.logEvent("VCC.updateNotificationsOnUiModeChanged()",
+ "mode=" + mConfigurationController.nightModeName)
log { "ViewConfigCoordinator.updateNotificationsOnUiModeChanged()" }
traceSection("updateNotifOnUiModeChanged") {
mPipeline?.allNotifs?.forEach { entry ->
@@ -131,6 +142,7 @@
}
private fun updateNotificationsOnDensityOrFontScaleChanged() {
+ colorUpdateLogger.logEvent("VCC.updateNotificationsOnDensityOrFontScaleChanged()")
mPipeline?.allNotifs?.forEach { entry ->
entry.onDensityOrFontScaleChanged()
val exposedGuts = entry.areGutsExposed()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
index 16f18a3..f792898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
@@ -19,6 +19,7 @@
import static android.graphics.PorterDuff.Mode.SRC_ATOP;
import static com.android.systemui.Flags.notificationBackgroundTintOptimization;
+import static com.android.systemui.util.ColorUtilKt.hexColorString;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
@@ -40,11 +41,13 @@
import com.android.settingslib.Utils;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.row.FooterViewButton;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.util.DrawableDumpKt;
import com.android.systemui.util.DumpUtilsKt;
import java.io.PrintWriter;
@@ -239,6 +242,10 @@
@Override
protected void onFinishInflate() {
+ ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();
+ if (colorUpdateLogger != null) {
+ colorUpdateLogger.logTriggerEvent("Footer.onFinishInflate()");
+ }
super.onFinishInflate();
mClearAllButton = (FooterViewButton) findSecondaryView();
mManageOrHistoryButton = findViewById(R.id.manage_text);
@@ -348,6 +355,10 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
+ ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();
+ if (colorUpdateLogger != null) {
+ colorUpdateLogger.logTriggerEvent("Footer.onConfigurationChanged()");
+ }
super.onConfigurationChanged(newConfig);
updateColors();
if (!FooterViewRefactor.isEnabled()) {
@@ -365,14 +376,17 @@
com.android.internal.R.attr.materialColorOnSurface);
final Drawable clearAllBg = theme.getDrawable(R.drawable.notif_footer_btn_background);
final Drawable manageBg = theme.getDrawable(R.drawable.notif_footer_btn_background);
+ final @ColorInt int scHigh;
if (!notificationBackgroundTintOptimization()) {
- final @ColorInt int scHigh = Utils.getColorAttrDefaultColor(mContext,
+ scHigh = Utils.getColorAttrDefaultColor(mContext,
com.android.internal.R.attr.materialColorSurfaceContainerHigh);
if (scHigh != 0) {
final ColorFilter bgColorFilter = new PorterDuffColorFilter(scHigh, SRC_ATOP);
clearAllBg.setColorFilter(bgColorFilter);
manageBg.setColorFilter(bgColorFilter);
}
+ } else {
+ scHigh = 0;
}
mClearAllButton.setBackground(clearAllBg);
mClearAllButton.setTextColor(onSurface);
@@ -380,6 +394,13 @@
mManageOrHistoryButton.setTextColor(onSurface);
mSeenNotifsFooterTextView.setTextColor(onSurface);
mSeenNotifsFooterTextView.setCompoundDrawableTintList(ColorStateList.valueOf(onSurface));
+ ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();
+ if (colorUpdateLogger != null) {
+ colorUpdateLogger.logEvent("Footer.updateColors()",
+ "textColor(onSurface)=" + hexColorString(onSurface)
+ + " backgroundTint(surfaceContainerHigh)=" + hexColorString(scHigh)
+ + " background=" + DrawableDumpKt.dumpToString(manageBg));
+ }
}
private void updateResources() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index fca527f..7358034 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -88,7 +88,7 @@
private boolean mActivated;
private Interpolator mCurrentAppearInterpolator;
- NotificationBackgroundView mBackgroundNormal;
+ protected NotificationBackgroundView mBackgroundNormal;
private float mAnimationTranslationY;
private boolean mDrawingAppearAnimation;
private ValueAnimator mAppearAnimator;
@@ -142,6 +142,10 @@
updateBackgroundTint();
}
+ protected int getNormalBgColor() {
+ return mNormalColor;
+ }
+
/**
* @param width The actual width to apply to the background view.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index cc91ed3..d828ad7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -21,6 +21,7 @@
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
+import static com.android.systemui.util.ColorUtilKt.hexColorString;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -85,6 +86,7 @@
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationFadeAware;
@@ -172,6 +174,7 @@
private Optional<BubblesManager> mBubblesManagerOptional;
private MetricsLogger mMetricsLogger;
private NotificationChildrenContainerLogger mChildrenContainerLogger;
+ private ColorUpdateLogger mColorUpdateLogger;
private NotificationDismissibilityProvider mDismissibilityProvider;
private FeatureFlags mFeatureFlags;
private int mIconTransformContentShift;
@@ -445,6 +448,7 @@
/**
* Sets animations running in the layouts of this row, including public, private, and children.
+ *
* @param running whether the animations should be started running or stopped.
*/
public void setAnimationRunning(boolean running) {
@@ -611,6 +615,12 @@
private void updateBackgroundColorsOfSelf() {
super.updateBackgroundColors();
+ if (mColorUpdateLogger.isEnabled()) {
+ mColorUpdateLogger.logNotificationEvent("ENR.updateBackgroundColorsOfSelf()",
+ mLoggingKey,
+ "normalBgColor=" + hexColorString(getNormalBgColor())
+ + " background=" + mBackgroundNormal.toDumpString());
+ }
}
@Override
@@ -1389,7 +1399,7 @@
}
public void setContentBackground(int customBackgroundColor, boolean animate,
- NotificationContentView notificationContentView) {
+ NotificationContentView notificationContentView) {
if (getShowingLayout() == notificationContentView) {
setTintColor(customBackgroundColor, animate);
}
@@ -1458,7 +1468,7 @@
}
/**
- * @return if this entry should be kept in its parent during removal.
+ * @return if this entry should be kept in its parent during removal.
*/
public boolean keepInParentForDismissAnimation() {
return mKeepInParentForDismissAnimation;
@@ -1769,6 +1779,7 @@
NotificationDismissibilityProvider dismissibilityProvider,
MetricsLogger metricsLogger,
NotificationChildrenContainerLogger childrenContainerLogger,
+ ColorUpdateLogger colorUpdateLogger,
SmartReplyConstants smartReplyConstants,
SmartReplyController smartReplyController,
FeatureFlags featureFlags,
@@ -1807,6 +1818,7 @@
mNotificationGutsManager = gutsManager;
mMetricsLogger = metricsLogger;
mChildrenContainerLogger = childrenContainerLogger;
+ mColorUpdateLogger = colorUpdateLogger;
mDismissibilityProvider = dismissibilityProvider;
mFeatureFlags = featureFlags;
}
@@ -2265,7 +2277,7 @@
}
public Animator getTranslateViewAnimator(final float leftTarget,
- AnimatorUpdateListener listener) {
+ AnimatorUpdateListener listener) {
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
}
@@ -2664,6 +2676,7 @@
return getCollapsedHeight();
}
}
+
/**
* @return {@code true} if the notification can show it's heads up layout. This is mostly true
* except for legacy use cases.
@@ -2833,7 +2846,7 @@
@Override
public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
- long duration) {
+ long duration) {
if (getVisibility() == GONE) {
// If we are GONE, the hideSensitive parameter will not be calculated and always be
// false, which is incorrect, let's wait until a real call comes in later.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 5614f3a..e59829b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -41,6 +41,7 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
@@ -86,6 +87,7 @@
private final SystemClock mClock;
private final String mAppName;
private final String mNotificationKey;
+ private final ColorUpdateLogger mColorUpdateLogger;
private final KeyguardBypassController mKeyguardBypassController;
private final GroupMembershipManager mGroupMembershipManager;
private final GroupExpansionManager mGroupExpansionManager;
@@ -200,6 +202,7 @@
ActivatableNotificationViewController activatableNotificationViewController,
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
MetricsLogger metricsLogger,
+ ColorUpdateLogger colorUpdateLogger,
NotificationRowLogger logBufferLogger,
NotificationChildrenContainerLogger childrenContainerLogger,
NotificationListContainer listContainer,
@@ -256,6 +259,7 @@
mDragController = dragController;
mMetricsLogger = metricsLogger;
mChildrenContainerLogger = childrenContainerLogger;
+ mColorUpdateLogger = colorUpdateLogger;
mLogBufferLogger = logBufferLogger;
mSmartReplyConstants = smartReplyConstants;
mSmartReplyController = smartReplyController;
@@ -290,6 +294,7 @@
mDismissibilityProvider,
mMetricsLogger,
mChildrenContainerLogger,
+ mColorUpdateLogger,
mSmartReplyConstants,
mSmartReplyController,
mFeatureFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index ec8e5d7..ea9df9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row;
+import static com.android.systemui.Flags.notificationColorUpdateLogger;
+
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
@@ -54,8 +56,8 @@
public abstract class ExpandableView extends FrameLayout implements Dumpable, Roundable {
private static final String TAG = "ExpandableView";
/** whether the dump() for this class should include verbose details */
- protected static final boolean DUMP_VERBOSE =
- Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
+ protected static final boolean DUMP_VERBOSE = Compile.IS_DEBUG
+ && (Log.isLoggable(TAG, Log.VERBOSE) || notificationColorUpdateLogger());
private RoundableState mRoundableState = null;
protected OnHeightChangedListener mOnHeightChangedListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 7ea9b14..ed3a38d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -36,6 +36,7 @@
import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.res.R;
+import com.android.systemui.util.DrawableDumpKt;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -333,6 +334,16 @@
pw.println("mActualHeight: " + mActualHeight);
pw.println("mTintColor: " + hexColorString(mTintColor));
pw.println("mRippleColor: " + hexColorString(mRippleColor));
- pw.println("mBackground: " + mBackground);
+ pw.println("mBackground: " + DrawableDumpKt.dumpToString(mBackground));
+ }
+
+ /** create a concise dump of this view's colors */
+ public String toDumpString() {
+ return "<NotificationBackgroundView"
+ + " tintColor=" + hexColorString(mTintColor)
+ + " rippleColor=" + hexColorString(mRippleColor)
+ + " bgColor=" + DrawableDumpKt.getSolidColor(mBackground)
+ + ">";
+
}
}
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 933a780..7925a1c 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
@@ -99,6 +99,7 @@
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationTransitionAnimatorController;
@@ -122,6 +123,7 @@
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.ColorUtilKt;
import com.android.systemui.util.DumpUtilsKt;
import com.google.errorprone.annotations.CompileTimeConstant;
@@ -805,8 +807,8 @@
updateBackgroundDimming();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- if (child instanceof ActivatableNotificationView) {
- ((ActivatableNotificationView) child).updateBackgroundColors();
+ if (child instanceof ActivatableNotificationView activatableView) {
+ activatableView.updateBackgroundColors();
}
}
}
@@ -4595,6 +4597,13 @@
final @ColorInt int onSurfaceVariant = Utils.getColorAttrDefaultColor(
mContext, com.android.internal.R.attr.materialColorOnSurfaceVariant);
+ ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();
+ if (colorUpdateLogger != null) {
+ colorUpdateLogger.logEvent("NSSL.updateDecorViews()",
+ "onSurface=" + ColorUtilKt.hexColorString(onSurface)
+ + " onSurfaceVariant=" + ColorUtilKt.hexColorString(onSurfaceVariant));
+ }
+
mSectionsManager.setHeaderForegroundColors(onSurface, onSurfaceVariant);
if (mFooterView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 78e6a79..d2ff266 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -96,6 +96,7 @@
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -177,6 +178,7 @@
private final ConfigurationController mConfigurationController;
private final ZenModeController mZenModeController;
private final MetricsLogger mMetricsLogger;
+ private final ColorUpdateLogger mColorUpdateLogger;
private final DumpManager mDumpManager;
private final FalsingCollector mFalsingCollector;
@@ -239,6 +241,7 @@
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
+ mColorUpdateLogger.logTriggerEvent("NSSLC.onViewAttachedToWindow()");
mConfigurationController.addCallback(mConfigurationListener);
if (!FooterViewRefactor.isEnabled()) {
mZenModeController.addCallback(mZenModeControllerCallback);
@@ -254,6 +257,7 @@
@Override
public void onViewDetachedFromWindow(View v) {
+ mColorUpdateLogger.logTriggerEvent("NSSLC.onViewDetachedFromWindow()");
mConfigurationController.removeCallback(mConfigurationListener);
if (!FooterViewRefactor.isEnabled()) {
mZenModeController.removeCallback(mZenModeControllerCallback);
@@ -332,12 +336,16 @@
@Override
public void onUiModeChanged() {
+ mColorUpdateLogger.logTriggerEvent("NSSLC.onUiModeChanged()",
+ "mode=" + mConfigurationController.getNightModeName());
mView.updateBgColor();
mView.updateDecorViews();
}
@Override
public void onThemeChanged() {
+ mColorUpdateLogger.logTriggerEvent("NSSLC.onThemeChanged()",
+ "mode=" + mConfigurationController.getNightModeName());
mView.updateCornerRadius();
mView.updateBgColor();
mView.updateDecorViews();
@@ -719,6 +727,7 @@
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
MetricsLogger metricsLogger,
+ ColorUpdateLogger colorUpdateLogger,
DumpManager dumpManager,
FalsingCollector falsingCollector,
FalsingManager falsingManager,
@@ -773,6 +782,7 @@
mZenModeController = zenModeController;
mLockscreenUserManager = lockscreenUserManager;
mMetricsLogger = metricsLogger;
+ mColorUpdateLogger = colorUpdateLogger;
mDumpManager = dumpManager;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mFalsingCollector = falsingCollector;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index 6e8ad2e..dea9416 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -159,6 +159,15 @@
override fun isLayoutRtl(): Boolean {
return layoutDirection == LAYOUT_DIRECTION_RTL
}
+
+ override fun getNightModeName(): String {
+ return when (uiMode and Configuration.UI_MODE_NIGHT_MASK) {
+ Configuration.UI_MODE_NIGHT_YES -> "night"
+ Configuration.UI_MODE_NIGHT_NO -> "day"
+ Configuration.UI_MODE_NIGHT_UNDEFINED -> "undefined"
+ else -> "err"
+ }
+ }
}
// This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index b2ef818..cec77c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -33,6 +33,9 @@
/** Query the current configuration's layout direction */
boolean isLayoutRtl();
+ /** Logging only; Query the current configuration's night mode name */
+ String getNightModeName();
+
interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {}
diff --git a/packages/SystemUI/src/com/android/systemui/util/DrawableDump.kt b/packages/SystemUI/src/com/android/systemui/util/DrawableDump.kt
new file mode 100644
index 0000000..0c079a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/DrawableDump.kt
@@ -0,0 +1,201 @@
+/*
+ * 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.util
+
+import android.content.res.ColorStateList
+import android.graphics.BlendMode
+import android.graphics.BlendModeColorFilter
+import android.graphics.ColorFilter
+import android.graphics.LightingColorFilter
+import android.graphics.PorterDuffColorFilter
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.DrawableWrapper
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.LayerDrawable
+import android.graphics.drawable.RippleDrawable
+import android.util.Log
+
+fun dumpToString(drawable: Drawable?): String =
+ if (Compile.IS_DEBUG) StringBuilder().appendDrawable(drawable).toString()
+ else drawable.toString()
+
+fun getSolidColor(drawable: Drawable?): String =
+ if (Compile.IS_DEBUG) hexColorString(getSolidColors(drawable)?.defaultColor)
+ else if (drawable == null) "null" else "?"
+
+private fun getSolidColors(drawable: Drawable?): ColorStateList? {
+ return when (drawable) {
+ is GradientDrawable -> {
+ return drawable.getStateField<ColorStateList>("mSolidColors")
+ }
+ is LayerDrawable -> {
+ for (iLayer in 0 until drawable.numberOfLayers) {
+ getSolidColors(drawable.getDrawable(iLayer))?.let {
+ return it
+ }
+ }
+ null
+ }
+ is DrawableWrapper -> {
+ return getSolidColors(drawable.drawable)
+ }
+ else -> null
+ }
+}
+
+private fun StringBuilder.appendDrawable(drawable: Drawable?): StringBuilder {
+ if (drawable == null) {
+ append("null")
+ return this
+ }
+ append("<")
+ append(drawable.javaClass.simpleName)
+
+ drawable.getStateField<ColorStateList>("mTint", fieldRequired = false)?.let {
+ append(" tint=")
+ appendColors(it)
+ append(" blendMode=")
+ append(drawable.getStateField<BlendMode>("mBlendMode"))
+ }
+ drawable.colorFilter
+ ?.takeUnless { drawable is DrawableWrapper }
+ ?.let {
+ append(" colorFilter=")
+ appendColorFilter(it)
+ }
+ when (drawable) {
+ is DrawableWrapper -> {
+ append(" wrapped=")
+ appendDrawable(drawable.drawable)
+ }
+ is LayerDrawable -> {
+ if (drawable is RippleDrawable) {
+ drawable.getStateField<ColorStateList>("mColor")?.let {
+ append(" color=")
+ appendColors(it)
+ }
+ drawable.effectColor?.let {
+ append(" effectColor=")
+ appendColors(it)
+ }
+ }
+ append(" layers=[")
+ for (iLayer in 0 until drawable.numberOfLayers) {
+ if (iLayer != 0) append(", ")
+ appendDrawable(drawable.getDrawable(iLayer))
+ }
+ append("]")
+ }
+ is GradientDrawable -> {
+ drawable
+ .getStateField<Int>("mShape")
+ ?.takeIf { it != 0 }
+ ?.let {
+ append(" shape=")
+ append(it)
+ }
+ drawable.getStateField<ColorStateList>("mSolidColors")?.let {
+ append(" solidColors=")
+ appendColors(it)
+ }
+ drawable.getStateField<ColorStateList>("mStrokeColors")?.let {
+ append(" strokeColors=")
+ appendColors(it)
+ }
+ drawable.colors?.let {
+ append(" gradientColors=[")
+ it.forEachIndexed { iColor, color ->
+ if (iColor != 0) append(", ")
+ append(hexColorString(color))
+ }
+ append("]")
+ }
+ }
+ }
+ append(">")
+ return this
+}
+
+private inline fun <reified T> Drawable.getStateField(
+ name: String,
+ fieldRequired: Boolean = true
+): T? {
+ val state = this.constantState ?: return null
+ val clazz = state.javaClass
+ return try {
+ val field = clazz.getDeclaredField(name)
+ field.isAccessible = true
+ field.get(state) as T?
+ } catch (ex: Exception) {
+ if (fieldRequired) {
+ Log.w(TAG, "Missing ${clazz.simpleName}.$name: ${T::class.simpleName}", ex)
+ } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Missing ${clazz.simpleName}.$name: ${T::class.simpleName} ($ex)")
+ }
+ null
+ }
+}
+
+private fun Appendable.appendColors(colorStateList: ColorStateList?) {
+ if (colorStateList == null) {
+ append("null")
+ return
+ }
+ val colors = colorStateList.colors
+ if (colors.size == 1) {
+ append(hexColorString(colors[0]))
+ return
+ }
+ append("<ColorStateList size=")
+ append(colors.size.toString())
+ append(" default=")
+ append(hexColorString(colorStateList.defaultColor))
+ append(">")
+}
+
+private fun Appendable.appendColorFilter(colorFilter: ColorFilter?) {
+ if (colorFilter == null) {
+ append("null")
+ return
+ }
+ append("<")
+ append(colorFilter.javaClass.simpleName)
+ when (colorFilter) {
+ is PorterDuffColorFilter -> {
+ append(" color=")
+ append(hexColorString(colorFilter.color))
+ append(" mode=")
+ append(colorFilter.mode.toString())
+ }
+ is BlendModeColorFilter -> {
+ append(" color=")
+ append(hexColorString(colorFilter.color))
+ append(" mode=")
+ append(colorFilter.mode.toString())
+ }
+ is LightingColorFilter -> {
+ append(" multiply=")
+ append(hexColorString(colorFilter.colorMultiply))
+ append(" add=")
+ append(hexColorString(colorFilter.colorAdd))
+ }
+ else -> append(" unhandled")
+ }
+ append(">")
+}
+
+private const val TAG = "DrawableDump"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
index 0830191..b1d2ea21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
+import com.android.systemui.statusbar.notification.ColorUpdateLogger
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -57,6 +58,7 @@
private val lockscreenUserManager: NotificationLockscreenUserManager = mock()
private val gutsManager: NotificationGutsManager = mock()
private val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock()
+ private val colorUpdateLogger: ColorUpdateLogger = mock()
@Before
fun setUp() {
@@ -66,7 +68,9 @@
configurationController,
lockscreenUserManager,
gutsManager,
- keyguardUpdateMonitor)
+ keyguardUpdateMonitor,
+ colorUpdateLogger,
+ )
coordinator.attach(pipeline)
userChangedListener = withArgCaptor {
verify(lockscreenUserManager).addUserChangedListener(capture())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
index 8ac2a33..210b1a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.statusbar.SmartReplyController
+import com.android.systemui.statusbar.notification.ColorUpdateLogger
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider
@@ -82,6 +83,7 @@
private val rivSubComponentFactory: RemoteInputViewSubcomponent.Factory = mock()
private val metricsLogger: MetricsLogger = mock()
private val logBufferLogger = NotificationRowLogger(logcatLogBuffer(), logcatLogBuffer())
+ private val colorUpdateLogger: ColorUpdateLogger = mock()
private val listContainer: NotificationListContainer = mock()
private val childrenContainer: NotificationChildrenContainer = mock()
private val smartReplyConstants: SmartReplyConstants = mock()
@@ -117,6 +119,7 @@
activableNotificationViewController,
rivSubComponentFactory,
metricsLogger,
+ colorUpdateLogger,
logBufferLogger,
NotificationChildrenContainerLogger(logcatLogBuffer()),
listContainer,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index c717991..e78081f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -65,6 +65,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -607,6 +608,7 @@
mDismissibilityProvider,
mock(MetricsLogger.class),
new NotificationChildrenContainerLogger(logcatLogBuffer()),
+ mock(ColorUpdateLogger.class),
mock(SmartReplyConstants.class),
mock(SmartReplyController.class),
mFeatureFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 354f3f6..f2ef4e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -78,6 +78,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -148,6 +149,7 @@
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private MetricsLogger mMetricsLogger;
+ @Mock private ColorUpdateLogger mColorUpdateLogger;
@Mock private DumpManager mDumpManager;
@Mock(answer = Answers.RETURNS_SELF)
private NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
@@ -1007,6 +1009,7 @@
mZenModeController,
mNotificationLockscreenUserManager,
mMetricsLogger,
+ mColorUpdateLogger,
mDumpManager,
new FalsingCollectorFake(),
new FalsingManagerFake(),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
index c51de33..46a1053 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
@@ -43,6 +43,7 @@
}
override fun isLayoutRtl(): Boolean = isRtl
+ override fun getNightModeName(): String = "undefined"
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeConfigurationController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
index 516eb6e..111c40d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
@@ -38,4 +38,9 @@
public boolean isLayoutRtl() {
return false;
}
+
+ @Override
+ public String getNightModeName() {
+ return "undefined";
+ }
}