Add "Stop" button for remote device am: 5fc4c2883d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13109608 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I139a01e203546ec1bfcbc6077445a24779ae4fb1
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
android:id="@+id/header_icon"
|
android:id="@+id/header_icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="16dp"/>
|
android:paddingEnd="@dimen/media_output_dialog_header_icon_padding"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -70,36 +70,14 @@
|
|||||||
android:id="@+id/device_list"
|
android:id="@+id/device_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="12dp"/>
|
|
||||||
|
|
||||||
<include
|
|
||||||
layout="@layout/media_output_list_item"
|
|
||||||
android:id="@+id/group_item_controller"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/group_item_divider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="?android:attr/listDivider"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/list_result"
|
android:id="@+id/list_result"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:overScrollMode="never"/>
|
android:overScrollMode="never"/>
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/list_bottom_padding"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="12dp"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -1404,9 +1404,10 @@
|
|||||||
<dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
|
<dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
|
||||||
|
|
||||||
<!-- Output switcher panel related dimensions -->
|
<!-- Output switcher panel related dimensions -->
|
||||||
<dimen name="media_output_dialog_padding_top">11dp</dimen>
|
<dimen name="media_output_dialog_list_margin">12dp</dimen>
|
||||||
<dimen name="media_output_dialog_list_max_height">364dp</dimen>
|
<dimen name="media_output_dialog_list_max_height">364dp</dimen>
|
||||||
<dimen name="media_output_dialog_header_album_icon_size">52dp</dimen>
|
<dimen name="media_output_dialog_header_album_icon_size">52dp</dimen>
|
||||||
<dimen name="media_output_dialog_header_back_icon_size">36dp</dimen>
|
<dimen name="media_output_dialog_header_back_icon_size">36dp</dimen>
|
||||||
|
<dimen name="media_output_dialog_header_icon_padding">16dp</dimen>
|
||||||
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import java.util.List;
|
|||||||
public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
||||||
|
|
||||||
private static final String TAG = "MediaOutputAdapter";
|
private static final String TAG = "MediaOutputAdapter";
|
||||||
private static final int PAIR_NEW = 1;
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
public MediaOutputAdapter(MediaOutputController controller) {
|
public MediaOutputAdapter(MediaOutputController controller) {
|
||||||
super(controller);
|
super(controller);
|
||||||
@@ -58,11 +58,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull MediaDeviceBaseViewHolder viewHolder, int position) {
|
public void onBindViewHolder(@NonNull MediaDeviceBaseViewHolder viewHolder, int position) {
|
||||||
if (mController.isZeroMode() && position == (mController.getMediaDevices().size())) {
|
final int size = mController.getMediaDevices().size();
|
||||||
viewHolder.onBind(PAIR_NEW);
|
if (mController.isZeroMode() && position == size) {
|
||||||
} else if (position < (mController.getMediaDevices().size())) {
|
viewHolder.onBind(CUSTOMIZED_ITEM_PAIR_NEW, false /* topMargin */,
|
||||||
viewHolder.onBind(((List<MediaDevice>) (mController.getMediaDevices())).get(position));
|
true /* bottomMargin */);
|
||||||
} else {
|
} else if (position < size) {
|
||||||
|
viewHolder.onBind(((List<MediaDevice>) (mController.getMediaDevices())).get(position),
|
||||||
|
position == 0 /* topMargin */, position == (size - 1) /* bottomMargin */);
|
||||||
|
} else if (DEBUG) {
|
||||||
Log.d(TAG, "Incorrect position: " + position);
|
Log.d(TAG, "Incorrect position: " + position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +86,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onItemClick(int customizedItem) {
|
void onItemClick(int customizedItem) {
|
||||||
if (customizedItem == PAIR_NEW) {
|
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
|
||||||
mController.launchBluetoothPairing();
|
mController.launchBluetoothPairing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,51 +115,49 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void onBind(MediaDevice device) {
|
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
|
||||||
super.onBind(device);
|
super.onBind(device, topMargin, bottomMargin);
|
||||||
if (mController.isTransferring()) {
|
if (mController.isTransferring()) {
|
||||||
if (device.getState() == MediaDeviceState.STATE_CONNECTING
|
if (device.getState() == MediaDeviceState.STATE_CONNECTING
|
||||||
&& !mController.hasAdjustVolumeUserRestriction()) {
|
&& !mController.hasAdjustVolumeUserRestriction()) {
|
||||||
setTwoLineLayout(device, true);
|
setTwoLineLayout(device, null /* title */, true /* bFocused */,
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
false /* showSeekBar*/, true /* showProgressBar */,
|
||||||
mSeekBar.setVisibility(View.GONE);
|
false /* showSubtitle */);
|
||||||
mSubTitleText.setVisibility(View.GONE);
|
|
||||||
} else {
|
} else {
|
||||||
setSingleLineLayout(getItemTitle(device), false);
|
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set different layout for each device
|
// Set different layout for each device
|
||||||
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
|
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
|
||||||
setTwoLineLayout(device, false);
|
setTwoLineLayout(device, null /* title */, false /* bFocused */,
|
||||||
mSubTitleText.setVisibility(View.VISIBLE);
|
false /* showSeekBar*/, false /* showProgressBar */,
|
||||||
mSeekBar.setVisibility(View.GONE);
|
true /* showSubtitle */);
|
||||||
mProgressBar.setVisibility(View.GONE);
|
|
||||||
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
|
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
|
||||||
mFrameLayout.setOnClickListener(v -> onItemClick(device));
|
mFrameLayout.setOnClickListener(v -> onItemClick(device));
|
||||||
} else if (!mController.hasAdjustVolumeUserRestriction()
|
} else if (!mController.hasAdjustVolumeUserRestriction()
|
||||||
&& isCurrentConnected(device)) {
|
&& isCurrentConnected(device)) {
|
||||||
setTwoLineLayout(device, true);
|
setTwoLineLayout(device, null /* title */, true /* bFocused */,
|
||||||
mSeekBar.setVisibility(View.VISIBLE);
|
true /* showSeekBar*/, false /* showProgressBar */,
|
||||||
mProgressBar.setVisibility(View.GONE);
|
false /* showSubtitle */);
|
||||||
mSubTitleText.setVisibility(View.GONE);
|
|
||||||
initSeekbar(device);
|
initSeekbar(device);
|
||||||
} else {
|
} else {
|
||||||
setSingleLineLayout(getItemTitle(device), false);
|
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
|
||||||
mFrameLayout.setOnClickListener(v -> onItemClick(device));
|
mFrameLayout.setOnClickListener(v -> onItemClick(device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void onBind(int customizedItem) {
|
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
|
||||||
if (customizedItem == PAIR_NEW) {
|
super.onBind(customizedItem, topMargin, bottomMargin);
|
||||||
|
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
|
||||||
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
|
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
|
||||||
false);
|
false /* bFocused */);
|
||||||
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
|
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
|
||||||
d.setColorFilter(new PorterDuffColorFilter(
|
d.setColorFilter(new PorterDuffColorFilter(
|
||||||
Utils.getColorAccentDefaultColor(mContext), PorterDuff.Mode.SRC_IN));
|
Utils.getColorAccentDefaultColor(mContext), PorterDuff.Mode.SRC_IN));
|
||||||
mTitleIcon.setImageDrawable(d);
|
mTitleIcon.setImageDrawable(d);
|
||||||
mFrameLayout.setOnClickListener(v -> onItemClick(PAIR_NEW));
|
mFrameLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,12 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
private static final String FONT_SELECTED_TITLE = "sans-serif-medium";
|
private static final String FONT_SELECTED_TITLE = "sans-serif-medium";
|
||||||
private static final String FONT_TITLE = "sans-serif";
|
private static final String FONT_TITLE = "sans-serif";
|
||||||
|
|
||||||
|
static final int CUSTOMIZED_ITEM_PAIR_NEW = 1;
|
||||||
|
|
||||||
final MediaOutputController mController;
|
final MediaOutputController mController;
|
||||||
|
|
||||||
private boolean mIsDragging;
|
private boolean mIsDragging;
|
||||||
|
private int mMargin;
|
||||||
|
|
||||||
Context mContext;
|
Context mContext;
|
||||||
View mHolderView;
|
View mHolderView;
|
||||||
@@ -60,6 +63,8 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
||||||
int viewType) {
|
int viewType) {
|
||||||
mContext = viewGroup.getContext();
|
mContext = viewGroup.getContext();
|
||||||
|
mMargin = mContext.getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.media_output_dialog_list_margin);
|
||||||
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.media_output_list_item,
|
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.media_output_list_item,
|
||||||
viewGroup, false);
|
viewGroup, false);
|
||||||
|
|
||||||
@@ -106,12 +111,26 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
mSeekBar = view.requireViewById(R.id.volume_seekbar);
|
mSeekBar = view.requireViewById(R.id.volume_seekbar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onBind(MediaDevice device) {
|
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
|
||||||
mTitleIcon.setImageIcon(mController.getDeviceIconCompat(device).toIcon(mContext));
|
mTitleIcon.setImageIcon(mController.getDeviceIconCompat(device).toIcon(mContext));
|
||||||
|
setMargin(topMargin, bottomMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onBind(int customizedItem) { }
|
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
|
||||||
|
setMargin(topMargin, bottomMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMargin(boolean topMargin, boolean bottomMargin) {
|
||||||
|
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mFrameLayout
|
||||||
|
.getLayoutParams();
|
||||||
|
if (topMargin) {
|
||||||
|
params.topMargin = mMargin;
|
||||||
|
}
|
||||||
|
if (bottomMargin) {
|
||||||
|
params.bottomMargin = mMargin;
|
||||||
|
}
|
||||||
|
mFrameLayout.setLayoutParams(params);
|
||||||
|
}
|
||||||
void setSingleLineLayout(CharSequence title, boolean bFocused) {
|
void setSingleLineLayout(CharSequence title, boolean bFocused) {
|
||||||
mTitleText.setVisibility(View.VISIBLE);
|
mTitleText.setVisibility(View.VISIBLE);
|
||||||
mTwoLineLayout.setVisibility(View.GONE);
|
mTwoLineLayout.setVisibility(View.GONE);
|
||||||
@@ -123,10 +142,19 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTwoLineLayout(MediaDevice device, boolean bFocused) {
|
void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
|
||||||
|
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
|
||||||
mTitleText.setVisibility(View.GONE);
|
mTitleText.setVisibility(View.GONE);
|
||||||
mTwoLineLayout.setVisibility(View.VISIBLE);
|
mTwoLineLayout.setVisibility(View.VISIBLE);
|
||||||
mTwoLineTitleText.setText(getItemTitle(device));
|
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
|
||||||
|
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
|
||||||
|
mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
|
||||||
|
if (device == null) {
|
||||||
|
mTwoLineTitleText.setText(title);
|
||||||
|
} else {
|
||||||
|
mTwoLineTitleText.setText(getItemTitle(device));
|
||||||
|
}
|
||||||
|
|
||||||
if (bFocused) {
|
if (bFocused) {
|
||||||
mTwoLineTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE,
|
mTwoLineTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE,
|
||||||
Typeface.NORMAL));
|
Typeface.NORMAL));
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import android.view.Window;
|
|||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -69,12 +68,9 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
private LinearLayout mDeviceListLayout;
|
private LinearLayout mDeviceListLayout;
|
||||||
private Button mDoneButton;
|
private Button mDoneButton;
|
||||||
private Button mStopButton;
|
private Button mStopButton;
|
||||||
private View mListBottomPadding;
|
|
||||||
private int mListMaxHeight;
|
private int mListMaxHeight;
|
||||||
|
|
||||||
MediaOutputBaseAdapter mAdapter;
|
MediaOutputBaseAdapter mAdapter;
|
||||||
FrameLayout mGroupItemController;
|
|
||||||
View mGroupDivider;
|
|
||||||
|
|
||||||
private final ViewTreeObserver.OnGlobalLayoutListener mDeviceListLayoutListener = () -> {
|
private final ViewTreeObserver.OnGlobalLayoutListener mDeviceListLayoutListener = () -> {
|
||||||
// Set max height for list
|
// Set max height for list
|
||||||
@@ -114,12 +110,9 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
|
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
|
||||||
mHeaderIcon = mDialogView.requireViewById(R.id.header_icon);
|
mHeaderIcon = mDialogView.requireViewById(R.id.header_icon);
|
||||||
mDevicesRecyclerView = mDialogView.requireViewById(R.id.list_result);
|
mDevicesRecyclerView = mDialogView.requireViewById(R.id.list_result);
|
||||||
mGroupItemController = mDialogView.requireViewById(R.id.group_item_controller);
|
|
||||||
mGroupDivider = mDialogView.requireViewById(R.id.group_item_divider);
|
|
||||||
mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
|
mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
|
||||||
mDoneButton = mDialogView.requireViewById(R.id.done);
|
mDoneButton = mDialogView.requireViewById(R.id.done);
|
||||||
mStopButton = mDialogView.requireViewById(R.id.stop);
|
mStopButton = mDialogView.requireViewById(R.id.stop);
|
||||||
mListBottomPadding = mDialogView.requireViewById(R.id.list_bottom_padding);
|
|
||||||
|
|
||||||
mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
|
mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||||
mDeviceListLayoutListener);
|
mDeviceListLayoutListener);
|
||||||
@@ -162,7 +155,9 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
}
|
}
|
||||||
if (mHeaderIcon.getVisibility() == View.VISIBLE) {
|
if (mHeaderIcon.getVisibility() == View.VISIBLE) {
|
||||||
final int size = getHeaderIconSize();
|
final int size = getHeaderIconSize();
|
||||||
mHeaderIcon.setLayoutParams(new LinearLayout.LayoutParams(size, size));
|
final int padding = mContext.getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.media_output_dialog_header_icon_padding);
|
||||||
|
mHeaderIcon.setLayoutParams(new LinearLayout.LayoutParams(size + padding, size));
|
||||||
}
|
}
|
||||||
// Update title and subtitle
|
// Update title and subtitle
|
||||||
mHeaderTitle.setText(getHeaderText());
|
mHeaderTitle.setText(getHeaderText());
|
||||||
@@ -178,12 +173,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
if (!mAdapter.isDragging()) {
|
if (!mAdapter.isDragging()) {
|
||||||
mAdapter.notifyDataSetChanged();
|
mAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
// Add extra padding when device amount is less than 6
|
// Show when remote media session is available
|
||||||
if (mMediaOutputController.getMediaDevices().size() < 6) {
|
mStopButton.setVisibility(getStopButtonVisibility());
|
||||||
mListBottomPadding.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
mListBottomPadding.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract int getHeaderIconRes();
|
abstract int getHeaderIconRes();
|
||||||
@@ -196,6 +187,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
|
|
||||||
abstract CharSequence getHeaderSubtitle();
|
abstract CharSequence getHeaderSubtitle();
|
||||||
|
|
||||||
|
abstract int getStopButtonVisibility();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaChanged() {
|
public void onMediaChanged() {
|
||||||
mMainThreadHandler.post(() -> refresh());
|
mMainThreadHandler.post(() -> refresh());
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.media.MediaMetadata;
|
import android.media.MediaMetadata;
|
||||||
|
import android.media.MediaRoute2Info;
|
||||||
import android.media.RoutingSessionInfo;
|
import android.media.RoutingSessionInfo;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.media.session.MediaSessionManager;
|
import android.media.session.MediaSessionManager;
|
||||||
@@ -63,7 +64,7 @@ import javax.inject.Inject;
|
|||||||
public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||||
|
|
||||||
private static final String TAG = "MediaOutputController";
|
private static final String TAG = "MediaOutputController";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
private final String mPackageName;
|
private final String mPackageName;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -406,6 +407,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
|||||||
mActivityStarter.dismissKeyguardThenExecute(postKeyguardAction, null, true);
|
mActivityStarter.dismissKeyguardThenExecute(postKeyguardAction, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isActiveRemoteDevice(@NonNull MediaDevice device) {
|
||||||
|
final List<String> features = device.getFeatures();
|
||||||
|
return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)
|
||||||
|
|| features.contains(MediaRoute2Info.FEATURE_REMOTE_AUDIO_PLAYBACK)
|
||||||
|
|| features.contains(MediaRoute2Info.FEATURE_REMOTE_VIDEO_PLAYBACK)
|
||||||
|
|| features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK));
|
||||||
|
}
|
||||||
|
|
||||||
private final MediaController.Callback mCb = new MediaController.Callback() {
|
private final MediaController.Callback mCb = new MediaController.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onMetadataChanged(MediaMetadata metadata) {
|
public void onMetadataChanged(MediaMetadata metadata) {
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mGroupItemController.setVisibility(View.GONE);
|
|
||||||
mGroupDivider.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -75,4 +73,10 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
|
|||||||
CharSequence getHeaderSubtitle() {
|
CharSequence getHeaderSubtitle() {
|
||||||
return mMediaOutputController.getHeaderSubTitle();
|
return mMediaOutputController.getHeaderSubTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getStopButtonVisibility() {
|
||||||
|
return mMediaOutputController.isActiveRemoteDevice(
|
||||||
|
mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import androidx.core.graphics.drawable.IconCompat;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.media.MediaDevice;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
@@ -55,7 +54,6 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// Mock
|
// Mock
|
||||||
private MediaOutputBaseAdapter mMediaOutputBaseAdapter = mock(MediaOutputBaseAdapter.class);
|
private MediaOutputBaseAdapter mMediaOutputBaseAdapter = mock(MediaOutputBaseAdapter.class);
|
||||||
|
|
||||||
private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
|
private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
|
||||||
private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
|
private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
|
||||||
private ShadeController mShadeController = mock(ShadeController.class);
|
private ShadeController mShadeController = mock(ShadeController.class);
|
||||||
@@ -157,30 +155,6 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
|||||||
verify(mMediaOutputBaseAdapter).notifyDataSetChanged();
|
verify(mMediaOutputBaseAdapter).notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void refresh_with6Devices_checkBottomPaddingVisibility() {
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
mMediaOutputController.mMediaDevices.add(mock(MediaDevice.class));
|
|
||||||
}
|
|
||||||
mMediaOutputBaseDialogImpl.refresh();
|
|
||||||
final View view = mMediaOutputBaseDialogImpl.mDialogView.requireViewById(
|
|
||||||
R.id.list_bottom_padding);
|
|
||||||
|
|
||||||
assertThat(view.getVisibility()).isEqualTo(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void refresh_with5Devices_checkBottomPaddingVisibility() {
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
mMediaOutputController.mMediaDevices.add(mock(MediaDevice.class));
|
|
||||||
}
|
|
||||||
mMediaOutputBaseDialogImpl.refresh();
|
|
||||||
final View view = mMediaOutputBaseDialogImpl.mDialogView.requireViewById(
|
|
||||||
R.id.list_bottom_padding);
|
|
||||||
|
|
||||||
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog {
|
class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog {
|
||||||
|
|
||||||
MediaOutputBaseDialogImpl(Context context, MediaOutputController mediaOutputController) {
|
MediaOutputBaseDialogImpl(Context context, MediaOutputController mediaOutputController) {
|
||||||
@@ -189,24 +163,34 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
|||||||
mAdapter = mMediaOutputBaseAdapter;
|
mAdapter = mMediaOutputBaseAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
int getHeaderIconRes() {
|
int getHeaderIconRes() {
|
||||||
return mHeaderIconRes;
|
return mHeaderIconRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
IconCompat getHeaderIcon() {
|
IconCompat getHeaderIcon() {
|
||||||
return mIconCompat;
|
return mIconCompat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
int getHeaderIconSize() {
|
int getHeaderIconSize() {
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
CharSequence getHeaderText() {
|
CharSequence getHeaderText() {
|
||||||
return mHeaderTitle;
|
return mHeaderTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
CharSequence getHeaderSubtitle() {
|
CharSequence getHeaderSubtitle() {
|
||||||
return mHeaderSubtitle;
|
return mHeaderSubtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getStopButtonVisibility() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.media.dialog;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.media.MediaRoute2Info;
|
||||||
|
import android.media.session.MediaSessionManager;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
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.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.statusbar.phone.ShadeController;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
public class MediaOutputDialogTest extends SysuiTestCase {
|
||||||
|
|
||||||
|
private static final String TEST_PACKAGE = "test_package";
|
||||||
|
|
||||||
|
// 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 LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
|
||||||
|
private MediaDevice mMediaDevice = mock(MediaDevice.class);
|
||||||
|
|
||||||
|
private MediaOutputDialog mMediaOutputDialog;
|
||||||
|
private MediaOutputController mMediaOutputController;
|
||||||
|
private List<String> mFeatures = new ArrayList<>();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
|
||||||
|
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||||
|
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
||||||
|
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController);
|
||||||
|
|
||||||
|
when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice);
|
||||||
|
when(mMediaDevice.getFeatures()).thenReturn(mFeatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStopButtonVisibility_remoteDevice_returnVisible() {
|
||||||
|
mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK);
|
||||||
|
|
||||||
|
assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
|
||||||
|
mFeatures.clear();
|
||||||
|
mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_AUDIO_PLAYBACK);
|
||||||
|
|
||||||
|
assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
|
||||||
|
mFeatures.clear();
|
||||||
|
mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_VIDEO_PLAYBACK);
|
||||||
|
|
||||||
|
assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
|
||||||
|
mFeatures.clear();
|
||||||
|
mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK);
|
||||||
|
|
||||||
|
assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStopButtonVisibility_localDevice_returnGone() {
|
||||||
|
mFeatures.add(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK);
|
||||||
|
|
||||||
|
assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user