Loading packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt +51 −23 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.os.UserHandle import android.util.ArrayMap import android.util.ArraySet import android.util.Log import androidx.annotation.MainThread import com.android.internal.util.Preconditions import com.android.systemui.Dumpable import java.io.FileDescriptor import java.io.PrintWriter Loading Loading @@ -72,7 +74,14 @@ class UserBroadcastDispatcher( internal fun isRegistered() = registered.get() private val registerReceiver = Runnable { // Only modify in BG thread private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>() private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>() // Only call on BG thread as it reads from the maps private fun createFilter(): IntentFilter { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") val categories = mutableSetOf<String>() receiverToReceiverData.values.flatten().forEach { it.filter.categoriesIterator()?.asSequence()?.let { Loading @@ -80,30 +89,13 @@ class UserBroadcastDispatcher( } } val intentFilter = IntentFilter().apply { actionsToReceivers.keys.forEach { addAction(it) } // The keys of the arrayMap are of type String! so null check is needed actionsToReceivers.keys.forEach { if (it != null) addAction(it) else Unit } categories.forEach { addCategory(it) } } if (registered.get()) { context.unregisterReceiver(this) registered.set(false) } // Short interval without receiver, this can be problematic if (intentFilter.countActions() > 0 && !registered.get()) { context.registerReceiverAsUser( this, UserHandle.of(userId), intentFilter, null, bgHandler) registered.set(true) } return intentFilter } // Only modify in BG thread private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>() private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>() override fun onReceive(context: Context, intent: Intent) { val id = if (DEBUG) index.getAndIncrement() else 0 if (DEBUG) Log.w(TAG, "[$id] Received $intent") Loading @@ -126,6 +118,8 @@ class UserBroadcastDispatcher( } private fun handleRegisterReceiver(receiverData: ReceiverData) { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}") receiverToReceiverData.getOrPut(receiverData.receiver, { ArraySet() }).add(receiverData) var changed = false Loading @@ -138,11 +132,13 @@ class UserBroadcastDispatcher( }.add(receiverData) } if (changed) { mainHandler.post(registerReceiver) createFilterAndRegisterReceiverBG() } } private fun handleUnregisterReceiver(receiver: BroadcastReceiver) { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver") val actions = receiverToReceiverData.getOrElse(receiver) { return } .flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet() Loading @@ -156,10 +152,16 @@ class UserBroadcastDispatcher( } } if (changed) { mainHandler.post(registerReceiver) createFilterAndRegisterReceiverBG() } } // Only call this from a BG thread private fun createFilterAndRegisterReceiverBG() { val intentFilter = createFilter() mainHandler.post(RegisterReceiverRunnable(intentFilter)) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { pw.println(" Registered=${registered.get()}") actionsToReceivers.forEach { (action, list) -> Loading Loading @@ -191,4 +193,30 @@ class UserBroadcastDispatcher( } } } private inner class RegisterReceiverRunnable(val intentFilter: IntentFilter) : Runnable { /* * Registers and unregisters the BroadcastReceiver * * Must be called from Main Thread */ @MainThread override fun run() { if (registered.get()) { context.unregisterReceiver(this@UserBroadcastDispatcher) registered.set(false) } // Short interval without receiver, this can be problematic if (intentFilter.countActions() > 0 && !registered.get()) { context.registerReceiverAsUser( this@UserBroadcastDispatcher, UserHandle.of(userId), intentFilter, null, bgHandler) registered.set(true) } } } } Loading
packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt +51 −23 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.os.UserHandle import android.util.ArrayMap import android.util.ArraySet import android.util.Log import androidx.annotation.MainThread import com.android.internal.util.Preconditions import com.android.systemui.Dumpable import java.io.FileDescriptor import java.io.PrintWriter Loading Loading @@ -72,7 +74,14 @@ class UserBroadcastDispatcher( internal fun isRegistered() = registered.get() private val registerReceiver = Runnable { // Only modify in BG thread private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>() private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>() // Only call on BG thread as it reads from the maps private fun createFilter(): IntentFilter { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") val categories = mutableSetOf<String>() receiverToReceiverData.values.flatten().forEach { it.filter.categoriesIterator()?.asSequence()?.let { Loading @@ -80,30 +89,13 @@ class UserBroadcastDispatcher( } } val intentFilter = IntentFilter().apply { actionsToReceivers.keys.forEach { addAction(it) } // The keys of the arrayMap are of type String! so null check is needed actionsToReceivers.keys.forEach { if (it != null) addAction(it) else Unit } categories.forEach { addCategory(it) } } if (registered.get()) { context.unregisterReceiver(this) registered.set(false) } // Short interval without receiver, this can be problematic if (intentFilter.countActions() > 0 && !registered.get()) { context.registerReceiverAsUser( this, UserHandle.of(userId), intentFilter, null, bgHandler) registered.set(true) } return intentFilter } // Only modify in BG thread private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>() private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>() override fun onReceive(context: Context, intent: Intent) { val id = if (DEBUG) index.getAndIncrement() else 0 if (DEBUG) Log.w(TAG, "[$id] Received $intent") Loading @@ -126,6 +118,8 @@ class UserBroadcastDispatcher( } private fun handleRegisterReceiver(receiverData: ReceiverData) { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}") receiverToReceiverData.getOrPut(receiverData.receiver, { ArraySet() }).add(receiverData) var changed = false Loading @@ -138,11 +132,13 @@ class UserBroadcastDispatcher( }.add(receiverData) } if (changed) { mainHandler.post(registerReceiver) createFilterAndRegisterReceiverBG() } } private fun handleUnregisterReceiver(receiver: BroadcastReceiver) { Preconditions.checkState(bgHandler.looper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver") val actions = receiverToReceiverData.getOrElse(receiver) { return } .flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet() Loading @@ -156,10 +152,16 @@ class UserBroadcastDispatcher( } } if (changed) { mainHandler.post(registerReceiver) createFilterAndRegisterReceiverBG() } } // Only call this from a BG thread private fun createFilterAndRegisterReceiverBG() { val intentFilter = createFilter() mainHandler.post(RegisterReceiverRunnable(intentFilter)) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { pw.println(" Registered=${registered.get()}") actionsToReceivers.forEach { (action, list) -> Loading Loading @@ -191,4 +193,30 @@ class UserBroadcastDispatcher( } } } private inner class RegisterReceiverRunnable(val intentFilter: IntentFilter) : Runnable { /* * Registers and unregisters the BroadcastReceiver * * Must be called from Main Thread */ @MainThread override fun run() { if (registered.get()) { context.unregisterReceiver(this@UserBroadcastDispatcher) registered.set(false) } // Short interval without receiver, this can be problematic if (intentFilter.countActions() > 0 && !registered.get()) { context.registerReceiverAsUser( this@UserBroadcastDispatcher, UserHandle.of(userId), intentFilter, null, bgHandler) registered.set(true) } } } }