blob: 7603c33d85ffae1b50a41aaeebc7e13b4036de96 [file] [log] [blame]
/*
* Copyright 2018 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.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.never;
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.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;
import org.junit.Before;
import org.junit.Ignore;
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();
@Mock private AdapterService mAdapterService;
@Mock private DatabaseManager mDatabaseManager;
@Before
public void setUp() throws Exception {
mTargetContext = InstrumentationRegistry.getTargetContext();
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
doReturn(true, false).when(mAdapterService).isStartedProfile(anyString());
TestUtils.startService(mServiceRule, PbapClientService.class);
mService = PbapClientService.getPbapClientService();
Assert.assertNotNull(mService);
// Try getting the Bluetooth adapter
mAdapter = BluetoothAdapter.getDefaultAdapter();
Assert.assertNotNull(mAdapter);
mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS);
}
@After
public void tearDown() throws Exception {
TestUtils.stopService(mServiceRule, PbapClientService.class);
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();
}
@Ignore("b/273396169")
@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_withActionAclDisconnectedNoTransport_doesNotCallDisconnect() {
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, never()).disconnect(mRemoteDevice);
}
@Test
public void broadcastReceiver_withActionAclDisconnectedLeTransport_doesNotCallDisconnect() {
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);
intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE);
mService.mPbapBroadcastReceiver.onReceive(mService, intent);
verify(sm, never()).disconnect(mRemoteDevice);
}
@Test
public void broadcastReceiver_withActionAclDisconnectedBrEdrTransport_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);
intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR);
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());
}
}