1 /*
2  * Copyright (C) 2020 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.render
18 
19 import android.content.Context
20 import android.view.View
21 import com.android.systemui.statusbar.notification.collection.GroupEntry
22 import com.android.systemui.statusbar.notification.collection.ListEntry
23 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
24 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
25 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
26 import com.android.systemui.statusbar.phone.NotificationIconAreaController
27 import com.android.systemui.util.traceSection
28 import javax.inject.Inject
29 
30 /**
31  * Responsible for building and applying the "shade node spec": the list (tree) of things that
32  * currently populate the notification shade.
33  */
34 class ShadeViewManager constructor(
35     context: Context,
36     listContainer: NotificationListContainer,
37     logger: ShadeViewDifferLogger,
38     private val viewBarn: NotifViewBarn,
39     private val notificationIconAreaController: NotificationIconAreaController
40 ) {
41     // We pass a shim view here because the listContainer may not actually have a view associated
42     // with it and the differ never actually cares about the root node's view.
43     private val rootController = RootNodeController(listContainer, View(context))
44     private val specBuilder = NodeSpecBuilder(viewBarn)
45     private val viewDiffer = ShadeViewDiffer(rootController, logger)
46 
47     fun attach(listBuilder: ShadeListBuilder) =
48             listBuilder.setOnRenderListListener(::onNewNotifTree)
49 
50     private fun onNewNotifTree(notifList: List<ListEntry>) {
51         traceSection("ShadeViewManager.onNewNotifTree") {
52             viewDiffer.applySpec(specBuilder.buildNodeSpec(rootController, notifList))
53             updateGroupCounts(notifList)
54             notificationIconAreaController.updateNotificationIcons(notifList)
55         }
56     }
57 
58     private fun updateGroupCounts(notifList: List<ListEntry>) {
59         traceSection("ShadeViewManager.updateGroupCounts") {
60             notifList.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
61                 val controller = viewBarn.requireView(checkNotNull(groupEntry.summary))
62                 val row = controller.view as ExpandableNotificationRow
63                 row.setUntruncatedChildCount(groupEntry.untruncatedChildCount)
64             }
65         }
66     }
67 }
68 
69 class ShadeViewManagerFactory @Inject constructor(
70     private val context: Context,
71     private val logger: ShadeViewDifferLogger,
72     private val viewBarn: NotifViewBarn,
73     private val notificationIconAreaController: NotificationIconAreaController
74 ) {
75     fun create(listContainer: NotificationListContainer) =
76             ShadeViewManager(
77                     context,
78                     listContainer,
79                     logger,
80                     viewBarn,
81                     notificationIconAreaController)
82 }
83