Use device type of MediaRoute2Info to classify MediaDevice

- This CL use device type of MediaRoute2Info to classify
  MediaDevice(e.g: BluetoothMediaDevice, InfoMediaDevice,
  PhoneMediaDevice).
- Move connect()/disconnect() methood to MediaDevice.java
- Add test case

Bug: 148765806
Test: make -j42 RunSettingsLibRoboTests
Change-Id: I9fa22d36cebea1f55fd3a5e389aca4e6abaa1797
This commit is contained in:
hughchen
2020-02-05 18:31:36 +08:00
parent df7b83819e
commit 491b9fccb1
11 changed files with 118 additions and 209 deletions

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.util.Log;
import android.util.Pair;
import com.android.settingslib.R;
@@ -68,20 +67,6 @@ public class BluetoothMediaDevice extends MediaDevice {
return MediaDeviceUtils.getId(mCachedDevice);
}
@Override
public boolean connect() {
//TODO(b/117129183): add callback to notify LocalMediaManager connection state.
final boolean isConnected = mCachedDevice.setActive();
setConnectedRecord();
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + isConnected);
return isConnected;
}
@Override
public void disconnect() {
//TODO(b/117129183): disconnected last select device
}
/**
* Get current CachedBluetoothDevice
*/

View File

@@ -62,13 +62,6 @@ public class InfoMediaDevice extends MediaDevice {
return MediaDeviceUtils.getId(mRouteInfo);
}
@Override
public boolean connect() {
setConnectedRecord();
mRouterManager.selectRoute(mPackageName, mRouteInfo);
return true;
}
@Override
public void requestSetVolume(int volume) {
mRouterManager.requestSetVolume(mRouteInfo, volume);
@@ -109,12 +102,6 @@ public class InfoMediaDevice extends MediaDevice {
return mContext.getResources().getString(R.string.unknown);
}
@Override
public void disconnect() {
//TODO(b/144535188): disconnected last select device
}
@Override
public boolean isConnected() {
return true;
}

View File

@@ -15,14 +15,23 @@
*/
package com.android.settingslib.media;
import static android.media.MediaRoute2Info.DEVICE_TYPE_BLUETOOTH;
import static android.media.MediaRoute2Info.DEVICE_TYPE_REMOTE_TV;
import static android.media.MediaRoute2Info.DEVICE_TYPE_UNKNOWN;
import android.app.Notification;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import java.util.List;
import java.util.concurrent.Executor;
@@ -45,11 +54,14 @@ public class InfoMediaManager extends MediaManager {
String mPackageName;
private MediaDevice mCurrentConnectedDevice;
private LocalBluetoothManager mBluetoothManager;
public InfoMediaManager(Context context, String packageName, Notification notification) {
public InfoMediaManager(Context context, String packageName, Notification notification,
LocalBluetoothManager localBluetoothManager) {
super(context, notification);
mRouterManager = MediaRouter2Manager.getInstance(context);
mBluetoothManager = localBluetoothManager;
if (!TextUtils.isEmpty(packageName)) {
mPackageName = packageName;
}
@@ -95,20 +107,53 @@ public class InfoMediaManager extends MediaManager {
private void buildAllRoutes() {
for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
final MediaDevice device = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
mMediaDevices.add(device);
addMediaDevice(route);
}
}
private void buildAvailableRoutes() {
for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) {
final MediaDevice device = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
if (TextUtils.equals(route.getClientPackageName(), mPackageName)) {
mCurrentConnectedDevice = device;
}
mMediaDevices.add(device);
addMediaDevice(route);
}
}
private void addMediaDevice(MediaRoute2Info route) {
final int deviceType = route.getDeviceType();
MediaDevice mediaDevice = null;
switch (deviceType) {
case DEVICE_TYPE_UNKNOWN:
//TODO(b/148765806): use correct device type once api is ready.
final String defaultRoute = "DEFAULT_ROUTE";
if (TextUtils.equals(defaultRoute, route.getOriginalId())) {
mediaDevice =
new PhoneMediaDevice(mContext, mRouterManager, route, mPackageName);
} else {
mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
if (!TextUtils.isEmpty(mPackageName)
&& TextUtils.equals(route.getClientPackageName(), mPackageName)) {
mCurrentConnectedDevice = mediaDevice;
}
}
break;
case DEVICE_TYPE_REMOTE_TV:
break;
case DEVICE_TYPE_BLUETOOTH:
final BluetoothDevice device =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice(route.getOriginalId());
final CachedBluetoothDevice cachedDevice =
mBluetoothManager.getCachedDeviceManager().findDevice(device);
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
route, mPackageName);
break;
default:
Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
break;
}
if (mediaDevice != null) {
mMediaDevices.add(mediaDevice);
}
}

View File

@@ -97,7 +97,8 @@ public class LocalMediaManager implements BluetoothCallback {
return;
}
mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
mInfoMediaManager =
new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager);
}
@VisibleForTesting
@@ -235,14 +236,17 @@ public class LocalMediaManager implements BluetoothCallback {
}
private MediaDevice updateCurrentConnectedDevice() {
MediaDevice phoneMediaDevice = null;
for (MediaDevice device : mMediaDevices) {
if (device instanceof BluetoothMediaDevice) {
if (isConnected(((BluetoothMediaDevice) device).getCachedDevice())) {
return device;
}
} else if (device instanceof PhoneMediaDevice) {
phoneMediaDevice = device;
}
}
return mMediaDevices.contains(mPhoneDevice) ? mPhoneDevice : null;
return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null;
}
private boolean isConnected(CachedBluetoothDevice device) {
@@ -266,17 +270,9 @@ public class LocalMediaManager implements BluetoothCallback {
final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
mCurrentConnectedDevice = infoMediaDevice != null
? infoMediaDevice : updateCurrentConnectedDevice();
updatePhoneMediaDeviceSummary();
dispatchDeviceListUpdate();
}
private void updatePhoneMediaDeviceSummary() {
if (mPhoneDevice != null) {
((PhoneMediaDevice) mPhoneDevice)
.updateSummary(mCurrentConnectedDevice == mPhoneDevice);
}
}
@Override
public void onDeviceRemoved(MediaDevice device) {
if (mMediaDevices.contains(device)) {
@@ -300,7 +296,6 @@ public class LocalMediaManager implements BluetoothCallback {
return;
}
mCurrentConnectedDevice = connectDevice;
updatePhoneMediaDeviceSummary();
dispatchDeviceAttributesChanged();
}

View File

@@ -23,6 +23,8 @@ import android.text.TextUtils;
import androidx.annotation.IntDef;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -42,10 +44,12 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
int TYPE_BLUETOOTH_DEVICE = 3;
}
@VisibleForTesting
int mType;
private int mConnectedRecord;
protected final Context mContext;
protected final int mType;
protected final MediaRoute2Info mRouteInfo;
protected final MediaRouter2Manager mRouterManager;
protected final String mPackageName;
@@ -92,24 +96,12 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
*/
public abstract String getId();
/**
* Transfer MediaDevice for media
*
* @return result of transfer media
*/
public abstract boolean connect();
void setConnectedRecord() {
mConnectedRecord++;
ConnectionRecordManager.getInstance().setConnectionRecord(mContext, getId(),
mConnectedRecord);
}
/**
* Stop transfer MediaDevice
*/
public abstract void disconnect();
/**
* According the MediaDevice type to check whether we are connected to this MediaDevice.
*
@@ -170,6 +162,23 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
return mType;
}
/**
* Transfer MediaDevice for media
*
* @return result of transfer media
*/
public boolean connect() {
setConnectedRecord();
mRouterManager.selectRoute(mPackageName, mRouteInfo);
return true;
}
/**
* Stop transfer MediaDevice
*/
public void disconnect() {
}
/**
* Rules:
* 1. If there is one of the connected devices identified as a carkit, this carkit will

View File

@@ -19,14 +19,9 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.util.Log;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
/**
* PhoneMediaDevice extends MediaDevice to represents Phone device.
@@ -37,16 +32,12 @@ public class PhoneMediaDevice extends MediaDevice {
public static final String ID = "phone_media_device_id_1";
private LocalBluetoothProfileManager mProfileManager;
private LocalBluetoothManager mLocalBluetoothManager;
private String mSummary = "";
PhoneMediaDevice(Context context, LocalBluetoothManager localBluetoothManager,
MediaRouter2Manager routerManager, MediaRoute2Info info, String packageName) {
PhoneMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
String packageName) {
super(context, MediaDeviceType.TYPE_PHONE_DEVICE, routerManager, info, packageName);
mLocalBluetoothManager = localBluetoothManager;
mProfileManager = mLocalBluetoothManager.getProfileManager();
initDeviceRecord();
}
@@ -71,32 +62,6 @@ public class PhoneMediaDevice extends MediaDevice {
return ID;
}
@Override
public boolean connect() {
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
// Some device may not have HearingAidProfile, consider all situation to set active device.
boolean isConnected = false;
if (hapProfile != null && a2dpProfile != null) {
isConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
} else if (a2dpProfile != null) {
isConnected = a2dpProfile.setActiveDevice(null);
} else if (hapProfile != null) {
isConnected = hapProfile.setActiveDevice(null);
}
updateSummary(isConnected);
setConnectedRecord();
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + isConnected);
return isConnected;
}
@Override
public void disconnect() {
updateSummary(false);
}
@Override
public boolean isConnected() {
return true;

View File

@@ -54,20 +54,6 @@ public class BluetoothMediaDeviceTest {
mBluetoothMediaDevice = new BluetoothMediaDevice(mContext, mDevice, null, null, null);
}
@Test
public void connect_setActiveSuccess_isConnectedReturnTrue() {
when(mDevice.setActive()).thenReturn(true);
assertThat(mBluetoothMediaDevice.connect()).isTrue();
}
@Test
public void connect_setActiveFail_isConnectedReturnFalse() {
when(mDevice.setActive()).thenReturn(false);
assertThat(mBluetoothMediaDevice.connect()).isFalse();
}
@Test
public void isCachedBluetoothDeviceConnected_deviceConnected_returnTrue() {
when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);

View File

@@ -18,7 +18,6 @@ package com.android.settingslib.media;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -108,13 +107,6 @@ public class InfoMediaDeviceTest {
assertThat(mInfoMediaDevice.getId()).isEqualTo(TEST_ID);
}
@Test
public void connect_shouldSelectRoute() {
mInfoMediaDevice.connect();
verify(mRouterManager).selectRoute(TEST_PACKAGE_NAME, mRouteInfo);
}
@Test
public void getClientPackageName_returnPackageName() {
when(mRouteInfo.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);

View File

@@ -27,6 +27,8 @@ import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,6 +48,8 @@ public class InfoMediaManagerTest {
@Mock
private MediaRouter2Manager mRouterManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
private InfoMediaManager mInfoMediaManager;
private Context mContext;
@@ -55,7 +59,8 @@ public class InfoMediaManagerTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mInfoMediaManager = new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null);
mInfoMediaManager =
new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null, mLocalBluetoothManager);
mInfoMediaManager.mRouterManager = mRouterManager;
}

View File

@@ -17,6 +17,7 @@ package com.android.settingslib.media;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothClass;
@@ -83,6 +84,14 @@ public class MediaDeviceTest {
@Mock
private MediaRoute2Info mRouteInfo3;
@Mock
private MediaRoute2Info mBluetoothRouteInfo1;
@Mock
private MediaRoute2Info mBluetoothRouteInfo2;
@Mock
private MediaRoute2Info mBluetoothRouteInfo3;
@Mock
private MediaRoute2Info mPhoneRouteInfo;
@Mock
private LocalBluetoothProfileManager mProfileManager;
@Mock
private HearingAidProfile mHapProfile;
@@ -90,6 +99,8 @@ public class MediaDeviceTest {
private A2dpProfile mA2dpProfile;
@Mock
private BluetoothDevice mDevice;
@Mock
private MediaRouter2Manager mMediaRouter2Manager;
private BluetoothMediaDevice mBluetoothMediaDevice1;
private BluetoothMediaDevice mBluetoothMediaDevice2;
@@ -100,7 +111,6 @@ public class MediaDeviceTest {
private InfoMediaDevice mInfoMediaDevice3;
private List<MediaDevice> mMediaDevices = new ArrayList<>();
private PhoneMediaDevice mPhoneMediaDevice;
private MediaRouter2Manager mMediaRouter2Manager;
@Before
public void setUp() {
@@ -134,12 +144,14 @@ public class MediaDeviceTest {
when(mA2dpProfile.getActiveDevice()).thenReturn(mDevice);
mBluetoothMediaDevice1 =
new BluetoothMediaDevice(mContext, mCachedDevice1, null, null, null);
new BluetoothMediaDevice(mContext, mCachedDevice1, mMediaRouter2Manager,
mBluetoothRouteInfo1, TEST_PACKAGE_NAME);
mBluetoothMediaDevice2 =
new BluetoothMediaDevice(mContext, mCachedDevice2, null, null, null);
new BluetoothMediaDevice(mContext, mCachedDevice2, mMediaRouter2Manager,
mBluetoothRouteInfo2, TEST_PACKAGE_NAME);
mBluetoothMediaDevice3 =
new BluetoothMediaDevice(mContext, mCachedDevice3, null, null, null);
mMediaRouter2Manager = MediaRouter2Manager.getInstance(mContext);
new BluetoothMediaDevice(mContext, mCachedDevice3, mMediaRouter2Manager,
mBluetoothRouteInfo3, TEST_PACKAGE_NAME);
mInfoMediaDevice1 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo1,
TEST_PACKAGE_NAME);
mInfoMediaDevice2 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo2,
@@ -147,7 +159,8 @@ public class MediaDeviceTest {
mInfoMediaDevice3 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo3,
TEST_PACKAGE_NAME);
mPhoneMediaDevice =
new PhoneMediaDevice(mContext, mLocalBluetoothManager, null, null, null);
new PhoneMediaDevice(mContext, mMediaRouter2Manager, mPhoneRouteInfo,
TEST_PACKAGE_NAME);
}
@Test
@@ -374,4 +387,11 @@ public class MediaDeviceTest {
assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice1);
assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice2);
}
@Test
public void connect_shouldSelectRoute() {
mInfoMediaDevice1.connect();
verify(mMediaRouter2Manager).selectRoute(TEST_PACKAGE_NAME, mRouteInfo1);
}
}

View File

@@ -18,21 +18,13 @@ package com.android.settingslib.media;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
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;
@@ -40,17 +32,6 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class PhoneMediaDeviceTest {
@Mock
private LocalBluetoothProfileManager mLocalProfileManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private HearingAidProfile mHapProfile;
@Mock
private A2dpProfile mA2dpProfile;
@Mock
private BluetoothDevice mDevice;
private Context mContext;
private PhoneMediaDevice mPhoneMediaDevice;
@@ -59,69 +40,8 @@ public class PhoneMediaDeviceTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalProfileManager);
when(mLocalProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
when(mA2dpProfile.getActiveDevice()).thenReturn(mDevice);
mPhoneMediaDevice =
new PhoneMediaDevice(mContext, mLocalBluetoothManager, null, null, null);
}
@Test
public void connect_phoneDeviceSetActiveSuccess_isConnectedReturnTrue() {
when(mA2dpProfile.setActiveDevice(null)).thenReturn(true);
when(mHapProfile.setActiveDevice(null)).thenReturn(true);
assertThat(mPhoneMediaDevice.connect()).isTrue();
}
@Test
public void connect_a2dpProfileSetActiveFail_isConnectedReturnFalse() {
when(mA2dpProfile.setActiveDevice(null)).thenReturn(false);
when(mHapProfile.setActiveDevice(null)).thenReturn(true);
assertThat(mPhoneMediaDevice.connect()).isFalse();
}
@Test
public void connect_hearingAidProfileSetActiveFail_isConnectedReturnFalse() {
when(mA2dpProfile.setActiveDevice(null)).thenReturn(true);
when(mHapProfile.setActiveDevice(null)).thenReturn(false);
assertThat(mPhoneMediaDevice.connect()).isFalse();
}
@Test
public void connect_hearingAidAndA2dpProfileSetActiveFail_isConnectedReturnFalse() {
when(mA2dpProfile.setActiveDevice(null)).thenReturn(false);
when(mHapProfile.setActiveDevice(null)).thenReturn(false);
assertThat(mPhoneMediaDevice.connect()).isFalse();
}
@Test
public void connect_hearingAidProfileIsNullAndA2dpProfileNotNull_isConnectedReturnTrue() {
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(null);
when(mA2dpProfile.setActiveDevice(null)).thenReturn(true);
assertThat(mPhoneMediaDevice.connect()).isTrue();
}
@Test
public void connect_hearingAidProfileNotNullAndA2dpProfileIsNull_isConnectedReturnTrue() {
when(mLocalProfileManager.getA2dpProfile()).thenReturn(null);
when(mHapProfile.setActiveDevice(null)).thenReturn(true);
assertThat(mPhoneMediaDevice.connect()).isTrue();
}
@Test
public void connect_hearingAidProfileAndA2dpProfileIsNull_isConnectedReturnFalse() {
when(mLocalProfileManager.getA2dpProfile()).thenReturn(null);
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(null);
assertThat(mPhoneMediaDevice.connect()).isFalse();
new PhoneMediaDevice(mContext, null, null, null);
}
@Test