1 /* <lambda>null2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.notification.collection.coordinator 18 19 import android.util.Log 20 import com.android.internal.widget.MessagingGroup 21 import com.android.internal.widget.MessagingMessage 22 import com.android.keyguard.KeyguardUpdateMonitor 23 import com.android.keyguard.KeyguardUpdateMonitorCallback 24 import com.android.systemui.statusbar.NotificationLockscreenUserManager 25 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener 26 import com.android.systemui.statusbar.notification.ColorUpdateLogger 27 import com.android.systemui.statusbar.notification.collection.NotifPipeline 28 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope 29 import com.android.systemui.statusbar.notification.row.NotificationGutsManager 30 import com.android.systemui.statusbar.policy.ConfigurationController 31 import com.android.systemui.util.Compile 32 import com.android.app.tracing.traceSection 33 import javax.inject.Inject 34 35 /** 36 * A coordinator which ensures that notifications within the new pipeline are correctly inflated 37 * for the current uiMode and screen properties; additionally deferring those changes when a user 38 * change is in progress until that process has completed. 39 */ 40 @CoordinatorScope 41 class ViewConfigCoordinator @Inject internal constructor( 42 private val mConfigurationController: ConfigurationController, 43 private val mLockscreenUserManager: NotificationLockscreenUserManager, 44 private val mGutsManager: NotificationGutsManager, 45 private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor, 46 private val colorUpdateLogger: ColorUpdateLogger, 47 ) : Coordinator, ConfigurationController.ConfigurationListener { 48 49 private var mIsSwitchingUser = false 50 private var mReinflateNotificationsOnUserSwitched = false 51 private var mDispatchUiModeChangeOnUserSwitched = false 52 private var mPipeline: NotifPipeline? = null 53 54 private val mKeyguardUpdateCallback = object : KeyguardUpdateMonitorCallback() { 55 override fun onUserSwitching(userId: Int) { 56 colorUpdateLogger.logTriggerEvent("VCC.mKeyguardUpdateCallback.onUserSwitching()") 57 log { "ViewConfigCoordinator.onUserSwitching(userId=$userId)" } 58 mIsSwitchingUser = true 59 } 60 61 override fun onUserSwitchComplete(userId: Int) { 62 colorUpdateLogger.logTriggerEvent("VCC.mKeyguardUpdateCallback.onUserSwitchComplete()") 63 log { "ViewConfigCoordinator.onUserSwitchComplete(userId=$userId)" } 64 mIsSwitchingUser = false 65 applyChangesOnUserSwitched() 66 } 67 } 68 69 private val mUserChangedListener = object : UserChangedListener { 70 override fun onUserChanged(userId: Int) { 71 colorUpdateLogger.logTriggerEvent("VCC.mUserChangedListener.onUserChanged()") 72 log { "ViewConfigCoordinator.onUserChanged(userId=$userId)" } 73 applyChangesOnUserSwitched() 74 } 75 } 76 77 override fun attach(pipeline: NotifPipeline) { 78 mPipeline = pipeline 79 mLockscreenUserManager.addUserChangedListener(mUserChangedListener) 80 mConfigurationController.addCallback(this) 81 mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback) 82 } 83 84 override fun onDensityOrFontScaleChanged() { 85 colorUpdateLogger.logTriggerEvent("VCC.onDensityOrFontScaleChanged()") 86 log { 87 val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser 88 "ViewConfigCoordinator.onDensityOrFontScaleChanged()" + 89 " isSwitchingUser=$mIsSwitchingUser" + 90 " keyguardUpdateMonitor.isSwitchingUser=$keyguardIsSwitchingUser" 91 } 92 MessagingMessage.dropCache() 93 MessagingGroup.dropCache() 94 if (!mIsSwitchingUser) { 95 updateNotificationsOnDensityOrFontScaleChanged() 96 } else { 97 mReinflateNotificationsOnUserSwitched = true 98 } 99 } 100 101 override fun onUiModeChanged() { 102 colorUpdateLogger.logTriggerEvent("VCC.onUiModeChanged()") 103 log { 104 val keyguardIsSwitchingUser = mKeyguardUpdateMonitor.isSwitchingUser 105 "ViewConfigCoordinator.onUiModeChanged()" + 106 " isSwitchingUser=$mIsSwitchingUser" + 107 " keyguardUpdateMonitor.isSwitchingUser=$keyguardIsSwitchingUser" 108 } 109 if (!mIsSwitchingUser) { 110 updateNotificationsOnUiModeChanged() 111 } else { 112 mDispatchUiModeChangeOnUserSwitched = true 113 } 114 } 115 116 override fun onThemeChanged() { 117 colorUpdateLogger.logTriggerEvent("VCC.onThemeChanged()") 118 onDensityOrFontScaleChanged() 119 } 120 121 private fun applyChangesOnUserSwitched() { 122 colorUpdateLogger.logEvent("VCC.applyChangesOnUserSwitched()") 123 if (mReinflateNotificationsOnUserSwitched) { 124 updateNotificationsOnDensityOrFontScaleChanged() 125 mReinflateNotificationsOnUserSwitched = false 126 } 127 if (mDispatchUiModeChangeOnUserSwitched) { 128 updateNotificationsOnUiModeChanged() 129 mDispatchUiModeChangeOnUserSwitched = false 130 } 131 } 132 133 private fun updateNotificationsOnUiModeChanged() { 134 colorUpdateLogger.logEvent("VCC.updateNotificationsOnUiModeChanged()", 135 "mode=" + mConfigurationController.nightModeName) 136 log { "ViewConfigCoordinator.updateNotificationsOnUiModeChanged()" } 137 traceSection("updateNotifOnUiModeChanged") { 138 mPipeline?.allNotifs?.forEach { entry -> 139 entry.row?.onUiModeChanged() 140 } 141 } 142 } 143 144 private fun updateNotificationsOnDensityOrFontScaleChanged() { 145 colorUpdateLogger.logEvent("VCC.updateNotificationsOnDensityOrFontScaleChanged()") 146 mPipeline?.allNotifs?.forEach { entry -> 147 entry.onDensityOrFontScaleChanged() 148 val exposedGuts = entry.areGutsExposed() 149 if (exposedGuts) { 150 mGutsManager.onDensityOrFontScaleChanged(entry) 151 } 152 } 153 } 154 155 private inline fun log(message: () -> String) { 156 if (DEBUG) Log.d(TAG, message()) 157 } 158 159 companion object { 160 private const val TAG = "ViewConfigCoordinator" 161 private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG) 162 } 163 } 164