blob: 6ba0c390fb50af44587c1a2a6f03858640c9ba3d [file] [log] [blame]
package com.android.clockwork.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.MatrixCursor;
import com.google.android.collect.Sets;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import java.util.HashSet;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.BLUETOOTH_MODE_NON_ALT;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.BLUETOOTH_MODE_UNKNOWN;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.BLUETOOTH_URI;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.KEY_BLUETOOTH_MODE;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.KEY_COMPANION_ADDRESS;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.SETTINGS_COLUMN_KEY;
import static com.android.clockwork.bluetooth.WearBluetoothConstants.SETTINGS_COLUMN_VALUE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@RunWith(RobolectricTestRunner.class)
public class CompanionTrackerTest {
private @Mock ContentResolver mockResolver;
private @Mock BluetoothAdapter mockBtAdapter;
private @Mock BluetoothDevice androidPhone;
private @Mock BluetoothDevice iOSPhone;
private @Mock BluetoothDevice btPeripheral;
private @Mock BluetoothClass phoneBluetoothClass;
private @Mock BluetoothClass peripheralBluetoothClass;
private @Mock CompanionTracker.Listener mockListener;
private CompanionTracker mTracker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTracker = new CompanionTracker(mockResolver, mockBtAdapter);
mTracker.addListener(mockListener);
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(btPeripheral.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_CLASSIC);
when(btPeripheral.getAddress()).thenReturn("MM:NN:OO:PP:QQ:RR");
when(btPeripheral.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);
verify(mockResolver).registerContentObserver(
BLUETOOTH_URI, false, mTracker.mSettingsObserver);
reset(mockResolver);
}
@Test
public void testNullBtAdapter() {
CompanionTracker nullBtTracker = new CompanionTracker(mockResolver, null);
nullBtTracker.addListener(mockListener);
Assert.assertNull(nullBtTracker.getCompanion());
Assert.assertFalse(nullBtTracker.isCompanionBle());
nullBtTracker.onBluetoothAdapterReady();
Assert.assertNull(nullBtTracker.getCompanion());
Assert.assertFalse(nullBtTracker.isCompanionBle());
mTracker.mSettingsObserver.onChange(false, BLUETOOTH_URI);
nullBtTracker.onBluetoothAdapterReady();
verifyNoMoreInteractions(mockListener);
}
@Test
public void testPreAdapterEnabledGetters() {
Assert.assertNull(mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
}
@Test
public void testOnAndroidCompanionAddressChanged() {
MatrixCursor cursor = buildCursor(androidPhone.getAddress(), -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices())
.thenReturn(Sets.newHashSet(androidPhone, btPeripheral));
mTracker.mSettingsObserver.onChange(false, BLUETOOTH_URI);
Assert.assertEquals(androidPhone, mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
verify(mockListener).onCompanionChanged();
}
@Test
public void testOnIosCompanionAddressChanged() {
MatrixCursor cursor = buildCursor(iOSPhone.getAddress(), -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices())
.thenReturn(Sets.newHashSet(iOSPhone, btPeripheral));
mTracker.mSettingsObserver.onChange(false, BLUETOOTH_URI);
Assert.assertEquals(iOSPhone, mTracker.getCompanion());
Assert.assertTrue(mTracker.isCompanionBle());
verify(mockListener).onCompanionChanged();
}
@Test
public void testAdapterReady_FreshUnpairedDevice() {
MatrixCursor cursor = buildCursor(null, -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices()).thenReturn(new HashSet<>());
mTracker.onBluetoothAdapterReady();
verify(mockResolver, never()).update(any(), any(), any(), any());
Assert.assertNull(mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
}
@Test
public void testAdapterReady_PairedAndroidDeviceNoMigrationNeeded() {
MatrixCursor cursor = buildCursor(androidPhone.getAddress(), -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(androidPhone));
mTracker.onBluetoothAdapterReady();
verify(mockResolver, never()).update(any(), any(), any(), any());
Assert.assertEquals(androidPhone, mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
}
@Test
public void testAdapterReady_PairedIOsDeviceNoMigrationNeeded() {
MatrixCursor cursor = buildCursor(iOSPhone.getAddress(), -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone));
mTracker.onBluetoothAdapterReady();
verify(mockResolver, never()).update(any(), any(), any(), any());
Assert.assertEquals(iOSPhone, mTracker.getCompanion());
Assert.assertTrue(mTracker.isCompanionBle());
}
@Test
public void testAdapterReady_MigrationNeededPairedAndroidDevice() {
MatrixCursor cursor = buildCursor(null, -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices())
.thenReturn(Sets.newHashSet(androidPhone, btPeripheral));
mTracker.onBluetoothAdapterReady();
ContentValues values = new ContentValues();
values.put(KEY_COMPANION_ADDRESS, androidPhone.getAddress());
verify(mockResolver).update(BLUETOOTH_URI, values, null, null);
Assert.assertEquals(androidPhone, mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
}
@Test
public void testAdapterReady_MigrationNeededPairedIOsDevice() {
MatrixCursor cursor = buildCursor(null, -9999);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices())
.thenReturn(Sets.newHashSet(iOSPhone, btPeripheral));
mTracker.onBluetoothAdapterReady();
ContentValues values = new ContentValues();
values.put(KEY_COMPANION_ADDRESS, iOSPhone.getAddress());
verify(mockResolver).update(BLUETOOTH_URI, values, null, null);
Assert.assertEquals(iOSPhone, mTracker.getCompanion());
Assert.assertTrue(mTracker.isCompanionBle());
}
@Test
public void testBluetoothModeBeatsAdapterType() {
MatrixCursor cursor = buildCursor(iOSPhone.getAddress(), BLUETOOTH_MODE_NON_ALT);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone));
mTracker.onBluetoothAdapterReady();
// even though the BluetoothDevice is BLE, the tracker should return false for
// isCompanionBle because of the KEY_BLUETOOTH_MODE field
Assert.assertEquals(iOSPhone, mTracker.getCompanion());
Assert.assertFalse(mTracker.isCompanionBle());
}
@Test
public void testBluetoothModeUnknownFallback() {
MatrixCursor cursor = buildCursor(iOSPhone.getAddress(), BLUETOOTH_MODE_UNKNOWN);
when(mockResolver.query(BLUETOOTH_URI, null, null, null, null))
.thenReturn(cursor);
when(mockBtAdapter.getBondedDevices()).thenReturn(Sets.newHashSet(iOSPhone));
mTracker.onBluetoothAdapterReady();
// since the BluetoothMode is unknown, it should return the type given by the device
Assert.assertEquals(iOSPhone, mTracker.getCompanion());
Assert.assertTrue(mTracker.isCompanionBle());
}
private MatrixCursor buildCursor(String companionAddress, int bluetoothMode) {
MatrixCursor cursor = new MatrixCursor(
new String[] {SETTINGS_COLUMN_KEY, SETTINGS_COLUMN_VALUE});
if (companionAddress != null) {
cursor.addRow(new Object[] {KEY_COMPANION_ADDRESS, companionAddress});
}
if (bluetoothMode >= 0) {
cursor.addRow(new Object[] {KEY_BLUETOOTH_MODE, bluetoothMode});
}
return cursor;
}
}