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