summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shaowei Shen <shaoweishen@google.com> 2022-05-03 13:49:43 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-05-03 13:49:43 +0000
commit8292f122d874c2489acca07c85545055cf25e37f (patch)
treedeab01a8ee3e345b5a83448ebd451627e6888ae9
parentabe29d73629bb41d06217ccd077c20d313599b90 (diff)
parent73706ceebfc232072b89808694990c6ac71a810d (diff)
Merge "DO NOT MERGE: Downbranch merge conflict [Output Switcher] Behavior improvement" into tm-dev
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java10
-rw-r--r--packages/SystemUI/res/layout/media_output_list_item.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java143
5 files changed, 126 insertions, 55 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index e1a2e8daf971..d6d73046bed3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -46,8 +46,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -56,7 +54,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
@RequiresApi(Build.VERSION_CODES.R)
public class LocalMediaManager implements BluetoothCallback {
- private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
private static final String TAG = "LocalMediaManager";
private static final int MAX_DISCONNECTED_DEVICE_NUM = 5;
@@ -65,13 +62,15 @@ public class LocalMediaManager implements BluetoothCallback {
MediaDeviceState.STATE_CONNECTING,
MediaDeviceState.STATE_DISCONNECTED,
MediaDeviceState.STATE_CONNECTING_FAILED,
- MediaDeviceState.STATE_SELECTED})
+ MediaDeviceState.STATE_SELECTED,
+ MediaDeviceState.STATE_GROUPING})
public @interface MediaDeviceState {
int STATE_CONNECTED = 0;
int STATE_CONNECTING = 1;
int STATE_DISCONNECTED = 2;
int STATE_CONNECTING_FAILED = 3;
int STATE_SELECTED = 4;
+ int STATE_GROUPING = 5;
}
private final Collection<DeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
@@ -322,6 +321,7 @@ public class LocalMediaManager implements BluetoothCallback {
* @return If add device successful return {@code true}, otherwise return {@code false}
*/
public boolean addDeviceToPlayMedia(MediaDevice device) {
+ device.setState(MediaDeviceState.STATE_GROUPING);
return mInfoMediaManager.addDeviceToPlayMedia(device);
}
@@ -332,6 +332,7 @@ public class LocalMediaManager implements BluetoothCallback {
* @return If device stop successful return {@code true}, otherwise return {@code false}
*/
public boolean removeDeviceFromPlayMedia(MediaDevice device) {
+ device.setState(MediaDeviceState.STATE_GROUPING);
return mInfoMediaManager.removeDeviceFromPlayMedia(device);
}
@@ -524,7 +525,6 @@ public class LocalMediaManager implements BluetoothCallback {
@Override
public void onDeviceListAdded(List<MediaDevice> devices) {
synchronized (mMediaDevicesLock) {
- Collections.sort(devices, COMPARATOR);
mMediaDevices.clear();
mMediaDevices.addAll(devices);
// Add disconnected bluetooth devices only when phone output device is available.
diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml
index daa9c04584ae..f79e534670d8 100644
--- a/packages/SystemUI/res/layout/media_output_list_item.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item.xml
@@ -39,6 +39,7 @@
android:visibility="gone"
android:paddingStart="0dp"
android:paddingEnd="0dp"
+ android:background="@null"
android:progressDrawable="@drawable/media_output_dialog_seekbar_background"
android:thumb="@null"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 694149a1e6e7..a397f32dcbbf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -166,6 +166,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
true /* showSubtitle */, true /* showStatus */);
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ } else if (device.getState() == MediaDeviceState.STATE_GROUPING) {
+ mProgressBar.getIndeterminateDrawable().setColorFilter(
+ new PorterDuffColorFilter(
+ mController.getColorItemContent(),
+ PorterDuff.Mode.SRC_IN));
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ false /* showSeekBar*/,
+ true /* showProgressBar */, false /* showStatus */);
} else if (mController.getSelectedMediaDevice().size() > 1
&& isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
mTitleText.setTextColor(mController.getColorItemContent());
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 22bdacae1bcd..5bb6557c3fe7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -184,6 +184,19 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
}
};
+ private class LayoutManagerWrapper extends LinearLayoutManager {
+ LayoutManagerWrapper(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onLayoutCompleted(RecyclerView.State state) {
+ super.onLayoutCompleted(state);
+ mMediaOutputController.setRefreshing(false);
+ mMediaOutputController.refreshDataSetIfNeeded();
+ }
+ }
+
public MediaOutputBaseDialog(Context context, BroadcastSender broadcastSender,
MediaOutputController mediaOutputController) {
super(context, R.style.Theme_SystemUI_Dialog_Media);
@@ -192,7 +205,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mContext = getContext();
mBroadcastSender = broadcastSender;
mMediaOutputController = mediaOutputController;
- mLayoutManager = new LinearLayoutManager(mContext);
+ mLayoutManager = new LayoutManagerWrapper(mContext);
mListMaxHeight = context.getResources().getDimensionPixelSize(
R.dimen.media_output_dialog_list_max_height);
mExecutor = Executors.newSingleThreadExecutor();
@@ -274,6 +287,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
}
void refresh(boolean deviceSetChanged) {
+ if (mMediaOutputController.isRefreshing()) {
+ return;
+ }
+ mMediaOutputController.setRefreshing(true);
// Update header icon
final int iconRes = getHeaderIconRes();
final IconCompat iconCompat = getHeaderIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 082f4bc3efe3..e7f97d25fabe 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -81,6 +81,8 @@ import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -108,11 +110,15 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
private final DialogLaunchAnimator mDialogLaunchAnimator;
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final CommonNotifCollection mNotifCollection;
+ private final Object mMediaDevicesLock = new Object();
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
+ final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager;
private final Map<String, Integer> mNearbyDeviceInfoMap = new ConcurrentHashMap<>();
+ private boolean mIsRefreshing = false;
+ private boolean mNeedRefresh = false;
private MediaController mMediaController;
@VisibleForTesting
Callback mCallback;
@@ -172,7 +178,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
void start(@NonNull Callback cb) {
- mMediaDevices.clear();
+ synchronized (mMediaDevicesLock) {
+ mCachedMediaDevices.clear();
+ mMediaDevices.clear();
+ }
mNearbyDeviceInfoMap.clear();
if (mNearbyMediaDevicesManager != null) {
mNearbyMediaDevicesManager.registerNearbyDevicesCallback(this);
@@ -211,6 +220,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
return routerParams != null && !routerParams.isMediaTransferReceiverEnabled();
}
+ void setRefreshing(boolean refreshing) {
+ mIsRefreshing = refreshing;
+ }
+
+ boolean isRefreshing() {
+ return mIsRefreshing;
+ }
+
void stop() {
if (mMediaController != null) {
mMediaController.unregisterCallback(mCb);
@@ -219,7 +236,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
mLocalMediaManager.unregisterCallback(this);
mLocalMediaManager.stopScan();
}
- mMediaDevices.clear();
+ synchronized (mMediaDevicesLock) {
+ mCachedMediaDevices.clear();
+ mMediaDevices.clear();
+ }
if (mNearbyMediaDevicesManager != null) {
mNearbyMediaDevicesManager.unregisterNearbyDevicesCallback(this);
}
@@ -228,15 +248,23 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
@Override
public void onDeviceListUpdate(List<MediaDevice> devices) {
- buildMediaDevices(devices);
- mCallback.onDeviceListChanged();
+ if (mMediaDevices.isEmpty() || !mIsRefreshing) {
+ buildMediaDevices(devices);
+ mCallback.onDeviceListChanged();
+ } else {
+ synchronized (mMediaDevicesLock) {
+ mNeedRefresh = true;
+ mCachedMediaDevices.clear();
+ mCachedMediaDevices.addAll(devices);
+ }
+ }
}
@Override
public void onSelectedDeviceStateChanged(MediaDevice device,
@LocalMediaManager.MediaDeviceState int state) {
mCallback.onRouteChanged();
- mMetricLogger.logOutputSuccess(device.toString(), mMediaDevices);
+ mMetricLogger.logOutputSuccess(device.toString(), new ArrayList<>(mMediaDevices));
}
@Override
@@ -247,7 +275,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
@Override
public void onRequestFailed(int reason) {
mCallback.onRouteChanged();
- mMetricLogger.logOutputFailure(mMediaDevices, reason);
+ mMetricLogger.logOutputFailure(new ArrayList<>(mMediaDevices), reason);
}
Drawable getAppSourceIcon() {
@@ -399,6 +427,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
}
+ void refreshDataSetIfNeeded() {
+ if (mNeedRefresh) {
+ buildMediaDevices(mCachedMediaDevices);
+ mCallback.onDeviceListChanged();
+ mNeedRefresh = false;
+ }
+ }
+
public int getColorConnectedItemBackground() {
return mColorConnectedItemBackground;
}
@@ -432,50 +468,55 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
private void buildMediaDevices(List<MediaDevice> devices) {
- // For the first time building list, to make sure the top device is the connected device.
- if (mMediaDevices.isEmpty()) {
- final MediaDevice connectedMediaDevice = getCurrentConnectedMediaDevice();
- if (connectedMediaDevice == null) {
- if (DEBUG) {
- Log.d(TAG, "No connected media device.");
+ synchronized (mMediaDevicesLock) {
+ attachRangeInfo(devices);
+ Collections.sort(devices, Comparator.naturalOrder());
+ // For the first time building list, to make sure the top device is the connected
+ // device.
+ if (mMediaDevices.isEmpty()) {
+ final MediaDevice connectedMediaDevice = getCurrentConnectedMediaDevice();
+ if (connectedMediaDevice == null) {
+ if (DEBUG) {
+ Log.d(TAG, "No connected media device.");
+ }
+ mMediaDevices.addAll(devices);
+ return;
+ }
+ for (MediaDevice device : devices) {
+ if (TextUtils.equals(device.getId(), connectedMediaDevice.getId())) {
+ mMediaDevices.add(0, device);
+ } else {
+ mMediaDevices.add(device);
+ }
}
- mMediaDevices.addAll(devices);
return;
}
- for (MediaDevice device : devices) {
- if (TextUtils.equals(device.getId(), connectedMediaDevice.getId())) {
- mMediaDevices.add(0, device);
- } else {
- mMediaDevices.add(device);
+ // To keep the same list order
+ final List<MediaDevice> targetMediaDevices = new ArrayList<>();
+ for (MediaDevice originalDevice : mMediaDevices) {
+ for (MediaDevice newDevice : devices) {
+ if (TextUtils.equals(originalDevice.getId(), newDevice.getId())) {
+ targetMediaDevices.add(newDevice);
+ break;
+ }
}
}
- return;
- }
- // To keep the same list order
- final Collection<MediaDevice> targetMediaDevices = new ArrayList<>();
- for (MediaDevice originalDevice : mMediaDevices) {
- for (MediaDevice newDevice : devices) {
- if (TextUtils.equals(originalDevice.getId(), newDevice.getId())) {
- targetMediaDevices.add(newDevice);
- break;
- }
+ if (targetMediaDevices.size() != devices.size()) {
+ devices.removeAll(targetMediaDevices);
+ targetMediaDevices.addAll(devices);
}
+ mMediaDevices.clear();
+ mMediaDevices.addAll(targetMediaDevices);
}
- if (targetMediaDevices.size() != devices.size()) {
- devices.removeAll(targetMediaDevices);
- targetMediaDevices.addAll(devices);
- }
- mMediaDevices.clear();
- mMediaDevices.addAll(targetMediaDevices);
- attachRangeInfo();
}
- private void attachRangeInfo() {
- for (MediaDevice mediaDevice : mMediaDevices) {
+ private void attachRangeInfo(List<MediaDevice> devices) {
+ for (MediaDevice mediaDevice : devices) {
if (mNearbyDeviceInfoMap.containsKey(mediaDevice.getId())) {
mediaDevice.setRangeZone(mNearbyDeviceInfoMap.get(mediaDevice.getId()));
}
}
+
}
List<MediaDevice> getGroupMediaDevices() {
@@ -609,26 +650,30 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
boolean isTransferring() {
- for (MediaDevice device : mMediaDevices) {
- if (device.getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) {
- return true;
+ synchronized (mMediaDevicesLock) {
+ for (MediaDevice device : mMediaDevices) {
+ if (device.getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) {
+ return true;
+ }
}
}
return false;
}
boolean isZeroMode() {
- if (mMediaDevices.size() == 1) {
- final MediaDevice device = mMediaDevices.iterator().next();
- // Add "pair new" only when local output device exists
- final int type = device.getDeviceType();
- if (type == MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE
- || type == MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE
- || type == MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE) {
- return true;
+ synchronized (mMediaDevicesLock) {
+ if (mMediaDevices.size() == 1) {
+ final MediaDevice device = mMediaDevices.iterator().next();
+ // Add "pair new" only when local output device exists
+ final int type = device.getDeviceType();
+ if (type == MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE
+ || type == MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE
+ || type == MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE) {
+ return true;
+ }
}
+ return false;
}
- return false;
}
void launchBluetoothPairing(View view) {