Loading android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java +20 −8 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.provider.CallLog; import android.sysprop.BluetoothProperties; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; Loading @@ -41,6 +42,7 @@ import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.hfpclient.HfpClientConnectionService; import com.android.bluetooth.sdp.SdpManager; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; import java.util.ArrayList; Loading Loading @@ -69,10 +71,12 @@ public class PbapClientService extends ProfileService { // MAXIMUM_DEVICES set to 10 to prevent an excessive number of simultaneous devices. private static final int MAXIMUM_DEVICES = 10; private Map<BluetoothDevice, PbapClientStateMachine> mPbapClientStateMachineMap = @VisibleForTesting Map<BluetoothDevice, PbapClientStateMachine> mPbapClientStateMachineMap = new ConcurrentHashMap<>(); private static PbapClientService sPbapClientService; private PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver(); @VisibleForTesting PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver(); private int mSdpHandle = -1; private DatabaseManager mDatabaseManager; Loading Loading @@ -162,6 +166,7 @@ public class PbapClientService extends ProfileService { for (PbapClientStateMachine pbapClientStateMachine : mPbapClientStateMachineMap.values()) { pbapClientStateMachine.doQuit(); } mPbapClientStateMachineMap.clear(); cleanupAuthenicationService(); setComponentAvailable(AUTHENTICATOR_SERVICE, false); return true; Loading Loading @@ -243,7 +248,8 @@ public class PbapClientService extends ProfileService { + CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME + "=?"; String[] selectionArgs = new String[]{accountName, componentName.flattenToString()}; try { getContentResolver().delete(CallLog.Calls.CONTENT_URI, selectionFilter, selectionArgs); BluetoothMethodProxy.getInstance().contentResolverDelete(getContentResolver(), CallLog.Calls.CONTENT_URI, selectionFilter, selectionArgs); } catch (IllegalArgumentException e) { Log.w(TAG, "Call Logs could not be deleted, they may not exist yet."); } Loading Loading @@ -278,7 +284,8 @@ public class PbapClientService extends ProfileService { } private class PbapBroadcastReceiver extends BroadcastReceiver { @VisibleForTesting class PbapBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Loading Loading @@ -314,7 +321,8 @@ public class PbapClientService extends ProfileService { /** * Handler for incoming service calls */ private static class BluetoothPbapClientBinder extends IBluetoothPbapClient.Stub @VisibleForTesting static class BluetoothPbapClientBinder extends IBluetoothPbapClient.Stub implements IProfileServiceBinder { private PbapClientService mService; Loading @@ -329,6 +337,9 @@ public class PbapClientService extends ProfileService { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private PbapClientService getService(AttributionSource source) { if (Utils.isInstrumentationTestMode()) { return mService; } if (!Utils.checkServiceAvailable(mService, TAG) || !Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG) || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) { Loading Loading @@ -461,7 +472,8 @@ public class PbapClientService extends ProfileService { return sPbapClientService; } private static synchronized void setPbapClientService(PbapClientService instance) { @VisibleForTesting static synchronized void setPbapClientService(PbapClientService instance) { if (VDBG) { Log.v(TAG, "setPbapClientService(): set to: " + instance); } Loading Loading @@ -511,7 +523,6 @@ public class PbapClientService extends ProfileService { if (pbapClientStateMachine != null) { pbapClientStateMachine.disconnect(device); return true; } else { Log.w(TAG, "disconnect() called on unconnected device."); return false; Loading @@ -523,7 +534,8 @@ public class PbapClientService extends ProfileService { return getDevicesMatchingConnectionStates(desiredStates); } private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @VisibleForTesting List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(0); for (Map.Entry<BluetoothDevice, PbapClientStateMachine> stateMachineEntry : mPbapClientStateMachineMap Loading android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ import com.android.internal.util.StateMachine; import java.util.ArrayList; import java.util.List; final class PbapClientStateMachine extends StateMachine { class PbapClientStateMachine extends StateMachine { private static final boolean DBG = false; //Utils.DBG; private static final String TAG = "PbapClientStateMachine"; Loading android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java +271 −1 Original line number Diff line number Diff line Loading @@ -15,21 +15,36 @@ */ package com.android.bluetooth.pbapclient; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.provider.CallLog; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.After; import org.junit.Assert; Loading @@ -38,15 +53,19 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @MediumTest @RunWith(AndroidJUnit4.class) public class PbapClientServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private PbapClientService mService = null; private BluetoothAdapter mAdapter = null; private Context mTargetContext; private BluetoothDevice mRemoteDevice; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -69,6 +88,7 @@ public class PbapClientServiceTest { // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); Assert.assertNotNull(mAdapter); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); } @After Loading @@ -80,10 +100,260 @@ public class PbapClientServiceTest { mService = PbapClientService.getPbapClientService(); Assert.assertNull(mService); TestUtils.clearAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(null); } @Test public void testInitialize() { Assert.assertNotNull(PbapClientService.getPbapClientService()); } @Test public void testSetPbapClientService_withNull() { PbapClientService.setPbapClientService(null); assertThat(PbapClientService.getPbapClientService()).isNull(); } @Test public void dump_callsStateMachineDump() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); StringBuilder builder = new StringBuilder(); mService.dump(builder); verify(sm).dump(builder); } @Test public void testSetConnectionPolicy_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.setConnectionPolicy( null, BluetoothProfile.CONNECTION_POLICY_ALLOWED)); } @Test public void testSetConnectionPolicy() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_UNKNOWN; when(mDatabaseManager.setProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT, connectionPolicy)).thenReturn(true); assertThat(mService.setConnectionPolicy(mRemoteDevice, connectionPolicy)).isTrue(); } @Test public void testGetConnectionPolicy_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.getConnectionPolicy(null)); } @Test public void testGetConnectionPolicy() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.getConnectionPolicy(mRemoteDevice)).isEqualTo(connectionPolicy); } @Test public void testConnect_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.connect(null)); } @Test public void testConnect_whenPolicyIsForbidden_returnsFalse() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.connect(mRemoteDevice)).isFalse(); } @Test public void testConnect_whenPolicyIsAllowed_returnsTrue() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.connect(mRemoteDevice)).isTrue(); } @Test public void testDisconnect_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.disconnect(null)); } @Test public void testDisconnect_whenNotConnected_returnsFalse() { assertThat(mService.disconnect(mRemoteDevice)).isFalse(); } @Test public void testDisconnect_whenConnected_returnsTrue() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); assertThat(mService.disconnect(mRemoteDevice)).isTrue(); verify(sm).disconnect(mRemoteDevice); } @Test public void testGetConnectionState_whenNotConnected() { assertThat(mService.getConnectionState(mRemoteDevice)) .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } @Test public void cleanUpDevice() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); mService.cleanupDevice(mRemoteDevice); assertThat(mService.mPbapClientStateMachineMap).doesNotContainKey(mRemoteDevice); } @Test public void getConnectedDevices() { int connectionState = BluetoothProfile.STATE_CONNECTED; PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState()).thenReturn(connectionState); assertThat(mService.getConnectedDevices()).contains(mRemoteDevice); } @Test public void binder_connect_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.connect(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).connect(mRemoteDevice); } @Test public void binder_disconnect_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.disconnect(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).disconnect(mRemoteDevice); } @Test public void binder_getConnectedDevices_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectedDevices(null, SynchronousResultReceiver.get()); verify(mockService).getConnectedDevices(); } @Test public void binder_getDevicesMatchingConnectionStates_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); int[] states = new int[] {BluetoothProfile.STATE_CONNECTED}; binder.getDevicesMatchingConnectionStates(states, null, SynchronousResultReceiver.get()); verify(mockService).getDevicesMatchingConnectionStates(states); } @Test public void binder_getConnectionState_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectionState(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).getConnectionState(mRemoteDevice); } @Test public void binder_setConnectionPolicy_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; binder.setConnectionPolicy(mRemoteDevice, connectionPolicy, null, SynchronousResultReceiver.get()); verify(mockService).setConnectionPolicy(mRemoteDevice, connectionPolicy); } @Test public void binder_getConnectionPolicy_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectionPolicy(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).getConnectionPolicy(mRemoteDevice); } @Test public void binder_cleanUp_doesNotCrash() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.cleanup(); } @Test public void broadcastReceiver_withActionAclDisconnected_callsDisconnect() { int connectionState = BluetoothProfile.STATE_CONNECTED; PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState(mRemoteDevice)).thenReturn(connectionState); Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); mService.mPbapBroadcastReceiver.onReceive(mService, intent); verify(sm).disconnect(mRemoteDevice); } @Test public void broadcastReceiver_withActionUserUnlocked_callsTryDownloadIfConnected() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); mService.mPbapBroadcastReceiver.onReceive(mService, intent); verify(sm).tryDownloadIfConnected(); } @Test public void broadcastReceiver_withActionHeadsetClientConnectionStateChanged() { BluetoothMethodProxy methodProxy = spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(methodProxy); Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mService.mPbapBroadcastReceiver.onReceive(mService, intent); ArgumentCaptor<Object> selectionArgsCaptor = ArgumentCaptor.forClass(Object.class); verify(methodProxy).contentResolverDelete(any(), eq(CallLog.Calls.CONTENT_URI), any(), (String[]) selectionArgsCaptor.capture()); assertThat(((String[]) selectionArgsCaptor.getValue())[0]) .isEqualTo(mRemoteDevice.getAddress()); } } Loading
android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java +20 −8 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.provider.CallLog; import android.sysprop.BluetoothProperties; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; Loading @@ -41,6 +42,7 @@ import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.hfpclient.HfpClientConnectionService; import com.android.bluetooth.sdp.SdpManager; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; import java.util.ArrayList; Loading Loading @@ -69,10 +71,12 @@ public class PbapClientService extends ProfileService { // MAXIMUM_DEVICES set to 10 to prevent an excessive number of simultaneous devices. private static final int MAXIMUM_DEVICES = 10; private Map<BluetoothDevice, PbapClientStateMachine> mPbapClientStateMachineMap = @VisibleForTesting Map<BluetoothDevice, PbapClientStateMachine> mPbapClientStateMachineMap = new ConcurrentHashMap<>(); private static PbapClientService sPbapClientService; private PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver(); @VisibleForTesting PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver(); private int mSdpHandle = -1; private DatabaseManager mDatabaseManager; Loading Loading @@ -162,6 +166,7 @@ public class PbapClientService extends ProfileService { for (PbapClientStateMachine pbapClientStateMachine : mPbapClientStateMachineMap.values()) { pbapClientStateMachine.doQuit(); } mPbapClientStateMachineMap.clear(); cleanupAuthenicationService(); setComponentAvailable(AUTHENTICATOR_SERVICE, false); return true; Loading Loading @@ -243,7 +248,8 @@ public class PbapClientService extends ProfileService { + CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME + "=?"; String[] selectionArgs = new String[]{accountName, componentName.flattenToString()}; try { getContentResolver().delete(CallLog.Calls.CONTENT_URI, selectionFilter, selectionArgs); BluetoothMethodProxy.getInstance().contentResolverDelete(getContentResolver(), CallLog.Calls.CONTENT_URI, selectionFilter, selectionArgs); } catch (IllegalArgumentException e) { Log.w(TAG, "Call Logs could not be deleted, they may not exist yet."); } Loading Loading @@ -278,7 +284,8 @@ public class PbapClientService extends ProfileService { } private class PbapBroadcastReceiver extends BroadcastReceiver { @VisibleForTesting class PbapBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Loading Loading @@ -314,7 +321,8 @@ public class PbapClientService extends ProfileService { /** * Handler for incoming service calls */ private static class BluetoothPbapClientBinder extends IBluetoothPbapClient.Stub @VisibleForTesting static class BluetoothPbapClientBinder extends IBluetoothPbapClient.Stub implements IProfileServiceBinder { private PbapClientService mService; Loading @@ -329,6 +337,9 @@ public class PbapClientService extends ProfileService { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private PbapClientService getService(AttributionSource source) { if (Utils.isInstrumentationTestMode()) { return mService; } if (!Utils.checkServiceAvailable(mService, TAG) || !Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG) || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) { Loading Loading @@ -461,7 +472,8 @@ public class PbapClientService extends ProfileService { return sPbapClientService; } private static synchronized void setPbapClientService(PbapClientService instance) { @VisibleForTesting static synchronized void setPbapClientService(PbapClientService instance) { if (VDBG) { Log.v(TAG, "setPbapClientService(): set to: " + instance); } Loading Loading @@ -511,7 +523,6 @@ public class PbapClientService extends ProfileService { if (pbapClientStateMachine != null) { pbapClientStateMachine.disconnect(device); return true; } else { Log.w(TAG, "disconnect() called on unconnected device."); return false; Loading @@ -523,7 +534,8 @@ public class PbapClientService extends ProfileService { return getDevicesMatchingConnectionStates(desiredStates); } private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @VisibleForTesting List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(0); for (Map.Entry<BluetoothDevice, PbapClientStateMachine> stateMachineEntry : mPbapClientStateMachineMap Loading
android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ import com.android.internal.util.StateMachine; import java.util.ArrayList; import java.util.List; final class PbapClientStateMachine extends StateMachine { class PbapClientStateMachine extends StateMachine { private static final boolean DBG = false; //Utils.DBG; private static final String TAG = "PbapClientStateMachine"; Loading
android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java +271 −1 Original line number Diff line number Diff line Loading @@ -15,21 +15,36 @@ */ package com.android.bluetooth.pbapclient; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.provider.CallLog; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.After; import org.junit.Assert; Loading @@ -38,15 +53,19 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @MediumTest @RunWith(AndroidJUnit4.class) public class PbapClientServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private PbapClientService mService = null; private BluetoothAdapter mAdapter = null; private Context mTargetContext; private BluetoothDevice mRemoteDevice; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -69,6 +88,7 @@ public class PbapClientServiceTest { // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); Assert.assertNotNull(mAdapter); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); } @After Loading @@ -80,10 +100,260 @@ public class PbapClientServiceTest { mService = PbapClientService.getPbapClientService(); Assert.assertNull(mService); TestUtils.clearAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(null); } @Test public void testInitialize() { Assert.assertNotNull(PbapClientService.getPbapClientService()); } @Test public void testSetPbapClientService_withNull() { PbapClientService.setPbapClientService(null); assertThat(PbapClientService.getPbapClientService()).isNull(); } @Test public void dump_callsStateMachineDump() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); StringBuilder builder = new StringBuilder(); mService.dump(builder); verify(sm).dump(builder); } @Test public void testSetConnectionPolicy_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.setConnectionPolicy( null, BluetoothProfile.CONNECTION_POLICY_ALLOWED)); } @Test public void testSetConnectionPolicy() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_UNKNOWN; when(mDatabaseManager.setProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT, connectionPolicy)).thenReturn(true); assertThat(mService.setConnectionPolicy(mRemoteDevice, connectionPolicy)).isTrue(); } @Test public void testGetConnectionPolicy_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.getConnectionPolicy(null)); } @Test public void testGetConnectionPolicy() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.getConnectionPolicy(mRemoteDevice)).isEqualTo(connectionPolicy); } @Test public void testConnect_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.connect(null)); } @Test public void testConnect_whenPolicyIsForbidden_returnsFalse() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.connect(mRemoteDevice)).isFalse(); } @Test public void testConnect_whenPolicyIsAllowed_returnsTrue() { int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; when(mDatabaseManager.getProfileConnectionPolicy( mRemoteDevice, BluetoothProfile.PBAP_CLIENT)).thenReturn(connectionPolicy); assertThat(mService.connect(mRemoteDevice)).isTrue(); } @Test public void testDisconnect_withNullDevice_throwsIAE() { assertThrows(IllegalArgumentException.class, () -> mService.disconnect(null)); } @Test public void testDisconnect_whenNotConnected_returnsFalse() { assertThat(mService.disconnect(mRemoteDevice)).isFalse(); } @Test public void testDisconnect_whenConnected_returnsTrue() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); assertThat(mService.disconnect(mRemoteDevice)).isTrue(); verify(sm).disconnect(mRemoteDevice); } @Test public void testGetConnectionState_whenNotConnected() { assertThat(mService.getConnectionState(mRemoteDevice)) .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } @Test public void cleanUpDevice() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); mService.cleanupDevice(mRemoteDevice); assertThat(mService.mPbapClientStateMachineMap).doesNotContainKey(mRemoteDevice); } @Test public void getConnectedDevices() { int connectionState = BluetoothProfile.STATE_CONNECTED; PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState()).thenReturn(connectionState); assertThat(mService.getConnectedDevices()).contains(mRemoteDevice); } @Test public void binder_connect_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.connect(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).connect(mRemoteDevice); } @Test public void binder_disconnect_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.disconnect(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).disconnect(mRemoteDevice); } @Test public void binder_getConnectedDevices_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectedDevices(null, SynchronousResultReceiver.get()); verify(mockService).getConnectedDevices(); } @Test public void binder_getDevicesMatchingConnectionStates_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); int[] states = new int[] {BluetoothProfile.STATE_CONNECTED}; binder.getDevicesMatchingConnectionStates(states, null, SynchronousResultReceiver.get()); verify(mockService).getDevicesMatchingConnectionStates(states); } @Test public void binder_getConnectionState_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectionState(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).getConnectionState(mRemoteDevice); } @Test public void binder_setConnectionPolicy_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; binder.setConnectionPolicy(mRemoteDevice, connectionPolicy, null, SynchronousResultReceiver.get()); verify(mockService).setConnectionPolicy(mRemoteDevice, connectionPolicy); } @Test public void binder_getConnectionPolicy_callsServiceMethod() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.getConnectionPolicy(mRemoteDevice, null, SynchronousResultReceiver.get()); verify(mockService).getConnectionPolicy(mRemoteDevice); } @Test public void binder_cleanUp_doesNotCrash() { PbapClientService mockService = mock(PbapClientService.class); PbapClientService.BluetoothPbapClientBinder binder = new PbapClientService.BluetoothPbapClientBinder(mockService); binder.cleanup(); } @Test public void broadcastReceiver_withActionAclDisconnected_callsDisconnect() { int connectionState = BluetoothProfile.STATE_CONNECTED; PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState(mRemoteDevice)).thenReturn(connectionState); Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); mService.mPbapBroadcastReceiver.onReceive(mService, intent); verify(sm).disconnect(mRemoteDevice); } @Test public void broadcastReceiver_withActionUserUnlocked_callsTryDownloadIfConnected() { PbapClientStateMachine sm = mock(PbapClientStateMachine.class); mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm); Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); mService.mPbapBroadcastReceiver.onReceive(mService, intent); verify(sm).tryDownloadIfConnected(); } @Test public void broadcastReceiver_withActionHeadsetClientConnectionStateChanged() { BluetoothMethodProxy methodProxy = spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(methodProxy); Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mService.mPbapBroadcastReceiver.onReceive(mService, intent); ArgumentCaptor<Object> selectionArgsCaptor = ArgumentCaptor.forClass(Object.class); verify(methodProxy).contentResolverDelete(any(), eq(CallLog.Calls.CONTENT_URI), any(), (String[]) selectionArgsCaptor.capture()); assertThat(((String[]) selectionArgsCaptor.getValue())[0]) .isEqualTo(mRemoteDevice.getAddress()); } }