1 package com.android.systemui.statusbar 2 3 import android.app.Notification 4 import android.os.RemoteException 5 import android.util.Log 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 31 fun addNotificationInteractionListener(listener: NotificationInteractionListener) { 32 Assert.isMainThread() 33 listeners.add(listener) 34 } 35 36 fun removeNotificationInteractionListener(listener: NotificationInteractionListener) { 37 Assert.isMainThread() 38 listeners.remove(listener) 39 } 40 41 private fun notifyListenersAboutInteraction(key: String) { 42 for (l in listeners) { 43 l.onNotificationInteraction(key) 44 } 45 } 46 47 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 } 62 mainExecutor.execute { 63 notifyListenersAboutInteraction(key) 64 } 65 } 66 67 fun onNotificationClick( 68 key: String, 69 visibility: NotificationVisibility 70 ) { 71 try { 72 barService.onNotificationClick(key, visibility) 73 } catch (e: RemoteException) { 74 // nothing 75 } 76 77 mainExecutor.execute { 78 notifyListenersAboutInteraction(key) 79 } 80 } 81 } 82 83 /** 84 * Interface for listeners to get notified when a notification is interacted with via a click or 85 * interaction with remote input or actions 86 */ 87 interface NotificationInteractionListener { 88 fun onNotificationInteraction(key: String) 89 } 90 91 private const val TAG = "NotificationClickNotifier" 92