Merge changes from topic "media_output_slice"

* changes:
  Add test case for media manager
  Add constants for launch MediaOutput slice
  Add onConnectedDeviceChanged() onServiceConnected() callback
This commit is contained in:
TreeHugger Robot
2019-01-22 08:52:57 +00:00
committed by Android (Google) Code Review
19 changed files with 1522 additions and 87 deletions

View File

@@ -74,6 +74,7 @@ public class A2dpProfile implements LocalBluetoothProfile {
device.refresh();
}
mIsProfileReady=true;
mProfileManager.callServiceConnectedListeners();
}
public void onServiceDisconnected(int profile) {

View File

@@ -71,8 +71,8 @@ public class HearingAidProfile implements LocalBluetoothProfile {
// Check current list of CachedDevices to see if any are Hearing Aid devices.
mDeviceManager.updateHearingAidsDevices();
mIsProfileReady=true;
mProfileManager.callServiceConnectedListeners();
}
public void onServiceDisconnected(int profile) {

View File

@@ -54,17 +54,17 @@ public class BluetoothMediaDevice extends MediaDevice {
}
@Override
public void connect() {
public boolean 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);
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
mIsConnected = false;
}
/**

View File

@@ -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;
@@ -35,36 +36,48 @@ import java.util.List;
/**
* BluetoothMediaManager provide interface to get Bluetooth device list.
*/
public class BluetoothMediaManager extends MediaManager implements BluetoothCallback {
public class BluetoothMediaManager extends MediaManager implements BluetoothCallback,
LocalBluetoothProfileManager.ServiceListener {
private static final String TAG = "BluetoothMediaManager";
private final DeviceAttributeChangeCallback mCachedDeviceCallback =
new DeviceAttributeChangeCallback();
private LocalBluetoothManager mLocalBluetoothManager;
private LocalBluetoothProfileManager mProfileManager;
private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
private MediaDevice mLastAddedDevice;
private MediaDevice mLastRemovedDevice;
private boolean mIsA2dpProfileReady = false;
private boolean mIsHearingAidProfileReady = false;
BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
Notification notification) {
super(context, notification);
mLocalBluetoothManager = localBluetoothManager;
mProfileManager = mLocalBluetoothManager.getProfileManager();
mCachedBluetoothDeviceManager = mLocalBluetoothManager.getCachedDeviceManager();
}
@Override
public void startScan() {
mMediaDevices.clear();
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 onServiceConnected() in LocalBluetoothProfileManager.
// When A2dpProfile or HearingAidProfile is connected will call buildBluetoothDeviceList()
// again to find the connected devices.
if (!mIsA2dpProfileReady || !mIsHearingAidProfileReady) {
mProfileManager.addServiceListener(this);
}
}
private void buildBluetoothDeviceList() {
mMediaDevices.clear();
addConnectedA2dpDevices();
addConnectedHearingAidDevices();
}
@@ -77,12 +90,10 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
}
final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
mLocalBluetoothManager.getCachedDeviceManager();
for (BluetoothDevice device : devices) {
final CachedBluetoothDevice cachedDevice =
cachedBluetoothDeviceManager.findDevice(device);
mCachedBluetoothDeviceManager.findDevice(device);
if (cachedDevice == null) {
Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
@@ -96,6 +107,8 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
addMediaDevice(cachedDevice);
}
}
mIsA2dpProfileReady = a2dpProfile.isProfileReady();
}
private void addConnectedHearingAidDevices() {
@@ -107,12 +120,10 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
final List<Long> devicesHiSyncIds = new ArrayList<>();
final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
mLocalBluetoothManager.getCachedDeviceManager();
for (BluetoothDevice device : devices) {
final CachedBluetoothDevice cachedDevice =
cachedBluetoothDeviceManager.findDevice(device);
mCachedBluetoothDeviceManager.findDevice(device);
if (cachedDevice == null) {
Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
@@ -130,13 +141,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);
}
@@ -145,16 +157,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
@@ -166,8 +168,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);
}
}
@@ -212,7 +212,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);
}
@@ -252,10 +251,34 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall
dispatchDeviceRemoved(cachedDevice);
}
}
class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
@Override
public void onDeviceAttributesChanged() {
dispatchDeviceAttributesChanged();
@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);
dispatchConnectedDeviceChanged(id);
}
}
@Override
public void onServiceConnected() {
if (!mIsA2dpProfileReady || !mIsHearingAidProfileReady) {
buildBluetoothDeviceList();
dispatchDeviceListAdded();
}
//Remove the listener once a2dpProfile and hearingAidProfile are ready.
if (mIsA2dpProfileReady && mIsHearingAidProfileReady) {
mProfileManager.removeServiceListener(this);
}
}
@Override
public void onServiceDisconnected() {
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settingslib.media;
import android.content.Context;
import android.widget.Toast;
import androidx.mediarouter.media.MediaRouter;
@@ -43,7 +44,7 @@ public class InfoMediaDevice extends MediaDevice {
@Override
public int getIcon() {
//TODO(b/117129183): This is not final icon for cast device, just for demo.
//TODO(b/121083246): This is not final icon for cast device, just for demo.
return R.drawable.ic_settings_print;
}
@@ -53,15 +54,15 @@ public class InfoMediaDevice extends MediaDevice {
}
@Override
public void connect() {
//TODO(b/117129183): use MediaController2 to transfer media
mIsConnected = true;
super.connect();
public boolean connect() {
//TODO(b/121083246): use SystemApi to transfer media
setConnectedRecord();
Toast.makeText(mContext, "This is cast device !", Toast.LENGTH_SHORT).show();
return false;
}
@Override
public void disconnect() {
//TODO(b/117129183): disconnected last select device
mIsConnected = false;
//TODO(b/121083246): disconnected last select device
}
}

View File

@@ -22,6 +22,8 @@ import android.util.Log;
import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;
import com.android.internal.annotations.VisibleForTesting;
/**
* InfoMediaManager provide interface to get InfoMediaDevice list.
*/
@@ -29,9 +31,13 @@ public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
private final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
@VisibleForTesting
final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
@VisibleForTesting
MediaRouteSelector mSelector;
@VisibleForTesting
MediaRouter mMediaRouter;
private MediaRouter mMediaRouter;
private String mPackageName;
InfoMediaManager(Context context, String packageName, Notification notification) {
@@ -39,24 +45,20 @@ public class InfoMediaManager extends MediaManager {
mMediaRouter = MediaRouter.getInstance(context);
mPackageName = packageName;
mSelector = new MediaRouteSelector.Builder()
.addControlCategory(getControlCategoryByPackageName(mPackageName))
.build();
}
@Override
public void startScan() {
mMediaDevices.clear();
startScanCastDevice();
}
private void startScanCastDevice() {
final MediaRouteSelector selector = new MediaRouteSelector.Builder()
.addControlCategory(getControlCategoryByPackageName(mPackageName))
.build();
mMediaRouter.addCallback(selector, mMediaRouterCallback,
mMediaRouter.addCallback(mSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
private String getControlCategoryByPackageName(String packageName) {
@VisibleForTesting
String getControlCategoryByPackageName(String packageName) {
//TODO(b/117129183): Use package name to get ControlCategory.
//Since api not ready, return fixed ControlCategory for prototype.
return "com.google.android.gms.cast.CATEGORY_CAST/4F8B3483";

View File

@@ -16,12 +16,15 @@
package com.android.settingslib.media;
import android.app.Notification;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
import androidx.annotation.IntDef;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import java.lang.annotation.Retention;
@@ -50,16 +53,20 @@ public class LocalMediaManager implements BluetoothCallback {
}
private final Collection<DeviceCallback> mCallbacks = new ArrayList<>();
private final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
@VisibleForTesting
final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
private Context mContext;
private List<MediaDevice> mMediaDevices = new ArrayList<>();
private BluetoothMediaManager mBluetoothMediaManager;
private InfoMediaManager mInfoMediaManager;
private LocalBluetoothManager mLocalBluetoothManager;
private MediaDevice mLastConnectedDevice;
private MediaDevice mPhoneDevice;
@VisibleForTesting
List<MediaDevice> mMediaDevices = new ArrayList<>();
@VisibleForTesting
MediaDevice mPhoneDevice;
@VisibleForTesting
MediaDevice mCurrentConnectedDevice;
/**
* Register to start receiving callbacks for MediaDevice events.
@@ -93,28 +100,40 @@ public class LocalMediaManager implements BluetoothCallback {
mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
}
@VisibleForTesting
LocalMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
BluetoothMediaManager bluetoothMediaManager, InfoMediaManager infoMediaManager) {
mContext = context;
mLocalBluetoothManager = localBluetoothManager;
mBluetoothMediaManager = bluetoothMediaManager;
mInfoMediaManager = infoMediaManager;
}
/**
* Connect the MediaDevice to transfer media
* @param connectDevice the MediaDevice
*/
public void connectDevice(MediaDevice connectDevice) {
if (connectDevice == mLastConnectedDevice) {
final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
if (device == mCurrentConnectedDevice) {
Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
return;
}
if (mLastConnectedDevice != null) {
mLastConnectedDevice.disconnect();
//TODO(b/121083246): Update it once remote media API is ready.
if (mCurrentConnectedDevice != null && !(connectDevice instanceof InfoMediaDevice)) {
mCurrentConnectedDevice.disconnect();
}
connectDevice.connect();
if (connectDevice.isConnected()) {
mLastConnectedDevice = connectDevice;
final boolean isConnected = device.connect();
if (isConnected) {
mCurrentConnectedDevice = device;
}
final int state = connectDevice.isConnected()
final int state = isConnected
? MediaDeviceState.STATE_CONNECTED
: MediaDeviceState.STATE_DISCONNECTED;
dispatchSelectedDeviceStateChanged(connectDevice, state);
dispatchSelectedDeviceStateChanged(device, state);
}
void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
@@ -189,6 +208,31 @@ public class LocalMediaManager implements BluetoothCallback {
return null;
}
/**
* Find the current connected MediaDevice.
*
* @return MediaDevice
*/
public MediaDevice getCurrentConnectedDevice() {
return mCurrentConnectedDevice;
}
private MediaDevice updateCurrentConnectedDevice() {
for (MediaDevice device : mMediaDevices) {
if (device instanceof BluetoothMediaDevice) {
if (isConnected(((BluetoothMediaDevice) device).getCachedDevice())) {
return device;
}
}
}
return mMediaDevices.contains(mPhoneDevice) ? mPhoneDevice : null;
}
private boolean isConnected(CachedBluetoothDevice device) {
return device.isActiveDevice(BluetoothProfile.A2DP)
|| device.isActiveDevice(BluetoothProfile.HEARING_AID);
}
class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
@Override
public void onDeviceAdded(MediaDevice device) {
@@ -201,8 +245,13 @@ public class LocalMediaManager implements BluetoothCallback {
@Override
public void onDeviceListAdded(List<MediaDevice> devices) {
mMediaDevices.addAll(devices);
for (MediaDevice device : devices) {
if (getMediaDeviceById(mMediaDevices, device.getId()) == null) {
mMediaDevices.add(device);
}
}
addPhoneDeviceIfNecessary();
mCurrentConnectedDevice = updateCurrentConnectedDevice();
dispatchDeviceListUpdate();
}
@@ -226,6 +275,20 @@ public class LocalMediaManager implements BluetoothCallback {
public void onDeviceAttributesChanged() {
dispatchDeviceListUpdate();
}
@Override
public void onConnectedDeviceChanged(String id) {
final MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
if (connectDevice == mCurrentConnectedDevice) {
Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected! : "
+ connectDevice.getName());
return;
}
mCurrentConnectedDevice = connectDevice;
dispatchDeviceListUpdate();
}
}

View File

@@ -41,7 +41,6 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
private int mConnectedRecord;
protected boolean mIsConnected = false;
protected Context mContext;
protected int mType;
@@ -56,15 +55,6 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
getId());
}
/**
* Check the MediaDevice is be connected to transfer.
*
* @return true if the MediaDevice is be connected to transfer, false otherwise.
*/
public boolean isConnected() {
return mIsConnected;
}
/**
* Get name from MediaDevice.
*
@@ -87,8 +77,12 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
/**
* Transfer MediaDevice for media
*
* @return result of transfer media
*/
public void connect() {
public abstract boolean connect();
void setConnectedRecord() {
mConnectedRecord++;
ConnectionRecordManager.getInstance().setConnectionRecord(mContext, getId(),
mConnectedRecord);

View File

@@ -96,7 +96,7 @@ public abstract class MediaManager {
protected void dispatchDeviceListAdded() {
synchronized (mCallbacks) {
for (MediaDeviceCallback callback : mCallbacks) {
callback.onDeviceListAdded(mMediaDevices);
callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
}
}
}
@@ -109,10 +109,10 @@ public abstract class MediaManager {
}
}
protected void dispatchDeviceAttributesChanged() {
protected void dispatchConnectedDeviceChanged(String id) {
synchronized (mCallbacks) {
for (MediaDeviceCallback callback : mCallbacks) {
callback.onDeviceAttributesChanged();
callback.onConnectedDeviceChanged(id);
}
}
}
@@ -153,5 +153,12 @@ public abstract class MediaManager {
* Callback for notifying MediaDevice attributes is changed.
*/
void onDeviceAttributesChanged();
/**
* Callback for notifying connected MediaDevice is changed.
*
* @param id the id of MediaDevice
*/
void onConnectedDeviceChanged(String id);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2019 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;
/**
* Class to access MediaOutput constants.
*/
public class MediaOutputSliceConstants {
/**
* Key for the Media output setting.
*/
public static final String KEY_MEDIA_OUTPUT = "media_output";
/**
* Activity Action: Show a settings dialog containing {@link MediaDevice} to transfer media.
*/
public static final String ACTION_MEDIA_OUTPUT =
"com.android.settings.panel.action.MEDIA_OUTPUT";
/**
* An string extra specifying a media package name.
*/
public static final String EXTRA_PACKAGE_NAME =
"com.android.settings.panel.extra.PACKAGE_NAME";
}

View File

@@ -62,20 +62,22 @@ public class PhoneMediaDevice extends MediaDevice {
}
@Override
public void connect() {
public boolean connect() {
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
boolean isConnected = false;
if (hapProfile != null && a2dpProfile != null) {
mIsConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
super.connect();
isConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
setConnectedRecord();
}
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + mIsConnected);
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + isConnected);
return isConnected;
}
@Override
public void disconnect() {
//TODO(b/117129183): disconnected last select device
mIsConnected = false;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2019 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.BluetoothProfile;
import android.content.Context;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
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;
@RunWith(RobolectricTestRunner.class)
public class BluetoothMediaDeviceTest {
@Mock
private CachedBluetoothDevice mDevice;
private Context mContext;
private BluetoothMediaDevice mBluetoothMediaDevice;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
when(mDevice.isActiveDevice(BluetoothProfile.A2DP)).thenReturn(true);
when(mDevice.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true);
mBluetoothMediaDevice = new BluetoothMediaDevice(mContext, mDevice);
}
@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();
}
}

View File

@@ -0,0 +1,416 @@
/*
* Copyright 2019 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.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BluetoothMediaManagerTest {
private static final String TEST_ADDRESS = "11:22:33:44:55:66";
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private LocalBluetoothProfileManager mProfileManager;
@Mock
private A2dpProfile mA2dpProfile;
@Mock
private HearingAidProfile mHapProfile;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
@Mock
private BluetoothEventManager mEventManager;
@Mock
private MediaManager.MediaDeviceCallback mCallback;
private BluetoothMediaManager mMediaManager;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
when(mLocalBluetoothManager.getEventManager()).thenReturn(mEventManager);
mMediaManager = new BluetoothMediaManager(mContext, mLocalBluetoothManager, null);
}
@Test
public void startScan_haveA2dpProfileConnectedBluetoothDevice_shouldAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
when(cachedDevice.isConnected()).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
assertThat(mMediaManager.mMediaDevices).hasSize(devices.size());
}
@Test
public void startScan_haveA2dpProfileDisconnectedBluetoothDevice_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
when(cachedDevice.isConnected()).thenReturn(false);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
assertThat(mMediaManager.mMediaDevices).isEmpty();
}
@Test
public void startScan_noA2dpProfileBluetoothDevice_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
assertThat(mMediaManager.mMediaDevices).isEmpty();
}
@Test
public void startScan_haveHapProfileConnectedBluetoothDevice_shouldAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
when(mHapProfile.getConnectedDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
when(cachedDevice.isConnected()).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
assertThat(mMediaManager.mMediaDevices).hasSize(devices.size());
}
@Test
public void startScan_noHapProfileBluetoothDevice_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
when(mHapProfile.getConnectedDevices()).thenReturn(devices);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
assertThat(mMediaManager.mMediaDevices).isEmpty();
}
@Test
public void starScan_a2dpAndHapProfileNotReady_shouldRegisterCallback() {
final Collection<CachedBluetoothDevice> mDevices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
mDevices.add(cachedDevice);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
when(mA2dpProfile.isProfileReady()).thenReturn(false);
when(mHapProfile.isProfileReady()).thenReturn(false);
mMediaManager.startScan();
verify(mProfileManager).addServiceListener(mMediaManager);
}
@Test
public void starScan_a2dpAndHapProfileReady_shouldNotRegisterCallback() {
final Collection<CachedBluetoothDevice> mDevices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
mDevices.add(cachedDevice);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
when(mA2dpProfile.isProfileReady()).thenReturn(true);
when(mHapProfile.isProfileReady()).thenReturn(true);
mMediaManager.startScan();
verify(mProfileManager, never()).addServiceListener(mMediaManager);
}
@Test
public void onServiceConnected_a2dpAndHapProfileNotReady_doNothing() {
final Collection<CachedBluetoothDevice> mDevices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
mDevices.add(cachedDevice);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
when(mA2dpProfile.isProfileReady()).thenReturn(false);
when(mHapProfile.isProfileReady()).thenReturn(false);
mMediaManager.startScan();
mMediaManager.onServiceConnected();
verify(mProfileManager, never()).removeServiceListener(mMediaManager);
}
@Test
public void onDeviceAttributesChanged_a2dpAndHapProfileReady_shouldUnregisterCallback() {
final Collection<CachedBluetoothDevice> mDevices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
mDevices.add(cachedDevice);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
when(mA2dpProfile.isProfileReady()).thenReturn(true);
when(mHapProfile.isProfileReady()).thenReturn(true);
mMediaManager.startScan();
mMediaManager.onServiceConnected();
verify(mProfileManager).removeServiceListener(mMediaManager);
}
@Test
public void onBluetoothStateChanged_bluetoothStateIsOn_callOnDeviceListAdded() {
mMediaManager.registerCallback(mCallback);
mMediaManager.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
verify(mCallback).onDeviceListAdded(any());
}
@Test
public void onBluetoothStateChanged_bluetoothStateIsOff_callOnDeviceListRemoved() {
final BluetoothMediaDevice device1 = mock(BluetoothMediaDevice.class);
final BluetoothMediaDevice device2 = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(device1);
mMediaManager.mMediaDevices.add(device2);
mMediaManager.registerCallback(mCallback);
mMediaManager.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
assertThat(mMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceListRemoved(any());
}
@Test
public void onDeviceAdded_cachedDeviceIsConnected_callOnDeviceAdded() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.isConnectedHearingAidDevice()).thenReturn(true);
when(device.isConnectedA2dpDevice()).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.registerCallback(mCallback);
mMediaManager.onDeviceAdded(device);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
verify(mCallback).onDeviceAdded(any());
}
@Test
public void onDeviceAdded_cachedDeviceIsDisconnected_doNothing() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.isConnectedHearingAidDevice()).thenReturn(false);
when(device.isConnectedA2dpDevice()).thenReturn(false);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.registerCallback(mCallback);
mMediaManager.onDeviceAdded(device);
assertThat(mMediaManager.mMediaDevices).isEmpty();
verify(mCallback, never()).onDeviceAdded(any());
}
@Test
public void onDeviceDeleted_cachedDeviceIsConnected_doNothing() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
when(device.isConnectedHearingAidDevice()).thenReturn(true);
when(device.isConnectedA2dpDevice()).thenReturn(true);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
mMediaManager.registerCallback(mCallback);
mMediaManager.onDeviceDeleted(device);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
verify(mCallback, never()).onDeviceRemoved(any());
}
@Test
public void onDeviceDeleted_cachedDeviceIsDisconnected_callOnDeviceRemoved() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
when(device.isConnectedHearingAidDevice()).thenReturn(false);
when(device.isConnectedA2dpDevice()).thenReturn(false);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
mMediaManager.registerCallback(mCallback);
mMediaManager.onDeviceDeleted(device);
assertThat(mMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceRemoved(any());
}
@Test
public void onProfileConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.isConnectedHearingAidDevice()).thenReturn(true);
when(device.isConnectedA2dpDevice()).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.registerCallback(mCallback);
mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
verify(mCallback).onDeviceAdded(any());
}
@Test
public void onProfileConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
when(device.isConnectedHearingAidDevice()).thenReturn(false);
when(device.isConnectedA2dpDevice()).thenReturn(false);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
mMediaManager.registerCallback(mCallback);
mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
assertThat(mMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceRemoved(any());
}
@Test
public void onAclConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.isConnectedHearingAidDevice()).thenReturn(true);
when(device.isConnectedA2dpDevice()).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.registerCallback(mCallback);
mMediaManager.onAclConnectionStateChanged(device, 0);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
verify(mCallback).onDeviceAdded(any());
}
@Test
public void onAclConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
when(device.isConnectedHearingAidDevice()).thenReturn(false);
when(device.isConnectedA2dpDevice()).thenReturn(false);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
assertThat(mMediaManager.mMediaDevices).hasSize(1);
mMediaManager.registerCallback(mCallback);
mMediaManager.onAclConnectionStateChanged(device, 0);
assertThat(mMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceRemoved(any());
}
@Test
public void onActiveDeviceChanged_isHapProfile_callOnActiveDeviceChanged() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
mMediaManager.registerCallback(mCallback);
mMediaManager.onActiveDeviceChanged(device, BluetoothProfile.HEARING_AID);
verify(mCallback).onConnectedDeviceChanged(any());
}
@Test
public void onActiveDeviceChanged_isA2dpProfile_callOnActiveDeviceChanged() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
mMediaManager.registerCallback(mCallback);
mMediaManager.onActiveDeviceChanged(device, BluetoothProfile.A2DP);
verify(mCallback).onConnectedDeviceChanged(any());
}
@Test
public void onActiveDeviceChanged_isNotA2dpAndHapProfile_doNothing() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
mMediaManager.registerCallback(mCallback);
mMediaManager.onActiveDeviceChanged(device, BluetoothProfile.HEALTH);
verify(mCallback, never()).onConnectedDeviceChanged(any());
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2019 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.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;
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;
@RunWith(RobolectricTestRunner.class)
public class InfoMediaManagerTest {
private static final String TEST_PACKAGE_NAME = "com.test.packagename";
private static final String TEST_ID = "test_id";
@Mock
private MediaRouter mMediaRouter;
@Mock
private MediaRouteSelector mSelector;
private InfoMediaManager mInfoMediaManager;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mInfoMediaManager = new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null);
mInfoMediaManager.mMediaRouter = mMediaRouter;
mInfoMediaManager.mSelector = mSelector;
}
@Test
public void stopScan_shouldRemoveCallback() {
mInfoMediaManager.stopScan();
verify(mMediaRouter).removeCallback(mInfoMediaManager.mMediaRouterCallback);
}
@Test
public void startScan_shouldAddCallback() {
mInfoMediaManager.startScan();
verify(mMediaRouter).addCallback(mSelector, mInfoMediaManager.mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
@Test
public void onRouteAdded_mediaDeviceNotExistInList_addMediaDevice() {
final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
when(info.getId()).thenReturn(TEST_ID);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
mInfoMediaManager.mMediaRouterCallback.onRouteAdded(mMediaRouter, info);
final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
}
@Test
public void onRouteAdded_mediaDeviceExistInList_doNothing() {
final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
when(info.getId()).thenReturn(TEST_ID);
final InfoMediaDevice infoDevice = new InfoMediaDevice(mContext, info);
mInfoMediaManager.mMediaDevices.add(infoDevice);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
final int size = mInfoMediaManager.mMediaDevices.size();
assertThat(mediaDevice).isNotNull();
mInfoMediaManager.mMediaRouterCallback.onRouteAdded(mMediaRouter, info);
assertThat(mInfoMediaManager.mMediaDevices).hasSize(size);
}
@Test
public void onRouteRemoved_mediaDeviceExistInList_removeMediaDevice() {
final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
when(info.getId()).thenReturn(TEST_ID);
final InfoMediaDevice infoDevice = new InfoMediaDevice(mContext, info);
mInfoMediaManager.mMediaDevices.add(infoDevice);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNotNull();
assertThat(mInfoMediaManager.mMediaDevices).hasSize(1);
mInfoMediaManager.mMediaRouterCallback.onRouteRemoved(mMediaRouter, info);
assertThat(mInfoMediaManager.mMediaDevices).isEmpty();
}
@Test
public void onRouteRemoved_mediaDeviceNotExistInList_doNothing() {
final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
when(info.getId()).thenReturn(TEST_ID);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
final int size = mInfoMediaManager.mMediaDevices.size();
assertThat(mediaDevice).isNull();
mInfoMediaManager.mMediaRouterCallback.onRouteRemoved(mMediaRouter, info);
assertThat(mInfoMediaManager.mMediaDevices).hasSize(size);
}
}

View File

@@ -0,0 +1,369 @@
/*
* Copyright 2019 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.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
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;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class LocalMediaManagerTest {
private static final String TEST_DEVICE_ID_1 = "device_id_1";
private static final String TEST_DEVICE_ID_2 = "device_id_2";
private static final String TEST_DEVICE_ID_3 = "device_id_3";
private static final String TEST_CURRENT_DEVICE_ID = "currentDevice_id";
@Mock
private BluetoothMediaManager mBluetoothMediaManager;
@Mock
private InfoMediaManager mInfoMediaManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private LocalMediaManager.DeviceCallback mCallback;
@Mock
private HearingAidProfile mHapProfile;
@Mock
private A2dpProfile mA2dpProfile;
@Mock
private LocalBluetoothProfileManager mLocalProfileManager;
private Context mContext;
private LocalMediaManager mLocalMediaManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalProfileManager);
when(mLocalProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
mLocalMediaManager = new LocalMediaManager(mContext, mLocalBluetoothManager,
mBluetoothMediaManager, mInfoMediaManager);
}
@Test
public void startScan_mediaDevicesListShouldBeClear() {
final MediaDevice device = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(1);
mLocalMediaManager.startScan();
assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
}
@Test
public void connectDevice_deviceNotEqualCurrentConnectedDevice_connectDevice() {
final MediaDevice currentDevice = mock(MediaDevice.class);
final MediaDevice device = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(currentDevice);
mLocalMediaManager.mMediaDevices.add(device);
mLocalMediaManager.mCurrentConnectedDevice = currentDevice;
when(device.getId()).thenReturn(TEST_DEVICE_ID_1);
when(currentDevice.getId()).thenReturn(TEST_CURRENT_DEVICE_ID);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.connectDevice(device);
verify(currentDevice).disconnect();
verify(device).connect();
verify(mCallback).onSelectedDeviceStateChanged(any(),
eq(LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED));
}
@Test
public void getMediaDeviceById_idExist_shouldReturnMediaDevice() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
final MediaDevice device = mLocalMediaManager
.getMediaDeviceById(mLocalMediaManager.mMediaDevices, TEST_DEVICE_ID_2);
assertThat(device.getId()).isEqualTo(TEST_DEVICE_ID_2);
}
@Test
public void getMediaDeviceById_idNotExist_shouldReturnNull() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
final MediaDevice device = mLocalMediaManager
.getMediaDeviceById(mLocalMediaManager.mMediaDevices, TEST_CURRENT_DEVICE_ID);
assertThat(device).isNull();
}
@Test
public void onDeviceAdded_mediaDeviceAndPhoneDeviceNotExistInList_addBothDevice() {
final MediaDevice device = mock(MediaDevice.class);
assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceAdded(device);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceAdded_mediaDeviceNotExistAndPhoneDeviceExistInList_addMediaDevice() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceAdded(device2);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceAdded_mediaDeviceAndPhoneDeviceExistInList_doNothing() {
final MediaDevice device1 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceAdded(device1);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
verify(mCallback, never()).onDeviceListUpdate(any());
}
@Test
public void onDeviceListAdded_phoneDeviceNotExistInList_addPhoneDeviceAndDevicesList() {
final List<MediaDevice> devices = new ArrayList<>();
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
devices.add(device1);
devices.add(device2);
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceListAdded_phoneDeviceExistInList_addDeviceList() {
final List<MediaDevice> devices = new ArrayList<>();
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
final MediaDevice device3 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
devices.add(device1);
devices.add(device2);
mLocalMediaManager.mMediaDevices.add(device3);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
when(device3.getId()).thenReturn(TEST_DEVICE_ID_3);
when(mLocalMediaManager.mPhoneDevice.getId()).thenReturn("test_phone_id");
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(4);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceRemoved_phoneDeviceIsLastDeviceAfterRemoveMediaDevice_removeBothDevice() {
final MediaDevice device1 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceRemoved(device1);
assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceRemoved_phoneDeviceNotLastDeviceAfterRemoveMediaDevice_removeMediaDevice() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceRemoved(device2);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceRemoved_removeMediaDeviceNotInList_doNothing() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceRemoved(device1);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
verify(mCallback, never()).onDeviceListUpdate(any());
}
@Test
public void onDeviceListRemoved_phoneDeviceIsLastDeviceAfterRemoveDeviceList_removeAll() {
final List<MediaDevice> devices = new ArrayList<>();
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
devices.add(device1);
devices.add(device2);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceListRemoved(devices);
assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceListRemoved_phoneDeviceNotLastDeviceAfterRemoveDeviceList_removeList() {
final List<MediaDevice> devices = new ArrayList<>();
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
final MediaDevice device3 = mock(MediaDevice.class);
mLocalMediaManager.mPhoneDevice = mock(PhoneMediaDevice.class);
devices.add(device1);
devices.add(device3);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mMediaDevices.add(device3);
mLocalMediaManager.mMediaDevices.add(mLocalMediaManager.mPhoneDevice);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(4);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceListRemoved(devices);
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onDeviceAttributesChanged_shouldDispatchDeviceListUpdate() {
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onConnectedDeviceChanged_connectedAndCurrentDeviceAreDifferent_notifyThemChanged() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mCurrentConnectedDevice = device1;
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_2);
assertThat(mLocalMediaManager.getCurrentConnectedDevice()).isEqualTo(device2);
verify(mCallback).onDeviceListUpdate(any());
}
@Test
public void onConnectedDeviceChanged_connectedAndCurrentDeviceAreSame_doNothing() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
mLocalMediaManager.mMediaDevices.add(device1);
mLocalMediaManager.mMediaDevices.add(device2);
mLocalMediaManager.mCurrentConnectedDevice = device1;
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_1);
verify(mCallback, never()).onDeviceListUpdate(any());
}
}

View File

@@ -25,8 +25,11 @@ 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.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.Before;
import org.junit.Test;
@@ -78,6 +81,14 @@ public class MediaDeviceTest {
private MediaRouter.RouteInfo mRouteInfo2;
@Mock
private MediaRouter.RouteInfo mRouteInfo3;
@Mock
private LocalBluetoothProfileManager mProfileManager;
@Mock
private HearingAidProfile mHapProfile;
@Mock
private A2dpProfile mA2dpProfile;
@Mock
private BluetoothDevice mDevice;
private BluetoothMediaDevice mBluetoothMediaDevice1;
private BluetoothMediaDevice mBluetoothMediaDevice2;
@@ -109,6 +120,10 @@ public class MediaDeviceTest {
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(mProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
when(mA2dpProfile.getActiveDevice()).thenReturn(mDevice);
mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1);
mBluetoothMediaDevice2 = new BluetoothMediaDevice(mContext, mCachedDevice2);

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2019 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 androidx.mediarouter.media.MediaRouter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
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;
@RunWith(RobolectricTestRunner.class)
public class MediaDeviceUtilsTest {
private static final String TEST_ADDRESS = "11:22:33:44:55:66";
private static final String TEST_ROUTE_ID = "test_route_id";
@Mock
private CachedBluetoothDevice mDevice;
@Mock
private MediaRouter.RouteInfo mRouteInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getId_returnBluetoothDeviceAddress() {
when(mDevice.getAddress()).thenReturn(TEST_ADDRESS);
final String id = MediaDeviceUtils.getId(mDevice);
assertThat(id).isEqualTo(TEST_ADDRESS);
}
@Test
public void getId_returnRouteInfoId() {
when(mRouteInfo.getId()).thenReturn(TEST_ROUTE_ID);
final String id = MediaDeviceUtils.getId(mRouteInfo);
assertThat(id).isEqualTo(TEST_ROUTE_ID);
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2019 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.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
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;
@RunWith(RobolectricTestRunner.class)
public class MediaManagerTest {
private static final String TEST_ID = "test_id";
@Mock
private MediaManager.MediaDeviceCallback mCallback;
@Mock
private MediaDevice mDevice;
private MediaManager mMediaManager;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
when(mDevice.getId()).thenReturn(TEST_ID);
mMediaManager = new MediaManager(mContext, null) {
@Override
public void startScan() {
}
@Override
public void stopScan() {
}
};
}
@Test
public void dispatchDeviceAdded_registerCallback_shouldDispatchCallback() {
mMediaManager.registerCallback(mCallback);
mMediaManager.dispatchDeviceAdded(mDevice);
verify(mCallback).onDeviceAdded(mDevice);
}
@Test
public void dispatchDeviceRemoved_registerCallback_shouldDispatchCallback() {
mMediaManager.registerCallback(mCallback);
mMediaManager.dispatchDeviceRemoved(mDevice);
verify(mCallback).onDeviceRemoved(mDevice);
}
@Test
public void dispatchDeviceListAdded_registerCallback_shouldDispatchCallback() {
mMediaManager.registerCallback(mCallback);
mMediaManager.dispatchDeviceListAdded();
verify(mCallback).onDeviceListAdded(any());
}
@Test
public void dispatchDeviceListRemoved_registerCallback_shouldDispatchCallback() {
mMediaManager.registerCallback(mCallback);
mMediaManager.dispatchDeviceListRemoved(mMediaManager.mMediaDevices);
verify(mCallback).onDeviceListRemoved(mMediaManager.mMediaDevices);
}
@Test
public void dispatchActiveDeviceChanged_registerCallback_shouldDispatchCallback() {
mMediaManager.registerCallback(mCallback);
mMediaManager.dispatchConnectedDeviceChanged(TEST_ID);
verify(mCallback).onConnectedDeviceChanged(TEST_ID);
}
@Test
public void findMediaDevice_idExist_shouldReturnMediaDevice() {
mMediaManager.mMediaDevices.add(mDevice);
final MediaDevice device = mMediaManager.findMediaDevice(TEST_ID);
assertThat(device.getId()).isEqualTo(mDevice.getId());
}
@Test
public void findMediaDevice_idNotExist_shouldReturnNull() {
mMediaManager.mMediaDevices.add(mDevice);
final MediaDevice device = mMediaManager.findMediaDevice("123");
assertThat(device).isNull();
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2019 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.BluetoothDevice;
import android.content.Context;
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;
@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;
@Before
public void setUp() {
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);
}
@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();
}
}