Loading android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +6 −10 Original line number Diff line number Diff line Loading @@ -166,7 +166,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect private PbapHandler mSessionStatusHandler; private HandlerThread mHandlerThread; private final HashMap<BluetoothDevice, PbapStateMachine> mPbapStateMachineMap = new HashMap<>(); @VisibleForTesting final HashMap<BluetoothDevice, PbapStateMachine> mPbapStateMachineMap = new HashMap<>(); private volatile int mNextNotificationId = PBAP_NOTIFICATION_ID_START; // package and class name to which we send intent to check phone book access permission Loading Loading @@ -276,7 +277,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } } private BroadcastReceiver mPbapReceiver = new BroadcastReceiver() { @VisibleForTesting BroadcastReceiver mPbapReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { parseIntent(intent); Loading Loading @@ -446,10 +448,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect public int getConnectionState(BluetoothDevice device) { enforceCallingOrSelfPermission( BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); if (mPbapStateMachineMap == null) { return BluetoothProfile.STATE_DISCONNECTED; } synchronized (mPbapStateMachineMap) { PbapStateMachine sm = mPbapStateMachineMap.get(device); if (sm == null) { Loading @@ -460,9 +458,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } List<BluetoothDevice> getConnectedDevices() { if (mPbapStateMachineMap == null) { return new ArrayList<>(); } synchronized (mPbapStateMachineMap) { return new ArrayList<>(mPbapStateMachineMap.keySet()); } Loading @@ -470,7 +465,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { List<BluetoothDevice> devices = new ArrayList<>(); if (mPbapStateMachineMap == null || states == null) { if (states == null) { return devices; } synchronized (mPbapStateMachineMap) { Loading Loading @@ -631,6 +626,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect getContentResolver().unregisterContentObserver(mContactChangeObserver); mContactChangeObserver = null; setComponentAvailable(PBAP_ACTIVITY, false); mPbapStateMachineMap.clear(); return true; } Loading android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +130 −11 Original line number Diff line number Diff line Loading @@ -15,38 +15,47 @@ */ package com.android.bluetooth.pbap; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Message; 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.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Assert; import org.junit.Assume; 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 BluetoothPbapServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private BluetoothPbapService mService; private BluetoothAdapter mAdapter = null; private Context mTargetContext; private BluetoothDevice mRemoteDevice; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -55,7 +64,6 @@ public class BluetoothPbapServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); Assume.assumeTrue("Ignore test when BluetoothPbapService is not enabled", BluetoothPbapService.isEnabled()); MockitoAnnotations.initMocks(this); Loading @@ -64,10 +72,11 @@ public class BluetoothPbapServiceTest { doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); TestUtils.startService(mServiceRule, BluetoothPbapService.class); mService = BluetoothPbapService.getBluetoothPbapService(); Assert.assertNotNull(mService); assertThat(mService).isNotNull(); // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); Assert.assertNotNull(mAdapter); assertThat(mAdapter).isNotNull(); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); } @After Loading @@ -77,12 +86,122 @@ public class BluetoothPbapServiceTest { } TestUtils.stopService(mServiceRule, BluetoothPbapService.class); mService = BluetoothPbapService.getBluetoothPbapService(); Assert.assertNull(mService); assertThat(mService).isNull(); TestUtils.clearAdapterService(mAdapterService); } @Test public void testInitialize() { Assert.assertNotNull(BluetoothPbapService.getBluetoothPbapService()); public void initialize() { assertThat(BluetoothPbapService.getBluetoothPbapService()).isNotNull(); } @Test public void disconnect() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.disconnect(mRemoteDevice); verify(sm).sendMessage(PbapStateMachine.DISCONNECT); } @Test public void getConnectedDevices() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); assertThat(mService.getConnectedDevices()).contains(mRemoteDevice); } @Test public void getConnectionPolicy_withDeviceIsNull_throwsNPE() { assertThrows(IllegalArgumentException.class, () -> mService.getConnectionPolicy(null)); } @Test public void getConnectionPolicy() { mService.getConnectionPolicy(mRemoteDevice); verify(mDatabaseManager).getProfileConnectionPolicy(mRemoteDevice, BluetoothProfile.PBAP); } @Test public void getDevicesMatchingConnectionStates_whenStatesIsNull_returnsEmptyList() { assertThat(mService.getDevicesMatchingConnectionStates(null)).isEmpty(); } @Test public void getDevicesMatchingConnectionStates() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED); int[] states = new int[] {BluetoothProfile.STATE_CONNECTED}; assertThat(mService.getDevicesMatchingConnectionStates(states)).contains(mRemoteDevice); } @Test public void onAcceptFailed() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.onAcceptFailed(); assertThat(mService.mPbapStateMachineMap).isEmpty(); } @Test public void broadcastReceiver_onReceive_withActionConnectionAccessReply() { Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, BluetoothDevice.CONNECTION_ACCESS_YES); intent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); verify(sm).sendMessage(PbapStateMachine.AUTHORIZED); } @Test public void broadcastReceiver_onReceive_withActionAuthResponse() { Intent intent = new Intent(BluetoothPbapService.AUTH_RESPONSE_ACTION); String sessionKey = "test_session_key"; intent.putExtra(BluetoothPbapService.EXTRA_SESSION_KEY, sessionKey); intent.putExtra(BluetoothPbapService.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); verify(sm).sendMessage(captor.capture()); Message msg = captor.getValue(); assertThat(msg.what).isEqualTo(PbapStateMachine.AUTH_KEY_INPUT); assertThat(msg.obj).isEqualTo(sessionKey); msg.recycle(); } @Test public void broadcastReceiver_onReceive_withActionAuthCancelled() { Intent intent = new Intent(BluetoothPbapService.AUTH_CANCELLED_ACTION); intent.putExtra(BluetoothPbapService.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); verify(sm).sendMessage(PbapStateMachine.AUTH_CANCELLED); } @Test public void broadcastReceiver_onReceive_withIllegalAction_doesNothing() { Intent intent = new Intent("test_random_action"); mService.mPbapReceiver.onReceive(null, intent); } } Loading
android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +6 −10 Original line number Diff line number Diff line Loading @@ -166,7 +166,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect private PbapHandler mSessionStatusHandler; private HandlerThread mHandlerThread; private final HashMap<BluetoothDevice, PbapStateMachine> mPbapStateMachineMap = new HashMap<>(); @VisibleForTesting final HashMap<BluetoothDevice, PbapStateMachine> mPbapStateMachineMap = new HashMap<>(); private volatile int mNextNotificationId = PBAP_NOTIFICATION_ID_START; // package and class name to which we send intent to check phone book access permission Loading Loading @@ -276,7 +277,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } } private BroadcastReceiver mPbapReceiver = new BroadcastReceiver() { @VisibleForTesting BroadcastReceiver mPbapReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { parseIntent(intent); Loading Loading @@ -446,10 +448,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect public int getConnectionState(BluetoothDevice device) { enforceCallingOrSelfPermission( BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); if (mPbapStateMachineMap == null) { return BluetoothProfile.STATE_DISCONNECTED; } synchronized (mPbapStateMachineMap) { PbapStateMachine sm = mPbapStateMachineMap.get(device); if (sm == null) { Loading @@ -460,9 +458,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } List<BluetoothDevice> getConnectedDevices() { if (mPbapStateMachineMap == null) { return new ArrayList<>(); } synchronized (mPbapStateMachineMap) { return new ArrayList<>(mPbapStateMachineMap.keySet()); } Loading @@ -470,7 +465,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { List<BluetoothDevice> devices = new ArrayList<>(); if (mPbapStateMachineMap == null || states == null) { if (states == null) { return devices; } synchronized (mPbapStateMachineMap) { Loading Loading @@ -631,6 +626,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect getContentResolver().unregisterContentObserver(mContactChangeObserver); mContactChangeObserver = null; setComponentAvailable(PBAP_ACTIVITY, false); mPbapStateMachineMap.clear(); return true; } Loading
android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +130 −11 Original line number Diff line number Diff line Loading @@ -15,38 +15,47 @@ */ package com.android.bluetooth.pbap; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Message; 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.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Assert; import org.junit.Assume; 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 BluetoothPbapServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private BluetoothPbapService mService; private BluetoothAdapter mAdapter = null; private Context mTargetContext; private BluetoothDevice mRemoteDevice; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -55,7 +64,6 @@ public class BluetoothPbapServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); Assume.assumeTrue("Ignore test when BluetoothPbapService is not enabled", BluetoothPbapService.isEnabled()); MockitoAnnotations.initMocks(this); Loading @@ -64,10 +72,11 @@ public class BluetoothPbapServiceTest { doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); TestUtils.startService(mServiceRule, BluetoothPbapService.class); mService = BluetoothPbapService.getBluetoothPbapService(); Assert.assertNotNull(mService); assertThat(mService).isNotNull(); // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); Assert.assertNotNull(mAdapter); assertThat(mAdapter).isNotNull(); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); } @After Loading @@ -77,12 +86,122 @@ public class BluetoothPbapServiceTest { } TestUtils.stopService(mServiceRule, BluetoothPbapService.class); mService = BluetoothPbapService.getBluetoothPbapService(); Assert.assertNull(mService); assertThat(mService).isNull(); TestUtils.clearAdapterService(mAdapterService); } @Test public void testInitialize() { Assert.assertNotNull(BluetoothPbapService.getBluetoothPbapService()); public void initialize() { assertThat(BluetoothPbapService.getBluetoothPbapService()).isNotNull(); } @Test public void disconnect() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.disconnect(mRemoteDevice); verify(sm).sendMessage(PbapStateMachine.DISCONNECT); } @Test public void getConnectedDevices() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); assertThat(mService.getConnectedDevices()).contains(mRemoteDevice); } @Test public void getConnectionPolicy_withDeviceIsNull_throwsNPE() { assertThrows(IllegalArgumentException.class, () -> mService.getConnectionPolicy(null)); } @Test public void getConnectionPolicy() { mService.getConnectionPolicy(mRemoteDevice); verify(mDatabaseManager).getProfileConnectionPolicy(mRemoteDevice, BluetoothProfile.PBAP); } @Test public void getDevicesMatchingConnectionStates_whenStatesIsNull_returnsEmptyList() { assertThat(mService.getDevicesMatchingConnectionStates(null)).isEmpty(); } @Test public void getDevicesMatchingConnectionStates() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); when(sm.getConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED); int[] states = new int[] {BluetoothProfile.STATE_CONNECTED}; assertThat(mService.getDevicesMatchingConnectionStates(states)).contains(mRemoteDevice); } @Test public void onAcceptFailed() { PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.onAcceptFailed(); assertThat(mService.mPbapStateMachineMap).isEmpty(); } @Test public void broadcastReceiver_onReceive_withActionConnectionAccessReply() { Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, BluetoothDevice.CONNECTION_ACCESS_YES); intent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); verify(sm).sendMessage(PbapStateMachine.AUTHORIZED); } @Test public void broadcastReceiver_onReceive_withActionAuthResponse() { Intent intent = new Intent(BluetoothPbapService.AUTH_RESPONSE_ACTION); String sessionKey = "test_session_key"; intent.putExtra(BluetoothPbapService.EXTRA_SESSION_KEY, sessionKey); intent.putExtra(BluetoothPbapService.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); verify(sm).sendMessage(captor.capture()); Message msg = captor.getValue(); assertThat(msg.what).isEqualTo(PbapStateMachine.AUTH_KEY_INPUT); assertThat(msg.obj).isEqualTo(sessionKey); msg.recycle(); } @Test public void broadcastReceiver_onReceive_withActionAuthCancelled() { Intent intent = new Intent(BluetoothPbapService.AUTH_CANCELLED_ACTION); intent.putExtra(BluetoothPbapService.EXTRA_DEVICE, mRemoteDevice); PbapStateMachine sm = mock(PbapStateMachine.class); mService.mPbapStateMachineMap.put(mRemoteDevice, sm); mService.mPbapReceiver.onReceive(null, intent); verify(sm).sendMessage(PbapStateMachine.AUTH_CANCELLED); } @Test public void broadcastReceiver_onReceive_withIllegalAction_doesNothing() { Intent intent = new Intent("test_random_action"); mService.mPbapReceiver.onReceive(null, intent); } }