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