• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.systemui.broadcast
2 
3 import android.annotation.AnyThread
4 import android.content.Context
5 import android.content.Intent
6 import android.os.Bundle
7 import android.os.UserHandle
8 import com.android.systemui.dagger.SysUISingleton
9 import com.android.systemui.dagger.qualifiers.Background
10 import com.android.systemui.util.wakelock.WakeLock
11 import java.util.concurrent.Executor
12 import javax.inject.Inject
13 
14 /**
15  * SystemUI master Broadcast sender
16  *
17  * This class dispatches broadcasts on background thread to avoid synchronous call to binder. Use
18  * this class instead of calling [Context.sendBroadcast] directly.
19  */
20 @SysUISingleton
21 class BroadcastSender @Inject constructor(
22     private val context: Context,
23     private val wakeLockBuilder: WakeLock.Builder,
24     @Background private val bgExecutor: Executor
25 ) {
26 
27     private val WAKE_LOCK_TAG = "SysUI:BroadcastSender"
28     private val WAKE_LOCK_SEND_REASON = "sendInBackground"
29 
30     /**
31      * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking
32      * synchronous binder call.
33      */
34     @AnyThread
sendBroadcastnull35     fun sendBroadcast(intent: Intent) {
36         sendInBackground {
37             context.sendBroadcast(intent)
38         }
39     }
40 
41     /**
42      * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking
43      * synchronous binder call.
44      */
45     @AnyThread
sendBroadcastnull46     fun sendBroadcast(intent: Intent, receiverPermission: String?) {
47         sendInBackground {
48             context.sendBroadcast(intent, receiverPermission)
49         }
50     }
51 
52     /**
53      * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking
54      * synchronous binder call.
55      */
56     @AnyThread
sendBroadcastAsUsernull57     fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle) {
58         sendInBackground {
59             context.sendBroadcastAsUser(intent, userHandle)
60         }
61     }
62 
63     /**
64      * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking
65      * synchronous binder call.
66      */
67     @AnyThread
sendBroadcastAsUsernull68     fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle, receiverPermission: String?) {
69         sendInBackground {
70             context.sendBroadcastAsUser(intent, userHandle, receiverPermission)
71         }
72     }
73 
74     /**
75      * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking
76      * synchronous binder call.
77      */
78     @AnyThread
sendBroadcastAsUsernull79     fun sendBroadcastAsUser(
80         intent: Intent,
81         userHandle: UserHandle,
82         receiverPermission: String?,
83         options: Bundle?
84     ) {
85         sendInBackground {
86             context.sendBroadcastAsUser(intent, userHandle, receiverPermission, options)
87         }
88     }
89 
90     /**
91      * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking
92      * synchronous binder call.
93      */
94     @AnyThread
sendBroadcastAsUsernull95     fun sendBroadcastAsUser(
96         intent: Intent,
97         userHandle: UserHandle,
98         receiverPermission: String?,
99         appOp: Int
100     ) {
101         sendInBackground {
102             context.sendBroadcastAsUser(intent, userHandle, receiverPermission, appOp)
103         }
104     }
105 
106     /**
107      * Sends [Intent.ACTION_CLOSE_SYSTEM_DIALOGS] broadcast to the system.
108      */
109     @AnyThread
closeSystemDialogsnull110     fun closeSystemDialogs() {
111         sendInBackground {
112             context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
113         }
114     }
115 
116     /**
117      * Dispatches parameter on background executor while holding a wakelock.
118      */
sendInBackgroundnull119     private fun sendInBackground(callable: () -> Unit) {
120         val broadcastWakelock = wakeLockBuilder.setTag(WAKE_LOCK_TAG)
121                                 .setMaxTimeout(5000)
122                                 .build()
123         broadcastWakelock.acquire(WAKE_LOCK_SEND_REASON)
124         bgExecutor.execute {
125             try {
126                 callable.invoke()
127             } finally {
128                 broadcastWakelock.release(WAKE_LOCK_SEND_REASON)
129             }
130         }
131     }
132 }