Enhancement for group operation in output switcher
-Add new group components in xml layout and assets -Adjust view objects in adapter for new layout -Add aboveStatusbar in MediaOutputControllter to keep the dialog style when switching -Add getGroupMediaDevices() in MediaOutputController to provide available device list for group operation -Update test cases Bug: 155822415 Test: atest MediaOutputAdapterTest MediaOutputControllerTest MediaOutputBaseDialogTest MediaOutputDialogTest Merged-In: If74bf2efb89a8ece61f4e0cf13e4dcfa30cb0a8a Change-Id: If74bf2efb89a8ece61f4e0cf13e4dcfa30cb0a8a
This commit is contained in:
26
packages/SystemUI/res/drawable/ic_check_box.xml
Normal file
26
packages/SystemUI/res/drawable/ic_check_box.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/checked"
|
||||
android:state_checked="true"
|
||||
android:drawable="@drawable/ic_check_box_blue_24dp" />
|
||||
<item
|
||||
android:id="@+id/unchecked"
|
||||
android:state_checked="false"
|
||||
android:drawable="@drawable/ic_check_box_outline_24dp" />
|
||||
</selector>
|
||||
26
packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml
Normal file
26
packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"
|
||||
android:fillColor="#4285F4"/>
|
||||
</vector>
|
||||
|
||||
26
packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml
Normal file
26
packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"
|
||||
android:fillColor="#757575"/>
|
||||
</vector>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -15,97 +15,124 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/device_container"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/device_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp">
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<FrameLayout
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp">
|
||||
<ImageView
|
||||
android:id="@+id/title_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="68dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"/>
|
||||
<FrameLayout
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp">
|
||||
<ImageView
|
||||
android:id="@+id/title_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/two_line_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="52dp"
|
||||
android:layout_marginEnd="69dp"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:id="@+id/two_line_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="68dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"/>
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="roboto-regular"
|
||||
android:visibility="gone"/>
|
||||
<SeekBar
|
||||
android:id="@+id/volume_seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/volume_indeterminate_progress"
|
||||
style="@*android:style/Widget.Material.ProgressBar.Horizontal"
|
||||
android:layout_width="258dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="68dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"/>
|
||||
<RelativeLayout
|
||||
android:id="@+id/two_line_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="52dp"
|
||||
android:layout_marginEnd="69dp"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:id="@+id/two_line_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"/>
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="roboto-regular"
|
||||
android:visibility="gone"/>
|
||||
<SeekBar
|
||||
android:id="@+id/volume_seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/volume_indeterminate_progress"
|
||||
style="@*android:style/Widget.Material.ProgressBar.Horizontal"
|
||||
android:layout_width="258dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="68dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/end_divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="68dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:background="?android:attr/listDivider"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/add_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:src="@drawable/ic_add"
|
||||
android:tint="?android:attr/colorAccent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/check_box"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:button="@drawable/ic_check_box"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="68dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:id="@+id/bottom_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?android:attr/listDivider"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/end_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -109,34 +109,45 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
||||
super.onBind(device, topMargin, bottomMargin);
|
||||
final boolean currentlyConnected = isCurrentlyConnected(device);
|
||||
if (currentlyConnected) {
|
||||
mConnectedItem = mFrameLayout;
|
||||
mConnectedItem = mContainerLayout;
|
||||
}
|
||||
mBottomDivider.setVisibility(View.GONE);
|
||||
mCheckBox.setVisibility(View.GONE);
|
||||
if (currentlyConnected && mController.isActiveRemoteDevice(device)) {
|
||||
// Init active device layout
|
||||
mDivider.setVisibility(View.VISIBLE);
|
||||
mDivider.setTransitionAlpha(1);
|
||||
mAddIcon.setVisibility(View.VISIBLE);
|
||||
mAddIcon.setTransitionAlpha(1);
|
||||
mAddIcon.setOnClickListener(v -> onEndItemClick());
|
||||
} else {
|
||||
// Init non-active device layout
|
||||
mDivider.setVisibility(View.GONE);
|
||||
mAddIcon.setVisibility(View.GONE);
|
||||
}
|
||||
if (mController.isTransferring()) {
|
||||
if (device.getState() == MediaDeviceState.STATE_CONNECTING
|
||||
&& !mController.hasAdjustVolumeUserRestriction()) {
|
||||
setTwoLineLayout(device, null /* title */, true /* bFocused */,
|
||||
false /* showSeekBar*/, true /* showProgressBar */,
|
||||
false /* showSubtitle */);
|
||||
setTwoLineLayout(device, true /* bFocused */, false /* showSeekBar*/,
|
||||
true /* showProgressBar */, false /* showSubtitle */);
|
||||
} else {
|
||||
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
|
||||
}
|
||||
} else {
|
||||
// Set different layout for each device
|
||||
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
|
||||
setTwoLineLayout(device, null /* title */, false /* bFocused */,
|
||||
false /* showSeekBar*/, false /* showProgressBar */,
|
||||
setTwoLineLayout(device, false /* bFocused */,
|
||||
false /* showSeekBar */, false /* showProgressBar */,
|
||||
true /* showSubtitle */);
|
||||
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
|
||||
mFrameLayout.setOnClickListener(v -> onItemClick(v, device));
|
||||
} else if (!mController.hasAdjustVolumeUserRestriction()
|
||||
&& currentlyConnected) {
|
||||
setTwoLineLayout(device, null /* title */, true /* bFocused */,
|
||||
true /* showSeekBar*/, false /* showProgressBar */,
|
||||
false /* showSubtitle */);
|
||||
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
|
||||
} else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
|
||||
setTwoLineLayout(device, true /* bFocused */, true /* showSeekBar */,
|
||||
false /* showProgressBar */, false /* showSubtitle */);
|
||||
initSeekbar(device);
|
||||
} else {
|
||||
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
|
||||
mFrameLayout.setOnClickListener(v -> onItemClick(v, device));
|
||||
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,13 +156,17 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
||||
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
|
||||
super.onBind(customizedItem, topMargin, bottomMargin);
|
||||
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
|
||||
mCheckBox.setVisibility(View.GONE);
|
||||
mDivider.setVisibility(View.GONE);
|
||||
mAddIcon.setVisibility(View.GONE);
|
||||
mBottomDivider.setVisibility(View.GONE);
|
||||
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
|
||||
false /* bFocused */);
|
||||
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
|
||||
d.setColorFilter(new PorterDuffColorFilter(
|
||||
Utils.getColorAccentDefaultColor(mContext), PorterDuff.Mode.SRC_IN));
|
||||
mTitleIcon.setImageDrawable(d);
|
||||
mFrameLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
|
||||
mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,5 +188,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
||||
mController.launchBluetoothPairing();
|
||||
}
|
||||
}
|
||||
|
||||
private void onEndItemClick() {
|
||||
mController.launchMediaOutputGroupDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,9 @@ import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SeekBar;
|
||||
@@ -44,19 +45,17 @@ import com.android.systemui.R;
|
||||
public abstract class MediaOutputBaseAdapter extends
|
||||
RecyclerView.Adapter<MediaOutputBaseAdapter.MediaDeviceBaseViewHolder> {
|
||||
|
||||
private static final String FONT_SELECTED_TITLE = "sans-serif-medium";
|
||||
private static final String FONT_TITLE = "sans-serif";
|
||||
|
||||
static final int CUSTOMIZED_ITEM_PAIR_NEW = 1;
|
||||
static final int CUSTOMIZED_ITEM_GROUP = 2;
|
||||
|
||||
final MediaOutputController mController;
|
||||
|
||||
private boolean mIsDragging;
|
||||
private int mMargin;
|
||||
private boolean mIsAnimating;
|
||||
|
||||
Context mContext;
|
||||
View mHolderView;
|
||||
boolean mIsDragging;
|
||||
|
||||
public MediaOutputBaseAdapter(MediaOutputController controller) {
|
||||
mController = controller;
|
||||
@@ -99,27 +98,33 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
|
||||
private static final int ANIM_DURATION = 200;
|
||||
|
||||
final FrameLayout mFrameLayout;
|
||||
final LinearLayout mContainerLayout;
|
||||
final TextView mTitleText;
|
||||
final TextView mTwoLineTitleText;
|
||||
final TextView mSubTitleText;
|
||||
final ImageView mTitleIcon;
|
||||
final ImageView mEndIcon;
|
||||
final ImageView mAddIcon;
|
||||
final ProgressBar mProgressBar;
|
||||
final SeekBar mSeekBar;
|
||||
final RelativeLayout mTwoLineLayout;
|
||||
final View mDivider;
|
||||
final View mBottomDivider;
|
||||
final CheckBox mCheckBox;
|
||||
|
||||
MediaDeviceBaseViewHolder(View view) {
|
||||
super(view);
|
||||
mFrameLayout = view.requireViewById(R.id.device_container);
|
||||
mContainerLayout = view.requireViewById(R.id.device_container);
|
||||
mTitleText = view.requireViewById(R.id.title);
|
||||
mSubTitleText = view.requireViewById(R.id.subtitle);
|
||||
mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
|
||||
mTwoLineTitleText = view.requireViewById(R.id.two_line_title);
|
||||
mTitleIcon = view.requireViewById(R.id.title_icon);
|
||||
mEndIcon = view.requireViewById(R.id.end_icon);
|
||||
mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
|
||||
mSeekBar = view.requireViewById(R.id.volume_seekbar);
|
||||
mDivider = view.requireViewById(R.id.end_divider);
|
||||
mBottomDivider = view.requireViewById(R.id.bottom_divider);
|
||||
mAddIcon = view.requireViewById(R.id.add_icon);
|
||||
mCheckBox = view.requireViewById(R.id.check_box);
|
||||
}
|
||||
|
||||
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
|
||||
@@ -132,11 +137,11 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
}
|
||||
|
||||
private void setMargin(boolean topMargin, boolean bottomMargin) {
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mFrameLayout
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mContainerLayout
|
||||
.getLayoutParams();
|
||||
params.topMargin = topMargin ? mMargin : 0;
|
||||
params.bottomMargin = bottomMargin ? mMargin : 0;
|
||||
mFrameLayout.setLayoutParams(params);
|
||||
mContainerLayout.setLayoutParams(params);
|
||||
}
|
||||
|
||||
void setSingleLineLayout(CharSequence title, boolean bFocused) {
|
||||
@@ -146,13 +151,26 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
mTitleText.setTranslationY(0);
|
||||
mTitleText.setText(title);
|
||||
if (bFocused) {
|
||||
mTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE, Typeface.NORMAL));
|
||||
mTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamilyMedium),
|
||||
Typeface.NORMAL));
|
||||
} else {
|
||||
mTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
|
||||
mTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamily), Typeface.NORMAL));
|
||||
}
|
||||
}
|
||||
|
||||
void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
|
||||
void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
|
||||
boolean showProgressBar, boolean showSubtitle) {
|
||||
setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle);
|
||||
}
|
||||
|
||||
void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
|
||||
boolean showProgressBar, boolean showSubtitle) {
|
||||
setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle);
|
||||
}
|
||||
|
||||
private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
|
||||
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
|
||||
mTitleText.setVisibility(View.GONE);
|
||||
mTwoLineLayout.setVisibility(View.VISIBLE);
|
||||
@@ -168,18 +186,21 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
}
|
||||
|
||||
if (bFocused) {
|
||||
mTwoLineTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE,
|
||||
mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamilyMedium),
|
||||
Typeface.NORMAL));
|
||||
} else {
|
||||
mTwoLineTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
|
||||
mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamily), Typeface.NORMAL));
|
||||
}
|
||||
}
|
||||
|
||||
void initSeekbar(MediaDevice device) {
|
||||
mSeekBar.setMax(device.getMaxVolume());
|
||||
mSeekBar.setMin(0);
|
||||
if (mSeekBar.getProgress() != device.getCurrentVolume()) {
|
||||
mSeekBar.setProgress(device.getCurrentVolume());
|
||||
final int currentVolume = device.getCurrentVolume();
|
||||
if (mSeekBar.getProgress() != currentVolume) {
|
||||
mSeekBar.setProgress(currentVolume);
|
||||
}
|
||||
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
@@ -213,7 +234,9 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
}
|
||||
mIsAnimating = true;
|
||||
// Animation for title text
|
||||
toTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE, Typeface.NORMAL));
|
||||
toTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamilyMedium),
|
||||
Typeface.NORMAL));
|
||||
toTitleText.animate()
|
||||
.setDuration(ANIM_DURATION)
|
||||
.translationY(-delta)
|
||||
@@ -234,7 +257,9 @@ public abstract class MediaOutputBaseAdapter extends
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
final TextView fromTitleText = from.requireViewById(
|
||||
R.id.two_line_title);
|
||||
fromTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
|
||||
fromTitleText.setTypeface(Typeface.create(mContext.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamily),
|
||||
Typeface.NORMAL));
|
||||
fromTitleText.animate()
|
||||
.setDuration(ANIM_DURATION)
|
||||
.translationY(delta)
|
||||
|
||||
@@ -119,6 +119,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
||||
// Init device list
|
||||
mDevicesRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mDevicesRecyclerView.setAdapter(mAdapter);
|
||||
// Init header icon
|
||||
mHeaderIcon.setOnClickListener(v -> onHeaderIconClick());
|
||||
// Init bottom buttons
|
||||
mDoneButton.setOnClickListener(v -> dismiss());
|
||||
mStopButton.setOnClickListener(v -> {
|
||||
@@ -218,4 +220,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
void onHeaderIconClick() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||
private final MediaSessionManager mMediaSessionManager;
|
||||
private final ShadeController mShadeController;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
|
||||
private final boolean mAboveStatusbar;
|
||||
@VisibleForTesting
|
||||
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -82,13 +84,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||
|
||||
@Inject
|
||||
public MediaOutputController(@NonNull Context context, String packageName,
|
||||
MediaSessionManager mediaSessionManager, LocalBluetoothManager
|
||||
boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
|
||||
lbm, ShadeController shadeController, ActivityStarter starter) {
|
||||
mContext = context;
|
||||
mPackageName = packageName;
|
||||
mMediaSessionManager = mediaSessionManager;
|
||||
mShadeController = shadeController;
|
||||
mActivityStarter = starter;
|
||||
mAboveStatusbar = aboveStatusbar;
|
||||
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
|
||||
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
|
||||
}
|
||||
@@ -271,6 +274,42 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||
mMediaDevices.addAll(targetMediaDevices);
|
||||
}
|
||||
|
||||
List<MediaDevice> getGroupMediaDevices() {
|
||||
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
|
||||
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
|
||||
if (mGroupMediaDevices.isEmpty()) {
|
||||
mGroupMediaDevices.addAll(selectedDevices);
|
||||
mGroupMediaDevices.addAll(selectableDevices);
|
||||
return mGroupMediaDevices;
|
||||
}
|
||||
// To keep the same list order
|
||||
final Collection<MediaDevice> sourceDevices = new ArrayList<>();
|
||||
final Collection<MediaDevice> targetMediaDevices = new ArrayList<>();
|
||||
sourceDevices.addAll(selectedDevices);
|
||||
sourceDevices.addAll(selectableDevices);
|
||||
for (MediaDevice originalDevice : mGroupMediaDevices) {
|
||||
for (MediaDevice newDevice : sourceDevices) {
|
||||
if (TextUtils.equals(originalDevice.getId(), newDevice.getId())) {
|
||||
targetMediaDevices.add(newDevice);
|
||||
sourceDevices.remove(newDevice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add new devices at the end of list if necessary
|
||||
if (!sourceDevices.isEmpty()) {
|
||||
targetMediaDevices.addAll(sourceDevices);
|
||||
}
|
||||
mGroupMediaDevices.clear();
|
||||
mGroupMediaDevices.addAll(targetMediaDevices);
|
||||
|
||||
return mGroupMediaDevices;
|
||||
}
|
||||
|
||||
void resetGroupMediaDevices() {
|
||||
mGroupMediaDevices.clear();
|
||||
}
|
||||
|
||||
void connectDevice(MediaDevice device) {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
mLocalMediaManager.connectDevice(device);
|
||||
@@ -309,15 +348,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||
return mLocalMediaManager.getDeselectableMediaDevice();
|
||||
}
|
||||
|
||||
boolean isDeviceIncluded(Collection<MediaDevice> deviceCollection, MediaDevice targetDevice) {
|
||||
for (MediaDevice device : deviceCollection) {
|
||||
if (TextUtils.equals(device.getId(), targetDevice.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void adjustSessionVolume(String sessionId, int volume) {
|
||||
mLocalMediaManager.adjustSessionVolume(sessionId, volume);
|
||||
}
|
||||
@@ -407,6 +437,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
|
||||
mActivityStarter.dismissKeyguardThenExecute(postKeyguardAction, null, true);
|
||||
}
|
||||
|
||||
void launchMediaOutputDialog() {
|
||||
mCallback.dismissDialog();
|
||||
new MediaOutputDialog(mContext, mAboveStatusbar, this);
|
||||
}
|
||||
|
||||
void launchMediaOutputGroupDialog() {
|
||||
mCallback.dismissDialog();
|
||||
new MediaOutputGroupDialog(mContext, mAboveStatusbar, this);
|
||||
}
|
||||
|
||||
boolean isActiveRemoteDevice(@NonNull MediaDevice device) {
|
||||
final List<String> features = device.getFeatures();
|
||||
return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)
|
||||
|
||||
@@ -40,9 +40,8 @@ class MediaOutputDialogFactory @Inject constructor(
|
||||
/** Creates a [MediaOutputDialog] for the given package. */
|
||||
fun create(packageName: String, aboveStatusBar: Boolean) {
|
||||
mediaOutputDialog?.dismiss()
|
||||
|
||||
mediaOutputDialog = MediaOutputController(context, packageName, mediaSessionManager, lbm,
|
||||
shadeController, starter).run {
|
||||
mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
|
||||
mediaSessionManager, lbm, shadeController, starter).run {
|
||||
MediaOutputDialog(context, aboveStatusBar, this) }
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import static org.mockito.Mockito.when;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -66,7 +66,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
public void setUp() {
|
||||
mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
|
||||
mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
|
||||
.onCreateViewHolder(new FrameLayout(mContext), 0);
|
||||
.onCreateViewHolder(new LinearLayout(mContext), 0);
|
||||
|
||||
when(mMediaOutputController.getMediaDevices()).thenReturn(mMediaDevices);
|
||||
when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false);
|
||||
@@ -75,6 +75,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat);
|
||||
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat);
|
||||
when(mMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice1);
|
||||
when(mMediaOutputController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(true);
|
||||
when(mIconCompat.toIcon(mContext)).thenReturn(mIcon);
|
||||
when(mMediaDevice1.getName()).thenReturn(TEST_DEVICE_NAME_1);
|
||||
when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_ID_1);
|
||||
@@ -107,6 +108,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
|
||||
R.string.media_output_dialog_pairing_new));
|
||||
}
|
||||
@@ -118,11 +124,29 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_bindNonActiveConnectedDevice_verifyView() {
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
|
||||
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_bindDisconnectedBluetoothDevice_verifyView() {
|
||||
when(mMediaDevice2.getDeviceType()).thenReturn(
|
||||
@@ -130,7 +154,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
when(mMediaDevice2.isConnected()).thenReturn(false);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
|
||||
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
|
||||
mContext.getString(R.string.media_output_dialog_disconnected, TEST_DEVICE_NAME_2));
|
||||
@@ -142,9 +170,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
|
||||
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
|
||||
@@ -162,7 +194,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
|
||||
}
|
||||
@@ -174,8 +210,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
|
||||
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
|
||||
}
|
||||
|
||||
@@ -183,7 +224,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
public void onItemClick_clickPairNew_verifyLaunchBluetoothPairing() {
|
||||
when(mMediaOutputController.isZeroMode()).thenReturn(true);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
|
||||
mViewHolder.mFrameLayout.performClick();
|
||||
mViewHolder.mContainerLayout.performClick();
|
||||
|
||||
verify(mMediaOutputController).launchBluetoothPairing();
|
||||
}
|
||||
@@ -194,7 +235,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
|
||||
LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
|
||||
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
|
||||
mViewHolder.mFrameLayout.performClick();
|
||||
mViewHolder.mContainerLayout.performClick();
|
||||
|
||||
verify(mMediaOutputController).connectDevice(mMediaDevice2);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
|
||||
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
|
||||
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
|
||||
mMediaOutputController);
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.media.RoutingSessionInfo;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSessionManager;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -60,6 +61,9 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
private static final String TEST_PACKAGE_NAME = "com.test.package.name";
|
||||
private static final String TEST_DEVICE_1_ID = "test_device_1_id";
|
||||
private static final String TEST_DEVICE_2_ID = "test_device_2_id";
|
||||
private static final String TEST_DEVICE_3_ID = "test_device_3_id";
|
||||
private static final String TEST_DEVICE_4_ID = "test_device_4_id";
|
||||
private static final String TEST_DEVICE_5_ID = "test_device_5_id";
|
||||
private static final String TEST_ARTIST = "test_artist";
|
||||
private static final String TEST_SONG = "test_song";
|
||||
private static final String TEST_SESSION_ID = "test_session_id";
|
||||
@@ -96,7 +100,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
MediaSessionManager.class);
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
|
||||
mCachedBluetoothDeviceManager);
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME,
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
|
||||
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
|
||||
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
||||
@@ -139,8 +143,8 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void start_withoutPackageName_verifyMediaControllerInit() {
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager,
|
||||
mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
|
||||
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||
|
||||
mMediaOutputController.start(mCb);
|
||||
|
||||
@@ -159,8 +163,8 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void stop_withoutPackageName_verifyMediaControllerDeinit() {
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager,
|
||||
mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
|
||||
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mMediaOutputController.start(mCb);
|
||||
|
||||
mMediaOutputController.stop();
|
||||
@@ -345,4 +349,78 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mMediaOutputController.isZeroMode()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGroupMediaDevices_differentDeviceOrder_showingSameOrder() {
|
||||
final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
|
||||
final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
|
||||
final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
|
||||
final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
|
||||
final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
|
||||
final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
|
||||
when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
|
||||
when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
|
||||
when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
|
||||
when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
|
||||
selectedMediaDevices.add(selectedMediaDevice1);
|
||||
selectedMediaDevices.add(selectedMediaDevice2);
|
||||
selectableMediaDevices.add(selectableMediaDevice1);
|
||||
selectableMediaDevices.add(selectableMediaDevice2);
|
||||
doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
|
||||
doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
|
||||
final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices();
|
||||
// Reset order
|
||||
selectedMediaDevices.clear();
|
||||
selectedMediaDevices.add(selectedMediaDevice2);
|
||||
selectedMediaDevices.add(selectedMediaDevice1);
|
||||
selectableMediaDevices.clear();
|
||||
selectableMediaDevices.add(selectableMediaDevice2);
|
||||
selectableMediaDevices.add(selectableMediaDevice1);
|
||||
final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices();
|
||||
|
||||
assertThat(newDevices.size()).isEqualTo(groupMediaDevices.size());
|
||||
for (int i = 0; i < groupMediaDevices.size(); i++) {
|
||||
assertThat(TextUtils.equals(groupMediaDevices.get(i).getId(),
|
||||
newDevices.get(i).getId())).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGroupMediaDevices_newDevice_verifyDeviceOrder() {
|
||||
final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
|
||||
final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
|
||||
final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
|
||||
final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
|
||||
final MediaDevice selectableMediaDevice3 = mock(MediaDevice.class);
|
||||
final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
|
||||
final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
|
||||
when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
|
||||
when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
|
||||
when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
|
||||
when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
|
||||
when(selectableMediaDevice3.getId()).thenReturn(TEST_DEVICE_5_ID);
|
||||
selectedMediaDevices.add(selectedMediaDevice1);
|
||||
selectedMediaDevices.add(selectedMediaDevice2);
|
||||
selectableMediaDevices.add(selectableMediaDevice1);
|
||||
selectableMediaDevices.add(selectableMediaDevice2);
|
||||
doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
|
||||
doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
|
||||
final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices();
|
||||
// Reset order
|
||||
selectedMediaDevices.clear();
|
||||
selectedMediaDevices.add(selectedMediaDevice2);
|
||||
selectedMediaDevices.add(selectedMediaDevice1);
|
||||
selectableMediaDevices.clear();
|
||||
selectableMediaDevices.add(selectableMediaDevice3);
|
||||
selectableMediaDevices.add(selectableMediaDevice2);
|
||||
selectableMediaDevices.add(selectableMediaDevice1);
|
||||
final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices();
|
||||
|
||||
assertThat(newDevices.size()).isEqualTo(5);
|
||||
for (int i = 0; i < groupMediaDevices.size(); i++) {
|
||||
assertThat(TextUtils.equals(groupMediaDevices.get(i).getId(),
|
||||
newDevices.get(i).getId())).isTrue();
|
||||
}
|
||||
assertThat(newDevices.get(4).getId()).isEqualTo(TEST_DEVICE_5_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
|
||||
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
|
||||
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
|
||||
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
||||
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController);
|
||||
|
||||
Reference in New Issue
Block a user