1 /* 2 * 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 com.android.systemui.statusbar.notification.collection.ListEntry 20 import com.android.systemui.statusbar.notification.collection.NotifPipeline 21 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope 22 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl 23 import com.android.systemui.statusbar.notification.collection.render.NotifStackController 24 import com.android.systemui.statusbar.notification.collection.render.NotifStats 25 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT 26 import com.android.systemui.statusbar.phone.NotificationIconAreaController 27 import com.android.systemui.util.traceSection 28 import javax.inject.Inject 29 30 /** 31 * A small coordinator which updates the notif stack (the view layer which holds notifications) 32 * with high-level data after the stack is populated with the final entries. 33 */ 34 @CoordinatorScope 35 class StackCoordinator @Inject internal constructor( 36 private val groupExpansionManagerImpl: GroupExpansionManagerImpl, 37 private val notificationIconAreaController: NotificationIconAreaController 38 ) : Coordinator { 39 40 override fun attach(pipeline: NotifPipeline) { 41 pipeline.addOnAfterRenderListListener(::onAfterRenderList) 42 // TODO(b/282865576): This has an issue where it makes changes to some groups without 43 // notifying listeners. To be fixed in QPR, but for now let's comment it out to avoid the 44 // group expansion bug. 45 // groupExpansionManagerImpl.attach(pipeline) 46 } 47 48 fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) = 49 traceSection("StackCoordinator.onAfterRenderList") { 50 controller.setNotifStats(calculateNotifStats(entries)) 51 notificationIconAreaController.updateNotificationIcons(entries) 52 } 53 54 private fun calculateNotifStats(entries: List<ListEntry>): NotifStats { 55 var hasNonClearableAlertingNotifs = false 56 var hasClearableAlertingNotifs = false 57 var hasNonClearableSilentNotifs = false 58 var hasClearableSilentNotifs = false 59 entries.forEach { 60 val section = checkNotNull(it.section) { "Null section for ${it.key}" } 61 val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" } 62 val isSilent = section.bucket == BUCKET_SILENT 63 // NOTE: NotificationEntry.isClearable will internally check group children to ensure 64 // the group itself definitively clearable. 65 val isClearable = entry.isClearable 66 when { 67 isSilent && isClearable -> hasClearableSilentNotifs = true 68 isSilent && !isClearable -> hasNonClearableSilentNotifs = true 69 !isSilent && isClearable -> hasClearableAlertingNotifs = true 70 !isSilent && !isClearable -> hasNonClearableAlertingNotifs = true 71 } 72 } 73 return NotifStats( 74 numActiveNotifs = entries.size, 75 hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs, 76 hasClearableAlertingNotifs = hasClearableAlertingNotifs, 77 hasNonClearableSilentNotifs = hasNonClearableSilentNotifs, 78 hasClearableSilentNotifs = hasClearableSilentNotifs 79 ) 80 } 81 }