Merge "Create new sysui thread for using broadcasts" into tm-qpr-dev am: 018b513b1a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20132132 Change-Id: If0eb577735e53f75d17770e6eb384b279f77e50e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -52,7 +52,7 @@ class ActionReceiver(
|
|||||||
private val userId: Int,
|
private val userId: Int,
|
||||||
private val registerAction: BroadcastReceiver.(IntentFilter) -> Unit,
|
private val registerAction: BroadcastReceiver.(IntentFilter) -> Unit,
|
||||||
private val unregisterAction: BroadcastReceiver.() -> Unit,
|
private val unregisterAction: BroadcastReceiver.() -> Unit,
|
||||||
private val bgExecutor: Executor,
|
private val workerExecutor: Executor,
|
||||||
private val logger: BroadcastDispatcherLogger,
|
private val logger: BroadcastDispatcherLogger,
|
||||||
private val testPendingRemovalAction: (BroadcastReceiver, Int) -> Boolean
|
private val testPendingRemovalAction: (BroadcastReceiver, Int) -> Boolean
|
||||||
) : BroadcastReceiver(), Dumpable {
|
) : BroadcastReceiver(), Dumpable {
|
||||||
@@ -112,7 +112,7 @@ class ActionReceiver(
|
|||||||
val id = index.getAndIncrement()
|
val id = index.getAndIncrement()
|
||||||
logger.logBroadcastReceived(id, userId, intent)
|
logger.logBroadcastReceived(id, userId, intent)
|
||||||
// Immediately return control to ActivityManager
|
// Immediately return control to ActivityManager
|
||||||
bgExecutor.execute {
|
workerExecutor.execute {
|
||||||
receiverDatas.forEach {
|
receiverDatas.forEach {
|
||||||
if (it.filter.matchCategories(intent.categories) == null &&
|
if (it.filter.matchCategories(intent.categories) == null &&
|
||||||
!testPendingRemovalAction(it.receiver, userId)) {
|
!testPendingRemovalAction(it.receiver, userId)) {
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
|
|||||||
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
||||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.BroadcastRunning
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
import com.android.systemui.dump.DumpManager
|
import com.android.systemui.dump.DumpManager
|
||||||
import com.android.systemui.settings.UserTracker
|
import com.android.systemui.settings.UserTracker
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
@@ -55,7 +56,6 @@ private const val MSG_ADD_RECEIVER = 0
|
|||||||
private const val MSG_REMOVE_RECEIVER = 1
|
private const val MSG_REMOVE_RECEIVER = 1
|
||||||
private const val MSG_REMOVE_RECEIVER_FOR_USER = 2
|
private const val MSG_REMOVE_RECEIVER_FOR_USER = 2
|
||||||
private const val TAG = "BroadcastDispatcher"
|
private const val TAG = "BroadcastDispatcher"
|
||||||
private const val DEBUG = true
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemUI master Broadcast Dispatcher.
|
* SystemUI master Broadcast Dispatcher.
|
||||||
@@ -73,15 +73,16 @@ private const val DEBUG = true
|
|||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
open class BroadcastDispatcher @Inject constructor(
|
open class BroadcastDispatcher @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@Background private val bgLooper: Looper,
|
@Main private val mainExecutor: Executor,
|
||||||
@Background private val bgExecutor: Executor,
|
@BroadcastRunning private val broadcastLooper: Looper,
|
||||||
|
@BroadcastRunning private val broadcastExecutor: Executor,
|
||||||
private val dumpManager: DumpManager,
|
private val dumpManager: DumpManager,
|
||||||
private val logger: BroadcastDispatcherLogger,
|
private val logger: BroadcastDispatcherLogger,
|
||||||
private val userTracker: UserTracker,
|
private val userTracker: UserTracker,
|
||||||
private val removalPendingStore: PendingRemovalStore
|
private val removalPendingStore: PendingRemovalStore
|
||||||
) : Dumpable {
|
) : Dumpable {
|
||||||
|
|
||||||
// Only modify in BG thread
|
// Only modify in BroadcastRunning thread
|
||||||
private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
|
private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
@@ -148,7 +149,7 @@ open class BroadcastDispatcher @Inject constructor(
|
|||||||
val data = ReceiverData(
|
val data = ReceiverData(
|
||||||
receiver,
|
receiver,
|
||||||
filter,
|
filter,
|
||||||
executor ?: context.mainExecutor,
|
executor ?: mainExecutor,
|
||||||
user ?: context.user,
|
user ?: context.user,
|
||||||
permission
|
permission
|
||||||
)
|
)
|
||||||
@@ -181,7 +182,7 @@ open class BroadcastDispatcher @Inject constructor(
|
|||||||
registerReceiver(
|
registerReceiver(
|
||||||
receiver,
|
receiver,
|
||||||
filter,
|
filter,
|
||||||
bgExecutor,
|
broadcastExecutor,
|
||||||
user,
|
user,
|
||||||
flags,
|
flags,
|
||||||
permission,
|
permission,
|
||||||
@@ -246,8 +247,8 @@ open class BroadcastDispatcher @Inject constructor(
|
|||||||
UserBroadcastDispatcher(
|
UserBroadcastDispatcher(
|
||||||
context,
|
context,
|
||||||
userId,
|
userId,
|
||||||
bgLooper,
|
broadcastLooper,
|
||||||
bgExecutor,
|
broadcastExecutor,
|
||||||
logger,
|
logger,
|
||||||
removalPendingStore
|
removalPendingStore
|
||||||
)
|
)
|
||||||
@@ -265,7 +266,7 @@ open class BroadcastDispatcher @Inject constructor(
|
|||||||
ipw.decreaseIndent()
|
ipw.decreaseIndent()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val handler = object : Handler(bgLooper) {
|
private val handler = object : Handler(broadcastLooper) {
|
||||||
|
|
||||||
override fun handleMessage(msg: Message) {
|
override fun handleMessage(msg: Message) {
|
||||||
when (msg.what) {
|
when (msg.what) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.broadcast
|
package com.android.systemui.broadcast
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@@ -46,8 +47,8 @@ private const val DEBUG = false
|
|||||||
open class UserBroadcastDispatcher(
|
open class UserBroadcastDispatcher(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val userId: Int,
|
private val userId: Int,
|
||||||
private val bgLooper: Looper,
|
private val workerLooper: Looper,
|
||||||
private val bgExecutor: Executor,
|
private val workerExecutor: Executor,
|
||||||
private val logger: BroadcastDispatcherLogger,
|
private val logger: BroadcastDispatcherLogger,
|
||||||
private val removalPendingStore: PendingRemovalStore
|
private val removalPendingStore: PendingRemovalStore
|
||||||
) : Dumpable {
|
) : Dumpable {
|
||||||
@@ -66,9 +67,11 @@ open class UserBroadcastDispatcher(
|
|||||||
val permission: String?
|
val permission: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
private val bgHandler = Handler(bgLooper)
|
private val wrongThreadErrorMsg = "This method should only be called from the worker thread " +
|
||||||
|
"(which is expected to be the BroadcastRunning thread)"
|
||||||
|
private val workerHandler = Handler(workerLooper)
|
||||||
|
|
||||||
// Only modify in BG thread
|
// Only modify in BroadcastRunning thread
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal val actionsToActionsReceivers = ArrayMap<ReceiverProperties, ActionReceiver>()
|
internal val actionsToActionsReceivers = ArrayMap<ReceiverProperties, ActionReceiver>()
|
||||||
private val receiverToActions = ArrayMap<BroadcastReceiver, MutableSet<String>>()
|
private val receiverToActions = ArrayMap<BroadcastReceiver, MutableSet<String>>()
|
||||||
@@ -97,8 +100,7 @@ open class UserBroadcastDispatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRegisterReceiver(receiverData: ReceiverData, flags: Int) {
|
private fun handleRegisterReceiver(receiverData: ReceiverData, flags: Int) {
|
||||||
Preconditions.checkState(bgLooper.isCurrentThread,
|
Preconditions.checkState(workerLooper.isCurrentThread, wrongThreadErrorMsg)
|
||||||
"This method should only be called from BG thread")
|
|
||||||
if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
|
if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
|
||||||
receiverToActions
|
receiverToActions
|
||||||
.getOrPut(receiverData.receiver, { ArraySet() })
|
.getOrPut(receiverData.receiver, { ArraySet() })
|
||||||
@@ -113,6 +115,7 @@ open class UserBroadcastDispatcher(
|
|||||||
logger.logReceiverRegistered(userId, receiverData.receiver, flags)
|
logger.logReceiverRegistered(userId, receiverData.receiver, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RegisterReceiverViaContextDetector")
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal open fun createActionReceiver(
|
internal open fun createActionReceiver(
|
||||||
action: String,
|
action: String,
|
||||||
@@ -128,7 +131,7 @@ open class UserBroadcastDispatcher(
|
|||||||
UserHandle.of(userId),
|
UserHandle.of(userId),
|
||||||
it,
|
it,
|
||||||
permission,
|
permission,
|
||||||
bgHandler,
|
workerHandler,
|
||||||
flags
|
flags
|
||||||
)
|
)
|
||||||
logger.logContextReceiverRegistered(userId, flags, it)
|
logger.logContextReceiverRegistered(userId, flags, it)
|
||||||
@@ -143,15 +146,14 @@ open class UserBroadcastDispatcher(
|
|||||||
IllegalStateException(e))
|
IllegalStateException(e))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bgExecutor,
|
workerExecutor,
|
||||||
logger,
|
logger,
|
||||||
removalPendingStore::isPendingRemoval
|
removalPendingStore::isPendingRemoval
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleUnregisterReceiver(receiver: BroadcastReceiver) {
|
private fun handleUnregisterReceiver(receiver: BroadcastReceiver) {
|
||||||
Preconditions.checkState(bgLooper.isCurrentThread,
|
Preconditions.checkState(workerLooper.isCurrentThread, wrongThreadErrorMsg)
|
||||||
"This method should only be called from BG thread")
|
|
||||||
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
|
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
|
||||||
receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach {
|
receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach {
|
||||||
actionsToActionsReceivers.forEach { (key, value) ->
|
actionsToActionsReceivers.forEach { (key, value) ->
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.dagger.qualifiers;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
@Documented
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface BroadcastRunning {
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import android.os.Process;
|
|||||||
|
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dagger.qualifiers.Background;
|
import com.android.systemui.dagger.qualifiers.Background;
|
||||||
|
import com.android.systemui.dagger.qualifiers.BroadcastRunning;
|
||||||
import com.android.systemui.dagger.qualifiers.LongRunning;
|
import com.android.systemui.dagger.qualifiers.LongRunning;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
|
||||||
@@ -51,6 +52,17 @@ public abstract class SysUIConcurrencyModule {
|
|||||||
return thread.getLooper();
|
return thread.getLooper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** BroadcastRunning Looper (for sending and receiving broadcasts) */
|
||||||
|
@Provides
|
||||||
|
@SysUISingleton
|
||||||
|
@BroadcastRunning
|
||||||
|
public static Looper provideBroadcastRunningLooper() {
|
||||||
|
HandlerThread thread = new HandlerThread("BroadcastRunning",
|
||||||
|
Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
thread.start();
|
||||||
|
return thread.getLooper();
|
||||||
|
}
|
||||||
|
|
||||||
/** Long running tasks Looper */
|
/** Long running tasks Looper */
|
||||||
@Provides
|
@Provides
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
@@ -83,7 +95,17 @@ public abstract class SysUIConcurrencyModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a Long running Executor by default.
|
* Provide a BroadcastRunning Executor (for sending and receiving broadcasts).
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@SysUISingleton
|
||||||
|
@BroadcastRunning
|
||||||
|
public static Executor provideBroadcastRunningExecutor(@BroadcastRunning Looper looper) {
|
||||||
|
return new ExecutorImpl(looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a Long running Executor.
|
||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var removalPendingStore: PendingRemovalStore
|
private lateinit var removalPendingStore: PendingRemovalStore
|
||||||
|
|
||||||
private lateinit var executor: Executor
|
private lateinit var mainExecutor: Executor
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData>
|
private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData>
|
||||||
@@ -108,11 +108,12 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
testableLooper = TestableLooper.get(this)
|
testableLooper = TestableLooper.get(this)
|
||||||
executor = FakeExecutor(FakeSystemClock())
|
mainExecutor = FakeExecutor(FakeSystemClock())
|
||||||
`when`(mockContext.mainExecutor).thenReturn(executor)
|
`when`(mockContext.mainExecutor).thenReturn(mainExecutor)
|
||||||
|
|
||||||
broadcastDispatcher = TestBroadcastDispatcher(
|
broadcastDispatcher = TestBroadcastDispatcher(
|
||||||
mockContext,
|
mockContext,
|
||||||
|
mainExecutor,
|
||||||
testableLooper.looper,
|
testableLooper.looper,
|
||||||
mock(Executor::class.java),
|
mock(Executor::class.java),
|
||||||
mock(DumpManager::class.java),
|
mock(DumpManager::class.java),
|
||||||
@@ -148,9 +149,9 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAddingReceiverToCorrectUBR_executor() {
|
fun testAddingReceiverToCorrectUBR_executor() {
|
||||||
broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, executor, user0)
|
broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mainExecutor, user0)
|
||||||
broadcastDispatcher.registerReceiver(
|
broadcastDispatcher.registerReceiver(
|
||||||
broadcastReceiverOther, intentFilterOther, executor, user1)
|
broadcastReceiverOther, intentFilterOther, mainExecutor, user1)
|
||||||
|
|
||||||
testableLooper.processAllMessages()
|
testableLooper.processAllMessages()
|
||||||
|
|
||||||
@@ -427,8 +428,9 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
|||||||
|
|
||||||
private class TestBroadcastDispatcher(
|
private class TestBroadcastDispatcher(
|
||||||
context: Context,
|
context: Context,
|
||||||
bgLooper: Looper,
|
mainExecutor: Executor,
|
||||||
executor: Executor,
|
backgroundRunningLooper: Looper,
|
||||||
|
backgroundRunningExecutor: Executor,
|
||||||
dumpManager: DumpManager,
|
dumpManager: DumpManager,
|
||||||
logger: BroadcastDispatcherLogger,
|
logger: BroadcastDispatcherLogger,
|
||||||
userTracker: UserTracker,
|
userTracker: UserTracker,
|
||||||
@@ -436,8 +438,9 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
|||||||
var mockUBRMap: Map<Int, UserBroadcastDispatcher>
|
var mockUBRMap: Map<Int, UserBroadcastDispatcher>
|
||||||
) : BroadcastDispatcher(
|
) : BroadcastDispatcher(
|
||||||
context,
|
context,
|
||||||
bgLooper,
|
mainExecutor,
|
||||||
executor,
|
backgroundRunningLooper,
|
||||||
|
backgroundRunningExecutor,
|
||||||
dumpManager,
|
dumpManager,
|
||||||
logger,
|
logger,
|
||||||
userTracker,
|
userTracker,
|
||||||
|
|||||||
@@ -84,9 +84,14 @@ public abstract class SysuiTestCase {
|
|||||||
initializer.init(true);
|
initializer.init(true);
|
||||||
mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency());
|
mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency());
|
||||||
Dependency.setInstance(mDependency);
|
Dependency.setInstance(mDependency);
|
||||||
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class),
|
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(
|
||||||
mock(Executor.class), mock(DumpManager.class),
|
mContext,
|
||||||
mock(BroadcastDispatcherLogger.class), mock(UserTracker.class));
|
mContext.getMainExecutor(),
|
||||||
|
mock(Looper.class),
|
||||||
|
mock(Executor.class),
|
||||||
|
mock(DumpManager.class),
|
||||||
|
mock(BroadcastDispatcherLogger.class),
|
||||||
|
mock(UserTracker.class));
|
||||||
|
|
||||||
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
|
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
Instrumentation inst = spy(mRealInstrumentation);
|
Instrumentation inst = spy(mRealInstrumentation);
|
||||||
|
|||||||
@@ -32,16 +32,18 @@ import java.util.concurrent.Executor
|
|||||||
|
|
||||||
class FakeBroadcastDispatcher(
|
class FakeBroadcastDispatcher(
|
||||||
context: SysuiTestableContext,
|
context: SysuiTestableContext,
|
||||||
looper: Looper,
|
mainExecutor: Executor,
|
||||||
executor: Executor,
|
broadcastRunningLooper: Looper,
|
||||||
|
broadcastRunningExecutor: Executor,
|
||||||
dumpManager: DumpManager,
|
dumpManager: DumpManager,
|
||||||
logger: BroadcastDispatcherLogger,
|
logger: BroadcastDispatcherLogger,
|
||||||
userTracker: UserTracker
|
userTracker: UserTracker
|
||||||
) :
|
) :
|
||||||
BroadcastDispatcher(
|
BroadcastDispatcher(
|
||||||
context,
|
context,
|
||||||
looper,
|
mainExecutor,
|
||||||
executor,
|
broadcastRunningLooper,
|
||||||
|
broadcastRunningExecutor,
|
||||||
dumpManager,
|
dumpManager,
|
||||||
logger,
|
logger,
|
||||||
userTracker,
|
userTracker,
|
||||||
|
|||||||
Reference in New Issue
Block a user