[DO NOT MERGE] Fix BroadcastDispatcher registering with CURRENT
When a BroadcastReceiver is registered with UserHandle.CURRENT, the current user should be obtained. This has to be cached in order to not call ActivityManager every time. As it is done in the initializer the initial value caching will happen before any other BroadcastReceiver is actually registered. The caching and updating is all done in the background thread. Also, remove unnecessary dependency. Test: manual Test: atest BroadcastDispatcher Fixes: 158298581 Change-Id: Idfd2dc65f9079c57e971250aa7b0aef222da5af5
This commit is contained in:
@@ -62,7 +62,7 @@ Acquire the dispatcher by using `@Inject` to obtain a `BroadcastDispatcher`. The
|
||||
* @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
|
||||
* executor in the main thread (default).
|
||||
* @param user A user handle to determine which broadcast should be dispatched to this receiver.
|
||||
* By default, it is the current user.
|
||||
* By default, it is the user of the context (system user in SystemUI).
|
||||
* @throws IllegalArgumentException if the filter has other constraints that are not actions or
|
||||
* categories or the filter has no actions.
|
||||
*/
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package com.android.systemui.broadcast
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Handler
|
||||
import android.os.HandlerExecutor
|
||||
@@ -29,14 +31,10 @@ import android.util.SparseArray
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import java.io.FileDescriptor
|
||||
import java.io.PrintWriter
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
data class ReceiverData(
|
||||
val receiver: BroadcastReceiver,
|
||||
@@ -48,6 +46,8 @@ data class ReceiverData(
|
||||
private const val MSG_ADD_RECEIVER = 0
|
||||
private const val MSG_REMOVE_RECEIVER = 1
|
||||
private const val MSG_REMOVE_RECEIVER_FOR_USER = 2
|
||||
private const val MSG_USER_SWITCH = 3
|
||||
private const val MSG_SET_STARTING_USER = 99
|
||||
private const val TAG = "BroadcastDispatcher"
|
||||
private const val DEBUG = true
|
||||
|
||||
@@ -62,21 +62,27 @@ private const val DEBUG = true
|
||||
* permissions, schemes, data types, data authorities or priority different than 0.
|
||||
* Cannot be used for getting sticky broadcasts (either as return of registering or as re-delivery).
|
||||
*/
|
||||
@Singleton
|
||||
open class BroadcastDispatcher @Inject constructor (
|
||||
open class BroadcastDispatcher constructor (
|
||||
private val context: Context,
|
||||
@Main private val mainHandler: Handler,
|
||||
@Background private val bgLooper: Looper,
|
||||
dumpManager: DumpManager,
|
||||
private val bgLooper: Looper,
|
||||
private val dumpManager: DumpManager,
|
||||
private val logger: BroadcastDispatcherLogger
|
||||
) : Dumpable {
|
||||
) : Dumpable, BroadcastReceiver() {
|
||||
|
||||
// Only modify in BG thread
|
||||
private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
|
||||
|
||||
init {
|
||||
// TODO: Don't do this in the constructor
|
||||
fun initialize() {
|
||||
dumpManager.registerDumpable(javaClass.name, this)
|
||||
handler.sendEmptyMessage(MSG_SET_STARTING_USER)
|
||||
registerReceiver(this, IntentFilter(Intent.ACTION_USER_SWITCHED), null, UserHandle.ALL)
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_USER_SWITCHED) {
|
||||
val user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)
|
||||
handler.obtainMessage(MSG_USER_SWITCH, user, 0).sendToTarget()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +94,7 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
* have at least one action.
|
||||
* @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 current user.
|
||||
* By default, it is the user of the context (system user in SystemUI).
|
||||
* @throws IllegalArgumentException if the filter has other constraints that are not actions or
|
||||
* categories or the filter has no actions.
|
||||
*/
|
||||
@@ -114,7 +120,7 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
* @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
|
||||
* executor in the main thread (default).
|
||||
* @param user A user handle to determine which broadcast should be dispatched to this receiver.
|
||||
* By default, it is the current user.
|
||||
* By default, it is the user of the context (system user in SystemUI).
|
||||
* @throws IllegalArgumentException if the filter has other constraints that are not actions or
|
||||
* categories or the filter has no actions.
|
||||
*/
|
||||
@@ -171,6 +177,7 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
|
||||
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
|
||||
pw.println("Broadcast dispatcher:")
|
||||
pw.println(" Current user: ${handler.currentUser}")
|
||||
for (index in 0 until receiversByUser.size()) {
|
||||
pw.println(" User ${receiversByUser.keyAt(index)}")
|
||||
receiversByUser.valueAt(index).dump(fd, pw, args)
|
||||
@@ -178,6 +185,8 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
}
|
||||
|
||||
private val handler = object : Handler(bgLooper) {
|
||||
var currentUser = UserHandle.USER_SYSTEM
|
||||
|
||||
override fun handleMessage(msg: Message) {
|
||||
when (msg.what) {
|
||||
MSG_ADD_RECEIVER -> {
|
||||
@@ -185,7 +194,7 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
// 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) {
|
||||
context.userId
|
||||
currentUser
|
||||
} else {
|
||||
data.user.identifier
|
||||
}
|
||||
@@ -208,6 +217,13 @@ open class BroadcastDispatcher @Inject constructor (
|
||||
receiversByUser.get(msg.arg1)?.unregisterReceiver(msg.obj as BroadcastReceiver)
|
||||
}
|
||||
|
||||
MSG_USER_SWITCH -> {
|
||||
currentUser = msg.arg1
|
||||
}
|
||||
MSG_SET_STARTING_USER -> {
|
||||
currentUser = ActivityManager.getCurrentUser()
|
||||
}
|
||||
|
||||
else -> super.handleMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.hardware.display.AmbientDisplayConfiguration;
|
||||
import android.hardware.display.NightDisplayListener;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Choreographer;
|
||||
@@ -39,9 +40,12 @@ import com.android.internal.util.NotificationMessagingUtil;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.ViewMediatorCallback;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.keyguard.KeyguardViewMediator;
|
||||
import com.android.systemui.plugins.PluginInitializerImpl;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
@@ -178,6 +182,21 @@ public class DependencyProvider {
|
||||
return ActivityManagerWrapper.getInstance();
|
||||
}
|
||||
|
||||
/** Provides and initializes the {#link BroadcastDispatcher} for SystemUI */
|
||||
@Singleton
|
||||
@Provides
|
||||
public BroadcastDispatcher providesBroadcastDispatcher(
|
||||
Context context,
|
||||
@Background Looper backgroundLooper,
|
||||
DumpManager dumpManager,
|
||||
BroadcastDispatcherLogger logger
|
||||
) {
|
||||
BroadcastDispatcher bD =
|
||||
new BroadcastDispatcher(context, backgroundLooper, dumpManager, logger);
|
||||
bD.initialize();
|
||||
return bD;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() {
|
||||
|
||||
@@ -73,8 +73,8 @@ public abstract class SysuiTestCase {
|
||||
public void SysuiSetup() throws Exception {
|
||||
SystemUIFactory.createFromConfig(mContext);
|
||||
mDependency = new TestableDependency(mContext);
|
||||
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Handler.class),
|
||||
mock(Looper.class), mock(DumpManager.class), mock(BroadcastDispatcherLogger.class));
|
||||
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class),
|
||||
mock(DumpManager.class), mock(BroadcastDispatcherLogger.class));
|
||||
|
||||
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
Instrumentation inst = spy(mRealInstrumentation);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.broadcast
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
@@ -96,7 +97,6 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
||||
|
||||
broadcastDispatcher = TestBroadcastDispatcher(
|
||||
mockContext,
|
||||
Handler(testableLooper.looper),
|
||||
testableLooper.looper,
|
||||
mock(DumpManager::class.java),
|
||||
logger,
|
||||
@@ -177,7 +177,12 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun testRegisterCurrentAsActualUser() {
|
||||
setUserMock(mockContext, user1)
|
||||
val intent = Intent(Intent.ACTION_USER_SWITCHED).apply {
|
||||
putExtra(Intent.EXTRA_USER_HANDLE, user1.identifier)
|
||||
}
|
||||
broadcastDispatcher.onReceive(mockContext, intent)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
|
||||
mockHandler, UserHandle.CURRENT)
|
||||
|
||||
@@ -240,12 +245,11 @@ class BroadcastDispatcherTest : SysuiTestCase() {
|
||||
|
||||
private class TestBroadcastDispatcher(
|
||||
context: Context,
|
||||
mainHandler: Handler,
|
||||
bgLooper: Looper,
|
||||
dumpManager: DumpManager,
|
||||
logger: BroadcastDispatcherLogger,
|
||||
var mockUBRMap: Map<Int, UserBroadcastDispatcher>
|
||||
) : BroadcastDispatcher(context, mainHandler, bgLooper, dumpManager, logger) {
|
||||
) : BroadcastDispatcher(context, bgLooper, dumpManager, logger) {
|
||||
override fun createUBRForUser(userId: Int): UserBroadcastDispatcher {
|
||||
return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java))
|
||||
}
|
||||
|
||||
@@ -30,11 +30,10 @@ import java.util.concurrent.Executor
|
||||
|
||||
class FakeBroadcastDispatcher(
|
||||
context: SysuiTestableContext,
|
||||
handler: Handler,
|
||||
looper: Looper,
|
||||
dumpManager: DumpManager,
|
||||
logger: BroadcastDispatcherLogger
|
||||
) : BroadcastDispatcher(context, handler, looper, dumpManager, logger) {
|
||||
) : BroadcastDispatcher(context, looper, dumpManager, logger) {
|
||||
|
||||
private val registeredReceivers = ArraySet<BroadcastReceiver>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user