From ff5e91f252d51637fdb1b6d639f13b724070dbf4 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Tue, 24 Sep 2019 15:38:08 -0400 Subject: [PATCH] Convert all SCREEN_OFF receivers to BroadcastDispatcher All broadcast receivers that filter for ACTION_SCREEN_OFF have been converted to register with BroadcastDispatcher instead of Context. In many cases this involves other Intents being covered by BroadcastDispatcher. Additionally, UserBroadcastDispatcher propagates the PendingResult so the individual receivers can access it (mostly to query getSendingUser). Test: enable logging of BroadcastQueue for ACTION_SCREEN_OFF only shows 2 receivers (user 0 and user -1) Test: Dump of BroadcastDispatcher shows all the classes registered to it Test: enable logging of UserBroadcastDispatcher Test: atest PowerUITest StatusBarTest VolumeDialogControllerImplTest SystemUIDialogTest NavigationBarFragmentTest Bug: 134566046 Change-Id: I0caa2a6b53f3f6b360bf2e8598dde29c45f1d4e3 --- .../com/android/systemui/SystemUIBinder.java | 7 ++++ .../systemui/broadcast/BroadcastDispatcher.kt | 8 +++-- .../broadcast/UserBroadcastDispatcher.kt | 8 +++-- .../globalactions/GlobalActionsDialog.java | 3 +- .../com/android/systemui/power/PowerUI.java | 11 ++++++- .../systemui/recents/RecentsOnboarding.java | 16 +++++++--- .../recents/ScreenPinningRequest.java | 7 ++-- .../phone/NavigationBarFragment.java | 12 +++++-- .../systemui/statusbar/phone/StatusBar.java | 21 ++++++++---- .../statusbar/phone/SystemUIDialog.java | 8 +++-- .../systemui/statusbar/policy/Clock.java | 26 +++++++++++---- .../util/InjectionInflationController.java | 6 ++++ .../volume/VolumeDialogControllerImpl.java | 9 ++++-- .../broadcast/UserBroadcastDispatcherTest.kt | 18 +++++++++++ .../android/systemui/power/PowerUITest.java | 17 +++++++++- .../phone/NavigationBarFragmentTest.java | 27 +++++++++++++++- .../statusbar/phone/StatusBarTest.java | 24 ++++++++++++-- .../statusbar/phone/SystemUIDialogTest.java | 22 +++++++------ .../VolumeDialogControllerImplTest.java | 32 ++++++++++++++++--- 19 files changed, 229 insertions(+), 53 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java index 4531c892a022c..0fa80aca97fb1 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java @@ -17,6 +17,7 @@ package com.android.systemui; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.power.PowerUI; import dagger.Binds; import dagger.Module; @@ -33,4 +34,10 @@ public abstract class SystemUIBinder { @IntoMap @ClassKey(KeyguardViewMediator.class) public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui); + + /** Inject into PowerUI. */ + @Binds + @IntoMap + @ClassKey(PowerUI.class) + public abstract SystemUI bindPowerUI(PowerUI sysui); } diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index f0e8c16e650ad..5e977b4684dc4 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -75,7 +75,7 @@ open class BroadcastDispatcher @Inject constructor ( * @param filter A filter to determine what broadcasts should be dispatched to this receiver. * It will only take into account actions and categories for filtering. * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the - * main handler. + * main handler. Pass `null` to use the default. * @param user A user handle to determine which broadcast should be dispatched to this receiver. * By default, it is the current user. */ @@ -83,10 +83,12 @@ open class BroadcastDispatcher @Inject constructor ( fun registerReceiver( receiver: BroadcastReceiver, filter: IntentFilter, - handler: Handler = mainHandler, + handler: Handler? = mainHandler, user: UserHandle = context.user ) { - this.handler.obtainMessage(MSG_ADD_RECEIVER, ReceiverData(receiver, filter, handler, user)) + this.handler + .obtainMessage(MSG_ADD_RECEIVER, + ReceiverData(receiver, filter, handler ?: mainHandler, user)) .sendToTarget() } diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt index d44b63e813e6e..54f9950239c2b 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean private const val MSG_REGISTER_RECEIVER = 0 private const val MSG_UNREGISTER_RECEIVER = 1 -private const val TAG = "UniversalReceiver" +private const val TAG = "UserBroadcastDispatcher" private const val DEBUG = false /** @@ -97,7 +97,7 @@ class UserBroadcastDispatcher( private val receiverToReceiverData = ArrayMap>() override fun onReceive(context: Context, intent: Intent) { - bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent)) + bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent, pendingResult)) } /** @@ -160,7 +160,8 @@ class UserBroadcastDispatcher( private class HandleBroadcastRunnable( val actionsToReceivers: Map>, val context: Context, - val intent: Intent + val intent: Intent, + val pendingResult: PendingResult ) : Runnable { override fun run() { if (DEBUG) Log.w(TAG, "Dispatching $intent") @@ -171,6 +172,7 @@ class UserBroadcastDispatcher( ?.forEach { it.handler.post { if (DEBUG) Log.w(TAG, "Dispatching to ${it.receiver}") + it.receiver.pendingResult = pendingResult it.receiver.onReceive(context, intent) } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 57a5ae63511c7..22846bc02a380 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -90,6 +90,7 @@ import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.MultiListLayout; import com.android.systemui.MultiListLayout.MultiListAdapter; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; @@ -187,7 +188,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); - context.registerReceiver(mBroadcastReceiver, filter); + Dependency.get(BroadcastDispatcher.class).registerReceiver(mBroadcastReceiver, filter); ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 75dc39722bcf7..a258f356bf53f 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -45,6 +45,7 @@ import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.phone.StatusBar; import java.io.FileDescriptor; @@ -53,6 +54,8 @@ import java.time.Duration; import java.util.Arrays; import java.util.concurrent.Future; +import javax.inject.Inject; + public class PowerUI extends SystemUI { static final String TAG = "PowerUI"; @@ -97,6 +100,12 @@ public class PowerUI extends SystemUI { private IThermalEventListener mSkinThermalEventListener; private IThermalEventListener mUsbThermalEventListener; + private final BroadcastDispatcher mBroadcastDispatcher; + + @Inject + public PowerUI(BroadcastDispatcher broadcastDispatcher) { + mBroadcastDispatcher = broadcastDispatcher; + } public void start() { mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -211,7 +220,7 @@ public class PowerUI extends SystemUI { filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_SWITCHED); - mContext.registerReceiver(this, filter, null, mHandler); + mBroadcastDispatcher.registerReceiver(this, filter, mHandler); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java index d0c47345a83a2..c1ce16337f8dd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java @@ -61,8 +61,10 @@ import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; +import com.android.systemui.Dependency; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; @@ -245,10 +247,15 @@ public class RecentsOnboarding { private final View.OnAttachStateChangeListener mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() { + + private final BroadcastDispatcher mBroadcastDispatcher = Dependency.get( + BroadcastDispatcher.class); + @Override public void onViewAttachedToWindow(View view) { if (view == mLayout) { - mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + mBroadcastDispatcher.registerReceiver(mReceiver, + new IntentFilter(Intent.ACTION_SCREEN_OFF)); mLayoutAttachedToWindow = true; if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) { mHasDismissedSwipeUpTip = false; @@ -273,7 +280,7 @@ public class RecentsOnboarding { } mOverviewOpenedCountSinceQuickScrubTipDismiss = 0; } - mContext.unregisterReceiver(mReceiver); + mBroadcastDispatcher.unregisterReceiver(mReceiver); } } }; @@ -335,10 +342,11 @@ public class RecentsOnboarding { private void notifyOnTip(int action, int target) { try { IOverviewProxy overviewProxy = mOverviewProxyService.getProxy(); - if(overviewProxy != null) { + if (overviewProxy != null) { overviewProxy.onTip(action, target); } - } catch (RemoteException e) {} + } catch (RemoteException e) { + } } public void onNavigationModeChanged(int mode) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java index c3c0d63f66c41..0f277ca8b2c69 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java +++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java @@ -47,6 +47,7 @@ import android.widget.TextView; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.phone.NavigationBarView; @@ -159,6 +160,8 @@ public class ScreenPinningRequest implements View.OnClickListener, private ValueAnimator mColorAnim; private ViewGroup mLayout; private boolean mShowCancel; + private final BroadcastDispatcher mBroadcastDispatcher = + Dependency.get(BroadcastDispatcher.class); public RequestWindowView(Context context, boolean showCancel) { super(context); @@ -212,7 +215,7 @@ public class ScreenPinningRequest implements View.OnClickListener, IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_SCREEN_OFF); - mContext.registerReceiver(mReceiver, filter); + mBroadcastDispatcher.registerReceiver(mReceiver, filter); } private void inflateView(int rotation) { @@ -313,7 +316,7 @@ public class ScreenPinningRequest implements View.OnClickListener, @Override public void onDetachedFromWindow() { - mContext.unregisterReceiver(mReceiver); + mBroadcastDispatcher.unregisterReceiver(mReceiver); } protected void onConfigurationChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 2b8c86b8c549a..6b7dd91a0a38f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -89,6 +89,7 @@ import com.android.systemui.R; import com.android.systemui.ScreenDecorations; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.model.SysUiState; @@ -170,6 +171,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback private OverviewProxyService mOverviewProxyService; + private final BroadcastDispatcher mBroadcastDispatcher; + @VisibleForTesting public int mDisplayId; private boolean mIsOnDefaultDisplay; @@ -248,7 +251,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback AssistManager assistManager, OverviewProxyService overviewProxyService, NavigationModeController navigationModeController, StatusBarStateController statusBarStateController, - SysUiState sysUiFlagsContainer) { + SysUiState sysUiFlagsContainer, + BroadcastDispatcher broadcastDispatcher) { mAccessibilityManagerWrapper = accessibilityManagerWrapper; mDeviceProvisionedController = deviceProvisionedController; mStatusBarStateController = statusBarStateController; @@ -258,6 +262,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback mAssistantAvailable = mAssistManager.getAssistInfoForUser(UserHandle.USER_CURRENT) != null; mOverviewProxyService = overviewProxyService; mNavBarMode = navigationModeController.addListener(this); + mBroadcastDispatcher = broadcastDispatcher; } // ----- Fragment Lifecycle Callbacks ----- @@ -334,7 +339,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_SWITCHED); - getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); + mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, Handler.getMain(), + UserHandle.ALL); notifyNavigationBarScreenOn(); mOverviewProxyService.addCallback(mOverviewProxyListener); @@ -372,7 +378,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback mNavigationBarView.getLightTransitionsController().destroy(getContext()); } mOverviewProxyService.removeCallback(mOverviewProxyListener); - getContext().unregisterReceiver(mBroadcastReceiver); + mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index f06fbbd80dfcc..793feb0e1dcb5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -147,6 +147,7 @@ import com.android.systemui.SystemUIFactory; import com.android.systemui.UiOffloadThread; import com.android.systemui.appops.AppOpsController; import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; @@ -222,7 +223,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; @@ -391,6 +391,9 @@ public class StatusBar extends SystemUI implements DemoMode, @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean mAllowNotificationLongPress; + @VisibleForTesting + BroadcastDispatcher mBroadcastDispatcher; + // expanded notifications protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window @@ -665,6 +668,7 @@ public class StatusBar extends SystemUI implements DemoMode, mBubbleController = Dependency.get(BubbleController.class); mBubbleController.setExpandListener(mBubbleExpandListener); mActivityIntentHelper = new ActivityIntentHelper(mContext); + mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class); KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance(); if (sliceProvider != null) { sliceProvider.initDependencies(mMediaManager, mStatusBarStateController, @@ -1046,11 +1050,7 @@ public class StatusBar extends SystemUI implements DemoMode, } // receive broadcasts - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); - context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); + registerBroadcastReceiver(); IntentFilter demoFilter = new IntentFilter(); if (DEBUG_MEDIA_FAKE_ARTWORK) { @@ -1071,6 +1071,15 @@ public class StatusBar extends SystemUI implements DemoMode, ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } + @VisibleForTesting + protected void registerBroadcastReceiver() { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); + mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL); + } + protected QS createDefaultQSFragment() { return FragmentHostManager.get(mStatusBarWindow).create(QSFragment.class); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java index 5bda34d64b736..ce929b7c621b4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java @@ -28,6 +28,7 @@ import android.view.WindowManager.LayoutParams; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -138,20 +139,21 @@ public class SystemUIDialog extends AlertDialog { private final Dialog mDialog; private boolean mRegistered; + private final BroadcastDispatcher mBroadcastDispatcher; DismissReceiver(Dialog dialog) { mDialog = dialog; + mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class); } void register() { - mDialog.getContext() - .registerReceiverAsUser(this, UserHandle.CURRENT, INTENT_FILTER, null, null); + mBroadcastDispatcher.registerReceiver(this, INTENT_FILTER, null, UserHandle.CURRENT); mRegistered = true; } void unregister() { if (mRegistered) { - mDialog.getContext().unregisterReceiver(this); + mBroadcastDispatcher.unregisterReceiver(this); mRegistered = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index c2c3f81527e8d..b331fc3bf0ce7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.policy; +import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; + import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -44,6 +46,7 @@ import com.android.systemui.Dependency; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.settings.CurrentUserTracker; @@ -60,6 +63,9 @@ import java.util.Calendar; import java.util.Locale; import java.util.TimeZone; +import javax.inject.Inject; +import javax.inject.Named; + /** * Digital clock for the status bar. */ @@ -107,15 +113,20 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C */ private int mNonAdaptedColor; - public Clock(Context context) { - this(context, null); - } + private final BroadcastDispatcher mBroadcastDispatcher; public Clock(Context context, AttributeSet attrs) { - this(context, attrs, 0); + this(context, attrs, null); } - public Clock(Context context, AttributeSet attrs, int defStyle) { + @Inject + public Clock(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, + BroadcastDispatcher broadcastDispatcher) { + this(context, attrs, 0, broadcastDispatcher); + } + + public Clock(Context context, AttributeSet attrs, int defStyle, + BroadcastDispatcher broadcastDispatcher) { super(context, attrs, defStyle); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, @@ -134,6 +145,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C mCurrentUserId = newUserId; } }; + mBroadcastDispatcher = broadcastDispatcher; } @Override @@ -358,11 +370,11 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C } IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); - mContext.registerReceiver(mScreenReceiver, filter); + mBroadcastDispatcher.registerReceiver(mScreenReceiver, filter); } } else { if (mSecondsHandler != null) { - mContext.unregisterReceiver(mScreenReceiver); + mBroadcastDispatcher.unregisterReceiver(mScreenReceiver); mSecondsHandler.removeCallbacks(mSecondTick); mSecondsHandler = null; updateClock(); diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java index e44e58a84dc86..7e801da9cd1b5 100644 --- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java +++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java @@ -37,6 +37,7 @@ import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.policy.Clock; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -178,6 +179,11 @@ public class InjectionInflationController { * Creates the QSCustomizer. */ QSCustomizer createQSCustomizer(); + + /** + * Creates a Clock. + */ + Clock createClock(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index a6b5b38fd728c..edea92f5952a7 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -59,6 +59,7 @@ import com.android.settingslib.volume.MediaSessions; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.qs.tiles.DndTile; @@ -137,9 +138,10 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa private UserActivityListener mUserActivityListener; protected final VC mVolumeController = new VC(); + protected final BroadcastDispatcher mBroadcastDispatcher; @Inject - public VolumeDialogControllerImpl(Context context) { + public VolumeDialogControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher) { mContext = context.getApplicationContext(); mNotificationManager = (NotificationManager) mContext.getSystemService( Context.NOTIFICATION_SERVICE); @@ -152,6 +154,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); mObserver = new SettingObserver(mWorker); + mBroadcastDispatcher = broadcastDispatcher; mObserver.init(); mReceiver.init(); mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); @@ -1004,11 +1007,11 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - mContext.registerReceiver(this, filter, null, mWorker); + mBroadcastDispatcher.registerReceiver(this, filter, mWorker); } public void destroy() { - mContext.unregisterReceiver(this); + mBroadcastDispatcher.unregisterReceiver(this); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt index 011c2cd575880..e838d9e94a31e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt @@ -70,6 +70,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { private lateinit var mockContext: Context @Mock private lateinit var mockHandler: Handler + @Mock + private lateinit var mPendingResult: BroadcastReceiver.PendingResult @Captor private lateinit var argumentCaptor: ArgumentCaptor @@ -88,6 +90,7 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { universalBroadcastReceiver = UserBroadcastDispatcher( mockContext, USER_ID, handler, testableLooper.looper) + universalBroadcastReceiver.pendingResult = mPendingResult } @Test @@ -227,4 +230,19 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { verify(broadcastReceiver).onReceive(mockContext, intent) verify(broadcastReceiverOther).onReceive(mockContext, intent) } + + @Test + fun testPendingResult() { + intentFilter = IntentFilter(ACTION_1) + universalBroadcastReceiver.registerReceiver( + ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + + val intent = Intent(ACTION_1) + universalBroadcastReceiver.onReceive(mockContext, intent) + + testableLooper.processAllMessages() + + verify(broadcastReceiver).onReceive(mockContext, intent) + verify(broadcastReceiver).pendingResult = mPendingResult + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 4d95f3f474b56..4958c649d5325 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -19,6 +19,7 @@ import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.anyObject; import static org.mockito.Mockito.mock; @@ -27,8 +28,11 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.IntentFilter; import android.os.BatteryManager; +import android.os.Handler; import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.PowerManager; @@ -43,6 +47,7 @@ import android.testing.TestableResources; import com.android.settingslib.fuelgauge.Estimate; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.power.PowerUI.WarningsUI; import com.android.systemui.statusbar.phone.StatusBar; @@ -80,6 +85,7 @@ public class PowerUITest extends SysuiTestCase { @Mock private IThermalService mThermalServiceMock; private IThermalEventListener mUsbThermalEventListener; private IThermalEventListener mSkinThermalEventListener; + @Mock private BroadcastDispatcher mBroadcastDispatcher; @Before public void setup() { @@ -95,6 +101,15 @@ public class PowerUITest extends SysuiTestCase { mUsbThermalEventListener = mPowerUI.new UsbThermalEventListener(); } + @Test + public void testReceiverIsRegisteredToDispatcherOnStart() { + mPowerUI.start(); + verify(mBroadcastDispatcher).registerReceiver( + any(BroadcastReceiver.class), + any(IntentFilter.class), + any(Handler.class)); //PowerUI does not call with User + } + @Test public void testSkinWarning_throttlingCritical() throws Exception { mPowerUI.start(); @@ -667,7 +682,7 @@ public class PowerUITest extends SysuiTestCase { } private void createPowerUi() { - mPowerUI = new PowerUI(); + mPowerUI = new PowerUI(mBroadcastDispatcher); mPowerUI.mContext = mContext; mPowerUI.mComponents = mContext.getComponents(); mPowerUI.mThermalService = mThermalServiceMock; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java index 33d3ac848f0f2..0bff5aa9e9913 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java @@ -24,9 +24,11 @@ import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.LayoutRes; @@ -34,11 +36,14 @@ import android.annotation.Nullable; import android.app.Fragment; import android.app.FragmentController; import android.app.FragmentHostCallback; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.IntentFilter; import android.hardware.display.DisplayManagerGlobal; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.LeakCheck.Tracker; import android.testing.TestableLooper; @@ -58,6 +63,7 @@ import com.android.systemui.Dependency; import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.SysuiTestableContext; import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; @@ -70,6 +76,8 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper() @@ -85,6 +93,8 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { private OverviewProxyService mOverviewProxyService; private CommandQueue mCommandQueue; private SysUiState mMockSysUiState; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; private AccessibilityManagerWrapper mAccessibilityWrapper = new AccessibilityManagerWrapper(mContext) { @@ -112,6 +122,8 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { @Before public void setupFragment() throws Exception { + MockitoAnnotations.initMocks(this); + setupSysuiDependency(); createRootView(); mOverviewProxyService = @@ -176,6 +188,18 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { navigationBarFragment.onHomeLongClick(navigationBarFragment.getView()); } + @Test + public void testRegisteredWithDispatcher() { + mFragments.dispatchResume(); + processAllMessages(); + + verify(mBroadcastDispatcher).registerReceiver( + any(BroadcastReceiver.class), + any(IntentFilter.class), + any(Handler.class), + any(UserHandle.class)); + } + @Test public void testSetImeWindowStatusWhenImeSwitchOnDisplay() { // Create default & external NavBar fragment. @@ -227,7 +251,8 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { mOverviewProxyService, mock(NavigationModeController.class), mock(StatusBarStateController.class), - mMockSysUiState); + mMockSysUiState, + mBroadcastDispatcher); } private class HostCallbacksForExternalDisplay extends diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 3be71c07009d5..b75cb8cf487c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -41,7 +41,9 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.app.StatusBarManager; import android.app.trust.TrustManager; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.IntentFilter; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.fingerprint.FingerprintManager; import android.metrics.LogMaker; @@ -51,6 +53,7 @@ import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; +import android.os.UserHandle; import android.service.dreams.IDreamManager; import android.support.test.metricshelper.MetricsAsserts; import android.testing.AndroidTestingRunner; @@ -75,6 +78,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.UiOffloadThread; import com.android.systemui.appops.AppOpsController; import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; @@ -171,6 +175,8 @@ public class StatusBarTest extends SysuiTestCase { private AmbientDisplayConfiguration mAmbientDisplayConfiguration; @Mock private StatusBarWindowView mStatusBarWindowView; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; private TestableStatusBar mStatusBar; private FakeMetricsLogger mMetricsLogger; @@ -199,6 +205,7 @@ public class StatusBarTest extends SysuiTestCase { mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter); mDependency.injectTestDependency(NotificationAlertingManager.class, mNotificationAlertingManager); + mDependency.injectTestDependency(BroadcastDispatcher.class, mBroadcastDispatcher); IPowerManager powerManagerService = mock(IPowerManager.class); mPowerManager = new PowerManager(mContext, powerManagerService, @@ -263,7 +270,8 @@ public class StatusBarTest extends SysuiTestCase { mDozeScrimController, mock(NotificationShelf.class), mLockscreenUserManager, mCommandQueue, mNotificationPresenter, mock(BubbleController.class), mock(NavigationBarController.class), - mock(AutoHideController.class), mKeyguardUpdateMonitor, mStatusBarWindowView); + mock(AutoHideController.class), mKeyguardUpdateMonitor, mStatusBarWindowView, + mBroadcastDispatcher); mStatusBar.mContext = mContext; mStatusBar.mComponents = mContext.getComponents(); SystemUIFactory.getInstance().getRootComponent() @@ -774,6 +782,16 @@ public class StatusBarTest extends SysuiTestCase { verify(mNotificationPanelView, never()).expand(anyBoolean()); } + @Test + public void testRegisterBroadcastsonDispatcher() { + mStatusBar.registerBroadcastReceiver(); + verify(mBroadcastDispatcher).registerReceiver( + any(BroadcastReceiver.class), + any(IntentFilter.class), + eq(null), + any(UserHandle.class)); + } + static class TestableStatusBar extends StatusBar { public TestableStatusBar(StatusBarKeyguardViewManager man, KeyguardIndicationController key, @@ -801,7 +819,8 @@ public class StatusBarTest extends SysuiTestCase { NavigationBarController navBarController, AutoHideController autoHideController, KeyguardUpdateMonitor keyguardUpdateMonitor, - StatusBarWindowView statusBarWindow) { + StatusBarWindowView statusBarWindow, + BroadcastDispatcher broadcastDispatcher) { mStatusBarKeyguardViewManager = man; mKeyguardIndicationController = key; mStackScroller = stack; @@ -835,6 +854,7 @@ public class StatusBarTest extends SysuiTestCase { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mStatusBarWindow = statusBarWindow; mDozeServiceHost.mWakeLockScreenPerformsAuth = false; + mBroadcastDispatcher = broadcastDispatcher; } private WakefulnessLifecycle createAwakeWakefulnessLifecycle() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java index a9a1392fb80bf..589aa03538708 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java @@ -18,11 +18,9 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.testing.AndroidTestingRunner; @@ -31,11 +29,14 @@ import android.testing.TestableLooper.RunWithLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper @@ -43,13 +44,16 @@ import org.mockito.ArgumentCaptor; public class SystemUIDialogTest extends SysuiTestCase { private SystemUIDialog mDialog; - - Context mContextSpy; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; @Before public void setup() { - mContextSpy = spy(mContext); - mDialog = new SystemUIDialog(mContextSpy); + MockitoAnnotations.initMocks(this); + + mDependency.injectTestDependency(BroadcastDispatcher.class, mBroadcastDispatcher); + + mDialog = new SystemUIDialog(mContext); } @Test @@ -60,12 +64,12 @@ public class SystemUIDialogTest extends SysuiTestCase { ArgumentCaptor.forClass(IntentFilter.class); mDialog.show(); - verify(mContextSpy).registerReceiverAsUser(broadcastReceiverCaptor.capture(), any(), - intentFilterCaptor.capture(), any(), any()); + verify(mBroadcastDispatcher).registerReceiver(broadcastReceiverCaptor.capture(), + intentFilterCaptor.capture(), eq(null), any()); assertTrue(intentFilterCaptor.getValue().hasAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); mDialog.dismiss(); - verify(mContextSpy).unregisterReceiver(eq(broadcastReceiverCaptor.getValue())); + verify(mBroadcastDispatcher).unregisterReceiver(eq(broadcastReceiverCaptor.getValue())); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index f4d0854b2c9f6..2e945f2481d2c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -16,40 +16,63 @@ package com.android.systemui.volume; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.IntentFilter; import android.media.AudioManager; import android.media.session.MediaSession; +import android.os.Handler; +import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.StatusBar; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +@RunWith(AndroidTestingRunner.class) @SmallTest public class VolumeDialogControllerImplTest extends SysuiTestCase { TestableVolumeDialogControllerImpl mVolumeController; VolumeDialogControllerImpl.C mCallback; StatusBar mStatusBar; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; @Before public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mCallback = mock(VolumeDialogControllerImpl.C.class); mStatusBar = mock(StatusBar.class); - mVolumeController = new TestableVolumeDialogControllerImpl(mContext, mCallback, mStatusBar); + mVolumeController = new TestableVolumeDialogControllerImpl(mContext, mCallback, mStatusBar, + mBroadcastDispatcher); mVolumeController.setEnableDialogs(true, true); } + @Test + public void testRegisteredWithDispatcher() { + verify(mBroadcastDispatcher).registerReceiver( + any(BroadcastReceiver.class), + any(IntentFilter.class), + any(Handler.class)); // VolumeDialogControllerImpl does not call with user + } + @Test public void testVolumeChangeW_deviceNotInteractiveAOD() { when(mStatusBar.isDeviceInteractive()).thenReturn(false); @@ -81,7 +104,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { public void testVolumeChangeW_nullStatusBar() { VolumeDialogControllerImpl.C callback = mock(VolumeDialogControllerImpl.C.class); TestableVolumeDialogControllerImpl nullStatusBarTestableDialog = new - TestableVolumeDialogControllerImpl(mContext, callback, null); + TestableVolumeDialogControllerImpl(mContext, callback, null, mBroadcastDispatcher); nullStatusBarTestableDialog.setEnableDialogs(true, true); nullStatusBarTestableDialog.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI); verify(callback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED); @@ -100,8 +123,9 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { } static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl { - public TestableVolumeDialogControllerImpl(Context context, C callback, StatusBar s) { - super(context); + TestableVolumeDialogControllerImpl(Context context, C callback, StatusBar s, + BroadcastDispatcher broadcastDispatcher) { + super(context, broadcastDispatcher); mCallbacks = callback; mStatusBar = s; }