Merge "Add Bluetooth callback for device connection state changed" into pi-dev

am: 15aa546a37

Change-Id: I110340139c1455dfe43ce4e5688ef40ee6118698
This commit is contained in:
Ryan Lin
2018-05-11 13:20:33 -07:00
committed by android-build-merger
20 changed files with 274 additions and 6 deletions

View File

@@ -94,6 +94,11 @@ public class A2dpProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.A2DP;
}
A2dpProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -85,6 +85,11 @@ final class A2dpSinkProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.A2DP_SINK;
}
A2dpSinkProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -30,4 +30,7 @@ public interface BluetoothCallback {
void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state);
void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile);
void onAudioModeChanged();
default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
int state, int bluetoothProfile) {
}
}

View File

@@ -497,4 +497,13 @@ public class BluetoothEventManager {
}
}
}
void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state,
int bluetoothProfile) {
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
}
}
}
}

View File

@@ -92,6 +92,11 @@ public class HeadsetProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.HEADSET;
}
HeadsetProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -93,6 +93,11 @@ public class HearingAidProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.HEARING_AID;
}
HearingAidProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -92,6 +92,11 @@ final class HfpClientProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.HEADSET_CLIENT;
}
HfpClientProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -97,6 +97,11 @@ public class HidDeviceProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.HID_DEVICE;
}
@Override
public boolean isConnectable() {
return true;

View File

@@ -80,6 +80,11 @@ public class HidProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.HID_HOST;
}
HidProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -49,6 +49,8 @@ public interface LocalBluetoothProfile {
boolean isProfileReady();
int getProfileId();
/** Display order for device profile settings. */
int getOrdinal();

View File

@@ -375,6 +375,8 @@ public class LocalBluetoothProfileManager {
}
}
mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
mProfile.getProfileId());
cachedDevice.onProfileStateChanged(mProfile, newState);
cachedDevice.refresh();
}

View File

@@ -94,6 +94,11 @@ public final class MapClientProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.MAP_CLIENT;
}
MapClientProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -93,6 +93,11 @@ public class MapProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.MAP;
}
MapProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -67,6 +67,11 @@ final class OppProfile implements LocalBluetoothProfile {
return true;
}
@Override
public int getProfileId() {
return BluetoothProfile.OPP;
}
public String toString() {
return NAME;
}

View File

@@ -69,6 +69,11 @@ public class PanProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.PAN;
}
PanProfile(Context context, LocalBluetoothAdapter adapter) {
mLocalAdapter = adapter;
mLocalAdapter.getProfileProxy(context, new PanServiceListener(),

View File

@@ -100,6 +100,11 @@ public final class PbapClientProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.PBAP_CLIENT;
}
PbapClientProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -71,6 +71,11 @@ public class PbapServerProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.PBAP;
}
PbapServerProfile(Context context) {
BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener());
}

View File

@@ -91,6 +91,11 @@ final class SapProfile implements LocalBluetoothProfile {
return mIsProfileReady;
}
@Override
public int getProfileId() {
return BluetoothProfile.SAP;
}
SapProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {

View File

@@ -15,13 +15,17 @@
*/
package com.android.settingslib.bluetooth;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +43,8 @@ public class BluetoothEventManagerTest {
private CachedBluetoothDeviceManager mCachedDeviceManager;
@Mock
private BluetoothCallback mBluetoothCallback;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
private Context mContext;
private Intent mIntent;
@@ -78,4 +84,19 @@ public class BluetoothEventManagerTest {
verify(mBluetoothCallback).onAudioModeChanged();
}
/**
* dispatchProfileConnectionStateChanged should dispatch to onProfileConnectionStateChanged
* callback.
*/
@Test
public void dispatchProfileConnectionStateChanged_registerCallback_shouldDispatchCallback() {
mBluetoothEventManager.registerCallback(mBluetoothCallback);
mBluetoothEventManager.dispatchProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
}
}

View File

@@ -18,12 +18,23 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.content.Intent;
import android.os.ParcelUuid;
import java.util.ArrayList;
@@ -41,18 +52,29 @@ import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(resourceDir = "../../res")
public class LocalBluetoothProfileManagerTest {
@Mock private CachedBluetoothDeviceManager mDeviceManager;
@Mock private BluetoothEventManager mEventManager;
@Mock private LocalBluetoothAdapter mAdapter;
@Mock private BluetoothDevice mDevice;
@Mock
private CachedBluetoothDeviceManager mDeviceManager;
@Mock
private BluetoothEventManager mEventManager;
@Mock
private LocalBluetoothAdapter mAdapter;
@Mock
private BluetoothDevice mDevice;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
private Context mContext;
private LocalBluetoothProfileManager mProfileManager;
private Intent mIntent;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mEventManager = spy(new BluetoothEventManager(mAdapter,
mDeviceManager, mContext));
when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
}
/**
@@ -74,7 +96,7 @@ public class LocalBluetoothProfileManagerTest {
public void updateLocalProfiles_addA2dpToLocalProfiles() {
mProfileManager =
new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[] {BluetoothUuid.AudioSource});
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
assertThat(mProfileManager.getA2dpProfile()).isNull();
assertThat(mProfileManager.getHeadsetProfile()).isNull();
@@ -104,4 +126,143 @@ public class LocalBluetoothProfileManagerTest {
assertThat(profiles.contains(mProfileManager.getHidProfile())).isTrue();
assertThat(removedProfiles.contains(mProfileManager.getHidProfile())).isFalse();
}
/**
* Verify BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
* profile connection state changed callback
*/
@Test
public void stateChangedHandler_receiveA2dpConnectionStateChanged_shouldDispatchCallback() {
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mEventManager).dispatchProfileConnectionStateChanged(
mCachedBluetoothDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
}
/**
* Verify BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
* profile connection state changed callback
*/
@Test
public void stateChangedHandler_receiveHeadsetConnectionStateChanged_shouldDispatchCallback() {
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.Handsfree_AG});
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEADSET);
}
/**
* Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
* profile connection state changed callback
*/
@Test
public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() {
ArrayList<Integer> supportProfiles = new ArrayList<>();
supportProfiles.add(BluetoothProfile.HEARING_AID);
when(mAdapter.getSupportedProfiles()).thenReturn(supportProfiles);
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.HearingAid});
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
}
/**
* Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuid will dispatch to
* profile connection state changed callback
*/
@Test
public void stateChangedHandler_receivePanConnectionStateChanged_shouldNotDispatchCallback() {
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mEventManager).dispatchProfileConnectionStateChanged(
any(CachedBluetoothDevice.class), anyInt(), anyInt());
}
/**
* Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent without uuids will not dispatch to
* handler and refresh CachedBluetoothDevice
*/
@Test
public void stateChangedHandler_receivePanConnectionStateChangedWithoutUuid_shouldNotRefresh() {
when(mAdapter.getUuids()).thenReturn(null);
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mCachedBluetoothDevice).refresh();
}
/**
* Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to
* handler and refresh CachedBluetoothDevice
*/
@Test
public void stateChangedHandler_receivePanConnectionStateChangedWithUuids_shouldRefresh() {
when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
mEventManager);
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
mContext.sendBroadcast(mIntent);
verify(mCachedBluetoothDevice).refresh();
}
}