1 package com.android.systemui.statusbar 2 3 import android.app.Flags.lifetimeExtensionRefactor 4 import android.app.Notification 5 import android.os.RemoteException 6 import com.android.internal.statusbar.IStatusBarService 7 import com.android.internal.statusbar.NotificationVisibility 8 import com.android.systemui.dagger.SysUISingleton 9 import com.android.systemui.dagger.qualifiers.Main 10 import com.android.systemui.dagger.qualifiers.UiBackground 11 import com.android.systemui.util.Assert 12 import java.util.concurrent.Executor 13 import javax.inject.Inject 14 15 /** 16 * Class to shim calls to IStatusBarManager#onNotificationClick/#onNotificationActionClick that 17 * allow an in-process notification to go out (e.g., for tracking interactions) as well as 18 * sending the messages along to system server. 19 * 20 * NOTE: this class eats exceptions from system server, as no current client of these APIs cares 21 * about errors 22 */ 23 @SysUISingleton 24 public class NotificationClickNotifier @Inject constructor( 25 val barService: IStatusBarService, 26 @Main val mainExecutor: Executor, 27 @UiBackground val backgroundExecutor: Executor 28 ) { 29 val listeners = mutableListOf<NotificationInteractionListener>() 30 addNotificationInteractionListenernull31 fun addNotificationInteractionListener(listener: NotificationInteractionListener) { 32 Assert.isMainThread() 33 listeners.add(listener) 34 } 35 removeNotificationInteractionListenernull36 fun removeNotificationInteractionListener(listener: NotificationInteractionListener) { 37 Assert.isMainThread() 38 listeners.remove(listener) 39 } 40 notifyListenersAboutInteractionnull41 private fun notifyListenersAboutInteraction(key: String) { 42 for (l in listeners) { 43 l.onNotificationInteraction(key) 44 } 45 } 46 onNotificationActionClicknull47 fun onNotificationActionClick( 48 key: String, 49 actionIndex: Int, 50 action: Notification.Action, 51 visibility: NotificationVisibility, 52 generatedByAssistant: Boolean 53 ) { 54 backgroundExecutor.execute { 55 try { 56 barService.onNotificationActionClick( 57 key, actionIndex, action, visibility, generatedByAssistant) 58 } catch (e: RemoteException) { 59 // nothing 60 } 61 if (lifetimeExtensionRefactor()) { 62 notifyListenersAboutInteraction(key) 63 } 64 } 65 if (!lifetimeExtensionRefactor()) { 66 mainExecutor.execute { 67 notifyListenersAboutInteraction(key) 68 } 69 } 70 } 71 onNotificationClicknull72 fun onNotificationClick( 73 key: String, 74 visibility: NotificationVisibility 75 ) { 76 try { 77 barService.onNotificationClick(key, visibility) 78 } catch (e: RemoteException) { 79 // nothing 80 } 81 82 mainExecutor.execute { 83 notifyListenersAboutInteraction(key) 84 } 85 } 86 } 87 88 /** 89 * Interface for listeners to get notified when a notification is interacted with via a click or 90 * interaction with remote input or actions 91 */ 92 interface NotificationInteractionListener { onNotificationInteractionnull93 fun onNotificationInteraction(key: String) 94 } 95 96 private const val TAG = "NotificationClickNotifier" 97