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.init
18 
19 import android.service.notification.StatusBarNotification
20 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
21 import com.android.systemui.statusbar.FeatureFlags
22 import com.android.systemui.statusbar.NotificationListener
23 import com.android.systemui.statusbar.NotificationPresenter
24 import com.android.systemui.statusbar.notification.NotificationActivityStarter
25 import com.android.systemui.statusbar.notification.NotificationClicker
26 import com.android.systemui.statusbar.notification.NotificationEntryManager
27 import com.android.systemui.statusbar.notification.NotificationListController
28 import com.android.systemui.statusbar.notification.collection.NotifPipeline
29 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
30 import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
31 import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
32 import com.android.systemui.statusbar.notification.interruption.HeadsUpController
33 import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
34 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
35 import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper
36 import com.android.systemui.statusbar.phone.NotificationGroupManager
37 import com.android.systemui.statusbar.phone.StatusBar
38 import com.android.systemui.statusbar.policy.DeviceProvisionedController
39 import com.android.systemui.statusbar.policy.HeadsUpManager
40 import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
41 import com.android.systemui.statusbar.policy.RemoteInputUriController
42 import dagger.Lazy
43 import java.io.FileDescriptor
44 import java.io.PrintWriter
45 import java.util.Optional
46 import javax.inject.Inject
47 import javax.inject.Singleton
48 
49 /**
50  * Master controller for all notifications-related work
51  *
52  * At the moment exposes a number of event-handler-esque methods; these are for historical reasons.
53  * Once we migrate away from the need for such things, this class becomes primarily a place to do
54  * any initialization work that notifications require.
55  */
56 @Singleton
57 class NotificationsControllerImpl @Inject constructor(
58     private val featureFlags: FeatureFlags,
59     private val notificationListener: NotificationListener,
60     private val entryManager: NotificationEntryManager,
61     private val notifPipeline: Lazy<NotifPipeline>,
62     private val targetSdkResolver: TargetSdkResolver,
63     private val newNotifPipeline: Lazy<NotifPipelineInitializer>,
64     private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
65     private val deviceProvisionedController: DeviceProvisionedController,
66     private val notificationRowBinder: NotificationRowBinderImpl,
67     private val remoteInputUriController: RemoteInputUriController,
68     private val groupManager: NotificationGroupManager,
69     private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
70     private val headsUpManager: HeadsUpManager,
71     private val headsUpController: HeadsUpController,
72     private val headsUpViewBinder: HeadsUpViewBinder,
73     private val clickerBuilder: NotificationClicker.Builder
74 ) : NotificationsController {
75 
initializenull76     override fun initialize(
77         statusBar: StatusBar,
78         presenter: NotificationPresenter,
79         listContainer: NotificationListContainer,
80         notificationActivityStarter: NotificationActivityStarter,
81         bindRowCallback: NotificationRowBinderImpl.BindRowCallback
82     ) {
83         notificationListener.registerAsSystemService()
84 
85         val listController =
86                 NotificationListController(
87                         entryManager,
88                         listContainer,
89                         deviceProvisionedController)
90         listController.bind()
91 
92         notificationRowBinder.setNotificationClicker(
93                 clickerBuilder.build(Optional.of(statusBar), notificationActivityStarter))
94         notificationRowBinder.setUpWithPresenter(
95                 presenter,
96                 listContainer,
97                 bindRowCallback)
98         headsUpViewBinder.setPresenter(presenter)
99         notifBindPipelineInitializer.initialize()
100 
101         if (featureFlags.isNewNotifPipelineEnabled) {
102             newNotifPipeline.get().initialize(
103                     notificationListener,
104                     notificationRowBinder,
105                     listContainer)
106         }
107 
108         if (featureFlags.isNewNotifPipelineRenderingEnabled) {
109             targetSdkResolver.initialize(notifPipeline.get())
110             // TODO
111         } else {
112             targetSdkResolver.initialize(entryManager)
113             remoteInputUriController.attach(entryManager)
114             groupAlertTransferHelper.bind(entryManager, groupManager)
115             headsUpManager.addListener(groupManager)
116             headsUpManager.addListener(groupAlertTransferHelper)
117             headsUpController.attach(entryManager, headsUpManager)
118             groupManager.setHeadsUpManager(headsUpManager)
119             groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
120 
121             entryManager.attach(notificationListener)
122         }
123     }
124 
dumpnull125     override fun dump(
126         fd: FileDescriptor,
127         pw: PrintWriter,
128         args: Array<String>,
129         dumpTruck: Boolean
130     ) {
131         if (dumpTruck) {
132             entryManager.dump(pw, "  ")
133         }
134         groupManager.dump(fd, pw, args)
135     }
136 
137     // TODO: Convert all functions below this line into listeners instead of public methods
138 
requestNotificationUpdatenull139     override fun requestNotificationUpdate(reason: String) {
140         entryManager.updateNotifications(reason)
141     }
142 
resetUserExpandedStatesnull143     override fun resetUserExpandedStates() {
144         for (entry in entryManager.visibleNotifications) {
145             entry.resetUserExpansion()
146         }
147     }
148 
setNotificationSnoozednull149     override fun setNotificationSnoozed(sbn: StatusBarNotification, snoozeOption: SnoozeOption) {
150         if (snoozeOption.snoozeCriterion != null) {
151             notificationListener.snoozeNotification(sbn.key, snoozeOption.snoozeCriterion.id)
152         } else {
153             notificationListener.snoozeNotification(
154                     sbn.key,
155                     snoozeOption.minutesToSnoozeFor * 60 * 1000.toLong())
156         }
157     }
158 
getActiveNotificationsCountnull159     override fun getActiveNotificationsCount(): Int {
160         return entryManager.activeNotificationsCount
161     }
162 
setNotificationSnoozednull163     override fun setNotificationSnoozed(sbn: StatusBarNotification, hoursToSnooze: Int) {
164         notificationListener.snoozeNotification(
165                 sbn.key,
166                 hoursToSnooze * 60 * 60 * 1000.toLong())
167     }
168 }
169