[DO NOT MERGE] Fix BroadcastDispatcher registering with CURRENT am: e771b7529e

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11792343

Change-Id: Ia1d89c5e65915027359b1e6d4b2abdc8c26bf24d
This commit is contained in:
Fabian Kozynski
2020-06-11 19:22:03 +00:00
committed by Automerger Merge Worker
6 changed files with 62 additions and 24 deletions

View File

@@ -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 * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
* executor in the main thread (default). * executor in the main thread (default).
* @param user A user handle to determine which broadcast should be dispatched to this receiver. * @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 * @throws IllegalArgumentException if the filter has other constraints that are not actions or
* categories or the filter has no actions. * categories or the filter has no actions.
*/ */

View File

@@ -16,8 +16,10 @@
package com.android.systemui.broadcast package com.android.systemui.broadcast
import android.app.ActivityManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Handler import android.os.Handler
import android.os.HandlerExecutor import android.os.HandlerExecutor
@@ -29,14 +31,10 @@ import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable import com.android.systemui.Dumpable
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger 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 com.android.systemui.dump.DumpManager
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.PrintWriter import java.io.PrintWriter
import java.util.concurrent.Executor import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Singleton
data class ReceiverData( data class ReceiverData(
val receiver: BroadcastReceiver, val receiver: BroadcastReceiver,
@@ -48,6 +46,8 @@ data class ReceiverData(
private const val MSG_ADD_RECEIVER = 0 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 MSG_USER_SWITCH = 3
private const val MSG_SET_STARTING_USER = 99
private const val TAG = "BroadcastDispatcher" private const val TAG = "BroadcastDispatcher"
private const val DEBUG = true 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. * 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). * Cannot be used for getting sticky broadcasts (either as return of registering or as re-delivery).
*/ */
@Singleton open class BroadcastDispatcher constructor (
open class BroadcastDispatcher @Inject constructor (
private val context: Context, private val context: Context,
@Main private val mainHandler: Handler, private val bgLooper: Looper,
@Background private val bgLooper: Looper, private val dumpManager: DumpManager,
dumpManager: DumpManager,
private val logger: BroadcastDispatcherLogger private val logger: BroadcastDispatcherLogger
) : Dumpable { ) : Dumpable, BroadcastReceiver() {
// Only modify in BG thread // Only modify in BG thread
private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20) private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
init { fun initialize() {
// TODO: Don't do this in the constructor
dumpManager.registerDumpable(javaClass.name, this) 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. * have at least one action.
* @param handler A handler to dispatch [BroadcastReceiver.onReceive]. * @param handler A handler to dispatch [BroadcastReceiver.onReceive].
* @param user A user handle to determine which broadcast should be dispatched to this receiver. * @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 * @throws IllegalArgumentException if the filter has other constraints that are not actions or
* categories or the filter has no actions. * 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 * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
* executor in the main thread (default). * executor in the main thread (default).
* @param user A user handle to determine which broadcast should be dispatched to this receiver. * @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 * @throws IllegalArgumentException if the filter has other constraints that are not actions or
* categories or the filter has no actions. * 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>) { override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("Broadcast dispatcher:") pw.println("Broadcast dispatcher:")
pw.println(" Current user: ${handler.currentUser}")
for (index in 0 until receiversByUser.size()) { for (index in 0 until receiversByUser.size()) {
pw.println(" User ${receiversByUser.keyAt(index)}") pw.println(" User ${receiversByUser.keyAt(index)}")
receiversByUser.valueAt(index).dump(fd, pw, args) receiversByUser.valueAt(index).dump(fd, pw, args)
@@ -178,6 +185,8 @@ open class BroadcastDispatcher @Inject constructor (
} }
private val handler = object : Handler(bgLooper) { private val handler = object : Handler(bgLooper) {
var currentUser = UserHandle.USER_SYSTEM
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
when (msg.what) { when (msg.what) {
MSG_ADD_RECEIVER -> { 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 // If the receiver asked to be registered under the current user, we register
// under the actual current user. // under the actual current user.
val userId = if (data.user.identifier == UserHandle.USER_CURRENT) { val userId = if (data.user.identifier == UserHandle.USER_CURRENT) {
context.userId currentUser
} else { } else {
data.user.identifier data.user.identifier
} }
@@ -208,6 +217,13 @@ open class BroadcastDispatcher @Inject constructor (
receiversByUser.get(msg.arg1)?.unregisterReceiver(msg.obj as BroadcastReceiver) 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) else -> super.handleMessage(msg)
} }
} }

View File

@@ -25,6 +25,7 @@ import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.NightDisplayListener; import android.hardware.display.NightDisplayListener;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.Choreographer; import android.view.Choreographer;
@@ -39,9 +40,12 @@ import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback; import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Prefs; 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.Background;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy; import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.PluginInitializerImpl; import com.android.systemui.plugins.PluginInitializerImpl;
import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.plugins.PluginManager;
@@ -178,6 +182,21 @@ public class DependencyProvider {
return ActivityManagerWrapper.getInstance(); 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 @Singleton
@Provides @Provides
public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() { public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() {

View File

@@ -73,8 +73,8 @@ public abstract class SysuiTestCase {
public void SysuiSetup() throws Exception { public void SysuiSetup() throws Exception {
SystemUIFactory.createFromConfig(mContext); SystemUIFactory.createFromConfig(mContext);
mDependency = new TestableDependency(mContext); mDependency = new TestableDependency(mContext);
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Handler.class), mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class),
mock(Looper.class), mock(DumpManager.class), mock(BroadcastDispatcherLogger.class)); mock(DumpManager.class), mock(BroadcastDispatcherLogger.class));
mRealInstrumentation = InstrumentationRegistry.getInstrumentation(); mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
Instrumentation inst = spy(mRealInstrumentation); Instrumentation inst = spy(mRealInstrumentation);

View File

@@ -18,6 +18,7 @@ package com.android.systemui.broadcast
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@@ -96,7 +97,6 @@ class BroadcastDispatcherTest : SysuiTestCase() {
broadcastDispatcher = TestBroadcastDispatcher( broadcastDispatcher = TestBroadcastDispatcher(
mockContext, mockContext,
Handler(testableLooper.looper),
testableLooper.looper, testableLooper.looper,
mock(DumpManager::class.java), mock(DumpManager::class.java),
logger, logger,
@@ -177,7 +177,12 @@ class BroadcastDispatcherTest : SysuiTestCase() {
@Test @Test
fun testRegisterCurrentAsActualUser() { 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, broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
mockHandler, UserHandle.CURRENT) mockHandler, UserHandle.CURRENT)
@@ -240,12 +245,11 @@ class BroadcastDispatcherTest : SysuiTestCase() {
private class TestBroadcastDispatcher( private class TestBroadcastDispatcher(
context: Context, context: Context,
mainHandler: Handler,
bgLooper: Looper, bgLooper: Looper,
dumpManager: DumpManager, dumpManager: DumpManager,
logger: BroadcastDispatcherLogger, logger: BroadcastDispatcherLogger,
var mockUBRMap: Map<Int, UserBroadcastDispatcher> var mockUBRMap: Map<Int, UserBroadcastDispatcher>
) : BroadcastDispatcher(context, mainHandler, bgLooper, dumpManager, logger) { ) : BroadcastDispatcher(context, bgLooper, dumpManager, logger) {
override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { override fun createUBRForUser(userId: Int): UserBroadcastDispatcher {
return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java))
} }

View File

@@ -30,11 +30,10 @@ import java.util.concurrent.Executor
class FakeBroadcastDispatcher( class FakeBroadcastDispatcher(
context: SysuiTestableContext, context: SysuiTestableContext,
handler: Handler,
looper: Looper, looper: Looper,
dumpManager: DumpManager, dumpManager: DumpManager,
logger: BroadcastDispatcherLogger logger: BroadcastDispatcherLogger
) : BroadcastDispatcher(context, handler, looper, dumpManager, logger) { ) : BroadcastDispatcher(context, looper, dumpManager, logger) {
private val registeredReceivers = ArraySet<BroadcastReceiver>() private val registeredReceivers = ArraySet<BroadcastReceiver>()