Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c737f68 authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Add flags to BroadcastDispatcher"

parents 2b00db99 def01e74
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ Additionally, the dispatcher supports the following:
* Subscriptions can be done in any thread.
* Broadcasts will be dispatched on the main thread (same as `system_server`) by default but a `Handler` can be specified for dispatching
* A `UserHandle` can be provided to filter the broadcasts by user.
* Flags (see [`Context#RegisterReceiverFlags`](/core/java/android/content/Context.java)) can be passed for the registration. By default, this will be `Context#RECEIVER_EXPORTED`.

If introducing a new `BroadcastReceiver` (not declared in `AndroidManifest`) that satisfies the constraints above, use the dispatcher to reduce the load on `system_server`.

@@ -63,6 +64,8 @@ Acquire the dispatcher by using `@Inject` to obtain a `BroadcastDispatcher`. The
 *                 executor in the main thread (default).
 * @param user A user handle to determine which broadcast should be dispatched to this receiver.
 *             Pass `null` to use the user of the context (system user in SystemUI).
 * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
 *              default.             
 * @throws IllegalArgumentException if the filter has other constraints that are not actions or
 *                                  categories or the filter has no actions.
 */
@@ -71,7 +74,8 @@ open fun registerReceiver(
    receiver: BroadcastReceiver,
    filter: IntentFilter,
    executor: Executor? = null,
    user: UserHandle? = null
    user: UserHandle? = null,
    @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
)
```

+19 −10
Original line number Diff line number Diff line
@@ -87,8 +87,11 @@ open class BroadcastDispatcher constructor (
     * @param handler A handler to dispatch [BroadcastReceiver.onReceive].
     * @param user A user handle to determine which broadcast should be dispatched to this receiver.
     *             By default, it is the user of the context (system user in SystemUI).
     * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
     *              default.
     * @throws IllegalArgumentException if the filter has other constraints that are not actions or
     *                                  categories or the filter has no actions.
     *
     */
    @Deprecated(message = "Replacing Handler for Executor in SystemUI",
            replaceWith = ReplaceWith("registerReceiver(receiver, filter, executor, user)"))
@@ -97,9 +100,10 @@ open class BroadcastDispatcher constructor (
        receiver: BroadcastReceiver,
        filter: IntentFilter,
        handler: Handler,
        user: UserHandle = context.user
        user: UserHandle = context.user,
        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
    ) {
        registerReceiver(receiver, filter, HandlerExecutor(handler), user)
        registerReceiver(receiver, filter, HandlerExecutor(handler), user, flags)
    }

    /**
@@ -113,6 +117,8 @@ open class BroadcastDispatcher constructor (
     *                 executor in the main thread (default).
     * @param user A user handle to determine which broadcast should be dispatched to this receiver.
     *             Pass `null` to use the user of the context (system user in SystemUI).
     * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
     *              default.
     * @throws IllegalArgumentException if the filter has other constraints that are not actions or
     *                                  categories or the filter has no actions.
     */
@@ -121,16 +127,18 @@ open class BroadcastDispatcher constructor (
        receiver: BroadcastReceiver,
        filter: IntentFilter,
        executor: Executor? = null,
        user: UserHandle? = null
        user: UserHandle? = null,
        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
    ) {
        checkFilter(filter)
        this.handler
                .obtainMessage(MSG_ADD_RECEIVER, ReceiverData(
        val data = ReceiverData(
                receiver,
                filter,
                executor ?: context.mainExecutor,
                user ?: context.user
                ))
        )
        this.handler
                .obtainMessage(MSG_ADD_RECEIVER, flags, 0, data)
                .sendToTarget()
    }

@@ -188,6 +196,7 @@ open class BroadcastDispatcher constructor (
            when (msg.what) {
                MSG_ADD_RECEIVER -> {
                    val data = msg.obj as ReceiverData
                    val flags = msg.arg1
                    // If the receiver asked to be registered under the current user, we register
                    // under the actual current user.
                    val userId = if (data.user.identifier == UserHandle.USER_CURRENT) {
@@ -201,7 +210,7 @@ open class BroadcastDispatcher constructor (
                    }
                    val uBR = receiversByUser.get(userId, createUBRForUser(userId))
                    receiversByUser.put(userId, uBR)
                    uBR.registerReceiver(data)
                    uBR.registerReceiver(data, flags)
                }

                MSG_REMOVE_RECEIVER -> {
+25 −13
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ open class UserBroadcastDispatcher(
    private val bgHandler = object : Handler(bgLooper) {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData)
                MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData, msg.arg1)
                MSG_UNREGISTER_RECEIVER -> handleUnregisterReceiver(msg.obj as BroadcastReceiver)
                else -> Unit
            }
@@ -73,7 +73,7 @@ open class UserBroadcastDispatcher(

    // Only modify in BG thread
    @VisibleForTesting
    internal val actionsToActionsReceivers = ArrayMap<String, ActionReceiver>()
    internal val actionsToActionsReceivers = ArrayMap<Pair<String, Int>, ActionReceiver>()
    private val receiverToActions = ArrayMap<BroadcastReceiver, MutableSet<String>>()

    @VisibleForTesting
@@ -86,8 +86,8 @@ open class UserBroadcastDispatcher(
    /**
     * Register a [ReceiverData] for this user.
     */
    fun registerReceiver(receiverData: ReceiverData) {
        bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, receiverData).sendToTarget()
    fun registerReceiver(receiverData: ReceiverData, flags: Int) {
        bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, flags, 0, receiverData).sendToTarget()
    }

    /**
@@ -97,7 +97,7 @@ open class UserBroadcastDispatcher(
        bgHandler.obtainMessage(MSG_UNREGISTER_RECEIVER, receiver).sendToTarget()
    }

    private fun handleRegisterReceiver(receiverData: ReceiverData) {
    private fun handleRegisterReceiver(receiverData: ReceiverData, flags: Int) {
        Preconditions.checkState(bgHandler.looper.isCurrentThread,
                "This method should only be called from BG thread")
        if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
@@ -106,20 +106,27 @@ open class UserBroadcastDispatcher(
                .addAll(receiverData.filter.actionsIterator()?.asSequence() ?: emptySequence())
        receiverData.filter.actionsIterator().forEach {
            actionsToActionsReceivers
                    .getOrPut(it, { createActionReceiver(it) })
                    .getOrPut(it to flags, { createActionReceiver(it, flags) })
                    .addReceiverData(receiverData)
        }
        logger.logReceiverRegistered(userId, receiverData.receiver)
        logger.logReceiverRegistered(userId, receiverData.receiver, flags)
    }

    @VisibleForTesting
    internal open fun createActionReceiver(action: String): ActionReceiver {
    internal open fun createActionReceiver(action: String, flags: Int): ActionReceiver {
        return ActionReceiver(
                action,
                userId,
                {
                    context.registerReceiverAsUser(this, UserHandle.of(userId), it, null, bgHandler)
                    logger.logContextReceiverRegistered(userId, it)
                    context.registerReceiverAsUser(
                            this,
                            UserHandle.of(userId),
                            it,
                            null,
                            bgHandler,
                            flags
                    )
                    logger.logContextReceiverRegistered(userId, flags, it)
                },
                {
                    try {
@@ -141,7 +148,11 @@ open class UserBroadcastDispatcher(
                "This method should only be called from BG thread")
        if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
        receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach {
            actionsToActionsReceivers.get(it)?.removeReceiver(receiver)
            actionsToActionsReceivers.forEach { (key, value) ->
                if (key.first == it) {
                    value.removeReceiver(receiver)
                }
            }
        }
        receiverToActions.remove(receiver)
        logger.logReceiverUnregistered(userId, receiver)
@@ -149,8 +160,9 @@ open class UserBroadcastDispatcher(

    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
        pw.indentIfPossible {
            actionsToActionsReceivers.forEach { (action, actionReceiver) ->
                println("$action:")
            actionsToActionsReceivers.forEach { (actionAndFlags, actionReceiver) ->
                println("(${actionAndFlags.first}: " +
                        "${BroadcastDispatcherLogger.flagToString(actionAndFlags.second)}):")
                actionReceiver.dump(fd, pw, args)
            }
        }
+27 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.broadcast.logging

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.android.systemui.log.LogBuffer
@@ -33,6 +34,25 @@ class BroadcastDispatcherLogger @Inject constructor(
    @BroadcastDispatcherLog private val buffer: LogBuffer
) {

    companion object {
        fun flagToString(@Context.RegisterReceiverFlags flag: Int): String {
            val b = StringBuilder("")
            if (flag and Context.RECEIVER_VISIBLE_TO_INSTANT_APPS != 0) {
                b.append("instant_apps,")
            }
            if (flag and Context.RECEIVER_NOT_EXPORTED != 0) {
                b.append("not_exported,")
            }
            if (flag and Context.RECEIVER_EXPORTED != 0) {
                b.append("exported")
            }
            if (b.isEmpty()) {
                b.append(flag)
            }
            return b.toString()
        }
    }

    fun logBroadcastReceived(broadcastId: Int, user: Int, intent: Intent) {
        val intentString = intent.toString()
        log(INFO, {
@@ -55,13 +75,15 @@ class BroadcastDispatcherLogger @Inject constructor(
        })
    }

    fun logReceiverRegistered(user: Int, receiver: BroadcastReceiver) {
    fun logReceiverRegistered(user: Int, receiver: BroadcastReceiver, flags: Int) {
        val receiverString = receiver.toString()
        val flagsString = flagToString(flags)
        log(INFO, {
            int1 = user
            str1 = receiverString
            str2 = flagsString
        }, {
            "Receiver $str1 registered for user $int1"
            "Receiver $str1 ($str2) registered for user $int1"
        })
    }

@@ -75,7 +97,7 @@ class BroadcastDispatcherLogger @Inject constructor(
        })
    }

    fun logContextReceiverRegistered(user: Int, filter: IntentFilter) {
    fun logContextReceiverRegistered(user: Int, flags: Int, filter: IntentFilter) {
        val actions = filter.actionsIterator().asSequence()
                .joinToString(separator = ",", prefix = "Actions(", postfix = ")")
        val categories = if (filter.countCategories() != 0) {
@@ -91,9 +113,10 @@ class BroadcastDispatcherLogger @Inject constructor(
            } else {
                actions
            }
            str2 = flagToString(flags)
        }, {
            """
                Receiver registered with Context for user $int1.
                Receiver registered with Context for user $int1. Flags=$str2
                $str1
            """.trimIndent()
        })
+59 −5
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.dump.DumpManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import junit.framework.Assert.assertSame
import org.junit.Before
@@ -54,6 +55,7 @@ class BroadcastDispatcherTest : SysuiTestCase() {
    companion object {
        val user0 = UserHandle.of(0)
        val user1 = UserHandle.of(1)
        const val DEFAULT_FLAG = Context.RECEIVER_EXPORTED

        fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
        const val TEST_ACTION = "TEST_ACTION"
@@ -96,6 +98,7 @@ class BroadcastDispatcherTest : SysuiTestCase() {
        MockitoAnnotations.initMocks(this)
        testableLooper = TestableLooper.get(this)
        executor = FakeExecutor(FakeSystemClock())
        `when`(mockContext.mainExecutor).thenReturn(executor)

        broadcastDispatcher = TestBroadcastDispatcher(
                mockContext,
@@ -121,12 +124,12 @@ class BroadcastDispatcherTest : SysuiTestCase() {

        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor))
        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)

        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
        assertSame(broadcastReceiverOther, argumentCaptor.value.receiver)
        assertSame(intentFilterOther, argumentCaptor.value.filter)
    }
@@ -139,16 +142,66 @@ class BroadcastDispatcherTest : SysuiTestCase() {

        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor))
        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)

        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
        assertSame(broadcastReceiverOther, argumentCaptor.value.receiver)
        assertSame(intentFilterOther, argumentCaptor.value.filter)
    }

    @Test
    fun testAddReceiverDefaultFlag_handler() {
        broadcastDispatcher.registerReceiverWithHandler(
                broadcastReceiver, intentFilter, mockHandler)
        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)
    }

    @Test
    fun testAddReceiverCorrectFlag_handler() {
        val flag = 3

        broadcastDispatcher.registerReceiverWithHandler(
                broadcastReceiver, intentFilter, mockHandler, flags = flag)
        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)
    }

    @Test
    fun testAddReceiverDefaultFlag_executor() {
        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter)
        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)
    }

    @Test
    fun testAddReceiverCorrectFlag_executor() {
        val flag = 3

        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, flags = flag)
        testableLooper.processAllMessages()

        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag))

        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
        assertSame(intentFilter, argumentCaptor.value.filter)
    }

    @Test
    fun testRemovingReceiversRemovesFromAllUBR() {
        broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
@@ -188,7 +241,8 @@ class BroadcastDispatcherTest : SysuiTestCase() {

        testableLooper.processAllMessages()

        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
        verify(mockUBRUser1).registerReceiver(
                capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED))
        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
    }

Loading