blob: c947159720d5fa362bc4bbc58be577d8b18d40fe [file] [log] [blame]
package com.android.clockwork.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import com.google.android.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
@RunWith(RobolectricTestRunner.class)
public class BluetoothScanModeEnforcerTest {
private Context mContext;
private @Mock BluetoothAdapter mockBtAdapter;
private @Mock CompanionTracker mockCompanionTracker;
private @Mock BluetoothDevice androidPhone;
private @Mock BluetoothDevice iOSPhone;
private @Mock BluetoothDevice btClassicPeripheral;
private @Mock BluetoothClass phoneBluetoothClass;
private @Mock BluetoothClass peripheralBluetoothClass;
private Intent bondingIntent;
private Intent scanModeDisableIntent;
private Intent unbondingIntent;
@Before
public void setUp() {
initMocks(this);
mContext = RuntimeEnvironment.application;
new BluetoothScanModeEnforcer(mContext, mockBtAdapter, mockCompanionTracker);
when(mockBtAdapter.isEnabled()).thenReturn(true);
when(phoneBluetoothClass.getMajorDeviceClass()).thenReturn(BluetoothClass.Device.Major.PHONE);
when(peripheralBluetoothClass.getMajorDeviceClass()).thenReturn(BluetoothClass.Device.Major.PERIPHERAL);
when(androidPhone.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_CLASSIC);
when(androidPhone.getAddress()).thenReturn("AA:BB:CC:DD:EE:FF");
when(androidPhone.getBluetoothClass()).thenReturn(phoneBluetoothClass);
when(btClassicPeripheral.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_CLASSIC);
when(btClassicPeripheral.getAddress()).thenReturn("MM:NN:OO:PP:QQ:RR");
when(btClassicPeripheral.getBluetoothClass()).thenReturn(peripheralBluetoothClass);
when(iOSPhone.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_DUAL);
when(iOSPhone.getAddress()).thenReturn("GG:HH:II:JJ:KK:LL");
when(iOSPhone.getBluetoothClass()).thenReturn(phoneBluetoothClass);
// Build scan mode and bonding intents.
scanModeDisableIntent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
scanModeDisableIntent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
bondingIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
bondingIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
unbondingIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
unbondingIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
}
@Test
public void testConstructorRegistersReceiver() {
assertTrue(ShadowApplication.getInstance().hasReceiverForIntent(
new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)));
assertTrue(ShadowApplication.getInstance().hasReceiverForIntent(
new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED)));
}
@Test
public void testScanModeRemainsEnabledOnPairingCancel() {
when(mockCompanionTracker.getCompanion()).thenReturn(null);
mContext.sendBroadcast(unbondingIntent);
verify(mockBtAdapter, never()).setScanMode(anyInt());
}
@Test
public void testAndroidWithHeadsetScanModeRemainsEnabled() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(false);
when(mockCompanionTracker.getCompanion()).thenReturn(androidPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(androidPhone, btClassicPeripheral));
mContext.sendBroadcast(scanModeDisableIntent);
verify(mockBtAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
// TODO this test is actually testing the exact same thing as above because
// btAdapter.getScanMode is never called or checked; which suggests that the
// underlying code is doing the wrong thing
@Test
public void testAndroidWithHeadsetScanModeRemainsEnabledOnDelayedBroadcast() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(false);
when(mockCompanionTracker.getCompanion()).thenReturn(androidPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(androidPhone, btClassicPeripheral));
// when scan mode is disabled by another component unknowingly
// (the ACTION_SCAN_MODE_CHANGED could be delayed, the current scan mode can be
// SCAN_MODE_CONNECTABLE, but the ACTION_SCAN_MODE_CHANGED could report SCAN_MODE_NONE).
when(mockBtAdapter.getScanMode()).thenReturn(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
mContext.sendBroadcast(scanModeDisableIntent);
verify(mockBtAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
@Test
public void testIosWithHeadsetScanModeRemainsEnabled() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(true);
when(mockCompanionTracker.getCompanion()).thenReturn(iOSPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone, btClassicPeripheral));
mContext.sendBroadcast(scanModeDisableIntent);
verify(mockBtAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
@Test
public void testAndroidScanModeEnabledAfterHeadsetBond() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(false);
when(mockCompanionTracker.getCompanion()).thenReturn(androidPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(androidPhone, btClassicPeripheral));
mContext.sendBroadcast(bondingIntent);
verify(mockBtAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
@Test
public void testIosScanModeEnabledAfterHeadsetBond() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(true);
when(mockCompanionTracker.getCompanion()).thenReturn(iOSPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone, btClassicPeripheral));
mContext.sendBroadcast(bondingIntent);
verify(mockBtAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
@Test
public void testAndroidScanModeStillEnabledAfterUnbond() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(false);
when(mockCompanionTracker.getCompanion()).thenReturn(androidPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(androidPhone));
mContext.sendBroadcast(unbondingIntent);
verify(mockBtAdapter, never()).setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
}
@Test
public void testIosScanModeStillEnabledAfterUnbond() {
when(mockCompanionTracker.isCompanionBle()).thenReturn(true);
when(mockCompanionTracker.getCompanion()).thenReturn(iOSPhone);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone));
mContext.sendBroadcast(unbondingIntent);
verify(mockBtAdapter, never()).setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
}
}