diff options
author | 2020-06-08 11:14:58 -0400 | |
---|---|---|
committer | 2020-06-11 16:27:46 +0000 | |
commit | 34f899a8493044356a93d36843b92726908dd3e9 (patch) | |
tree | 4bf4c9203a4a21c5262de35813ab91d15d0b033f | |
parent | e8d82057f8cfac91864fae151447fd1071bd6fe1 (diff) |
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
6 files changed, 62 insertions, 24 deletions
diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md index 6c8488b332c2..8ec20f5689ff 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 d61de0623fe8..67c0c620f136 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<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) } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 6dbb1e933fbd..45e47228e16a 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; @@ -40,9 +41,12 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.Prefs; import com.android.systemui.accessibility.ModeSwitchesController; +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; @@ -185,6 +189,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 aa3f91a22208..713aef9e8a91 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 86ddb209f321..4ed284ede634 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<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)) } 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 6e982e26b8cb..09a091689a23 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<BroadcastReceiver>() |