1 /*
<lambda>null2  * Copyright (C) 2019 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
18 
19 import android.content.Context
20 import android.media.MediaMetadata
21 import android.provider.Settings
22 import com.android.keyguard.KeyguardUpdateMonitor
23 import com.android.systemui.plugins.statusbar.StatusBarStateController
24 import com.android.systemui.statusbar.NotificationLockscreenUserManager
25 import com.android.systemui.statusbar.NotificationMediaManager
26 import com.android.systemui.statusbar.StatusBarState
27 import com.android.systemui.statusbar.notification.collection.NotificationEntry
28 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
29 import com.android.systemui.statusbar.phone.KeyguardBypassController
30 import com.android.systemui.tuner.TunerService
31 import javax.inject.Inject
32 import javax.inject.Singleton
33 
34 /**
35  * A class that automatically creates heads up for important notification when bypassing the
36  * lockscreen
37  */
38 @Singleton
39 class BypassHeadsUpNotifier @Inject constructor(
40         private val context: Context,
41         private val bypassController: KeyguardBypassController,
42         private val statusBarStateController: StatusBarStateController,
43         private val headsUpManager: HeadsUpManagerPhone,
44         private val notificationLockscreenUserManager: NotificationLockscreenUserManager,
45         private val mediaManager: NotificationMediaManager,
46         tunerService: TunerService) : StatusBarStateController.StateListener,
47         NotificationMediaManager.MediaListener {
48 
49     private lateinit var entryManager: NotificationEntryManager
50     private var currentMediaEntry: NotificationEntry? = null
51     private var enabled = true
52 
53     var fullyAwake = false
54         set(value) {
55             field = value
56             if (value) {
57                 updateAutoHeadsUp(currentMediaEntry)
58             }
59         }
60 
61     init {
62         statusBarStateController.addCallback(this)
63         tunerService.addTunable(
64                 TunerService.Tunable { _, _ ->
65                     enabled = Settings.Secure.getIntForUser(
66                             context.contentResolver,
67                             Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING,
68                             0 /* default */,
69                             KeyguardUpdateMonitor.getCurrentUser()) != 0
70                 }, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING)
71     }
72 
73     fun setUp(entryManager: NotificationEntryManager) {
74         this.entryManager = entryManager
75         mediaManager.addCallback(this)
76     }
77 
78     override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
79         val previous = currentMediaEntry
80         var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
81         if (!NotificationMediaManager.isPlayingState(state)) {
82             newEntry = null
83         }
84         currentMediaEntry = newEntry
85         updateAutoHeadsUp(previous)
86         updateAutoHeadsUp(currentMediaEntry)
87     }
88 
89     private fun updateAutoHeadsUp(entry: NotificationEntry?) {
90         entry?.let {
91             val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp(it)
92             it.isAutoHeadsUp = autoHeadsUp
93             if (autoHeadsUp) {
94                 headsUpManager.showNotification(it)
95             }
96         }
97     }
98 
99     /**
100      * @return {@code true} if this entry be autoHeadsUpped right now.
101      */
102     private fun canAutoHeadsUp(entry: NotificationEntry): Boolean {
103         if (!isAutoHeadsUpAllowed()) {
104             return false;
105         }
106         if (entry.isSensitive) {
107             // filter sensitive notifications
108             return false
109         }
110         if (!notificationLockscreenUserManager.shouldShowOnKeyguard(entry)) {
111             // filter notifications invisible on Keyguard
112             return false
113         }
114         if (!entryManager.notificationData.activeNotifications.contains(entry)) {
115             // filter notifications not the active list currently
116             return false
117         }
118         return true
119     }
120 
121     override fun onStatePostChange() {
122         updateAutoHeadsUp(currentMediaEntry)
123     }
124 
125     /**
126      * @return {@code true} if autoHeadsUp is possible right now.
127      */
128     private fun isAutoHeadsUpAllowed() : Boolean {
129         if (!enabled) {
130             return false
131         }
132         if (!bypassController.bypassEnabled) {
133             return false
134         }
135         if (statusBarStateController.state != StatusBarState.KEYGUARD) {
136             return false
137         }
138         if (!fullyAwake) {
139             return false
140         }
141         return true
142     }
143 }
144