From d4f426b04757c73a6e86d385818d12534bc5aada Mon Sep 17 00:00:00 2001 From: Jernej Virag Date: Mon, 7 Mar 2022 12:22:54 +0100 Subject: [PATCH] Remove main thread sendBroadcast calls sendBroadcast ends up with a synchronous Binder call which can block main thread. This moves multiple broadcast calls to background thread to avoid jank. Bug: 221339831 Test: Unit tests Change-Id: I907797466a51641fa47c43c35e11d8aeebf82ccd --- .../systemui/broadcast/BroadcastSender.kt | 132 ++++++++++++++++ .../ui/ControlActionCoordinatorImpl.kt | 12 +- .../systemui/controls/ui/DetailDialog.kt | 4 +- .../systemui/media/MediaControlPanel.java | 10 +- .../android/systemui/media/MediaDataFilter.kt | 4 +- .../media/dialog/MediaOutputBaseDialog.java | 9 +- .../media/dialog/MediaOutputController.java | 28 +--- .../media/dialog/MediaOutputDialog.java | 7 +- .../media/dialog/MediaOutputDialogFactory.kt | 13 +- .../media/dialog/MediaOutputGroupDialog.java | 7 +- .../power/PowerNotificationWarnings.java | 12 +- .../screenshot/ScreenshotController.java | 17 +- .../policy/FlashlightControllerImpl.java | 3 + .../policy/UserSwitcherController.java | 6 +- .../systemui/broadcast/BroadcastSenderTest.kt | 145 ++++++++++++++++++ .../ControlActionCoordinatorImplTest.kt | 4 + .../systemui/controls/ui/DetailDialogTest.kt | 4 + .../systemui/media/MediaControlPanelTest.kt | 6 +- .../systemui/media/MediaDataFilterTest.kt | 5 +- .../dialog/MediaOutputBaseDialogTest.java | 22 ++- .../dialog/MediaOutputControllerTest.java | 28 ++-- .../media/dialog/MediaOutputDialogTest.java | 14 +- .../dialog/MediaOutputGroupDialogTest.java | 14 +- .../power/PowerNotificationWarningsTest.java | 5 +- .../policy/UserSwitcherControllerTest.kt | 3 + 25 files changed, 410 insertions(+), 104 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt new file mode 100644 index 0000000000000..6615f6b0b9eb8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt @@ -0,0 +1,132 @@ +package com.android.systemui.broadcast + +import android.annotation.AnyThread +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.util.wakelock.WakeLock +import java.util.concurrent.Executor +import javax.inject.Inject + +/** + * SystemUI master Broadcast sender + * + * This class dispatches broadcasts on background thread to avoid synchronous call to binder. Use + * this class instead of calling [Context.sendBroadcast] directly. + */ +@SysUISingleton +class BroadcastSender @Inject constructor( + private val context: Context, + private val wakeLockBuilder: WakeLock.Builder, + @Background private val bgExecutor: Executor +) { + + private val WAKE_LOCK_TAG = "SysUI:BroadcastSender" + private val WAKE_LOCK_SEND_REASON = "sendInBackground" + + /** + * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcast(intent: Intent) { + sendInBackground { + context.sendBroadcast(intent) + } + } + + /** + * Sends broadcast via [Context.sendBroadcast] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcast(intent: Intent, receiverPermission: String?) { + sendInBackground { + context.sendBroadcast(intent, receiverPermission) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser(intent: Intent, userHandle: UserHandle, receiverPermission: String?) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser( + intent: Intent, + userHandle: UserHandle, + receiverPermission: String?, + options: Bundle? + ) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission, options) + } + } + + /** + * Sends broadcast via [Context.sendBroadcastAsUser] on background thread to avoid blocking + * synchronous binder call. + */ + @AnyThread + fun sendBroadcastAsUser( + intent: Intent, + userHandle: UserHandle, + receiverPermission: String?, + appOp: Int + ) { + sendInBackground { + context.sendBroadcastAsUser(intent, userHandle, receiverPermission, appOp) + } + } + + /** + * Sends [Intent.ACTION_CLOSE_SYSTEM_DIALOGS] broadcast to the system. + */ + @AnyThread + fun closeSystemDialogs() { + sendInBackground { + context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + } + } + + /** + * Dispatches parameter on background executor while holding a wakelock. + */ + private fun sendInBackground(callable: () -> Unit) { + val broadcastWakelock = wakeLockBuilder.setTag(WAKE_LOCK_TAG) + .setMaxTimeout(5000) + .build() + broadcastWakelock.acquire(WAKE_LOCK_SEND_REASON) + bgExecutor.execute { + try { + callable.invoke() + } finally { + broadcastWakelock.release(WAKE_LOCK_SEND_REASON) + } + } + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index 5c1d8c3929cbd..e53f2673841c9 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -16,11 +16,11 @@ package com.android.systemui.controls.ui +import android.annotation.AnyThread import android.annotation.MainThread import android.app.Dialog import android.app.PendingIntent import android.content.Context -import android.content.Intent import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.database.ContentObserver @@ -35,6 +35,7 @@ import android.service.controls.actions.FloatAction import android.util.Log import android.view.HapticFeedbackConstants import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -53,6 +54,7 @@ class ControlActionCoordinatorImpl @Inject constructor( private val bgExecutor: DelayableExecutor, @Main private val uiExecutor: DelayableExecutor, private val activityStarter: ActivityStarter, + private val broadcastSender: BroadcastSender, private val keyguardStateController: KeyguardStateController, private val taskViewFactory: Optional, private val controlsMetricsLogger: ControlsMetricsLogger, @@ -199,11 +201,12 @@ class ControlActionCoordinatorImpl @Inject constructor( false } + @AnyThread @VisibleForTesting fun bouncerOrRun(action: Action, authRequired: Boolean) { if (keyguardStateController.isShowing() && authRequired) { if (isLocked) { - context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + broadcastSender.closeSystemDialogs() // pending actions will only run after the control state has been refreshed pendingAction = action @@ -233,7 +236,10 @@ class ControlActionCoordinatorImpl @Inject constructor( // make sure the intent is valid before attempting to open the dialog if (activities.isNotEmpty() && taskViewFactory.isPresent) { taskViewFactory.get().create(context, uiExecutor, { - dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also { + dialog = DetailDialog( + activityContext, broadcastSender, + it, pendingIntent, cvh + ).also { it.setOnDismissListener { _ -> dialog = null } it.show() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index dc3d1b52495ca..80589a2711ccf 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -33,6 +33,7 @@ import android.view.WindowManager import android.widget.ImageView import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.R +import com.android.systemui.broadcast.BroadcastSender import com.android.wm.shell.TaskView /** @@ -42,6 +43,7 @@ import com.android.wm.shell.TaskView */ class DetailDialog( val activityContext: Context, + val broadcastSender: BroadcastSender, val taskView: TaskView, val pendingIntent: PendingIntent, val cvh: ControlViewHolder @@ -147,7 +149,7 @@ class DetailDialog( // startActivity() below is called. removeDetailTask() dismiss() - context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + broadcastSender.closeSystemDialogs() pendingIntent.send() } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 831a606e95b2a..2d5295f944c25 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -54,6 +54,7 @@ import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.GhostedViewLaunchAnimatorController; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.monet.ColorScheme; @@ -108,6 +109,7 @@ public class MediaControlPanel { private SeekBarObserver mSeekBarObserver; protected final Executor mBackgroundExecutor; private final ActivityStarter mActivityStarter; + private final BroadcastSender mBroadcastSender; private Context mContext; private MediaViewHolder mMediaViewHolder; @@ -142,14 +144,16 @@ public class MediaControlPanel { */ @Inject public MediaControlPanel(Context context, @Background Executor backgroundExecutor, - ActivityStarter activityStarter, MediaViewController mediaViewController, - SeekBarViewModel seekBarViewModel, Lazy lazyMediaDataManager, + ActivityStarter activityStarter, BroadcastSender broadcastSender, + MediaViewController mediaViewController, SeekBarViewModel seekBarViewModel, + Lazy lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) { mContext = context; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; + mBroadcastSender = broadcastSender; mSeekBarViewModel = seekBarViewModel; mMediaViewController = mediaViewController; mMediaDataManagerLazy = lazyMediaDataManager; @@ -899,7 +903,7 @@ public class MediaControlPanel { // Dismiss the card Smartspace data through Smartspace trampoline activity. mContext.startActivity(dismissIntent); } else { - mContext.sendBroadcast(dismissIntent); + mBroadcastSender.sendBroadcast(dismissIntent); } }); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index ae5c1f2b19a98..de44a9c469638 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -21,6 +21,7 @@ import android.os.SystemProperties import android.util.Log import com.android.internal.annotations.VisibleForTesting import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -56,6 +57,7 @@ internal val SMARTSPACE_MAX_AGE = SystemProperties class MediaDataFilter @Inject constructor( private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, + private val broadcastSender: BroadcastSender, private val lockscreenUserManager: NotificationLockscreenUserManager, @Main private val executor: Executor, private val systemClock: SystemClock @@ -249,7 +251,7 @@ class MediaDataFilter @Inject constructor( // Dismiss the card Smartspace data through Smartspace trampoline activity. context.startActivity(dismissIntent) } else { - context.sendBroadcast(dismissIntent) + broadcastSender.sendBroadcast(dismissIntent) } smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index 355c69f9a48d6..a8141c0e2fec3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -21,7 +21,6 @@ import static android.view.WindowInsets.Type.statusBars; import android.app.WallpaperColors; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -55,6 +54,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.statusbar.phone.SystemUIDialog; /** @@ -71,6 +71,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements final Context mContext; final MediaOutputController mMediaOutputController; + final BroadcastSender mBroadcastSender; @VisibleForTesting View mDialogView; @@ -98,11 +99,13 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } }; - public MediaOutputBaseDialog(Context context, MediaOutputController mediaOutputController) { + public MediaOutputBaseDialog(Context context, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { super(context, R.style.Theme_SystemUI_Dialog_Media); // Save the context that is wrapped with our theme. mContext = getContext(); + mBroadcastSender = broadcastSender; mMediaOutputController = mediaOutputController; mLayoutManager = new LinearLayoutManager(mContext); mListMaxHeight = context.getResources().getDimensionPixelSize( @@ -152,7 +155,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements dismiss(); }); mAppButton.setOnClickListener(v -> { - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + mBroadcastSender.closeSystemDialogs(); if (mMediaOutputController.getAppLaunchIntent() != null) { mContext.startActivity(mMediaOutputController.getAppLaunchIntent()); } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 0c202e09b62ef..0b6c68d17a4ca 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -53,7 +53,6 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.mediarouter.media.MediaRouter; import androidx.mediarouter.media.MediaRouterParams; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; @@ -70,7 +69,6 @@ import com.android.systemui.monet.ColorScheme; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; -import com.android.systemui.statusbar.phone.ShadeController; import java.util.ArrayList; import java.util.Collection; @@ -95,12 +93,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private final String mPackageName; private final Context mContext; private final MediaSessionManager mMediaSessionManager; - private final LocalBluetoothManager mLocalBluetoothManager; - private final ShadeController mShadeController; private final ActivityStarter mActivityStarter; private final DialogLaunchAnimator mDialogLaunchAnimator; private final List mGroupMediaDevices = new CopyOnWriteArrayList<>(); - private final boolean mAboveStatusbar; private final CommonNotifCollection mNotifCollection; @VisibleForTesting final List mMediaDevices = new CopyOnWriteArrayList<>(); @@ -114,7 +109,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, LocalMediaManager mLocalMediaManager; private MediaOutputMetricLogger mMetricLogger; - private UiEventLogger mUiEventLogger; private int mColorActiveItem; private int mColorInactiveItem; @@ -124,23 +118,19 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @Inject public MediaOutputController(@NonNull Context context, String packageName, - boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager - lbm, ShadeController shadeController, ActivityStarter starter, - CommonNotifCollection notifCollection, UiEventLogger uiEventLogger, + MediaSessionManager mediaSessionManager, LocalBluetoothManager + lbm, ActivityStarter starter, + CommonNotifCollection notifCollection, DialogLaunchAnimator dialogLaunchAnimator, Optional nearbyMediaDevicesManagerOptional) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; - mLocalBluetoothManager = lbm; - mShadeController = shadeController; mActivityStarter = starter; - mAboveStatusbar = aboveStatusbar; mNotifCollection = notifCollection; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); - mUiEventLogger = uiEventLogger; mDialogLaunchAnimator = dialogLaunchAnimator; mNearbyMediaDevicesManager = nearbyMediaDevicesManagerOptional.orElse(null); mColorActiveItem = Utils.getColorStateListDefaultColor(mContext, @@ -630,18 +620,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mActivityStarter.startActivity(launchIntent, true, controller); } - void launchMediaOutputGroupDialog(View mediaOutputDialog) { - // We show the output group dialog from the output dialog. - MediaOutputController controller = new MediaOutputController(mContext, mPackageName, - mAboveStatusbar, mMediaSessionManager, mLocalBluetoothManager, mShadeController, - mActivityStarter, mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager)); - - MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar, - controller); - mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog); - } - boolean isActiveRemoteDevice(@NonNull MediaDevice device) { final List features = device.getFeatures(); return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK) diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index 7696a1f63c01a..7834ec0fa17f0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -28,6 +28,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; /** @@ -37,9 +38,9 @@ import com.android.systemui.dagger.SysUISingleton; public class MediaOutputDialog extends MediaOutputBaseDialog { final UiEventLogger mUiEventLogger; - MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController, UiEventLogger uiEventLogger) { - super(context, mediaOutputController); + MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController, UiEventLogger uiEventLogger) { + super(context, broadcastSender, mediaOutputController); mUiEventLogger = uiEventLogger; mAdapter = new MediaOutputAdapter(mMediaOutputController, this); if (!aboveStatusbar) { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index a7e54801bf47b..0d7d60ac59238 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -22,10 +22,10 @@ import android.view.View import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.media.nearby.NearbyMediaDevicesManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection -import com.android.systemui.statusbar.phone.ShadeController import java.util.Optional import javax.inject.Inject @@ -36,8 +36,8 @@ class MediaOutputDialogFactory @Inject constructor( private val context: Context, private val mediaSessionManager: MediaSessionManager, private val lbm: LocalBluetoothManager?, - private val shadeController: ShadeController, private val starter: ActivityStarter, + private val broadcastSender: BroadcastSender, private val notifCollection: CommonNotifCollection, private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, @@ -52,10 +52,11 @@ class MediaOutputDialogFactory @Inject constructor( // Dismiss the previous dialog, if any. mediaOutputDialog?.dismiss() - val controller = MediaOutputController(context, packageName, aboveStatusBar, - mediaSessionManager, lbm, shadeController, starter, notifCollection, - uiEventLogger, dialogLaunchAnimator, nearbyMediaDevicesManagerOptional) - val dialog = MediaOutputDialog(context, aboveStatusBar, controller, uiEventLogger) + val controller = MediaOutputController(context, packageName, + mediaSessionManager, lbm, starter, notifCollection, + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional) + val dialog = + MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger) mediaOutputDialog = dialog // Show the dialog. diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java index f1c66016a49a4..bb3f969c86dfc 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java @@ -25,6 +25,7 @@ import android.view.WindowManager; import androidx.core.graphics.drawable.IconCompat; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; /** * Dialog for media output group. @@ -32,9 +33,9 @@ import com.android.systemui.R; // TODO(b/203073091): Remove this class once group logic been implemented. public class MediaOutputGroupDialog extends MediaOutputBaseDialog { - MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController) { - super(context, mediaOutputController); + MediaOutputGroupDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { + super(context, broadcastSender, mediaOutputController); mMediaOutputController.resetGroupMediaDevices(); mAdapter = new MediaOutputGroupAdapter(mMediaOutputController); if (!aboveStatusbar) { diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index e19483ae78457..84b1c4e2d32b8 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -60,6 +60,7 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.R; import com.android.systemui.SystemUIApplication; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -158,17 +159,20 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { @VisibleForTesting SystemUIDialog mUsbHighTempDialog; private BatteryStateSnapshot mCurrentBatterySnapshot; private ActivityStarter mActivityStarter; + private final BroadcastSender mBroadcastSender; /** */ @Inject - public PowerNotificationWarnings(Context context, ActivityStarter activityStarter) { + public PowerNotificationWarnings(Context context, ActivityStarter activityStarter, + BroadcastSender broadcastSender) { mContext = context; mNoMan = mContext.getSystemService(NotificationManager.class); mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mKeyguard = mContext.getSystemService(KeyguardManager.class); mReceiver.init(); mActivityStarter = activityStarter; + mBroadcastSender = broadcastSender; mUseSevereDialog = mContext.getResources().getBoolean(R.bool.config_severe_battery_dialog); } @@ -256,7 +260,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { protected void showWarningNotification() { if (showSevereLowBatteryDialog()) { - mContext.sendBroadcast(new Intent(ACTION_ENABLE_SEVERE_BATTERY_DIALOG) + mBroadcastSender.sendBroadcast(new Intent(ACTION_ENABLE_SEVERE_BATTERY_DIALOG) .setPackage(mContext.getPackageName()) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND)); @@ -714,9 +718,9 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mSaverConfirmation.dismiss(); } // Also close the notification shade, if it's open. - mContext.sendBroadcast( + mBroadcastSender.sendBroadcast( new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) - .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)); + .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)); final Uri uri = Uri.parse(getURL()); Context context = widget.getContext(); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 50765f227554b..009d4b9b48e60 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -88,10 +88,12 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.policy.PhoneWindow; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.clipboardoverlay.ClipboardOverlayController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition; import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback; +import com.android.systemui.util.Assert; import com.google.common.util.concurrent.ListenableFuture; @@ -247,6 +249,7 @@ public class ScreenshotController { private final ImageExporter mImageExporter; private final Executor mMainExecutor; private final ExecutorService mBgExecutor; + private final BroadcastSender mBroadcastSender; private final WindowManager mWindowManager; private final WindowManager.LayoutParams mWindowLayoutParams; @@ -271,7 +274,6 @@ public class ScreenshotController { private String mPackageName = ""; private BroadcastReceiver mCopyBroadcastReceiver; - /** Tracks config changes that require re-creating UI */ private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( ActivityInfo.CONFIG_ORIENTATION @@ -293,7 +295,8 @@ public class ScreenshotController { ScrollCaptureController scrollCaptureController, LongScreenshotData longScreenshotHolder, ActivityManager activityManager, - TimeoutHandler timeoutHandler) { + TimeoutHandler timeoutHandler, + BroadcastSender broadcastSender) { mScreenshotSmartActions = screenshotSmartActions; mNotificationsController = screenshotNotificationsController; mScrollCaptureClient = scrollCaptureClient; @@ -304,6 +307,7 @@ public class ScreenshotController { mLongScreenshotHolder = longScreenshotHolder; mIsLowRamDevice = activityManager.isLowRamDevice(); mBgExecutor = Executors.newSingleThreadExecutor(); + mBroadcastSender = broadcastSender; mScreenshotHandler = timeoutHandler; mScreenshotHandler.setDefaultTimeoutMillis(SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS); @@ -355,8 +359,10 @@ public class ScreenshotController { ClipboardOverlayController.SELF_PERMISSION, null, Context.RECEIVER_NOT_EXPORTED); } + @MainThread void takeScreenshotFullscreen(ComponentName topComponent, Consumer finisher, RequestCallback requestCallback) { + Assert.isMainThread(); mCurrentRequestCallback = requestCallback; DisplayMetrics displayMetrics = new DisplayMetrics(); getDefaultDisplay().getRealMetrics(displayMetrics); @@ -365,11 +371,12 @@ public class ScreenshotController { new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels)); } + @MainThread void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds, Insets visibleInsets, int taskId, int userId, ComponentName topComponent, Consumer finisher, RequestCallback requestCallback) { // TODO: use task Id, userId, topComponent for smart handler - + Assert.isMainThread(); if (screenshot == null) { Log.e(TAG, "Got null bitmap from screenshot message"); mNotificationsController.notifyScreenshotError( @@ -392,8 +399,10 @@ public class ScreenshotController { /** * Displays a screenshot selector */ + @MainThread void takeScreenshotPartial(ComponentName topComponent, final Consumer finisher, RequestCallback requestCallback) { + Assert.isMainThread(); mScreenshotView.reset(); mCurrentRequestCallback = requestCallback; @@ -517,7 +526,7 @@ public class ScreenshotController { saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, topComponent, true); - mContext.sendBroadcast(new Intent(ClipboardOverlayController.SCREENSHOT_ACTION), + mBroadcastSender.sendBroadcast(new Intent(ClipboardOverlayController.SCREENSHOT_ACTION), ClipboardOverlayController.SELF_PERMISSION); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java index ad47e2bc44a85..01fe8657fe476 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy; +import android.annotation.WorkerThread; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -219,6 +220,7 @@ public class FlashlightControllerImpl implements FlashlightController { new CameraManager.TorchCallback() { @Override + @WorkerThread public void onTorchModeUnavailable(String cameraId) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(false); @@ -229,6 +231,7 @@ public class FlashlightControllerImpl implements FlashlightController { } @Override + @WorkerThread public void onTorchModeChanged(String cameraId, boolean enabled) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index d7c8a91608072..57ee3f1ec2491 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -67,6 +67,7 @@ import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -122,6 +123,7 @@ public class UserSwitcherController implements Dumpable { protected final Handler mHandler; private final ActivityStarter mActivityStarter; private final BroadcastDispatcher mBroadcastDispatcher; + private final BroadcastSender mBroadcastSender; private final TelephonyListenerManager mTelephonyListenerManager; private final InteractionJankMonitor mInteractionJankMonitor; private final LatencyTracker mLatencyTracker; @@ -165,6 +167,7 @@ public class UserSwitcherController implements Dumpable { @Main Handler handler, ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, + BroadcastSender broadcastSender, UiEventLogger uiEventLogger, FalsingManager falsingManager, TelephonyListenerManager telephonyListenerManager, @@ -179,6 +182,7 @@ public class UserSwitcherController implements Dumpable { mActivityManager = activityManager; mUserTracker = userTracker; mBroadcastDispatcher = broadcastDispatcher; + mBroadcastSender = broadcastSender; mTelephonyListenerManager = telephonyListenerManager; mUiEventLogger = uiEventLogger; mFalsingManager = falsingManager; @@ -1201,7 +1205,7 @@ public class UserSwitcherController implements Dumpable { } // Use broadcast instead of ShadeController, as this dialog may have started in // another process and normal dagger bindings are not available - getContext().sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + mBroadcastSender.closeSystemDialogs(); getContext().startActivityAsUser( CreateUserActivity.createIntentForStart(getContext()), mUserTracker.getUserHandle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt new file mode 100644 index 0000000000000..fbd2c918648a3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.broadcast + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.wakelock.WakeLockFake +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class BroadcastSenderTest : SysuiTestCase() { + + @Mock + private lateinit var mockContext: Context + + private lateinit var broadcastSender: BroadcastSender + private lateinit var executor: FakeExecutor + private lateinit var wakeLock: WakeLockFake + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + executor = FakeExecutor(FakeSystemClock()) + wakeLock = WakeLockFake() + val wakeLockBuilder = WakeLockFake.Builder(mContext) + wakeLockBuilder.setWakeLock(wakeLock) + broadcastSender = BroadcastSender(mockContext, wakeLockBuilder, executor) + } + + @Test + fun sendBroadcast_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + broadcastSender.sendBroadcast(intent) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intent) + } + } + + @Test + fun sendBroadcastWithPermission_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + broadcastSender.sendBroadcast(intent, permission) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intent, permission) + } + } + + @Test + fun sendBroadcastAsUser_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL) + } + } + + @Test + fun sendBroadcastAsUserWithPermission_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission) + } + } + + @Test + fun sendBroadcastAsUserWithPermissionAndOptions_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + val options = Bundle() + options.putString("key", "value") + + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission, options) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission, options) + } + } + + @Test + fun sendBroadcastAsUserWithPermissionAndAppOp_dispatchesWithWakelock() { + val intent = Intent(Intent.ACTION_VIEW) + val permission = "Permission" + + broadcastSender.sendBroadcastAsUser(intent, UserHandle.ALL, permission, 12) + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcastAsUser(intent, UserHandle.ALL, permission, 12) + } + } + + @Test + fun sendCloseSystemDialogs_dispatchesWithWakelock() { + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + + broadcastSender.closeSystemDialogs() + + runExecutorAssertingWakelock { + verify(mockContext).sendBroadcast(intentCaptor.capture()) + assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) + } + } + + private fun runExecutorAssertingWakelock(verification: () -> Unit) { + assertThat(wakeLock.isHeld).isTrue() + executor.runAllReady() + verification.invoke() + assertThat(wakeLock.isHeld).isFalse() + } +} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt index da25c6202b219..49eaf8239ca0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt @@ -23,6 +23,7 @@ import android.provider.Settings import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.VibratorHelper @@ -62,6 +63,8 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var taskViewFactory: Optional @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var cvh: ControlViewHolder @@ -94,6 +97,7 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { bgExecutor, uiExecutor, activityStarter, + broadcastSender, keyguardStateController, taskViewFactory, metricsLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt index 87b9172dcefcd..0166fa25d5267 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -21,6 +21,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.wm.shell.TaskView import org.junit.Before import org.junit.Test @@ -39,6 +40,8 @@ class DetailDialogTest : SysuiTestCase() { @Mock private lateinit var taskView: TaskView @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var controlViewHolder: ControlViewHolder @Mock private lateinit var pendingIntent: PendingIntent @@ -63,6 +66,7 @@ class DetailDialogTest : SysuiTestCase() { private fun createDialog(pendingIntent: PendingIntent): DetailDialog { return DetailDialog( mContext, + broadcastSender, taskView, pendingIntent, controlViewHolder diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 708fc915410cf..d1c195dcf4b9a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -40,6 +40,7 @@ import androidx.lifecycle.LiveData import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.media.dialog.MediaOutputDialogFactory import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -85,6 +86,7 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var bgExecutor: FakeExecutor @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var broadcastSender: BroadcastSender @Mock private lateinit var holder: PlayerViewHolder @Mock private lateinit var sessionHolder: PlayerSessionViewHolder @@ -144,8 +146,8 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(mediaViewController.expandedLayout).thenReturn(expandedSet) whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet) - player = MediaControlPanel(context, bgExecutor, activityStarter, mediaViewController, - seekBarViewModel, Lazy { mediaDataManager }, + player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender, + mediaViewController, seekBarViewModel, Lazy { mediaDataManager }, mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock) whenever(seekBarViewModel.progress).thenReturn(seekBarData) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index 6b203bcf68281..82a48efafa3a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -23,6 +23,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -65,6 +66,8 @@ class MediaDataFilterTest : SysuiTestCase() { @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher @Mock + private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var mediaResumeListener: MediaResumeListener @Mock private lateinit var mediaDataManager: MediaDataManager @@ -87,7 +90,7 @@ class MediaDataFilterTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) MediaPlayerData.clear() - mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, + mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, broadcastSender, lockscreenUserManager, executor, clock) mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index 13e582196ffbf..380fa6d50df75 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -37,15 +37,14 @@ import android.widget.TextView; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.Before; import org.junit.Test; @@ -64,11 +63,10 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private MediaOutputBaseAdapter mMediaOutputBaseAdapter = mock(MediaOutputBaseAdapter.class); private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); + private BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); @@ -77,17 +75,16 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private MediaOutputController mMediaOutputController; private int mHeaderIconRes; private IconCompat mIconCompat; - private Drawable mAppSourceDrawable; private CharSequence mHeaderTitle; private CharSequence mHeaderSubtitle; @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); - mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, + mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); } @@ -178,15 +175,16 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog { - MediaOutputBaseDialogImpl(Context context, MediaOutputController mediaOutputController) { - super(context, mediaOutputController); + MediaOutputBaseDialogImpl(Context context, BroadcastSender broadcastSender, + MediaOutputController mediaOutputController) { + super(context, broadcastSender, mediaOutputController); mAdapter = mMediaOutputBaseAdapter; } @Override Drawable getAppSourceIcon() { - return mAppSourceDrawable; + return null; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 6230700a6a2ed..d2dae745bcdcf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -45,7 +45,6 @@ import android.text.TextUtils; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; @@ -57,7 +56,6 @@ import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; -import com.android.systemui.statusbar.phone.ShadeController; import com.google.common.collect.ImmutableList; @@ -96,10 +94,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class); private MediaMetadata mMediaMetadata = mock(MediaMetadata.class); private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); @@ -124,9 +120,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn( mCachedBluetoothDeviceManager); - mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; @@ -176,9 +172,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_withoutPackageName_verifyMediaControllerInit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.start(mCb); @@ -205,9 +201,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void stop_withoutPackageName_verifyMediaControllerDeinit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.start(mCb); @@ -510,9 +506,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getNotificationLargeIcon_withoutPackageName_returnsNull() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotifCollection, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mSpyContext, null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index cb52e7c20464e..db56f875dd5c1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -37,10 +37,10 @@ import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.After; import org.junit.Before; @@ -61,8 +61,8 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Mock private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private final ShadeController mShadeController = mock(ShadeController.class); private final ActivityStarter mStarter = mock(ActivityStarter.class); + private final BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); private final MediaDevice mMediaDevice = mock(MediaDevice.class); private final NotificationEntryManager mNotificationEntryManager = @@ -78,12 +78,12 @@ public class MediaOutputDialogTest extends SysuiTestCase { @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputDialog = new MediaOutputDialog(mContext, false, + mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); mMediaOutputDialog.show(); @@ -129,7 +129,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Check the visibility metric logging by creating a new MediaOutput dialog, // and verify if the calling times increases. public void onCreate_ShouldLogVisibility() { - MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, + MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); testDialog.show(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index f186f57fd0e55..0cdde0775b2dc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -28,17 +28,16 @@ import android.view.View; import androidx.test.filters.SmallTest; -import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.ShadeController; import org.junit.After; import org.junit.Before; @@ -59,14 +58,13 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { // Mock private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); private ActivityStarter mStarter = mock(ActivityStarter.class); + private BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); private MediaDevice mMediaDevice = mock(MediaDevice.class); private MediaDevice mMediaDevice1 = mock(MediaDevice.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); - private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); @@ -77,12 +75,12 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { @Before public void setUp() { - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, - mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotificationEntryManager, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager)); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, + mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender, mMediaOutputController); mMediaOutputGroupDialog.show(); when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices); diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java index afb63ab0ebcf7..a156820ad141f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java @@ -37,6 +37,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.util.NotificationChannels; @@ -59,7 +60,9 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { // Test Instance. mContext.addMockSystemService(NotificationManager.class, mMockNotificationManager); ActivityStarter starter = mDependency.injectMockDependency(ActivityStarter.class); - mPowerNotificationWarnings = new PowerNotificationWarnings(mContext, starter); + BroadcastSender broadcastSender = mDependency.injectMockDependency(BroadcastSender.class); + mPowerNotificationWarnings = new PowerNotificationWarnings(mContext, starter, + broadcastSender); BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1, BatteryManager.BATTERY_HEALTH_GOOD, 5, 15); mPowerNotificationWarnings.updateSnapshot(snapshot); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index 91c347fc4685a..1caacb89ba100 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -41,6 +41,7 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -83,6 +84,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var userManager: UserManager @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher + @Mock private lateinit var broadcastSender: BroadcastSender @Mock private lateinit var telephonyListenerManager: TelephonyListenerManager @Mock private lateinit var secureSettings: SecureSettings @Mock private lateinit var falsingManager: FalsingManager @@ -159,6 +161,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { handler, activityStarter, broadcastDispatcher, + broadcastSender, uiEventLogger, falsingManager, telephonyListenerManager,