diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md index 6c8488b332c2a..8ec20f5689ff4 100644 --- a/packages/SystemUI/docs/broadcasts.md +++ b/packages/SystemUI/docs/broadcasts.md @@ -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. */ diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index d61de0623fe85..67c0c620f136b 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -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(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) { 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) } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 8368b2c1ae867..1f30305ab1693 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -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() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index aa3f91a222080..713aef9e8a91f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -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); diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index 86ddb209f3217..4ed284ede6344 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -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 - ) : 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)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt index 6e982e26b8cba..09a091689a233 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt @@ -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()