Bluetooth: Always scan while on pairing or DevicePicker page

* Modified DeviceListPreferenceFragment to have enable/disable scanning
  methods. In ENABLE state, each onScanningStateChanged(false) will
  restart another round of scanning
* Subclasses of DeviceListPreferenceFragment should call enable/disable
  scanning when scanning is needed for long period of time
* Currently, BluetoothPairingDetail and DevicePickerFragment call
  enableScanning() when Bluetooth is turned ON and call disableScanning
  when some device is picked in their lists
* Both BluetoothPairingDetail and DevicePickerFragment will re-enable
  scanning if pairing failed for selected device
* Added associated unit tests as well

Bug: 32172815
Test: make, pair Bluetooth device, send file over Bluetooth Opp
Change-Id: I99325e06aadd7b00e7a7ba6d6c282a6831859d8b
This commit is contained in:
Jack He
2017-05-30 23:05:46 -07:00
parent fe23da579d
commit c11af01481
5 changed files with 210 additions and 51 deletions

View File

@@ -23,7 +23,9 @@ import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothAdapter;
@@ -103,7 +105,7 @@ public class BluetoothPairingDetailTest {
mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
mFragment.mDeviceListGroup = mAvailableDevicesCategory;
mFragment.startScanning();
mFragment.enableScanning();
verify(mLocalAdapter).startScanning(true);
verify(mAvailableDevicesCategory).removeAll();
@@ -130,4 +132,54 @@ public class BluetoothPairingDetailTest {
verify(mFragment).finish();
}
@Test
public void testOnScanningStateChanged_restartScanAfterInitialScanning() {
mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
mFragment.mFooterPreference = mFooterPreference;
mFragment.mDeviceListGroup = mAvailableDevicesCategory;
doNothing().when(mFragment).addDeviceCategory(any(), anyInt(), any(), anyBoolean());
// Initial Bluetooth ON will trigger scan enable, list clear and scan start
mFragment.updateContent(BluetoothAdapter.STATE_ON);
verify(mFragment).enableScanning();
assertThat(mAvailableDevicesCategory.getPreferenceCount()).isEqualTo(0);
verify(mLocalAdapter).startScanning(true);
// Subsequent scan started event will not trigger start/stop nor list clear
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
verify(mAvailableDevicesCategory, times(1)).setProgress(true);
// Subsequent scan finished event will trigger scan start without list clean
mFragment.onScanningStateChanged(false);
verify(mLocalAdapter, times(2)).startScanning(true);
verify(mAvailableDevicesCategory, times(2)).setProgress(true);
// Subsequent scan started event will not trigger any change
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
verify(mAvailableDevicesCategory, times(3)).setProgress(true);
verify(mLocalAdapter, never()).stopScanning();
// Disable scanning will trigger scan stop
mFragment.disableScanning();
verify(mLocalAdapter, times(1)).stopScanning();
// Subsequent scan start event will not trigger any change besides progress circle
mFragment.onScanningStateChanged(true);
verify(mAvailableDevicesCategory, times(4)).setProgress(true);
// However, subsequent scan finished event won't trigger new scan start and will stop
// progress circle from spinning
mFragment.onScanningStateChanged(false);
verify(mAvailableDevicesCategory, times(1)).setProgress(false);
verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
verify(mLocalAdapter, times(1)).stopScanning();
// Verify that clean up only happen once at initialization
verify(mAvailableDevicesCategory, times(1)).removeAll();
}
}

View File

@@ -19,9 +19,12 @@ package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.res.Resources;
@@ -83,6 +86,92 @@ public class DeviceListPreferenceFragmentTest {
assertThat(mMyDevicePreference.getTitle()).isEqualTo(FOOTAGE_MAC_STRING);
}
@Test
public void testEnableDisableScanning_testStateAfterEanbleDisable() {
mFragment.enableScanning();
verify(mLocalAdapter).startScanning(true);
assertThat(mFragment.mScanEnabled).isTrue();
mFragment.disableScanning();
verify(mLocalAdapter).stopScanning();
assertThat(mFragment.mScanEnabled).isFalse();
}
@Test
public void testScanningStateChanged_testScanStarted() {
mFragment.enableScanning();
assertThat(mFragment.mScanEnabled).isTrue();
verify(mLocalAdapter).startScanning(true);
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
}
@Test
public void testScanningStateChanged_testScanFinished() {
// Could happen when last scanning not done while current scan gets enabled
mFragment.enableScanning();
verify(mLocalAdapter).startScanning(true);
assertThat(mFragment.mScanEnabled).isTrue();
mFragment.onScanningStateChanged(false);
verify(mLocalAdapter, times(2)).startScanning(true);
}
@Test
public void testScanningStateChanged_testScanStateMultiple() {
// Could happen when last scanning not done while current scan gets enabled
mFragment.enableScanning();
assertThat(mFragment.mScanEnabled).isTrue();
verify(mLocalAdapter).startScanning(true);
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
mFragment.onScanningStateChanged(false);
verify(mLocalAdapter, times(2)).startScanning(true);
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
mFragment.disableScanning();
verify(mLocalAdapter).stopScanning();
mFragment.onScanningStateChanged(false);
verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
}
@Test
public void testScanningStateChanged_testScanFinishedAfterDisable() {
mFragment.enableScanning();
verify(mLocalAdapter).startScanning(true);
assertThat(mFragment.mScanEnabled).isTrue();
mFragment.disableScanning();
verify(mLocalAdapter).stopScanning();
assertThat(mFragment.mScanEnabled).isFalse();
mFragment.onScanningStateChanged(false);
verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
}
@Test
public void testScanningStateChanged_testScanStartedAfterDisable() {
mFragment.enableScanning();
verify(mLocalAdapter).startScanning(true);
assertThat(mFragment.mScanEnabled).isTrue();
mFragment.disableScanning();
verify(mLocalAdapter).stopScanning();
assertThat(mFragment.mScanEnabled).isFalse();
mFragment.onScanningStateChanged(true);
verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
}
/**
* Fragment to test since {@code DeviceListPreferenceFragment} is abstract
*/
@@ -98,14 +187,10 @@ public class DeviceListPreferenceFragmentTest {
}
@Override
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
}
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {}
@Override
void initPreferencesFromPreferenceScreen() {
}
void initPreferencesFromPreferenceScreen() {}
@Override
public String getDeviceListKey() {