diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 24d7011d9a354..c05915685e838 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -74,6 +74,7 @@ public class A2dpProfile implements LocalBluetoothProfile { device.refresh(); } mIsProfileReady=true; + mProfileManager.callServiceConnectedListeners(); } public void onServiceDisconnected(int profile) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java index 577d98d934052..77dfbe9944888 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java @@ -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) { diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java index 959f9b24133cf..a5c6f0c28e78e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java @@ -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; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java index ab1cca0084c45..fa2dd887bd3d1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java @@ -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 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 devicesHiSyncIds = new ArrayList<>(); final List 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 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() { + + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java index 21a81e03037ae..04f70cc676d98 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java @@ -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 } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 6907238082fcd..bc8e2c35291d3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -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"; diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index c9479d44f7919..44d945a9ee0e2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -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 mCallbacks = new ArrayList<>(); - private final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback(); + @VisibleForTesting + final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback(); private Context mContext; - private List mMediaDevices = new ArrayList<>(); private BluetoothMediaManager mBluetoothMediaManager; private InfoMediaManager mInfoMediaManager; - private LocalBluetoothManager mLocalBluetoothManager; - private MediaDevice mLastConnectedDevice; - private MediaDevice mPhoneDevice; + + @VisibleForTesting + List 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 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(); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java index 33b621cb28da0..f35c30edd16af 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java @@ -41,7 +41,6 @@ public abstract class MediaDevice implements Comparable { private int mConnectedRecord; - protected boolean mIsConnected = false; protected Context mContext; protected int mType; @@ -56,15 +55,6 @@ public abstract class MediaDevice implements Comparable { 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 { /** * 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); diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java index 72b6b09d637ea..2c3a96cafa562 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java @@ -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); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java new file mode 100644 index 0000000000000..e600cb892c44c --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java @@ -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"; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java index e0f3c2ff76923..c808214dbcf4f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java @@ -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; } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java new file mode 100644 index 0000000000000..e5d1b18177263 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java @@ -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(); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java new file mode 100644 index 0000000000000..a20e22bb4f26a --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java @@ -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 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 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 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 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 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 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 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 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 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()); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java new file mode 100644 index 0000000000000..b11cf69b04f46 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java @@ -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); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java new file mode 100644 index 0000000000000..355681401b9a8 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java @@ -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 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 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 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 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()); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java index 9bbdd0102fad6..fc514f0ac25cb 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java @@ -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); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java new file mode 100644 index 0000000000000..6e29e137c9f23 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java @@ -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); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java new file mode 100644 index 0000000000000..98eccb506f63e --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java @@ -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(); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java new file mode 100644 index 0000000000000..5ba33f569e441 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java @@ -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(); + } +}