Merge "Implement naive rule of device order on seamless transfer"
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.settingslib.media;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -33,6 +35,13 @@ public class BluetoothMediaDevice extends MediaDevice {
|
||||
BluetoothMediaDevice(Context context, CachedBluetoothDevice device) {
|
||||
super(context, MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
|
||||
mCachedDevice = device;
|
||||
initDeviceRecord();
|
||||
buildConnectedState(device);
|
||||
}
|
||||
|
||||
private void buildConnectedState(CachedBluetoothDevice device) {
|
||||
mIsConnected = device.isActiveDevice(BluetoothProfile.A2DP)
|
||||
|| device.isActiveDevice(BluetoothProfile.HEARING_AID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,10 +60,16 @@ public class BluetoothMediaDevice extends MediaDevice {
|
||||
return MediaDeviceUtils.getId(mCachedDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyConnectedChanged() {
|
||||
buildConnectedState(mCachedDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
//TODO(b/117129183): add callback to notify LocalMediaManager connection state.
|
||||
mIsConnected = mCachedDevice.setActive();
|
||||
super.connect();
|
||||
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + mIsConnected);
|
||||
}
|
||||
|
||||
@@ -70,4 +85,18 @@ public class BluetoothMediaDevice extends MediaDevice {
|
||||
public CachedBluetoothDevice getCachedDevice() {
|
||||
return mCachedDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCarKitDevice() {
|
||||
final BluetoothClass bluetoothClass = mCachedDevice.getDevice().getBluetoothClass();
|
||||
if (bluetoothClass != null) {
|
||||
switch (bluetoothClass.getDeviceClass()) {
|
||||
// Both are common CarKit class
|
||||
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
|
||||
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settingslib.media;
|
||||
import android.app.Notification;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -30,6 +31,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -39,8 +41,8 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
|
||||
private static final String TAG = "BluetoothMediaManager";
|
||||
|
||||
private final DeviceAttributeChangeCallback mCachedDeviceCallback =
|
||||
new DeviceAttributeChangeCallback();
|
||||
private final DeviceProfileNotReadyObserverCallback mObserverCallback =
|
||||
new DeviceProfileNotReadyObserverCallback();
|
||||
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@@ -48,6 +50,10 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
private MediaDevice mLastAddedDevice;
|
||||
private MediaDevice mLastRemovedDevice;
|
||||
|
||||
private boolean mIsA2dpProfileReady = false;
|
||||
private boolean mIsHearingAidProfileReady = false;
|
||||
private Collection<CachedBluetoothDevice> mCachedDevices;
|
||||
|
||||
BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
|
||||
Notification notification) {
|
||||
super(context, notification);
|
||||
@@ -62,6 +68,18 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
||||
buildBluetoothDeviceList();
|
||||
dispatchDeviceListAdded();
|
||||
|
||||
// The profile may not ready when calling startScan().
|
||||
// Device status are all disconnected since profiles are not ready to connected.
|
||||
// In this case, we observe all devices in CachedDeviceManager.
|
||||
// When one of these device is connected to profile, will call buildBluetoothDeviceList()
|
||||
// again to find the connected devices.
|
||||
if (!mIsA2dpProfileReady && !mIsHearingAidProfileReady) {
|
||||
mCachedDevices = mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
|
||||
for (CachedBluetoothDevice device : mCachedDevices) {
|
||||
device.registerCallback(mObserverCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildBluetoothDeviceList() {
|
||||
@@ -75,6 +93,7 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
|
||||
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
|
||||
mLocalBluetoothManager.getCachedDeviceManager();
|
||||
@@ -95,6 +114,8 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
addMediaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
mIsA2dpProfileReady = a2dpProfile.isProfileReady();
|
||||
}
|
||||
|
||||
private void addConnectedHearingAidDevices() {
|
||||
@@ -103,6 +124,7 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<Long> devicesHiSyncIds = new ArrayList<>();
|
||||
final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
|
||||
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
|
||||
@@ -128,13 +150,14 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
addMediaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
mIsHearingAidProfileReady = hapProfile.isProfileReady();
|
||||
}
|
||||
|
||||
private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
|
||||
MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
|
||||
if (mediaDevice == null) {
|
||||
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
|
||||
cachedDevice.registerCallback(mCachedDeviceCallback);
|
||||
mLastAddedDevice = mediaDevice;
|
||||
mMediaDevices.add(mediaDevice);
|
||||
}
|
||||
@@ -143,16 +166,6 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
@Override
|
||||
public void stopScan() {
|
||||
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
|
||||
unregisterCachedDeviceCallback();
|
||||
}
|
||||
|
||||
private void unregisterCachedDeviceCallback() {
|
||||
for (MediaDevice device : mMediaDevices) {
|
||||
if (device instanceof BluetoothMediaDevice) {
|
||||
((BluetoothMediaDevice) device).getCachedDevice()
|
||||
.unregisterCallback(mCachedDeviceCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,8 +177,6 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
final List<MediaDevice> removeDevicesList = new ArrayList<>();
|
||||
for (MediaDevice device : mMediaDevices) {
|
||||
if (device instanceof BluetoothMediaDevice) {
|
||||
((BluetoothMediaDevice) device).getCachedDevice()
|
||||
.unregisterCallback(mCachedDeviceCallback);
|
||||
removeDevicesList.add(device);
|
||||
}
|
||||
}
|
||||
@@ -185,7 +196,7 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
private boolean isCachedDeviceConnected(CachedBluetoothDevice cachedDevice) {
|
||||
final boolean isConnectedHearingAidDevice = cachedDevice.isConnectedHearingAidDevice();
|
||||
final boolean isConnectedA2dpDevice = cachedDevice.isConnectedA2dpDevice();
|
||||
Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice.getName()
|
||||
Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice
|
||||
+ ", is hearing aid connected : " + isConnectedHearingAidDevice
|
||||
+ ", is a2dp connected : " + isConnectedA2dpDevice);
|
||||
|
||||
@@ -210,7 +221,6 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
|
||||
final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
|
||||
if (mediaDevice != null) {
|
||||
cachedDevice.unregisterCallback(mCachedDeviceCallback);
|
||||
mLastRemovedDevice = mediaDevice;
|
||||
mMediaDevices.remove(mediaDevice);
|
||||
}
|
||||
@@ -226,7 +236,7 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
@Override
|
||||
public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
|
||||
int bluetoothProfile) {
|
||||
Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice.getName()
|
||||
Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice
|
||||
+ ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
|
||||
|
||||
if (isCachedDeviceConnected(cachedDevice)) {
|
||||
@@ -240,8 +250,7 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
|
||||
@Override
|
||||
public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice.getName()
|
||||
+ ", state: " + state);
|
||||
Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice + ", state: " + state);
|
||||
|
||||
if (isCachedDeviceConnected(cachedDevice)) {
|
||||
addMediaDevice(cachedDevice);
|
||||
@@ -252,10 +261,29 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
|
||||
@Override
|
||||
public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
||||
Log.d(TAG, "onActiveDeviceChanged : device : "
|
||||
+ activeDevice + ", profile : " + bluetoothProfile);
|
||||
if (BluetoothProfile.HEARING_AID == bluetoothProfile
|
||||
|| BluetoothProfile.A2DP == bluetoothProfile) {
|
||||
final String id = activeDevice == null
|
||||
? PhoneMediaDevice.ID : MediaDeviceUtils.getId(activeDevice);
|
||||
dispatchActiveDeviceChanged(id);
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceProfileNotReadyObserverCallback implements CachedBluetoothDevice.Callback {
|
||||
|
||||
@Override
|
||||
public void onDeviceAttributesChanged() {
|
||||
dispatchDeviceAttributesChanged();
|
||||
if (!mIsA2dpProfileReady && !mIsHearingAidProfileReady) {
|
||||
for (CachedBluetoothDevice device : mCachedDevices) {
|
||||
device.unregisterCallback(mObserverCallback);
|
||||
}
|
||||
buildBluetoothDeviceList();
|
||||
dispatchDeviceListAdded();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2018 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.settingslib.media;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
/**
|
||||
* ConnectionRecordManager represents the sharedPreferences operation on device usage record
|
||||
*/
|
||||
public class ConnectionRecordManager {
|
||||
private static final Object sInstanceSync = new Object();
|
||||
private static final String KEY_LAST_SELECTED_DEVICE = "last_selected_device";
|
||||
private static final String SHARED_PREFERENCES_NAME = "seamless_transfer_record";
|
||||
private static final String TAG = "ConnectionRecordManager";
|
||||
private static ConnectionRecordManager sInstance;
|
||||
|
||||
private String mLastSelectedDevice;
|
||||
|
||||
/**
|
||||
* Get an {@code ConnectionRecordManager} instance (create one if necessary).
|
||||
*/
|
||||
public static ConnectionRecordManager getInstance() {
|
||||
synchronized (sInstanceSync) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new ConnectionRecordManager();
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private SharedPreferences getSharedPreferences(Context context) {
|
||||
return context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get connection record from sharedPreferences
|
||||
*
|
||||
* @param id a unique device Id
|
||||
* @return the the usage result
|
||||
*/
|
||||
public synchronized int fetchConnectionRecord(Context context, String id) {
|
||||
return getSharedPreferences(context).getInt(id, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last selected device from sharedPreferences
|
||||
*/
|
||||
public synchronized void fetchLastSelectedDevice(Context context) {
|
||||
mLastSelectedDevice = getSharedPreferences(context).getString(KEY_LAST_SELECTED_DEVICE,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set device usage time and last selected device in sharedPreference
|
||||
*
|
||||
* @param id a unique device Id
|
||||
* @param record usage times
|
||||
*/
|
||||
public synchronized void setConnectionRecord(Context context, String id, int record) {
|
||||
final SharedPreferences.Editor editor = getSharedPreferences(context).edit();
|
||||
// Update used times
|
||||
mLastSelectedDevice = id;
|
||||
editor.putInt(mLastSelectedDevice, record);
|
||||
// Update last used device
|
||||
editor.putString(KEY_LAST_SELECTED_DEVICE, mLastSelectedDevice);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last selected device
|
||||
*/
|
||||
public synchronized String getLastSelectedDevice() {
|
||||
return mLastSelectedDevice;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.android.settingslib.media;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.mediarouter.media.MediaRouter;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class InfoMediaDevice extends MediaDevice {
|
||||
InfoMediaDevice(Context context, MediaRouter.RouteInfo info) {
|
||||
super(context, MediaDeviceType.TYPE_CAST_DEVICE);
|
||||
mRouteInfo = info;
|
||||
initDeviceRecord();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,15 +53,23 @@ public class InfoMediaDevice extends MediaDevice {
|
||||
return MediaDeviceUtils.getId(mRouteInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyConnectedChanged() {
|
||||
//TODO(b/117129183): check mIsConnected state
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
//TODO(b/117129183): use MediaController2 to transfer media
|
||||
mIsConnected = true;
|
||||
super.connect();
|
||||
//mIsConnected = true;
|
||||
Toast.makeText(mContext, "This is cast device !", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
//TODO(b/117129183): disconnected last select device
|
||||
mIsConnected = false;
|
||||
//mIsConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,15 +28,20 @@ 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;
|
||||
|
||||
/**
|
||||
* LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
|
||||
*/
|
||||
public class LocalMediaManager implements BluetoothCallback {
|
||||
|
||||
private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
|
||||
private static final String TAG = "LocalMediaManager";
|
||||
|
||||
public static final String NOTIFICATION_EXTRA = "notification_extra";
|
||||
public static final String NOTIFICATION_PACKAGE_NAME = "notification_package_name";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({MediaDeviceState.STATE_CONNECTED,
|
||||
MediaDeviceState.STATE_CONNECTING,
|
||||
@@ -56,7 +61,6 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
private InfoMediaManager mInfoMediaManager;
|
||||
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private MediaDevice mLastConnectedDevice;
|
||||
private MediaDevice mPhoneDevice;
|
||||
|
||||
/**
|
||||
@@ -96,29 +100,43 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
* @param connectDevice the MediaDevice
|
||||
*/
|
||||
public void connectDevice(MediaDevice connectDevice) {
|
||||
if (connectDevice == mLastConnectedDevice) {
|
||||
final MediaDevice currentDevice = getCurrentConnectedDevice();
|
||||
final MediaDevice device =
|
||||
MediaDeviceUtils.findMediaDevice(mMediaDevices, connectDevice.getId());
|
||||
if (device != null && currentDevice != null
|
||||
&& device.getId().equals(currentDevice.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLastConnectedDevice != null) {
|
||||
mLastConnectedDevice.disconnect();
|
||||
//TODO(b/117129183): For demo, will remove check connectDevice is InfoMediaDevice.
|
||||
if (currentDevice != null && !(connectDevice instanceof InfoMediaDevice)) {
|
||||
currentDevice.disconnect();
|
||||
}
|
||||
|
||||
connectDevice.connect();
|
||||
if (connectDevice.isConnected()) {
|
||||
mLastConnectedDevice = connectDevice;
|
||||
}
|
||||
device.connect();
|
||||
|
||||
final int state = connectDevice.isConnected()
|
||||
final int state = device.isConnected()
|
||||
? MediaDeviceState.STATE_CONNECTED
|
||||
: MediaDeviceState.STATE_DISCONNECTED;
|
||||
dispatchSelectedDeviceStateChanged(connectDevice, state);
|
||||
dispatchSelectedDeviceStateChanged(mMediaDevices, device, state);
|
||||
}
|
||||
|
||||
void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
|
||||
private MediaDevice getCurrentConnectedDevice() {
|
||||
for (MediaDevice device : mMediaDevices) {
|
||||
if (device.isConnected()) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
Log.w(TAG, "getCurrentConnectedDevice() cannot find current connected device !");
|
||||
return null;
|
||||
}
|
||||
|
||||
void dispatchSelectedDeviceStateChanged(List<MediaDevice> mMediaDevices, MediaDevice device,
|
||||
@MediaDeviceState int state) {
|
||||
synchronized (mCallbacks) {
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onSelectedDeviceStateChanged(device, state);
|
||||
callback.onSelectedDeviceStateChanged(new ArrayList<>(mMediaDevices), device,
|
||||
state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,6 +171,7 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
|
||||
void dispatchDeviceListUpdate() {
|
||||
synchronized (mCallbacks) {
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
@@ -206,6 +225,25 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
public void onDeviceAttributesChanged() {
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActiveDeviceChanged(String id) {
|
||||
final MediaDevice currentDevice = getCurrentConnectedDevice();
|
||||
final MediaDevice connectDevice = MediaDeviceUtils.findMediaDevice(mMediaDevices, id);
|
||||
|
||||
if (connectDevice != null && currentDevice != null
|
||||
&& connectDevice.getId().equals(currentDevice.getId())) {
|
||||
return;
|
||||
}
|
||||
if (currentDevice != null) {
|
||||
currentDevice.notifyConnectedChanged();
|
||||
}
|
||||
if (connectDevice != null) {
|
||||
connectDevice.notifyConnectedChanged();
|
||||
}
|
||||
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -229,6 +267,7 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
* {@link MediaDeviceState#STATE_CONNECTING},
|
||||
* {@link MediaDeviceState#STATE_DISCONNECTED}
|
||||
*/
|
||||
void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
|
||||
void onSelectedDeviceStateChanged(List<MediaDevice> devices, MediaDevice device,
|
||||
@MediaDeviceState int state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
package com.android.settingslib.media;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
@@ -25,20 +27,21 @@ import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* MediaDevice represents a media device(such like Bluetooth device, cast device and phone device).
|
||||
*/
|
||||
public abstract class MediaDevice {
|
||||
|
||||
public abstract class MediaDevice implements Comparable<MediaDevice> {
|
||||
private static final String TAG = "MediaDevice";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
|
||||
MediaDeviceType.TYPE_CAST_DEVICE,
|
||||
@IntDef({MediaDeviceType.TYPE_CAST_DEVICE,
|
||||
MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
|
||||
MediaDeviceType.TYPE_PHONE_DEVICE})
|
||||
public @interface MediaDeviceType {
|
||||
int TYPE_BLUETOOTH_DEVICE = 1;
|
||||
int TYPE_CAST_DEVICE = 2;
|
||||
int TYPE_CAST_DEVICE = 1;
|
||||
int TYPE_BLUETOOTH_DEVICE = 2;
|
||||
int TYPE_PHONE_DEVICE = 3;
|
||||
}
|
||||
|
||||
private int mConnectedRecord;
|
||||
|
||||
protected boolean mIsConnected = false;
|
||||
protected Context mContext;
|
||||
protected int mType;
|
||||
@@ -48,6 +51,13 @@ public abstract class MediaDevice {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
void initDeviceRecord() {
|
||||
ConnectionRecordManager.getInstance().fetchLastSelectedDevice(mContext);
|
||||
mConnectedRecord = ConnectionRecordManager.getInstance().fetchConnectionRecord(mContext,
|
||||
getId());
|
||||
Log.d("ttttt", getName() + " used: " + mConnectedRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the MediaDevice is be connected to transfer.
|
||||
*
|
||||
@@ -77,13 +87,79 @@ public abstract class MediaDevice {
|
||||
*/
|
||||
public abstract String getId();
|
||||
|
||||
/**
|
||||
* Notify MediaDevice to change their connected state.
|
||||
*/
|
||||
public abstract void notifyConnectedChanged();
|
||||
|
||||
/**
|
||||
* Transfer MediaDevice for media
|
||||
*/
|
||||
public abstract void connect();
|
||||
public void connect() {
|
||||
mConnectedRecord++;
|
||||
ConnectionRecordManager.getInstance().setConnectionRecord(mContext, getId(),
|
||||
mConnectedRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop transfer MediaDevice
|
||||
*/
|
||||
public abstract void disconnect();
|
||||
|
||||
/**
|
||||
* Rules:
|
||||
* 1. If there is one of the connected devices identified as a carkit, this carkit will
|
||||
* be always on the top of the device list. Rule 2 and Rule 3 can’t overrule this rule.
|
||||
* 2. For devices without any usage data yet
|
||||
* WiFi device group sorted by alphabetical order + BT device group sorted by alphabetical
|
||||
* order + phone speaker
|
||||
* 3. For devices with usage record.
|
||||
* The most recent used one + device group with usage info sorted by how many times the
|
||||
* device has been used.
|
||||
*
|
||||
* So the device list will look like 4 slots ranked as below.
|
||||
* Rule 1 + the most recently used device + Rule 3 + Rule 2
|
||||
* Any slot could be empty. And available device will belong to one of the slots.
|
||||
*
|
||||
* @return a negative integer, zero, or a positive integer
|
||||
* as this object is less than, equal to, or greater than the specified object.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(MediaDevice another) {
|
||||
// Check carkit
|
||||
if (isCarKitDevice()) {
|
||||
return -1;
|
||||
} else if (another.isCarKitDevice()) {
|
||||
return 1;
|
||||
}
|
||||
// Set last used device at the first item
|
||||
String lastSelectedDevice = ConnectionRecordManager.getInstance().getLastSelectedDevice();
|
||||
if (TextUtils.equals(lastSelectedDevice, getId())) {
|
||||
return -1;
|
||||
} else if (TextUtils.equals(lastSelectedDevice, another.getId())) {
|
||||
return 1;
|
||||
}
|
||||
// Sort by how many times the device has been used if there is usage record
|
||||
if ((mConnectedRecord != another.mConnectedRecord)
|
||||
&& (another.mConnectedRecord > 0 || mConnectedRecord > 0)) {
|
||||
return (another.mConnectedRecord - mConnectedRecord);
|
||||
}
|
||||
// Both devices have never been used
|
||||
// To devices with the same type, sort by alphabetical order
|
||||
if (mType == another.mType) {
|
||||
final String s1 = getName();
|
||||
final String s2 = another.getName();
|
||||
return s1.compareToIgnoreCase(s2);
|
||||
}
|
||||
// Both devices have never been used, the priority is Cast > Bluetooth > Phone
|
||||
return mType - another.mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is CarKit device
|
||||
* @return true if it is CarKit device
|
||||
*/
|
||||
protected boolean isCarKitDevice() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,21 @@
|
||||
*/
|
||||
package com.android.settingslib.media;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.mediarouter.media.MediaRouter;
|
||||
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MediaDeviceUtils provides utility function for MediaDevice
|
||||
*/
|
||||
public class MediaDeviceUtils {
|
||||
|
||||
private static final String TAG = "MediaDeviceUtils";
|
||||
|
||||
/**
|
||||
* Use CachedBluetoothDevice address to represent unique id
|
||||
*
|
||||
@@ -43,4 +49,21 @@ public class MediaDeviceUtils {
|
||||
public static String getId(MediaRouter.RouteInfo route) {
|
||||
return route.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the MediaDevice through id.
|
||||
*
|
||||
* @param devices the list of MediaDevice
|
||||
* @param id the unique id of MediaDevice
|
||||
* @return MediaDevice
|
||||
*/
|
||||
public static MediaDevice findMediaDevice(List<MediaDevice> devices, String id) {
|
||||
for (MediaDevice mediaDevice : devices) {
|
||||
if (mediaDevice.getId().equals(id)) {
|
||||
return mediaDevice;
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "findMediaDevice() can't found device");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.android.settingslib.media;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -68,13 +67,7 @@ public abstract class MediaManager {
|
||||
public abstract void stopScan();
|
||||
|
||||
protected MediaDevice findMediaDevice(String id) {
|
||||
for (MediaDevice mediaDevice : mMediaDevices) {
|
||||
if (mediaDevice.getId().equals(id)) {
|
||||
return mediaDevice;
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "findMediaDevice() can't found device");
|
||||
return null;
|
||||
return MediaDeviceUtils.findMediaDevice(mMediaDevices, id);
|
||||
}
|
||||
|
||||
protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
|
||||
@@ -96,7 +89,7 @@ public abstract class MediaManager {
|
||||
protected void dispatchDeviceListAdded() {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListAdded(mMediaDevices);
|
||||
callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,6 +110,14 @@ public abstract class MediaManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchActiveDeviceChanged(String id) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onActiveDeviceChanged(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for notifying device is added, removed and attributes changed.
|
||||
*/
|
||||
@@ -153,5 +154,12 @@ public abstract class MediaManager {
|
||||
* Callback for notifying MediaDevice attributes is changed.
|
||||
*/
|
||||
void onDeviceAttributesChanged();
|
||||
|
||||
/**
|
||||
* Callback for notifying active MediaDevice is changed.
|
||||
*
|
||||
* @param id the id of MediaDevice
|
||||
*/
|
||||
void onActiveDeviceChanged(String id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.settingslib.media;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -24,6 +25,8 @@ import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PhoneMediaDevice extends MediaDevice to represents Phone device.
|
||||
*/
|
||||
@@ -41,6 +44,30 @@ public class PhoneMediaDevice extends MediaDevice {
|
||||
|
||||
mLocalBluetoothManager = localBluetoothManager;
|
||||
mProfileManager = mLocalBluetoothManager.getProfileManager();
|
||||
initDeviceRecord();
|
||||
|
||||
mIsConnected = isPhoneActive();
|
||||
}
|
||||
|
||||
private boolean isPhoneActive() {
|
||||
boolean isActive = true;
|
||||
|
||||
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
|
||||
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
|
||||
|
||||
if (a2dpProfile.getActiveDevice() == null) {
|
||||
final List<BluetoothDevice> activeDevices = hapProfile.getActiveDevices();
|
||||
for (BluetoothDevice btDevice : activeDevices) {
|
||||
if (btDevice != null) {
|
||||
isActive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isActive = false;
|
||||
}
|
||||
|
||||
return isActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,14 +87,19 @@ public class PhoneMediaDevice extends MediaDevice {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyConnectedChanged() {
|
||||
mIsConnected = isPhoneActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
|
||||
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
|
||||
|
||||
if (hapProfile != null && a2dpProfile != null) {
|
||||
mIsConnected =
|
||||
hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
|
||||
mIsConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
|
||||
super.connect();
|
||||
}
|
||||
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + mIsConnected);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2018 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.settingslib.media;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.mediarouter.media.MediaRouter;
|
||||
|
||||
import com.android.settingslib.bluetooth.A2dpProfile;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class MediaDeviceTest {
|
||||
private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
|
||||
private static final String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
|
||||
private static final String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
|
||||
private static final String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33";
|
||||
private static final String DEVICE_NAME_1 = "TestName_1";
|
||||
private static final String DEVICE_NAME_2 = "TestName_2";
|
||||
private static final String DEVICE_NAME_3 = "TestName_3";
|
||||
private static final String ROUTER_ID_1 = "RouterId_1";
|
||||
private static final String ROUTER_ID_2 = "RouterId_2";
|
||||
private static final String ROUTER_ID_3 = "RouterId_3";
|
||||
private final BluetoothClass mHeadreeClass =
|
||||
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
|
||||
private final BluetoothClass mCarkitClass =
|
||||
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
|
||||
|
||||
@Mock
|
||||
private A2dpProfile mA2dpProfile;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice1;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice2;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice3;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice1;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice2;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice3;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@Mock
|
||||
private MediaRouter.RouteInfo mRouteInfo1;
|
||||
@Mock
|
||||
private MediaRouter.RouteInfo mRouteInfo2;
|
||||
@Mock
|
||||
private MediaRouter.RouteInfo mRouteInfo3;
|
||||
|
||||
private BluetoothMediaDevice mBluetoothMediaDevice1;
|
||||
private BluetoothMediaDevice mBluetoothMediaDevice2;
|
||||
private BluetoothMediaDevice mBluetoothMediaDevice3;
|
||||
private Context mContext;
|
||||
private InfoMediaDevice mInfoMediaDevice1;
|
||||
private InfoMediaDevice mInfoMediaDevice2;
|
||||
private InfoMediaDevice mInfoMediaDevice3;
|
||||
private List<MediaDevice> mMediaDevices = new ArrayList<>();
|
||||
private PhoneMediaDevice mPhoneMediaDevice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
when(mCachedDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
|
||||
when(mCachedDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
|
||||
when(mCachedDevice3.getAddress()).thenReturn(DEVICE_ADDRESS_3);
|
||||
when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME_1);
|
||||
when(mCachedDevice2.getName()).thenReturn(DEVICE_NAME_2);
|
||||
when(mCachedDevice3.getName()).thenReturn(DEVICE_NAME_3);
|
||||
when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
|
||||
when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
|
||||
when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
|
||||
when(mRouteInfo1.getId()).thenReturn(ROUTER_ID_1);
|
||||
when(mRouteInfo2.getId()).thenReturn(ROUTER_ID_2);
|
||||
when(mRouteInfo3.getId()).thenReturn(ROUTER_ID_3);
|
||||
when(mRouteInfo1.getName()).thenReturn(DEVICE_NAME_1);
|
||||
when(mRouteInfo2.getName()).thenReturn(DEVICE_NAME_2);
|
||||
when(mRouteInfo3.getName()).thenReturn(DEVICE_NAME_3);
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
|
||||
when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
|
||||
when(mA2dpProfile.getActiveDevice()).thenReturn(mDevice1);
|
||||
|
||||
mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1);
|
||||
mBluetoothMediaDevice2 = new BluetoothMediaDevice(mContext, mCachedDevice2);
|
||||
mBluetoothMediaDevice3 = new BluetoothMediaDevice(mContext, mCachedDevice3);
|
||||
mInfoMediaDevice1 = new InfoMediaDevice(mContext, mRouteInfo1);
|
||||
mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2);
|
||||
mInfoMediaDevice3 = new InfoMediaDevice(mContext, mRouteInfo3);
|
||||
mPhoneMediaDevice = new PhoneMediaDevice(mContext, mLocalBluetoothManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_carKit_nonCarKitBluetooth_carKitFirst() {
|
||||
when(mDevice1.getBluetoothClass()).thenReturn(mHeadreeClass);
|
||||
when(mDevice2.getBluetoothClass()).thenReturn(mCarkitClass);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
mMediaDevices.add(mBluetoothMediaDevice2);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_carKit_info_carKitFirst() {
|
||||
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
|
||||
mMediaDevices.add(mInfoMediaDevice1);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mInfoMediaDevice1);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_carKit_phone_carKitFirst() {
|
||||
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
|
||||
mMediaDevices.add(mPhoneMediaDevice);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_lastSelected_others_lastSelectedFirst() {
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
mMediaDevices.add(mBluetoothMediaDevice2);
|
||||
mBluetoothMediaDevice2.connect();
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
|
||||
}
|
||||
@Test
|
||||
public void compareTo_connectionRecord_sortByRecord() {
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
mMediaDevices.add(mBluetoothMediaDevice2);
|
||||
mBluetoothMediaDevice1.connect();
|
||||
mBluetoothMediaDevice2.connect();
|
||||
mBluetoothMediaDevice2.connect();
|
||||
// Reset last selected record
|
||||
ConnectionRecordManager.getInstance().setConnectionRecord(mContext, null, 0);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice2);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
|
||||
assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_info_bluetooth_infoFirst() {
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
mMediaDevices.add(mInfoMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mInfoMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_bluetooth_phone_bluetoothFirst() {
|
||||
mMediaDevices.add(mPhoneMediaDevice);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_twoInfo_sortByAlphabet() {
|
||||
mMediaDevices.add(mInfoMediaDevice2);
|
||||
mMediaDevices.add(mInfoMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mInfoMediaDevice2);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mInfoMediaDevice1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo_twoBluetooth_sortByAlphabet() {
|
||||
mMediaDevices.add(mBluetoothMediaDevice2);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
}
|
||||
|
||||
// 1.mInfoMediaDevice1: Last Selected device
|
||||
// 2.mBluetoothMediaDevice1: CarKit device
|
||||
// 3.mInfoMediaDevice2: * 2 times usage
|
||||
// 4.mInfoMediaDevice3: * 1 time usage
|
||||
// 5.mBluetoothMediaDevice2: * 2 times usage
|
||||
// 6.mBluetoothMediaDevice3: * 1 time usage
|
||||
// 7.mPhoneMediaDevice: * 0 time usage
|
||||
// Order: 2 -> 1 -> 3 -> 5 -> 4 -> 6 -> 7
|
||||
@Test
|
||||
public void compareTo_mixedDevices_carKitFirst() {
|
||||
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
|
||||
when(mDevice2.getBluetoothClass()).thenReturn(mHeadreeClass);
|
||||
when(mDevice3.getBluetoothClass()).thenReturn(mHeadreeClass);
|
||||
mMediaDevices.add(mBluetoothMediaDevice1);
|
||||
mMediaDevices.add(mBluetoothMediaDevice2);
|
||||
mMediaDevices.add(mBluetoothMediaDevice3);
|
||||
mMediaDevices.add(mInfoMediaDevice1);
|
||||
mMediaDevices.add(mInfoMediaDevice2);
|
||||
mMediaDevices.add(mInfoMediaDevice3);
|
||||
mMediaDevices.add(mPhoneMediaDevice);
|
||||
mBluetoothMediaDevice3.connect();
|
||||
mBluetoothMediaDevice2.connect();
|
||||
mBluetoothMediaDevice2.connect();
|
||||
mInfoMediaDevice3.connect();
|
||||
mInfoMediaDevice2.connect();
|
||||
mInfoMediaDevice2.connect();
|
||||
mInfoMediaDevice1.connect();
|
||||
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
|
||||
assertThat(mMediaDevices.get(1)).isEqualTo(mInfoMediaDevice1);
|
||||
assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice2);
|
||||
assertThat(mMediaDevices.get(3)).isEqualTo(mBluetoothMediaDevice2);
|
||||
assertThat(mMediaDevices.get(4)).isEqualTo(mInfoMediaDevice3);
|
||||
assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice3);
|
||||
assertThat(mMediaDevices.get(6)).isEqualTo(mPhoneMediaDevice);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user