Animate media dialogs

This CL applies the DialogLaunchAnimator to the media output and media
output group dialogs.

See b/200781817#comment2 for before/after videos.

Bug: 200781817
Test: Open media output dialog
Change-Id: I1bff28cc7647db6b97b8933e5b7605d7df15c63f
This commit is contained in:
Jordan Demeulenaere
2021-08-25 12:54:37 +02:00
parent e5b54057c1
commit ef3876e165
26 changed files with 147 additions and 89 deletions

View File

@@ -15,7 +15,14 @@
limitations under the License.
-->
<resources>
<style name="Animation.LaunchHostDialog" parent="@android:style/Animation">
<style name="HostDialogTheme">
<item name="android:windowAnimationStyle">@style/Animation.HostDialog</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Animation.HostDialog" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/launch_host_dialog_enter</item>
<item name="android:windowExitAnimation">@anim/launch_host_dialog_exit</item>
</style>

View File

@@ -118,6 +118,20 @@ class DialogLaunchAnimator(
fun onDozeAmountChanged(amount: Float) {
currentAnimations.forEach { it.onDozeAmountChanged(amount) }
}
/**
* Ensure that all dialogs currently shown won't animate into their touch surface when
* dismissed.
*
* This is a temporary API meant to be called right before we both dismiss a dialog and start
* an activity, which currently does not look good if we animate the dialog into the touch
* surface at the same time as the activity starts.
*
* TODO(b/193634619): Remove this function and animate dialog into opening activity instead.
*/
fun disableAllCurrentDialogsExitAnimations() {
currentAnimations.forEach { it.exitAnimationDisabled = true }
}
}
interface HostDialogProvider {
@@ -133,6 +147,7 @@ interface HostDialogProvider {
*/
fun createHostDialog(
context: Context,
theme: Int,
onCreateCallback: () -> Unit,
dismissOverride: (() -> Unit) -> Unit
): Dialog
@@ -180,7 +195,7 @@ private class DialogLaunchAnimation(
* [originalDialog].
*/
val hostDialog = hostDialogProvider.createHostDialog(
context, this::onHostDialogCreated, this::onHostDialogDismissed)
context, R.style.HostDialogTheme, this::onHostDialogCreated, this::onHostDialogDismissed)
/** The root content view of [hostDialog]. */
private val hostDialogRoot = FrameLayout(context)
@@ -208,6 +223,7 @@ private class DialogLaunchAnimation(
private var dismissRequested = false
private var drawHostDialog = false
var ignoreNextCallToHide = false
var exitAnimationDisabled = false
fun start() {
// Show the host (fullscreen) dialog, to which we will add the stolen dialog view.
@@ -236,10 +252,6 @@ private class DialogLaunchAnimation(
WindowManager.LayoutParams.MATCH_PARENT
)
// The host dialog animation is a translation of 0px so that it is shown directly. The
// translation lasts X ms, so that the scrim fades in during that amount of time.
window.attributes.windowAnimations = R.style.Animation_LaunchHostDialog
// Prevent the host dialog from drawing until the animation starts.
hostDialogRoot.viewTreeObserver.addOnPreDrawListener(
object : ViewTreeObserver.OnPreDrawListener {
@@ -318,9 +330,11 @@ private class DialogLaunchAnimation(
(dialogView.parent as? ViewGroup)?.removeView(dialogView)
hostDialogRoot.addView(
dialogView,
// We give it the size of its original dialog window.
FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
originalDialog.window.attributes.width,
originalDialog.window.attributes.height,
Gravity.CENTER
)
)
@@ -496,6 +510,10 @@ private class DialogLaunchAnimation(
}
private fun shouldAnimateDialogIntoView(): Boolean {
if (exitAnimationDisabled) {
return false
}
// The touch surface should be invisible by now, if it's not then something else changed its
// visibility and we probably don't want to run the animation.
if (touchSurface.visibility != View.INVISIBLE) {

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 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.
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="?android:attr/colorBackground" />
</shape>
</inset>

View File

@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/internet_connectivity_dialog"
android:layout_width="@dimen/internet_dialog_list_max_width"
android:layout_width="@dimen/large_dialog_width"
android:layout_height="@dimen/internet_dialog_list_max_height"
android:background="@drawable/internet_dialog_rounded_top_corner_background"
android:orientation="vertical">

View File

@@ -18,7 +18,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/media_output_dialog"
android:layout_width="match_parent"
android:layout_width="@dimen/large_dialog_width"
android:layout_height="wrap_content"
android:orientation="vertical">

View File

@@ -134,6 +134,7 @@
android:background="@drawable/qs_media_light_source"
android:forceHasOverlappingRendering="false">
<LinearLayout
android:id="@+id/media_seamless_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@dimen/qs_seamless_height"

View File

@@ -104,6 +104,6 @@
<!-- When split shade is used, this panel should be aligned to the top -->
<dimen name="qs_detail_margin_top">0dp</dimen>
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_max_width">624dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">624dp</dimen>
</resources>

View File

@@ -1600,7 +1600,9 @@
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_margin">12dp</dimen>
<dimen name="internet_dialog_list_max_height">646dp</dimen>
<dimen name="internet_dialog_list_max_width">@dimen/match_parent</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">@dimen/match_parent</dimen>
<!-- Signal icon in internet dialog -->
<dimen name="signal_strength_icon_size">24dp</dimen>

View File

@@ -331,9 +331,6 @@
<style name="Animation.ShutdownUi" parent="@android:style/Animation.Toast">
</style>
<style name="Animation.MediaOutputDialog" parent="@android:style/Animation.InputMethod">
</style>
<!-- Standard animations for hiding and showing the status bar. -->
<style name="Animation.StatusBar">
</style>
@@ -434,10 +431,6 @@
<item name="android:windowCloseOnTouchOutside">true</item>
</style>
<style name="Theme.SystemUI.Dialog.MediaOutput">
<item name="android:windowBackground">@drawable/media_output_dialog_background</item>
</style>
<style name="QSBorderlessButton">
<item name="android:padding">12dp</item>
<item name="android:background">@drawable/qs_btn_borderless_rect</item>

View File

@@ -361,9 +361,9 @@ public class MediaControlPanel {
seamlessView.setVisibility(View.VISIBLE);
setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */);
setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */);
seamlessView.setOnClickListener(v -> {
mMediaOutputDialogFactory.create(data.getPackageName(), true);
});
seamlessView.setOnClickListener(
v -> mMediaOutputDialogFactory.create(data.getPackageName(), true,
mPlayerViewHolder.getSeamlessButton()));
ImageView iconView = mPlayerViewHolder.getSeamlessIcon();
TextView deviceName = mPlayerViewHolder.getSeamlessText();

View File

@@ -43,6 +43,7 @@ class PlayerViewHolder private constructor(itemView: View) {
val seamless = itemView.requireViewById<ViewGroup>(R.id.media_seamless)
val seamlessIcon = itemView.requireViewById<ImageView>(R.id.media_seamless_image)
val seamlessText = itemView.requireViewById<TextView>(R.id.media_seamless_text)
val seamlessButton = itemView.requireViewById<View>(R.id.media_seamless_button)
// Seek bar
val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar)

View File

@@ -45,11 +45,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
private static final String TAG = "MediaOutputAdapter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final MediaOutputDialog mMediaOutputDialog;
private ViewGroup mConnectedItem;
private boolean mIncludeDynamicGroup;
public MediaOutputAdapter(MediaOutputController controller) {
public MediaOutputAdapter(MediaOutputController controller,
MediaOutputDialog mediaOutputDialog) {
super(controller);
mMediaOutputDialog = mediaOutputDialog;
}
@Override
@@ -136,7 +139,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mDivider.setTransitionAlpha(1);
mAddIcon.setVisibility(View.VISIBLE);
mAddIcon.setTransitionAlpha(1);
mAddIcon.setOnClickListener(v -> onEndItemClick());
mAddIcon.setOnClickListener(this::onEndItemClick);
} else {
// Init non-active device layout
mDivider.setVisibility(View.GONE);
@@ -197,7 +200,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mDivider.setTransitionAlpha(1);
mAddIcon.setVisibility(View.VISIBLE);
mAddIcon.setTransitionAlpha(1);
mAddIcon.setOnClickListener(v -> onEndItemClick());
mAddIcon.setOnClickListener(this::onEndItemClick);
} else {
mDivider.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
@@ -232,8 +235,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
}
}
private void onEndItemClick() {
mController.launchMediaOutputGroupDialog();
private void onEndItemClick(View view) {
mController.launchMediaOutputGroupDialog(mMediaOutputDialog.getDialogView());
}
}
}

View File

@@ -82,7 +82,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
};
public MediaOutputBaseDialog(Context context, MediaOutputController mediaOutputController) {
super(context, R.style.Theme_SystemUI_Dialog_MediaOutput);
super(context);
mContext = context;
mMediaOutputController = mediaOutputController;
mLayoutManager = new LinearLayoutManager(mContext);
@@ -97,15 +97,15 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mDialogView = LayoutInflater.from(mContext).inflate(R.layout.media_output_dialog, null);
final Window window = getWindow();
final WindowManager.LayoutParams lp = window.getAttributes();
lp.gravity = Gravity.BOTTOM;
lp.gravity = Gravity.CENTER;
// Config insets to make sure the layout is above the navigation bar
lp.setFitInsetsTypes(statusBars() | navigationBars());
lp.setFitInsetsSides(WindowInsets.Side.all());
lp.setFitInsetsIgnoringVisibility(true);
window.setAttributes(lp);
window.setContentView(mDialogView);
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
window.setWindowAnimations(R.style.Animation_MediaOutputDialog);
window.setLayout(mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width),
ViewGroup.LayoutParams.WRAP_CONTENT);
mHeaderTitle = mDialogView.requireViewById(R.id.header_title);
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
@@ -229,4 +229,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
void onHeaderIconClick() {
}
View getDialogView() {
return mDialogView;
}
}

View File

@@ -32,6 +32,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -48,6 +49,7 @@ import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.media.MediaOutputConstants;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -73,6 +75,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
private final MediaSessionManager mMediaSessionManager;
private final ShadeController mShadeController;
private final ActivityStarter mActivityStarter;
private final DialogLaunchAnimator mDialogLaunchAnimator;
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final boolean mAboveStatusbar;
private final NotificationEntryManager mNotificationEntryManager;
@@ -82,6 +85,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
private MediaController mMediaController;
@VisibleForTesting
Callback mCallback;
Callback mPreviousCallback;
@VisibleForTesting
LocalMediaManager mLocalMediaManager;
@@ -92,7 +96,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
public MediaOutputController(@NonNull Context context, String packageName,
boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
lbm, ShadeController shadeController, ActivityStarter starter,
NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger) {
NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger,
DialogLaunchAnimator dialogLaunchAnimator) {
mContext = context;
mPackageName = packageName;
mMediaSessionManager = mediaSessionManager;
@@ -104,6 +109,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
mUiEventLogger = uiEventLogger;
mDialogLaunchAnimator = dialogLaunchAnimator;
}
void start(@NonNull Callback cb) {
@@ -129,7 +135,19 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
}
return;
}
if (mPreviousCallback != null) {
Log.w(TAG,
"Callback started when mPreviousCallback is not null, which is unexpected");
mPreviousCallback.dismissDialog();
}
// If we start the output group dialog when the output dialog is shown, we need to keep a
// reference to the output dialog to set it back as the callback once we dismiss the output
// group dialog.
mPreviousCallback = mCallback;
mCallback = cb;
mLocalMediaManager.unregisterCallback(this);
mLocalMediaManager.stopScan();
mLocalMediaManager.registerCallback(this);
@@ -145,6 +163,15 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
mLocalMediaManager.stopScan();
}
mMediaDevices.clear();
// If there was a previous callback, i.e. we just dismissed the output group dialog and are
// now back on the output dialog, then we reset the callback to its previous value.
mCallback = null;
Callback previous = mPreviousCallback;
mPreviousCallback = null;
if (previous != null) {
start(previous);
}
}
@Override
@@ -436,6 +463,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
}
void launchBluetoothPairing() {
// Dismissing a dialog into its touch surface and starting an activity at the same time
// looks bad, so let's make sure the dialog just fades out quickly.
mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
final ActivityStarter.OnDismissAction postKeyguardAction = () -> {
mContext.sendBroadcast(new Intent()
@@ -447,14 +478,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
mActivityStarter.dismissKeyguardThenExecute(postKeyguardAction, null, true);
}
void launchMediaOutputDialog() {
mCallback.dismissDialog();
new MediaOutputDialog(mContext, mAboveStatusbar, this, mUiEventLogger);
}
void launchMediaOutputGroupDialog() {
mCallback.dismissDialog();
new MediaOutputGroupDialog(mContext, mAboveStatusbar, this);
void launchMediaOutputGroupDialog(View mediaOutputDialog) {
// We show the output group dialog from the output dialog.
MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar, this);
mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
}
boolean isActiveRemoteDevice(@NonNull MediaDevice device) {

View File

@@ -40,11 +40,10 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
mediaOutputController, UiEventLogger uiEventLogger) {
super(context, mediaOutputController);
mUiEventLogger = uiEventLogger;
mAdapter = new MediaOutputAdapter(mMediaOutputController);
mAdapter = new MediaOutputAdapter(mMediaOutputController, this);
if (!aboveStatusbar) {
getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
show();
}
@Override

View File

@@ -18,8 +18,10 @@ package com.android.systemui.media.dialog
import android.content.Context
import android.media.session.MediaSessionManager
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.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.phone.ShadeController
@@ -35,19 +37,29 @@ class MediaOutputDialogFactory @Inject constructor(
private val shadeController: ShadeController,
private val starter: ActivityStarter,
private val notificationEntryManager: NotificationEntryManager,
private val uiEventLogger: UiEventLogger
private val uiEventLogger: UiEventLogger,
private val dialogLaunchAnimator: DialogLaunchAnimator
) {
companion object {
var mediaOutputDialog: MediaOutputDialog? = null
}
/** Creates a [MediaOutputDialog] for the given package. */
fun create(packageName: String, aboveStatusBar: Boolean) {
fun create(packageName: String, aboveStatusBar: Boolean, view: View? = null) {
// Dismiss the previous dialog, if any.
mediaOutputDialog?.dismiss()
mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
uiEventLogger).run {
MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger)
val controller = MediaOutputController(context, packageName, aboveStatusBar,
mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
uiEventLogger, dialogLaunchAnimator)
val dialog = MediaOutputDialog(context, aboveStatusBar, controller, uiEventLogger)
mediaOutputDialog = dialog
// Show the dialog.
if (view != null) {
dialogLaunchAnimator.showFromView(dialog, view)
} else {
dialog.show()
}
}

View File

@@ -38,7 +38,6 @@ public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
if (!aboveStatusbar) {
getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
show();
}
@Override
@@ -83,6 +82,8 @@ public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
@Override
void onHeaderIconClick() {
mMediaOutputController.launchMediaOutputDialog();
// Given that we launched the media output group dialog from the media output dialog,
// dismissing this dialog will show the media output dialog again.
dismiss();
}
}

View File

@@ -126,7 +126,6 @@ public class InternetDialog extends SystemUIDialog implements
private Button mDoneButton;
private Drawable mBackgroundOn;
private int mListMaxHeight;
private int mLayoutWidth;
private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mCanConfigMobileData;
@@ -181,8 +180,6 @@ public class InternetDialog extends SystemUIDialog implements
};
mListMaxHeight = context.getResources().getDimensionPixelSize(
R.dimen.internet_dialog_list_max_height);
mLayoutWidth = context.getResources().getDimensionPixelSize(
R.dimen.internet_dialog_list_max_width);
mUiEventLogger = uiEventLogger;
mAdapter = new InternetAdapter(mInternetDialogController);
if (!aboveStatusBar) {
@@ -211,7 +208,7 @@ public class InternetDialog extends SystemUIDialog implements
window.setContentView(mDialogView);
//Only fix the width for large screen or tablet.
window.setLayout(mContext.getResources().getDimensionPixelSize(
R.dimen.internet_dialog_list_max_width), ViewGroup.LayoutParams.WRAP_CONTENT);
R.dimen.large_dialog_width), ViewGroup.LayoutParams.WRAP_CONTENT);
window.setWindowAnimations(R.style.Animation_InternetDialog);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.addFlags(FLAG_LAYOUT_NO_LIMITS);

View File

@@ -2521,7 +2521,8 @@ public class StatusBar extends SystemUI implements
animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
true /* isActivityIntent */);
ActivityLaunchAnimator.Controller animController =
animate ? wrapAnimationController(animationController, dismissShade) : null;
animationController != null ? wrapAnimationController(animationController,
dismissShade) : null;
// If we animate, we will dismiss the shade only once the animation is done. This is taken
// care of by the StatusBarLaunchAnimationController.

View File

@@ -9,17 +9,19 @@ import com.android.systemui.animation.HostDialogProvider
class SystemUIHostDialogProvider : HostDialogProvider {
override fun createHostDialog(
context: Context,
theme: Int,
onCreateCallback: () -> Unit,
dismissOverride: (() -> Unit) -> Unit
): Dialog {
return SystemUIHostDialog(context, onCreateCallback, dismissOverride)
return SystemUIHostDialog(context, theme, onCreateCallback, dismissOverride)
}
private class SystemUIHostDialog(
context: Context,
theme: Int,
private val onCreateCallback: () -> Unit,
private val dismissOverride: (() -> Unit) -> Unit
) : SystemUIDialog(context) {
) : SystemUIDialog(context, theme) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onCreateCallback()

View File

@@ -97,6 +97,7 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
private class TestHostDialogProvider : HostDialogProvider {
override fun createHostDialog(
context: Context,
theme: Int,
onCreateCallback: () -> Unit,
dismissOverride: (() -> Unit) -> Unit
): Dialog = TestHostDialog(context, onCreateCallback, dismissOverride)

View File

@@ -54,6 +54,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
// Mock
private MediaOutputController mMediaOutputController = mock(MediaOutputController.class);
private MediaOutputDialog mMediaOutputDialog = mock(MediaOutputDialog.class);
private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
private Icon mIcon = mock(Icon.class);
@@ -65,7 +66,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
@Before
public void setUp() {
mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController, mMediaOutputDialog);
mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
.onCreateViewHolder(new LinearLayout(mContext), 0);

View File

@@ -39,6 +39,7 @@ 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.plugins.ActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -63,6 +64,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
private MediaOutputController mMediaOutputController;
@@ -75,7 +77,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
mMediaOutputController);
mMediaOutputBaseDialogImpl.onCreate(new Bundle());

View File

@@ -49,6 +49,7 @@ 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.plugins.ActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -91,6 +92,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private Context mSpyContext;
private MediaOutputController mMediaOutputController;
@@ -113,7 +115,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -157,7 +159,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
public void start_withoutPackageName_verifyMediaControllerInit() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mMediaOutputController.start(mCb);
@@ -178,7 +180,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
public void stop_withoutPackageName_verifyMediaControllerDeinit() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mMediaOutputController.start(mCb);
@@ -449,7 +451,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}

View File

@@ -36,6 +36,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
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.plugins.ActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -65,6 +66,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
private final NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private MediaOutputDialog mMediaOutputDialog;
private MediaOutputController mMediaOutputController;
@@ -74,10 +76,11 @@ public class MediaOutputDialogTest extends SysuiTestCase {
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputDialog = new MediaOutputDialog(mContext, false,
mMediaOutputController, mUiEventLogger);
mMediaOutputDialog.show();
when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice);
when(mMediaDevice.getFeatures()).thenReturn(mFeatures);
@@ -123,6 +126,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
public void onCreate_ShouldLogVisibility() {
MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false,
mMediaOutputController, mUiEventLogger);
testDialog.show();
testDialog.dismissDialog();

View File

@@ -34,6 +34,7 @@ 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.plugins.ActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -64,6 +65,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private MediaOutputGroupDialog mMediaOutputGroupDialog;
private MediaOutputController mMediaOutputController;
@@ -73,10 +75,11 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
mNotificationEntryManager, mUiEventLogger);
mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
mMediaOutputController);
mMediaOutputGroupDialog.show();
when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices);
}