1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bluetooth.le_scan; 18 19 import static android.bluetooth.BluetoothDevice.PHY_LE_1M_MASK; 20 import static android.bluetooth.BluetoothDevice.PHY_LE_CODED; 21 import static android.bluetooth.BluetoothDevice.PHY_LE_CODED_MASK; 22 import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH; 23 import static android.bluetooth.le.ScanSettings.PHY_LE_ALL_SUPPORTED; 24 import static android.bluetooth.le.ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY; 25 import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED; 26 import static android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY; 27 import static android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_POWER; 28 import static android.bluetooth.le.ScanSettings.SCAN_MODE_OPPORTUNISTIC; 29 import static android.bluetooth.le.ScanSettings.SCAN_MODE_SCREEN_OFF; 30 import static android.bluetooth.le.ScanSettings.SCAN_MODE_SCREEN_OFF_BALANCED; 31 32 import static com.android.bluetooth.btservice.AdapterService.DeviceConfigListener.DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS; 33 import static com.android.bluetooth.btservice.AdapterService.DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS; 34 import static com.android.bluetooth.btservice.AdapterService.DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS; 35 import static com.android.bluetooth.le_scan.ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; 36 import static com.android.bluetooth.le_scan.ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS; 37 import static com.android.bluetooth.le_scan.ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS; 38 import static com.android.bluetooth.le_scan.ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS; 39 40 import static com.google.common.truth.Truth.assertThat; 41 42 import static org.mockito.ArgumentMatchers.any; 43 import static org.mockito.ArgumentMatchers.anyBoolean; 44 import static org.mockito.ArgumentMatchers.anyInt; 45 import static org.mockito.ArgumentMatchers.anyLong; 46 import static org.mockito.Mockito.atLeastOnce; 47 import static org.mockito.Mockito.doReturn; 48 import static org.mockito.Mockito.eq; 49 import static org.mockito.Mockito.inOrder; 50 import static org.mockito.Mockito.mock; 51 import static org.mockito.Mockito.never; 52 import static org.mockito.Mockito.spy; 53 import static org.mockito.Mockito.verify; 54 55 import android.app.ActivityManager; 56 import android.app.AlarmManager; 57 import android.bluetooth.BluetoothProfile; 58 import android.bluetooth.BluetoothProtoEnums; 59 import android.bluetooth.le.ScanFilter; 60 import android.bluetooth.le.ScanSettings; 61 import android.content.Context; 62 import android.hardware.display.DisplayManager; 63 import android.location.LocationManager; 64 import android.os.BatteryStatsManager; 65 import android.os.Binder; 66 import android.os.Bundle; 67 import android.os.Message; 68 import android.os.SystemProperties; 69 import android.os.WorkSource; 70 import android.os.test.TestLooper; 71 import android.platform.test.annotations.EnableFlags; 72 import android.platform.test.flag.junit.SetFlagsRule; 73 import android.provider.Settings; 74 import android.test.mock.MockContentProvider; 75 import android.test.mock.MockContentResolver; 76 import android.util.Log; 77 import android.util.SparseIntArray; 78 79 import androidx.test.InstrumentationRegistry; 80 import androidx.test.filters.SmallTest; 81 import androidx.test.runner.AndroidJUnit4; 82 83 import com.android.bluetooth.BluetoothStatsLog; 84 import com.android.bluetooth.TestUtils; 85 import com.android.bluetooth.TestUtils.FakeTimeProvider; 86 import com.android.bluetooth.btservice.AdapterService; 87 import com.android.bluetooth.btservice.BluetoothAdapterProxy; 88 import com.android.bluetooth.btservice.MetricsLogger; 89 import com.android.bluetooth.flags.Flags; 90 import com.android.bluetooth.gatt.GattNativeInterface; 91 import com.android.bluetooth.gatt.GattObjectsFactory; 92 import com.android.internal.app.IBatteryStats; 93 94 import org.junit.After; 95 import org.junit.Before; 96 import org.junit.Rule; 97 import org.junit.Test; 98 import org.junit.runner.RunWith; 99 import org.mockito.InOrder; 100 import org.mockito.Mock; 101 import org.mockito.Mockito; 102 import org.mockito.Spy; 103 import org.mockito.junit.MockitoJUnit; 104 import org.mockito.junit.MockitoRule; 105 106 import java.time.Duration; 107 import java.util.ArrayList; 108 import java.util.List; 109 import java.util.Set; 110 111 /** Test cases for {@link ScanManager}. */ 112 @SmallTest 113 @RunWith(AndroidJUnit4.class) 114 public class ScanManagerTest { 115 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 116 @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 117 118 @Mock private AdapterService mAdapterService; 119 @Mock private BluetoothAdapterProxy mBluetoothAdapterProxy; 120 @Mock private GattNativeInterface mNativeInterface; 121 @Mock private LocationManager mLocationManager; 122 @Mock private MetricsLogger mMetricsLogger; 123 @Mock private ScanNativeInterface mScanNativeInterface; 124 @Mock private TransitionalScanHelper mScanHelper; 125 126 @Spy private GattObjectsFactory mGattObjectsFactory = GattObjectsFactory.getInstance(); 127 @Spy private ScanObjectsFactory mScanObjectsFactory = ScanObjectsFactory.getInstance(); 128 129 private static final String TAG = ScanManagerTest.class.getSimpleName(); 130 private static final int DEFAULT_REGULAR_SCAN_REPORT_DELAY_MS = 0; 131 private static final int DEFAULT_BATCH_SCAN_REPORT_DELAY_MS = 100; 132 private static final int DEFAULT_NUM_OFFLOAD_SCAN_FILTER = 16; 133 private static final int DEFAULT_BYTES_OFFLOAD_SCAN_RESULT_STORAGE = 4096; 134 private static final int TEST_SCAN_QUOTA_COUNT = 5; 135 private static final String TEST_APP_NAME = "Test"; 136 private static final String TEST_PACKAGE_NAME = "com.test.package"; 137 138 // MSFT-based hardware scan offload sysprop 139 private static final String MSFT_HCI_EXT_ENABLED = "bluetooth.core.le.use_msft_hci_ext"; 140 141 private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); 142 // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the 143 // underlying binder calls. 144 private final BatteryStatsManager mBatteryStatsManager = 145 new BatteryStatsManager(mock(IBatteryStats.class)); 146 147 private AppScanStats mMockAppScanStats; 148 private MockContentResolver mMockContentResolver; 149 150 private ScanManager mScanManager; 151 private TestLooper mLooper; 152 private long mScanReportDelay; 153 private FakeTimeProvider mTimeProvider; 154 private InOrder mInOrder; 155 156 @Before setUp()157 public void setUp() throws Exception { 158 doReturn(DEFAULT_SCAN_TIMEOUT_MILLIS).when(mAdapterService).getScanTimeoutMillis(); 159 doReturn(DEFAULT_NUM_OFFLOAD_SCAN_FILTER) 160 .when(mAdapterService) 161 .getNumOfOffloadedScanFilterSupported(); 162 doReturn(DEFAULT_BYTES_OFFLOAD_SCAN_RESULT_STORAGE) 163 .when(mAdapterService) 164 .getOffloadedScanResultStorage(); 165 doReturn(TEST_SCAN_QUOTA_COUNT).when(mAdapterService).getScanQuotaCount(); 166 doReturn(SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS) 167 .when(mAdapterService) 168 .getScreenOffLowPowerWindowMillis(); 169 doReturn(SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS) 170 .when(mAdapterService) 171 .getScreenOffBalancedWindowMillis(); 172 doReturn(SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS) 173 .when(mAdapterService) 174 .getScreenOffLowPowerIntervalMillis(); 175 doReturn(SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS) 176 .when(mAdapterService) 177 .getScreenOffBalancedIntervalMillis(); 178 179 TestUtils.mockGetSystemService( 180 mAdapterService, Context.LOCATION_SERVICE, LocationManager.class, mLocationManager); 181 doReturn(true).when(mLocationManager).isLocationEnabled(); 182 183 TestUtils.mockGetSystemService( 184 mAdapterService, 185 Context.DISPLAY_SERVICE, 186 DisplayManager.class, 187 mTargetContext.getSystemService(DisplayManager.class)); 188 TestUtils.mockGetSystemService( 189 mAdapterService, 190 Context.BATTERY_STATS_SERVICE, 191 BatteryStatsManager.class, 192 mBatteryStatsManager); 193 TestUtils.mockGetSystemService(mAdapterService, Context.ALARM_SERVICE, AlarmManager.class); 194 195 mMockContentResolver = new MockContentResolver(mTargetContext); 196 mMockContentResolver.addProvider( 197 Settings.AUTHORITY, 198 new MockContentProvider() { 199 @Override 200 public Bundle call(String method, String request, Bundle args) { 201 return Bundle.EMPTY; 202 } 203 }); 204 doReturn(mMockContentResolver).when(mAdapterService).getContentResolver(); 205 BluetoothAdapterProxy.setInstanceForTesting(mBluetoothAdapterProxy); 206 // Needed to mock Native call/callback when hw offload scan filter is enabled 207 doReturn(true).when(mBluetoothAdapterProxy).isOffloadedScanFilteringSupported(); 208 209 GattObjectsFactory.setInstanceForTesting(mGattObjectsFactory); 210 ScanObjectsFactory.setInstanceForTesting(mScanObjectsFactory); 211 doReturn(mNativeInterface).when(mGattObjectsFactory).getNativeInterface(); 212 doReturn(mScanNativeInterface).when(mScanObjectsFactory).getScanNativeInterface(); 213 // Mock JNI callback in ScanNativeInterface 214 doReturn(true).when(mScanNativeInterface).waitForCallback(anyInt()); 215 216 MetricsLogger.setInstanceForTesting(mMetricsLogger); 217 mInOrder = inOrder(mMetricsLogger); 218 219 doReturn(mTargetContext.getUser()).when(mAdapterService).getUser(); 220 doReturn(mTargetContext.getPackageName()).when(mAdapterService).getPackageName(); 221 222 mTimeProvider = new FakeTimeProvider(); 223 mLooper = new TestLooper(); 224 mScanManager = 225 new ScanManager( 226 mAdapterService, 227 mScanHelper, 228 mBluetoothAdapterProxy, 229 mLooper.getLooper(), 230 mTimeProvider); 231 232 mScanReportDelay = DEFAULT_BATCH_SCAN_REPORT_DELAY_MS; 233 mMockAppScanStats = 234 spy( 235 new AppScanStats( 236 TEST_APP_NAME, 237 null, 238 null, 239 mAdapterService, 240 mScanHelper, 241 mTimeProvider)); 242 } 243 244 @After tearDown()245 public void tearDown() throws Exception { 246 BluetoothAdapterProxy.setInstanceForTesting(null); 247 GattObjectsFactory.setInstanceForTesting(null); 248 ScanObjectsFactory.setInstanceForTesting(null); 249 MetricsLogger.setInstanceForTesting(null); 250 MetricsLogger.getInstance(); 251 } 252 advanceTime(Duration amountToAdvance)253 private void advanceTime(Duration amountToAdvance) { 254 mLooper.moveTimeForward(amountToAdvance.toMillis()); 255 mTimeProvider.advanceTime(amountToAdvance); 256 } 257 advanceTime(long amountToAdvanceMillis)258 private void advanceTime(long amountToAdvanceMillis) { 259 mLooper.moveTimeForward(amountToAdvanceMillis); 260 mTimeProvider.advanceTime(Duration.ofMillis(amountToAdvanceMillis)); 261 } 262 syncHandler(int... what)263 private void syncHandler(int... what) { 264 TestUtils.syncHandler(mLooper, what); 265 } 266 sendMessageWaitForProcessed(Message msg)267 private void sendMessageWaitForProcessed(Message msg) { 268 mScanManager.mHandler.sendMessage(msg); 269 mLooper.dispatchAll(); 270 } 271 createScanClient( int id, boolean isFiltered, boolean isEmptyFilter, int scanMode, boolean isBatch, boolean isAutoBatch, int appUid, AppScanStats appScanStats)272 private ScanClient createScanClient( 273 int id, 274 boolean isFiltered, 275 boolean isEmptyFilter, 276 int scanMode, 277 boolean isBatch, 278 boolean isAutoBatch, 279 int appUid, 280 AppScanStats appScanStats) { 281 List<ScanFilter> scanFilterList = createScanFilterList(isFiltered, isEmptyFilter); 282 ScanSettings scanSettings = createScanSettings(scanMode, isBatch, isAutoBatch); 283 284 ScanClient client = new ScanClient(id, scanSettings, scanFilterList, appUid); 285 client.stats = appScanStats; 286 client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null); 287 return client; 288 } 289 createScanClient(int id, boolean isFiltered, int scanMode)290 private ScanClient createScanClient(int id, boolean isFiltered, int scanMode) { 291 return createScanClient( 292 id, 293 isFiltered, 294 false, 295 scanMode, 296 false, 297 false, 298 Binder.getCallingUid(), 299 mMockAppScanStats); 300 } 301 createScanClient( int id, boolean isFiltered, int scanMode, int appUid, AppScanStats appScanStats)302 private ScanClient createScanClient( 303 int id, boolean isFiltered, int scanMode, int appUid, AppScanStats appScanStats) { 304 return createScanClient( 305 id, isFiltered, false, scanMode, false, false, appUid, appScanStats); 306 } 307 createScanClient( int id, boolean isFiltered, int scanMode, boolean isBatch, boolean isAutoBatch)308 private ScanClient createScanClient( 309 int id, boolean isFiltered, int scanMode, boolean isBatch, boolean isAutoBatch) { 310 return createScanClient( 311 id, 312 isFiltered, 313 false, 314 scanMode, 315 isBatch, 316 isAutoBatch, 317 Binder.getCallingUid(), 318 mMockAppScanStats); 319 } 320 createScanClient( int id, boolean isFiltered, boolean isEmptyFilter, int scanMode)321 private ScanClient createScanClient( 322 int id, boolean isFiltered, boolean isEmptyFilter, int scanMode) { 323 return createScanClient( 324 id, 325 isFiltered, 326 isEmptyFilter, 327 scanMode, 328 false, 329 false, 330 Binder.getCallingUid(), 331 mMockAppScanStats); 332 } 333 createScanFilterList(boolean isFiltered, boolean isEmptyFilter)334 private List<ScanFilter> createScanFilterList(boolean isFiltered, boolean isEmptyFilter) { 335 List<ScanFilter> scanFilterList = null; 336 if (isFiltered) { 337 scanFilterList = new ArrayList<>(); 338 if (isEmptyFilter) { 339 scanFilterList.add(new ScanFilter.Builder().build()); 340 } else { 341 scanFilterList.add(new ScanFilter.Builder().setDeviceName("TestName").build()); 342 } 343 } 344 return scanFilterList; 345 } 346 createScanSettings(int scanMode, boolean isBatch, boolean isAutoBatch)347 private ScanSettings createScanSettings(int scanMode, boolean isBatch, boolean isAutoBatch) { 348 349 ScanSettings scanSettings = null; 350 if (isBatch && isAutoBatch) { 351 int autoCallbackType = CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH; 352 scanSettings = 353 new ScanSettings.Builder() 354 .setScanMode(scanMode) 355 .setReportDelay(mScanReportDelay) 356 .setCallbackType(autoCallbackType) 357 .build(); 358 } else if (isBatch) { 359 scanSettings = 360 new ScanSettings.Builder() 361 .setScanMode(scanMode) 362 .setReportDelay(mScanReportDelay) 363 .build(); 364 } else { 365 scanSettings = new ScanSettings.Builder().setScanMode(scanMode).build(); 366 } 367 return scanSettings; 368 } 369 createScanSettingsWithPhy(int scanMode, int phy)370 private ScanSettings createScanSettingsWithPhy(int scanMode, int phy) { 371 ScanSettings scanSettings; 372 scanSettings = new ScanSettings.Builder().setScanMode(scanMode).setPhy(phy).build(); 373 374 return scanSettings; 375 } 376 createScanClientWithPhy( int id, boolean isFiltered, boolean isEmptyFilter, int scanMode, int phy)377 private ScanClient createScanClientWithPhy( 378 int id, boolean isFiltered, boolean isEmptyFilter, int scanMode, int phy) { 379 List<ScanFilter> scanFilterList = createScanFilterList(isFiltered, isEmptyFilter); 380 ScanSettings scanSettings = createScanSettingsWithPhy(scanMode, phy); 381 382 ScanClient client = new ScanClient(id, scanSettings, scanFilterList); 383 client.stats = mMockAppScanStats; 384 client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null); 385 return client; 386 } 387 createStartStopScanMessage(boolean isStartScan, Object obj)388 private Message createStartStopScanMessage(boolean isStartScan, Object obj) { 389 Message message = new Message(); 390 message.what = isStartScan ? ScanManager.MSG_START_BLE_SCAN : ScanManager.MSG_STOP_BLE_SCAN; 391 message.obj = obj; 392 return message; 393 } 394 createScreenOnOffMessage(boolean isScreenOn)395 private Message createScreenOnOffMessage(boolean isScreenOn) { 396 Message message = new Message(); 397 message.what = isScreenOn ? ScanManager.MSG_SCREEN_ON : ScanManager.MSG_SCREEN_OFF; 398 message.obj = null; 399 return message; 400 } 401 createLocationOnOffMessage(boolean isLocationOn)402 private Message createLocationOnOffMessage(boolean isLocationOn) { 403 Message message = new Message(); 404 message.what = isLocationOn ? ScanManager.MSG_RESUME_SCANS : ScanManager.MSG_SUSPEND_SCANS; 405 message.obj = null; 406 return message; 407 } 408 createImportanceMessage(boolean isForeground)409 private Message createImportanceMessage(boolean isForeground) { 410 return createImportanceMessage(isForeground, Binder.getCallingUid()); 411 } 412 createImportanceMessage(boolean isForeground, int uid)413 private Message createImportanceMessage(boolean isForeground, int uid) { 414 final int importance = 415 isForeground 416 ? ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE 417 : ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE + 1; 418 Message message = new Message(); 419 message.what = ScanManager.MSG_IMPORTANCE_CHANGE; 420 message.obj = new ScanManager.UidImportance(uid, importance); 421 return message; 422 } 423 createConnectingMessage(boolean isConnectingOn)424 private Message createConnectingMessage(boolean isConnectingOn) { 425 Message message = new Message(); 426 message.what = 427 isConnectingOn ? ScanManager.MSG_START_CONNECTING : ScanManager.MSG_STOP_CONNECTING; 428 message.obj = null; 429 return message; 430 } 431 432 @Test testScreenOffStartUnfilteredScan()433 public void testScreenOffStartUnfilteredScan() { 434 // Set filtered scan flag 435 final boolean isFiltered = false; 436 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 437 SparseIntArray scanModeMap = new SparseIntArray(); 438 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 439 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 440 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 441 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 442 443 for (int i = 0; i < scanModeMap.size(); i++) { 444 int scanMode = scanModeMap.keyAt(i); 445 int expectedScanMode = scanModeMap.get(scanMode); 446 Log.d( 447 TAG, 448 "ScanMode: " 449 + String.valueOf(scanMode) 450 + " expectedScanMode: " 451 + String.valueOf(expectedScanMode)); 452 453 // Turn off screen 454 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 455 // Create scan client 456 ScanClient client = createScanClient(i, isFiltered, scanMode); 457 // Start scan 458 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 459 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 460 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 461 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 462 } 463 } 464 465 @Test testScreenOffStartFilteredScan()466 public void testScreenOffStartFilteredScan() { 467 // Set filtered scan flag 468 final boolean isFiltered = true; 469 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 470 SparseIntArray scanModeMap = new SparseIntArray(); 471 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 472 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF_BALANCED); 473 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 474 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF_BALANCED); 475 476 for (int i = 0; i < scanModeMap.size(); i++) { 477 int scanMode = scanModeMap.keyAt(i); 478 int expectedScanMode = scanModeMap.get(scanMode); 479 Log.d( 480 TAG, 481 "ScanMode: " 482 + String.valueOf(scanMode) 483 + " expectedScanMode: " 484 + String.valueOf(expectedScanMode)); 485 486 // Turn off screen 487 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 488 // Create scan client 489 ScanClient client = createScanClient(i, isFiltered, scanMode); 490 // Start scan 491 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 492 assertThat(mScanManager.getRegularScanQueue()).contains(client); 493 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 494 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 495 } 496 } 497 498 @Test testScreenOffStartEmptyFilterScan()499 public void testScreenOffStartEmptyFilterScan() { 500 // Set filtered scan flag 501 final boolean isFiltered = true; 502 final boolean isEmptyFilter = true; 503 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 504 SparseIntArray scanModeMap = new SparseIntArray(); 505 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 506 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 507 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 508 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 509 510 for (int i = 0; i < scanModeMap.size(); i++) { 511 int scanMode = scanModeMap.keyAt(i); 512 int expectedScanMode = scanModeMap.get(scanMode); 513 Log.d( 514 TAG, 515 "ScanMode: " 516 + String.valueOf(scanMode) 517 + " expectedScanMode: " 518 + String.valueOf(expectedScanMode)); 519 520 // Turn off screen 521 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 522 // Create scan client 523 ScanClient client = createScanClient(i, isFiltered, isEmptyFilter, scanMode); 524 // Start scan 525 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 526 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 527 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 528 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 529 } 530 } 531 532 @Test testScreenOnStartUnfilteredScan()533 public void testScreenOnStartUnfilteredScan() { 534 // Set filtered scan flag 535 final boolean isFiltered = false; 536 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 537 SparseIntArray scanModeMap = new SparseIntArray(); 538 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 539 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 540 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 541 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 542 543 for (int i = 0; i < scanModeMap.size(); i++) { 544 int scanMode = scanModeMap.keyAt(i); 545 int expectedScanMode = scanModeMap.get(scanMode); 546 Log.d( 547 TAG, 548 "ScanMode: " 549 + String.valueOf(scanMode) 550 + " expectedScanMode: " 551 + String.valueOf(expectedScanMode)); 552 553 // Turn on screen 554 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 555 // Create scan client 556 ScanClient client = createScanClient(i, isFiltered, scanMode); 557 // Start scan 558 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 559 assertThat(mScanManager.getRegularScanQueue()).contains(client); 560 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 561 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 562 } 563 } 564 565 @Test testScreenOnStartFilteredScan()566 public void testScreenOnStartFilteredScan() { 567 // Set filtered scan flag 568 final boolean isFiltered = true; 569 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 570 SparseIntArray scanModeMap = new SparseIntArray(); 571 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 572 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 573 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 574 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 575 576 for (int i = 0; i < scanModeMap.size(); i++) { 577 int scanMode = scanModeMap.keyAt(i); 578 int expectedScanMode = scanModeMap.get(scanMode); 579 Log.d( 580 TAG, 581 "ScanMode: " 582 + String.valueOf(scanMode) 583 + " expectedScanMode: " 584 + String.valueOf(expectedScanMode)); 585 586 // Turn on screen 587 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 588 // Create scan client 589 ScanClient client = createScanClient(i, isFiltered, scanMode); 590 // Start scan 591 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 592 assertThat(mScanManager.getRegularScanQueue()).contains(client); 593 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 594 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 595 } 596 } 597 598 @Test testResumeUnfilteredScanAfterScreenOn()599 public void testResumeUnfilteredScanAfterScreenOn() { 600 // Set filtered scan flag 601 final boolean isFiltered = false; 602 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 603 SparseIntArray scanModeMap = new SparseIntArray(); 604 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 605 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF_BALANCED); 606 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 607 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF_BALANCED); 608 609 for (int i = 0; i < scanModeMap.size(); i++) { 610 int scanMode = scanModeMap.keyAt(i); 611 int expectedScanMode = scanModeMap.get(scanMode); 612 Log.d( 613 TAG, 614 "ScanMode: " 615 + String.valueOf(scanMode) 616 + " expectedScanMode: " 617 + String.valueOf(expectedScanMode)); 618 619 // Turn off screen 620 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 621 // Create scan client 622 ScanClient client = createScanClient(i, isFiltered, scanMode); 623 // Start scan 624 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 625 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 626 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 627 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 628 // Turn on screen 629 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 630 assertThat(mScanManager.getRegularScanQueue()).contains(client); 631 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 632 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 633 } 634 } 635 636 @Test testResumeFilteredScanAfterScreenOn()637 public void testResumeFilteredScanAfterScreenOn() { 638 // Set filtered scan flag 639 final boolean isFiltered = true; 640 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 641 SparseIntArray scanModeMap = new SparseIntArray(); 642 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 643 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF_BALANCED); 644 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 645 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF_BALANCED); 646 647 for (int i = 0; i < scanModeMap.size(); i++) { 648 int scanMode = scanModeMap.keyAt(i); 649 int expectedScanMode = scanModeMap.get(scanMode); 650 Log.d( 651 TAG, 652 "ScanMode: " 653 + String.valueOf(scanMode) 654 + " expectedScanMode: " 655 + String.valueOf(expectedScanMode)); 656 657 // Turn off screen 658 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 659 // Create scan client 660 ScanClient client = createScanClient(i, isFiltered, scanMode); 661 // Start scan 662 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 663 assertThat(mScanManager.getRegularScanQueue()).contains(client); 664 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 665 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 666 // Turn on screen 667 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 668 assertThat(mScanManager.getRegularScanQueue()).contains(client); 669 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 670 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 671 } 672 } 673 674 @Test testUnfilteredScanTimeout()675 public void testUnfilteredScanTimeout() { 676 // Set filtered scan flag 677 final boolean isFiltered = false; 678 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 679 SparseIntArray scanModeMap = new SparseIntArray(); 680 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_OPPORTUNISTIC); 681 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_OPPORTUNISTIC); 682 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_OPPORTUNISTIC); 683 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_OPPORTUNISTIC); 684 685 for (int i = 0; i < scanModeMap.size(); i++) { 686 int scanMode = scanModeMap.keyAt(i); 687 int expectedScanMode = scanModeMap.get(scanMode); 688 Log.d( 689 TAG, 690 "ScanMode: " 691 + String.valueOf(scanMode) 692 + " expectedScanMode: " 693 + String.valueOf(expectedScanMode)); 694 695 // Turn on screen 696 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 697 // Create scan client 698 ScanClient client = createScanClient(i, isFiltered, scanMode); 699 // Start scan 700 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 701 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 702 // Wait for scan timeout 703 advanceTime(DEFAULT_SCAN_TIMEOUT_MILLIS); 704 mLooper.dispatchAll(); 705 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 706 assertThat(client.stats.isScanTimeout(client.scannerId)).isTrue(); 707 // Turn off screen 708 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 709 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 710 // Turn on screen 711 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 712 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 713 // Set as background app 714 sendMessageWaitForProcessed(createImportanceMessage(false)); 715 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 716 // Set as foreground app 717 sendMessageWaitForProcessed(createImportanceMessage(true)); 718 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 719 } 720 } 721 722 @Test testFilteredScanTimeout()723 public void testFilteredScanTimeout() { 724 // Set filtered scan flag 725 final boolean isFiltered = true; 726 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 727 SparseIntArray scanModeMap = new SparseIntArray(); 728 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 729 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_LOW_POWER); 730 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_POWER); 731 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_POWER); 732 733 for (int i = 0; i < scanModeMap.size(); i++) { 734 int scanMode = scanModeMap.keyAt(i); 735 int expectedScanMode = scanModeMap.get(scanMode); 736 Log.d( 737 TAG, 738 "ScanMode: " 739 + String.valueOf(scanMode) 740 + " expectedScanMode: " 741 + String.valueOf(expectedScanMode)); 742 743 // Turn on screen 744 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 745 // Create scan client 746 ScanClient client = createScanClient(i, isFiltered, scanMode); 747 // Start scan, this sends scan timeout message with delay 748 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 749 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 750 // Move time forward so scan timeout message can be dispatched 751 advanceTime(DEFAULT_SCAN_TIMEOUT_MILLIS); 752 // Since we are using a TestLooper, need to mock AppScanStats.isScanningTooLong to 753 // return true because no real time is elapsed 754 doReturn(true).when(mMockAppScanStats).isScanningTooLong(); 755 syncHandler(ScanManager.MSG_SCAN_TIMEOUT); 756 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 757 assertThat(client.stats.isScanTimeout(client.scannerId)).isTrue(); 758 // Turn off screen 759 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 760 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_SCREEN_OFF); 761 // Set as background app 762 sendMessageWaitForProcessed(createImportanceMessage(false)); 763 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_SCREEN_OFF); 764 // Turn on screen 765 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 766 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 767 // Set as foreground app 768 sendMessageWaitForProcessed(createImportanceMessage(true)); 769 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 770 } 771 } 772 773 @Test testScanTimeoutResetForNewScan()774 public void testScanTimeoutResetForNewScan() { 775 // Set filtered scan flag 776 final boolean isFiltered = false; 777 // Turn on screen 778 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 779 // Create scan client 780 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_POWER); 781 782 // Put a timeout message in the queue to emulate the scan being started already 783 Message timeoutMessage = 784 mScanManager.mHandler.obtainMessage(ScanManager.MSG_SCAN_TIMEOUT, client); 785 mScanManager.mHandler.sendMessageDelayed(timeoutMessage, DEFAULT_SCAN_TIMEOUT_MILLIS / 2); 786 mScanManager.mHandler.sendMessage(createStartStopScanMessage(true, client)); 787 // Dispatching all messages only runs start scan 788 assertThat(mLooper.dispatchAll()).isEqualTo(1); 789 790 advanceTime(DEFAULT_SCAN_TIMEOUT_MILLIS / 2); 791 // After restarting the scan, we can check that the initial timeout message is not triggered 792 assertThat(mLooper.dispatchAll()).isEqualTo(0); 793 794 // After timeout, the next message that is run should be a timeout message 795 advanceTime(DEFAULT_SCAN_TIMEOUT_MILLIS / 2); 796 Message nextMessage = mLooper.nextMessage(); 797 assertThat(nextMessage.what).isEqualTo(ScanManager.MSG_SCAN_TIMEOUT); 798 assertThat(nextMessage.obj).isEqualTo(client); 799 } 800 801 @Test testSwitchForeBackgroundUnfilteredScan()802 public void testSwitchForeBackgroundUnfilteredScan() { 803 // Set filtered scan flag 804 final boolean isFiltered = false; 805 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 806 SparseIntArray scanModeMap = new SparseIntArray(); 807 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 808 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_LOW_POWER); 809 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_POWER); 810 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_POWER); 811 812 for (int i = 0; i < scanModeMap.size(); i++) { 813 int scanMode = scanModeMap.keyAt(i); 814 int expectedScanMode = scanModeMap.get(scanMode); 815 Log.d( 816 TAG, 817 "ScanMode: " 818 + String.valueOf(scanMode) 819 + " expectedScanMode: " 820 + String.valueOf(expectedScanMode)); 821 822 // Turn on screen 823 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 824 // Create scan client 825 ScanClient client = createScanClient(i, isFiltered, scanMode); 826 // Start scan 827 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 828 assertThat(mScanManager.getRegularScanQueue()).contains(client); 829 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 830 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 831 // Set as background app 832 sendMessageWaitForProcessed(createImportanceMessage(false)); 833 assertThat(mScanManager.getRegularScanQueue()).contains(client); 834 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 835 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 836 // Set as foreground app 837 sendMessageWaitForProcessed(createImportanceMessage(true)); 838 assertThat(mScanManager.getRegularScanQueue()).contains(client); 839 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 840 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 841 } 842 } 843 844 @Test testSwitchForeBackgroundFilteredScan()845 public void testSwitchForeBackgroundFilteredScan() { 846 // Set filtered scan flag 847 final boolean isFiltered = true; 848 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 849 SparseIntArray scanModeMap = new SparseIntArray(); 850 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 851 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_LOW_POWER); 852 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_POWER); 853 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_POWER); 854 855 for (int i = 0; i < scanModeMap.size(); i++) { 856 int scanMode = scanModeMap.keyAt(i); 857 int expectedScanMode = scanModeMap.get(scanMode); 858 Log.d( 859 TAG, 860 "ScanMode: " 861 + String.valueOf(scanMode) 862 + " expectedScanMode: " 863 + String.valueOf(expectedScanMode)); 864 865 // Turn on screen 866 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 867 // Create scan client 868 ScanClient client = createScanClient(i, isFiltered, scanMode); 869 // Start scan 870 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 871 assertThat(mScanManager.getRegularScanQueue()).contains(client); 872 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 873 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 874 // Set as background app 875 sendMessageWaitForProcessed(createImportanceMessage(false)); 876 assertThat(mScanManager.getRegularScanQueue()).contains(client); 877 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 878 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 879 // Set as foreground app 880 sendMessageWaitForProcessed(createImportanceMessage(true)); 881 assertThat(mScanManager.getRegularScanQueue()).contains(client); 882 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 883 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 884 } 885 } 886 887 @Test testUpgradeStartScan()888 public void testUpgradeStartScan() { 889 // Set filtered scan flag 890 final boolean isFiltered = true; 891 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 892 SparseIntArray scanModeMap = new SparseIntArray(); 893 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_BALANCED); 894 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_LOW_LATENCY); 895 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 896 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_LATENCY); 897 doReturn(DEFAULT_SCAN_UPGRADE_DURATION_MILLIS) 898 .when(mAdapterService) 899 .getScanUpgradeDurationMillis(); 900 901 for (int i = 0; i < scanModeMap.size(); i++) { 902 int scanMode = scanModeMap.keyAt(i); 903 int expectedScanMode = scanModeMap.get(scanMode); 904 Log.d( 905 TAG, 906 "ScanMode: " 907 + String.valueOf(scanMode) 908 + " expectedScanMode: " 909 + String.valueOf(expectedScanMode)); 910 911 // Turn on screen 912 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 913 // Set as foreground app 914 sendMessageWaitForProcessed(createImportanceMessage(true)); 915 // Create scan client 916 ScanClient client = createScanClient(i, isFiltered, scanMode); 917 // Start scan 918 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 919 assertThat(mScanManager.getRegularScanQueue()).contains(client); 920 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 921 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 922 // Wait for upgrade duration 923 advanceTime(DEFAULT_SCAN_UPGRADE_DURATION_MILLIS); 924 mLooper.dispatchAll(); 925 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 926 } 927 } 928 929 @Test testUpDowngradeStartScanForConcurrency()930 public void testUpDowngradeStartScanForConcurrency() { 931 // Set filtered scan flag 932 final boolean isFiltered = true; 933 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 934 SparseIntArray scanModeMap = new SparseIntArray(); 935 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_BALANCED); 936 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 937 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_BALANCED); 938 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_BALANCED); 939 doReturn(DEFAULT_SCAN_UPGRADE_DURATION_MILLIS) 940 .when(mAdapterService) 941 .getScanUpgradeDurationMillis(); 942 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 943 .when(mAdapterService) 944 .getScanDowngradeDurationMillis(); 945 946 for (int i = 0; i < scanModeMap.size(); i++) { 947 int scanMode = scanModeMap.keyAt(i); 948 int expectedScanMode = scanModeMap.get(scanMode); 949 Log.d( 950 TAG, 951 "ScanMode: " 952 + String.valueOf(scanMode) 953 + " expectedScanMode: " 954 + String.valueOf(expectedScanMode)); 955 956 // Turn on screen 957 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 958 // Set as foreground app 959 sendMessageWaitForProcessed(createImportanceMessage(true)); 960 // Set connecting state 961 sendMessageWaitForProcessed(createConnectingMessage(true)); 962 // Create scan client 963 ScanClient client = createScanClient(i, isFiltered, scanMode); 964 // Start scan 965 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 966 assertThat(mScanManager.getRegularScanQueue()).contains(client); 967 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 968 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 969 // Wait for upgrade and downgrade duration 970 int max_duration = 971 DEFAULT_SCAN_UPGRADE_DURATION_MILLIS 972 > DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS 973 ? DEFAULT_SCAN_UPGRADE_DURATION_MILLIS 974 : DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS; 975 advanceTime(max_duration); 976 mLooper.dispatchAll(); 977 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 978 } 979 } 980 981 @Test testDowngradeDuringScanForConcurrency()982 public void testDowngradeDuringScanForConcurrency() { 983 // Set filtered scan flag 984 final boolean isFiltered = true; 985 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 986 SparseIntArray scanModeMap = new SparseIntArray(); 987 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 988 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 989 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_BALANCED); 990 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 991 992 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 993 .when(mAdapterService) 994 .getScanDowngradeDurationMillis(); 995 996 for (int i = 0; i < scanModeMap.size(); i++) { 997 int scanMode = scanModeMap.keyAt(i); 998 int expectedScanMode = scanModeMap.get(scanMode); 999 Log.d( 1000 TAG, 1001 "ScanMode: " 1002 + String.valueOf(scanMode) 1003 + " expectedScanMode: " 1004 + String.valueOf(expectedScanMode)); 1005 1006 // Turn on screen 1007 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1008 // Set as foreground app 1009 sendMessageWaitForProcessed(createImportanceMessage(true)); 1010 // Create scan client 1011 ScanClient client = createScanClient(i, isFiltered, scanMode); 1012 // Start scan 1013 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1014 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1015 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1016 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1017 // Set connecting state 1018 sendMessageWaitForProcessed(createConnectingMessage(true)); 1019 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 1020 // Wait for downgrade duration 1021 advanceTime(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS); 1022 mLooper.dispatchAll(); 1023 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1024 } 1025 } 1026 1027 @Test testDowngradeDuringScanForConcurrencyScreenOff()1028 public void testDowngradeDuringScanForConcurrencyScreenOff() { 1029 // Set filtered scan flag 1030 final boolean isFiltered = true; 1031 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1032 SparseIntArray scanModeMap = new SparseIntArray(); 1033 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 1034 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF_BALANCED); 1035 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 1036 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF_BALANCED); 1037 1038 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1039 .when(mAdapterService) 1040 .getScanDowngradeDurationMillis(); 1041 1042 for (int i = 0; i < scanModeMap.size(); i++) { 1043 int scanMode = scanModeMap.keyAt(i); 1044 int expectedScanMode = scanModeMap.get(scanMode); 1045 Log.d( 1046 TAG, 1047 "ScanMode: " 1048 + String.valueOf(scanMode) 1049 + " expectedScanMode: " 1050 + String.valueOf(expectedScanMode)); 1051 1052 // Turn on screen 1053 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1054 // Set as foreground app 1055 sendMessageWaitForProcessed(createImportanceMessage(true)); 1056 // Create scan client 1057 ScanClient client = createScanClient(i, isFiltered, scanMode); 1058 // Start scan 1059 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1060 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1061 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1062 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1063 // Set connecting state 1064 sendMessageWaitForProcessed(createConnectingMessage(true)); 1065 // Turn off screen 1066 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1067 // Move time forward so that MSG_STOP_CONNECTING can be dispatched 1068 advanceTime(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS); 1069 syncHandler(ScanManager.MSG_STOP_CONNECTING); 1070 mLooper.dispatchAll(); 1071 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1072 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1073 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 1074 } 1075 } 1076 1077 @Test testDowngradeDuringScanForConcurrencyBackground()1078 public void testDowngradeDuringScanForConcurrencyBackground() { 1079 // Set filtered scan flag 1080 final boolean isFiltered = true; 1081 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1082 SparseIntArray scanModeMap = new SparseIntArray(); 1083 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 1084 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_LOW_POWER); 1085 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_POWER); 1086 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_POWER); 1087 1088 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1089 .when(mAdapterService) 1090 .getScanDowngradeDurationMillis(); 1091 1092 for (int i = 0; i < scanModeMap.size(); i++) { 1093 int scanMode = scanModeMap.keyAt(i); 1094 int expectedScanMode = scanModeMap.get(scanMode); 1095 Log.d( 1096 TAG, 1097 "ScanMode: " 1098 + String.valueOf(scanMode) 1099 + " expectedScanMode: " 1100 + String.valueOf(expectedScanMode)); 1101 1102 // Turn on screen 1103 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1104 // Set as foreground app 1105 sendMessageWaitForProcessed(createImportanceMessage(true)); 1106 // Create scan client 1107 ScanClient client = createScanClient(i, isFiltered, scanMode); 1108 // Start scan 1109 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1110 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1111 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1112 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1113 // Set connecting state 1114 sendMessageWaitForProcessed(createConnectingMessage(true)); 1115 // Set as background app 1116 sendMessageWaitForProcessed(createImportanceMessage(false)); 1117 // Wait for downgrade duration 1118 advanceTime(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS); 1119 mLooper.dispatchAll(); 1120 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1121 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1122 assertThat(client.settings.getScanMode()).isEqualTo(expectedScanMode); 1123 } 1124 } 1125 1126 @Test testStartUnfilteredBatchScan()1127 public void testStartUnfilteredBatchScan() { 1128 // Set filtered and batch scan flag 1129 final boolean isFiltered = false; 1130 final boolean isBatch = true; 1131 final boolean isAutoBatch = false; 1132 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1133 SparseIntArray scanModeMap = new SparseIntArray(); 1134 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 1135 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 1136 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 1137 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_LATENCY); 1138 1139 for (int i = 0; i < scanModeMap.size(); i++) { 1140 int scanMode = scanModeMap.keyAt(i); 1141 int expectedScanMode = scanModeMap.get(scanMode); 1142 Log.d( 1143 TAG, 1144 "ScanMode: " 1145 + String.valueOf(scanMode) 1146 + " expectedScanMode: " 1147 + String.valueOf(expectedScanMode)); 1148 1149 // Turn off screen 1150 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1151 // Create scan client 1152 ScanClient client = createScanClient(i, isFiltered, scanMode, isBatch, isAutoBatch); 1153 // Start scan 1154 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1155 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1156 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1157 assertThat(mScanManager.getBatchScanQueue()).doesNotContain(client); 1158 // Turn on screen 1159 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1160 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1161 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1162 assertThat(mScanManager.getBatchScanQueue()).contains(client); 1163 assertThat(mScanManager.getBatchScanParams().scanMode).isEqualTo(expectedScanMode); 1164 } 1165 } 1166 1167 @Test testStartFilteredBatchScan()1168 public void testStartFilteredBatchScan() { 1169 // Set filtered and batch scan flag 1170 final boolean isFiltered = true; 1171 final boolean isBatch = true; 1172 final boolean isAutoBatch = false; 1173 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1174 SparseIntArray scanModeMap = new SparseIntArray(); 1175 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 1176 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 1177 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 1178 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_LOW_LATENCY); 1179 1180 for (int i = 0; i < scanModeMap.size(); i++) { 1181 int scanMode = scanModeMap.keyAt(i); 1182 int expectedScanMode = scanModeMap.get(scanMode); 1183 Log.d( 1184 TAG, 1185 "ScanMode: " 1186 + String.valueOf(scanMode) 1187 + " expectedScanMode: " 1188 + String.valueOf(expectedScanMode)); 1189 1190 // Turn off screen 1191 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1192 // Create scan client 1193 ScanClient client = createScanClient(i, isFiltered, scanMode, isBatch, isAutoBatch); 1194 // Start scan 1195 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1196 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1197 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1198 assertThat(mScanManager.getBatchScanParams().scanMode).isEqualTo(expectedScanMode); 1199 // Turn on screen 1200 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1201 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1202 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1203 assertThat(mScanManager.getBatchScanQueue()).contains(client); 1204 assertThat(mScanManager.getBatchScanParams().scanMode).isEqualTo(expectedScanMode); 1205 } 1206 } 1207 1208 @Test testUnfilteredAutoBatchScan()1209 public void testUnfilteredAutoBatchScan() { 1210 // Set filtered and batch scan flag 1211 final boolean isFiltered = false; 1212 final boolean isBatch = true; 1213 final boolean isAutoBatch = true; 1214 // Set report delay for auto batch scan callback type 1215 mScanReportDelay = ScanSettings.AUTO_BATCH_MIN_REPORT_DELAY_MILLIS; 1216 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1217 SparseIntArray scanModeMap = new SparseIntArray(); 1218 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 1219 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF); 1220 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_SCREEN_OFF); 1221 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF); 1222 1223 for (int i = 0; i < scanModeMap.size(); i++) { 1224 int scanMode = scanModeMap.keyAt(i); 1225 int expectedScanMode = scanModeMap.get(scanMode); 1226 Log.d( 1227 TAG, 1228 "ScanMode: " 1229 + String.valueOf(scanMode) 1230 + " expectedScanMode: " 1231 + String.valueOf(expectedScanMode)); 1232 1233 // Turn off screen 1234 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1235 // Create scan client 1236 ScanClient client = createScanClient(i, isFiltered, scanMode, isBatch, isAutoBatch); 1237 // Start scan 1238 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1239 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1240 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1241 assertThat(mScanManager.getBatchScanQueue()).doesNotContain(client); 1242 assertThat(mScanManager.getBatchScanParams()).isNull(); 1243 // Turn on screen 1244 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1245 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1246 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1247 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1248 assertThat(mScanManager.getBatchScanQueue()).doesNotContain(client); 1249 assertThat(mScanManager.getBatchScanParams()).isNull(); 1250 // Turn off screen 1251 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1252 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1253 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1254 assertThat(mScanManager.getBatchScanQueue()).doesNotContain(client); 1255 assertThat(mScanManager.getBatchScanParams()).isNull(); 1256 } 1257 } 1258 1259 @Test testFilteredAutoBatchScan()1260 public void testFilteredAutoBatchScan() { 1261 // Set filtered and batch scan flag 1262 final boolean isFiltered = true; 1263 final boolean isBatch = true; 1264 final boolean isAutoBatch = true; 1265 // Set report delay for auto batch scan callback type 1266 mScanReportDelay = ScanSettings.AUTO_BATCH_MIN_REPORT_DELAY_MILLIS; 1267 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 1268 SparseIntArray scanModeMap = new SparseIntArray(); 1269 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_SCREEN_OFF); 1270 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_SCREEN_OFF); 1271 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_SCREEN_OFF); 1272 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_SCREEN_OFF); 1273 1274 for (int i = 0; i < scanModeMap.size(); i++) { 1275 int scanMode = scanModeMap.keyAt(i); 1276 int expectedScanMode = scanModeMap.get(scanMode); 1277 Log.d( 1278 TAG, 1279 "ScanMode: " 1280 + String.valueOf(scanMode) 1281 + " expectedScanMode: " 1282 + String.valueOf(expectedScanMode)); 1283 1284 // Turn off screen 1285 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1286 // Create scan client 1287 ScanClient client = createScanClient(i, isFiltered, scanMode, isBatch, isAutoBatch); 1288 // Start scan 1289 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1290 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1291 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1292 assertThat(mScanManager.getBatchScanQueue()).contains(client); 1293 assertThat(mScanManager.getBatchScanParams().scanMode).isEqualTo(expectedScanMode); 1294 // Turn on screen 1295 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1296 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1297 assertThat(client.settings.getScanMode()).isEqualTo(scanMode); 1298 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1299 assertThat(mScanManager.getBatchScanQueue()).doesNotContain(client); 1300 assertThat(mScanManager.getBatchScanParams()).isNull(); 1301 // Turn off screen 1302 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1303 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1304 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1305 assertThat(mScanManager.getBatchScanQueue()).contains(client); 1306 assertThat(mScanManager.getBatchScanParams().scanMode).isEqualTo(expectedScanMode); 1307 } 1308 } 1309 1310 @Test testLocationAndScreenOnOffResumeUnfilteredScan()1311 public void testLocationAndScreenOnOffResumeUnfilteredScan() { 1312 // Set filtered scan flag 1313 final boolean isFiltered = false; 1314 // Set scan mode array 1315 int[] scanModeArr = { 1316 SCAN_MODE_LOW_POWER, 1317 SCAN_MODE_BALANCED, 1318 SCAN_MODE_LOW_LATENCY, 1319 SCAN_MODE_AMBIENT_DISCOVERY 1320 }; 1321 1322 for (int i = 0; i < scanModeArr.length; i++) { 1323 int scanMode = scanModeArr[i]; 1324 Log.d(TAG, "ScanMode: " + String.valueOf(scanMode)); 1325 // Turn on screen 1326 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1327 // Create scan client 1328 ScanClient client = createScanClient(i, isFiltered, scanMode); 1329 // Start scan 1330 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1331 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1332 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1333 // Turn off location 1334 doReturn(false).when(mLocationManager).isLocationEnabled(); 1335 sendMessageWaitForProcessed(createLocationOnOffMessage(false)); 1336 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1337 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1338 // Turn off screen 1339 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1340 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1341 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1342 // Turn on screen 1343 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1344 assertThat(mScanManager.getRegularScanQueue()).doesNotContain(client); 1345 assertThat(mScanManager.getSuspendedScanQueue()).contains(client); 1346 // Turn on location 1347 doReturn(true).when(mLocationManager).isLocationEnabled(); 1348 sendMessageWaitForProcessed(createLocationOnOffMessage(true)); 1349 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1350 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1351 } 1352 } 1353 1354 @Test 1355 @EnableFlags(Flags.FLAG_BLE_SCAN_ADV_METRICS_REDESIGN) testMetricsAppScanScreenOn()1356 public void testMetricsAppScanScreenOn() { 1357 // Set filtered scan flag 1358 final boolean isFiltered = true; 1359 final long scanTestDuration = 100; 1360 // Turn on screen 1361 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1362 1363 // Set scan mode map {original scan mode (ScanMode) : logged scan mode (loggedScanMode)} 1364 SparseIntArray scanModeMap = new SparseIntArray(); 1365 scanModeMap.put( 1366 SCAN_MODE_LOW_POWER, 1367 BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_POWER); 1368 scanModeMap.put( 1369 SCAN_MODE_BALANCED, 1370 BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_BALANCED); 1371 scanModeMap.put( 1372 SCAN_MODE_LOW_LATENCY, 1373 BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_LATENCY); 1374 scanModeMap.put( 1375 SCAN_MODE_AMBIENT_DISCOVERY, 1376 BluetoothStatsLog 1377 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_AMBIENT_DISCOVERY); 1378 1379 for (int i = 0; i < scanModeMap.size(); i++) { 1380 int scanMode = scanModeMap.keyAt(i); 1381 int loggedScanMode = scanModeMap.get(scanMode); 1382 1383 // Create workSource for the app 1384 final String APP_NAME = TEST_APP_NAME + i; 1385 final int UID = 10000 + i; 1386 final String PACKAGE_NAME = TEST_PACKAGE_NAME + i; 1387 WorkSource source = new WorkSource(UID, PACKAGE_NAME); 1388 // Create app scan stats for the app 1389 AppScanStats appScanStats = 1390 spy( 1391 new AppScanStats( 1392 APP_NAME, 1393 source, 1394 null, 1395 mAdapterService, 1396 mScanHelper, 1397 mTimeProvider)); 1398 // Create scan client for the app, which also records scan start 1399 ScanClient client = createScanClient(i, isFiltered, scanMode, UID, appScanStats); 1400 // Verify that the app scan start is logged 1401 mInOrder.verify(mMetricsLogger) 1402 .logAppScanStateChanged( 1403 new int[] {UID}, 1404 new String[] {PACKAGE_NAME}, 1405 true, 1406 true, 1407 false, 1408 BluetoothStatsLog 1409 .LE_APP_SCAN_STATE_CHANGED__SCAN_CALLBACK_TYPE__TYPE_ALL_MATCHES, 1410 BluetoothStatsLog 1411 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR, 1412 loggedScanMode, 1413 DEFAULT_REGULAR_SCAN_REPORT_DELAY_MS, 1414 0, 1415 0, 1416 true, 1417 false); 1418 1419 advanceTime(scanTestDuration); 1420 // Record scan stop 1421 client.stats.recordScanStop(i); 1422 // Verify that the app scan stop is logged 1423 mInOrder.verify(mMetricsLogger) 1424 .logAppScanStateChanged( 1425 eq(new int[] {UID}), 1426 eq(new String[] {PACKAGE_NAME}), 1427 eq(false), 1428 eq(true), 1429 eq(false), 1430 eq( 1431 BluetoothStatsLog 1432 .LE_APP_SCAN_STATE_CHANGED__SCAN_CALLBACK_TYPE__TYPE_ALL_MATCHES), 1433 eq( 1434 BluetoothStatsLog 1435 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1436 eq(loggedScanMode), 1437 eq((long) DEFAULT_REGULAR_SCAN_REPORT_DELAY_MS), 1438 eq(scanTestDuration), 1439 eq(0), 1440 eq(true), 1441 eq(false)); 1442 } 1443 } 1444 1445 @Test 1446 @EnableFlags(Flags.FLAG_BLE_SCAN_ADV_METRICS_REDESIGN) testMetricsRadioScanScreenOnOffMultiScan()1447 public void testMetricsRadioScanScreenOnOffMultiScan() { 1448 // Set filtered scan flag 1449 final boolean isFiltered = true; 1450 final long scanTestDuration = 100; 1451 // Turn on screen 1452 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1453 1454 // Create workSource for the first app 1455 final int UID_1 = 10001; 1456 final String APP_NAME_1 = TEST_APP_NAME + UID_1; 1457 final String PACKAGE_NAME_1 = TEST_PACKAGE_NAME + UID_1; 1458 WorkSource source1 = new WorkSource(UID_1, PACKAGE_NAME_1); 1459 // Create app scan stats for the first app 1460 AppScanStats appScanStats1 = 1461 spy( 1462 new AppScanStats( 1463 APP_NAME_1, 1464 source1, 1465 null, 1466 mAdapterService, 1467 mScanHelper, 1468 mTimeProvider)); 1469 // Create scan client for the first app 1470 ScanClient client1 = 1471 createScanClient(0, isFiltered, SCAN_MODE_LOW_POWER, UID_1, appScanStats1); 1472 // Start scan with lower duty cycle for the first app 1473 sendMessageWaitForProcessed(createStartStopScanMessage(true, client1)); 1474 advanceTime(scanTestDuration); 1475 1476 // Create workSource for the second app 1477 final int UID_2 = 10002; 1478 final String APP_NAME_2 = TEST_APP_NAME + UID_2; 1479 final String PACKAGE_NAME_2 = TEST_PACKAGE_NAME + UID_2; 1480 WorkSource source2 = new WorkSource(UID_2, PACKAGE_NAME_2); 1481 // Create app scan stats for the second app 1482 AppScanStats appScanStats2 = 1483 spy( 1484 new AppScanStats( 1485 APP_NAME_2, 1486 source2, 1487 null, 1488 mAdapterService, 1489 mScanHelper, 1490 mTimeProvider)); 1491 // Create scan client for the second app 1492 ScanClient client2 = 1493 createScanClient(1, isFiltered, SCAN_MODE_BALANCED, UID_2, appScanStats2); 1494 // Start scan with higher duty cycle for the second app 1495 sendMessageWaitForProcessed(createStartStopScanMessage(true, client2)); 1496 // Verify radio scan stop is logged with the first app 1497 mInOrder.verify(mMetricsLogger) 1498 .logRadioScanStopped( 1499 eq(new int[] {UID_1}), 1500 eq(new String[] {PACKAGE_NAME_1}), 1501 eq( 1502 BluetoothStatsLog 1503 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1504 eq( 1505 BluetoothStatsLog 1506 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_POWER), 1507 eq((long) ScanManager.SCAN_MODE_LOW_POWER_INTERVAL_MS), 1508 eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS), 1509 eq(true), 1510 eq(scanTestDuration)); 1511 advanceTime(scanTestDuration); 1512 1513 // Create workSource for the third app 1514 final int UID_3 = 10003; 1515 final String APP_NAME_3 = TEST_APP_NAME + UID_3; 1516 final String PACKAGE_NAME_3 = TEST_PACKAGE_NAME + UID_3; 1517 WorkSource source3 = new WorkSource(UID_3, PACKAGE_NAME_3); 1518 // Create app scan stats for the third app 1519 AppScanStats appScanStats3 = 1520 spy( 1521 new AppScanStats( 1522 APP_NAME_3, 1523 source3, 1524 null, 1525 mAdapterService, 1526 mScanHelper, 1527 mTimeProvider)); 1528 // Create scan client for the third app 1529 ScanClient client3 = 1530 createScanClient(2, isFiltered, SCAN_MODE_LOW_LATENCY, UID_3, appScanStats3); 1531 // Start scan with highest duty cycle for the third app 1532 sendMessageWaitForProcessed(createStartStopScanMessage(true, client3)); 1533 // Verify radio scan stop is logged with the second app 1534 mInOrder.verify(mMetricsLogger) 1535 .logRadioScanStopped( 1536 eq(new int[] {UID_2}), 1537 eq(new String[] {PACKAGE_NAME_2}), 1538 eq( 1539 BluetoothStatsLog 1540 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1541 eq( 1542 BluetoothStatsLog 1543 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_BALANCED), 1544 eq((long) ScanManager.SCAN_MODE_BALANCED_INTERVAL_MS), 1545 eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS), 1546 eq(true), 1547 eq(scanTestDuration)); 1548 advanceTime(scanTestDuration); 1549 1550 // Create workSource for the fourth app 1551 final int UID_4 = 10004; 1552 final String APP_NAME_4 = TEST_APP_NAME + UID_4; 1553 final String PACKAGE_NAME_4 = TEST_PACKAGE_NAME + UID_4; 1554 WorkSource source4 = new WorkSource(UID_4, PACKAGE_NAME_4); 1555 // Create app scan stats for the fourth app 1556 AppScanStats appScanStats4 = 1557 spy( 1558 new AppScanStats( 1559 APP_NAME_4, 1560 source4, 1561 null, 1562 mAdapterService, 1563 mScanHelper, 1564 mTimeProvider)); 1565 // Create scan client for the fourth app 1566 ScanClient client4 = 1567 createScanClient(3, isFiltered, SCAN_MODE_AMBIENT_DISCOVERY, UID_4, appScanStats4); 1568 // Start scan with lower duty cycle for the fourth app 1569 sendMessageWaitForProcessed(createStartStopScanMessage(true, client4)); 1570 // Verify radio scan stop is not logged with the third app since there is no change in radio 1571 // scan 1572 mInOrder.verify(mMetricsLogger, never()) 1573 .logRadioScanStopped( 1574 eq(new int[] {UID_3}), 1575 eq(new String[] {PACKAGE_NAME_3}), 1576 anyInt(), 1577 anyInt(), 1578 anyLong(), 1579 anyLong(), 1580 anyBoolean(), 1581 anyLong()); 1582 advanceTime(scanTestDuration); 1583 1584 // Set as background app 1585 sendMessageWaitForProcessed(createImportanceMessage(false, UID_1)); 1586 sendMessageWaitForProcessed(createImportanceMessage(false, UID_2)); 1587 sendMessageWaitForProcessed(createImportanceMessage(false, UID_3)); 1588 sendMessageWaitForProcessed(createImportanceMessage(false, UID_4)); 1589 // Turn off screen 1590 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1591 // Verify radio scan stop is logged with the third app when screen turns off 1592 mInOrder.verify(mMetricsLogger) 1593 .logRadioScanStopped( 1594 eq(new int[] {UID_3}), 1595 eq(new String[] {PACKAGE_NAME_3}), 1596 eq( 1597 BluetoothStatsLog 1598 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1599 eq( 1600 BluetoothStatsLog 1601 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_LATENCY), 1602 eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_INTERVAL_MS), 1603 eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS), 1604 eq(true), 1605 eq(scanTestDuration * 2)); 1606 advanceTime(scanTestDuration); 1607 1608 // Get the most aggressive scan client when screen is off 1609 // Since all the clients are updated to SCAN_MODE_SCREEN_OFF when screen is off and 1610 // app is in background mode, get the first client in the iterator 1611 Set<ScanClient> scanClients = mScanManager.getRegularScanQueue(); 1612 ScanClient mostAggressiveClient = scanClients.iterator().next(); 1613 1614 // Turn on screen 1615 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1616 // Set as foreground app 1617 sendMessageWaitForProcessed(createImportanceMessage(true, UID_1)); 1618 sendMessageWaitForProcessed(createImportanceMessage(true, UID_2)); 1619 sendMessageWaitForProcessed(createImportanceMessage(true, UID_3)); 1620 sendMessageWaitForProcessed(createImportanceMessage(true, UID_4)); 1621 // Verify radio scan stop is logged with the third app when screen turns on 1622 mInOrder.verify(mMetricsLogger) 1623 .logRadioScanStopped( 1624 eq(new int[] {mostAggressiveClient.appUid}), 1625 eq(new String[] {TEST_PACKAGE_NAME + mostAggressiveClient.appUid}), 1626 eq( 1627 BluetoothStatsLog 1628 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1629 eq(AppScanStats.convertScanMode(mostAggressiveClient.scanModeApp)), 1630 eq((long) SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS), 1631 eq((long) SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS), 1632 eq(false), 1633 eq(scanTestDuration)); 1634 advanceTime(scanTestDuration); 1635 1636 // Stop scan for the fourth app 1637 sendMessageWaitForProcessed(createStartStopScanMessage(false, client4)); 1638 // Verify radio scan stop is not logged with the third app since there is no change in radio 1639 // scan 1640 mInOrder.verify(mMetricsLogger, never()) 1641 .logRadioScanStopped( 1642 eq(new int[] {UID_3}), 1643 eq(new String[] {PACKAGE_NAME_3}), 1644 anyInt(), 1645 anyInt(), 1646 anyLong(), 1647 anyLong(), 1648 anyBoolean(), 1649 anyLong()); 1650 advanceTime(scanTestDuration); 1651 1652 // Stop scan for the third app 1653 sendMessageWaitForProcessed(createStartStopScanMessage(false, client3)); 1654 // Verify radio scan stop is logged with the third app 1655 mInOrder.verify(mMetricsLogger) 1656 .logRadioScanStopped( 1657 eq(new int[] {UID_3}), 1658 eq(new String[] {PACKAGE_NAME_3}), 1659 eq( 1660 BluetoothStatsLog 1661 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1662 eq( 1663 BluetoothStatsLog 1664 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_LATENCY), 1665 eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_INTERVAL_MS), 1666 eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS), 1667 eq(true), 1668 eq(scanTestDuration * 2)); 1669 advanceTime(scanTestDuration); 1670 1671 // Stop scan for the second app 1672 sendMessageWaitForProcessed(createStartStopScanMessage(false, client2)); 1673 // Verify radio scan stop is logged with the second app 1674 mInOrder.verify(mMetricsLogger) 1675 .logRadioScanStopped( 1676 eq(new int[] {UID_2}), 1677 eq(new String[] {PACKAGE_NAME_2}), 1678 eq( 1679 BluetoothStatsLog 1680 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1681 eq( 1682 BluetoothStatsLog 1683 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_BALANCED), 1684 eq((long) ScanManager.SCAN_MODE_BALANCED_INTERVAL_MS), 1685 eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS), 1686 eq(true), 1687 eq(scanTestDuration)); 1688 advanceTime(scanTestDuration); 1689 1690 // Stop scan for the first app 1691 sendMessageWaitForProcessed(createStartStopScanMessage(false, client1)); 1692 // Verify radio scan stop is logged with the first app 1693 mInOrder.verify(mMetricsLogger) 1694 .logRadioScanStopped( 1695 eq(new int[] {UID_1}), 1696 eq(new String[] {PACKAGE_NAME_1}), 1697 eq( 1698 BluetoothStatsLog 1699 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR), 1700 eq( 1701 BluetoothStatsLog 1702 .LE_APP_SCAN_STATE_CHANGED__LE_SCAN_MODE__SCAN_MODE_LOW_POWER), 1703 eq((long) ScanManager.SCAN_MODE_LOW_POWER_INTERVAL_MS), 1704 eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS), 1705 eq(true), 1706 eq(scanTestDuration)); 1707 } 1708 1709 @Test testMetricsScanRadioDurationScreenOn()1710 public void testMetricsScanRadioDurationScreenOn() { 1711 // Set filtered scan flag 1712 final boolean isFiltered = true; 1713 // Turn on screen 1714 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1715 Mockito.clearInvocations(mMetricsLogger); 1716 // Create scan client 1717 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_POWER); 1718 // Start scan 1719 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1720 mInOrder.verify(mMetricsLogger, never()) 1721 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1722 mInOrder.verify(mMetricsLogger, never()) 1723 .cacheCount( 1724 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1725 anyLong()); 1726 mInOrder.verify(mMetricsLogger, never()) 1727 .cacheCount( 1728 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1729 anyLong()); 1730 advanceTime(50); 1731 // Stop scan 1732 sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); 1733 mInOrder.verify(mMetricsLogger) 1734 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1735 mInOrder.verify(mMetricsLogger) 1736 .cacheCount( 1737 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1738 anyLong()); 1739 mInOrder.verify(mMetricsLogger, never()) 1740 .cacheCount( 1741 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1742 anyLong()); 1743 } 1744 1745 @Test testMetricsScanRadioDurationScreenOnOff()1746 public void testMetricsScanRadioDurationScreenOnOff() { 1747 // Set filtered scan flag 1748 final boolean isFiltered = true; 1749 // Turn on screen 1750 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1751 Mockito.clearInvocations(mMetricsLogger); 1752 // Create scan client 1753 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_POWER); 1754 // Start scan 1755 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1756 mInOrder.verify(mMetricsLogger, never()) 1757 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1758 mInOrder.verify(mMetricsLogger, never()) 1759 .cacheCount( 1760 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1761 anyLong()); 1762 mInOrder.verify(mMetricsLogger, never()) 1763 .cacheCount( 1764 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1765 anyLong()); 1766 advanceTime(50); 1767 // Turn off screen 1768 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1769 mInOrder.verify(mMetricsLogger) 1770 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1771 mInOrder.verify(mMetricsLogger) 1772 .cacheCount( 1773 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1774 anyLong()); 1775 mInOrder.verify(mMetricsLogger, never()) 1776 .cacheCount( 1777 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1778 anyLong()); 1779 advanceTime(50); 1780 // Turn on screen 1781 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1782 mInOrder.verify(mMetricsLogger) 1783 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1784 mInOrder.verify(mMetricsLogger, never()) 1785 .cacheCount( 1786 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1787 anyLong()); 1788 mInOrder.verify(mMetricsLogger) 1789 .cacheCount( 1790 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1791 anyLong()); 1792 advanceTime(50); 1793 // Stop scan 1794 sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); 1795 mInOrder.verify(mMetricsLogger) 1796 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1797 mInOrder.verify(mMetricsLogger) 1798 .cacheCount( 1799 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1800 anyLong()); 1801 mInOrder.verify(mMetricsLogger, never()) 1802 .cacheCount( 1803 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1804 anyLong()); 1805 } 1806 1807 @Test testMetricsScanRadioDurationMultiScan()1808 public void testMetricsScanRadioDurationMultiScan() { 1809 // Set filtered scan flag 1810 final boolean isFiltered = true; 1811 // Turn on screen 1812 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1813 Mockito.clearInvocations(mMetricsLogger); 1814 // Create scan clients with different duty cycles 1815 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_POWER); 1816 ScanClient client2 = createScanClient(1, isFiltered, SCAN_MODE_BALANCED); 1817 // Start scan with lower duty cycle 1818 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1819 mInOrder.verify(mMetricsLogger, never()) 1820 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1821 mInOrder.verify(mMetricsLogger, never()) 1822 .cacheCount( 1823 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1824 anyLong()); 1825 mInOrder.verify(mMetricsLogger, never()) 1826 .cacheCount( 1827 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1828 anyLong()); 1829 advanceTime(50); 1830 // Start scan with higher duty cycle 1831 sendMessageWaitForProcessed(createStartStopScanMessage(true, client2)); 1832 mInOrder.verify(mMetricsLogger) 1833 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1834 mInOrder.verify(mMetricsLogger) 1835 .cacheCount( 1836 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1837 anyLong()); 1838 mInOrder.verify(mMetricsLogger, never()) 1839 .cacheCount( 1840 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1841 anyLong()); 1842 advanceTime(50); 1843 // Stop scan with lower duty cycle 1844 sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); 1845 mInOrder.verify(mMetricsLogger, never()).cacheCount(anyInt(), anyLong()); 1846 // Stop scan with higher duty cycle 1847 sendMessageWaitForProcessed(createStartStopScanMessage(false, client2)); 1848 mInOrder.verify(mMetricsLogger) 1849 .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); 1850 mInOrder.verify(mMetricsLogger) 1851 .cacheCount( 1852 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), 1853 anyLong()); 1854 mInOrder.verify(mMetricsLogger, never()) 1855 .cacheCount( 1856 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_OFF), 1857 anyLong()); 1858 } 1859 1860 @Test testMetricsScanRadioWeightedDuration()1861 public void testMetricsScanRadioWeightedDuration() { 1862 // Set filtered scan flag 1863 final boolean isFiltered = true; 1864 final long scanTestDuration = 100; 1865 // Set scan mode map {scan mode (ScanMode) : scan weight (ScanWeight)} 1866 SparseIntArray scanModeMap = new SparseIntArray(); 1867 scanModeMap.put(SCAN_MODE_SCREEN_OFF, AppScanStats.SCREEN_OFF_LOW_POWER_WEIGHT); 1868 scanModeMap.put(SCAN_MODE_LOW_POWER, AppScanStats.LOW_POWER_WEIGHT); 1869 scanModeMap.put(SCAN_MODE_BALANCED, AppScanStats.BALANCED_WEIGHT); 1870 scanModeMap.put(SCAN_MODE_LOW_LATENCY, AppScanStats.LOW_LATENCY_WEIGHT); 1871 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, AppScanStats.AMBIENT_DISCOVERY_WEIGHT); 1872 1873 // Turn on screen 1874 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1875 for (int i = 0; i < scanModeMap.size(); i++) { 1876 int scanMode = scanModeMap.keyAt(i); 1877 long weightedScanDuration = 1878 (long) (scanTestDuration * scanModeMap.get(scanMode) * 0.01); 1879 Log.d( 1880 TAG, 1881 "ScanMode: " 1882 + String.valueOf(scanMode) 1883 + " weightedScanDuration: " 1884 + String.valueOf(weightedScanDuration)); 1885 1886 // Create scan client 1887 ScanClient client = createScanClient(i, isFiltered, scanMode); 1888 // Start scan 1889 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1890 // Wait for scan test duration 1891 advanceTime(Duration.ofMillis(scanTestDuration)); 1892 // Stop scan 1893 sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); 1894 mInOrder.verify(mMetricsLogger) 1895 .cacheCount( 1896 eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), 1897 eq(weightedScanDuration)); 1898 } 1899 } 1900 1901 @Test testMetricsScreenOnOff()1902 public void testMetricsScreenOnOff() { 1903 // Turn off screen initially 1904 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1905 Mockito.clearInvocations(mMetricsLogger); 1906 // Turn on screen 1907 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 1908 mInOrder.verify(mMetricsLogger, never()) 1909 .cacheCount(eq(BluetoothProtoEnums.SCREEN_OFF_EVENT), anyLong()); 1910 mInOrder.verify(mMetricsLogger) 1911 .cacheCount(eq(BluetoothProtoEnums.SCREEN_ON_EVENT), anyLong()); 1912 // Turn off screen 1913 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1914 mInOrder.verify(mMetricsLogger, never()) 1915 .cacheCount(eq(BluetoothProtoEnums.SCREEN_ON_EVENT), anyLong()); 1916 mInOrder.verify(mMetricsLogger) 1917 .cacheCount(eq(BluetoothProtoEnums.SCREEN_OFF_EVENT), anyLong()); 1918 } 1919 1920 @Test testDowngradeWithNonNullClientAppScanStats()1921 public void testDowngradeWithNonNullClientAppScanStats() { 1922 // Set filtered scan flag 1923 final boolean isFiltered = true; 1924 1925 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1926 .when(mAdapterService) 1927 .getScanDowngradeDurationMillis(); 1928 1929 // Turn off screen 1930 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1931 // Create scan client 1932 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_LATENCY); 1933 // Start Scan 1934 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1935 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1936 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1937 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_LOW_LATENCY); 1938 // Set connecting state 1939 sendMessageWaitForProcessed(createConnectingMessage(true)); 1940 // SCAN_MODE_LOW_LATENCY is now downgraded to SCAN_MODE_BALANCED 1941 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_BALANCED); 1942 } 1943 1944 @Test testDowngradeWithNullClientAppScanStats()1945 public void testDowngradeWithNullClientAppScanStats() { 1946 // Set filtered scan flag 1947 final boolean isFiltered = true; 1948 1949 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1950 .when(mAdapterService) 1951 .getScanDowngradeDurationMillis(); 1952 1953 // Turn off screen 1954 sendMessageWaitForProcessed(createScreenOnOffMessage(false)); 1955 // Create scan client 1956 ScanClient client = createScanClient(0, isFiltered, SCAN_MODE_LOW_LATENCY); 1957 // Start Scan 1958 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 1959 assertThat(mScanManager.getRegularScanQueue()).contains(client); 1960 assertThat(mScanManager.getSuspendedScanQueue()).doesNotContain(client); 1961 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_LOW_LATENCY); 1962 // Set AppScanStats to null 1963 client.stats = null; 1964 // Set connecting state 1965 sendMessageWaitForProcessed(createConnectingMessage(true)); 1966 // Since AppScanStats is null, no downgrade takes place for scan mode 1967 assertThat(client.settings.getScanMode()).isEqualTo(SCAN_MODE_LOW_LATENCY); 1968 } 1969 1970 @Test profileConnectionStateChanged_sendStartConnectionMessage()1971 public void profileConnectionStateChanged_sendStartConnectionMessage() { 1972 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1973 .when(mAdapterService) 1974 .getScanDowngradeDurationMillis(); 1975 assertThat(mScanManager.mIsConnecting).isFalse(); 1976 1977 mScanManager.handleBluetoothProfileConnectionStateChanged( 1978 BluetoothProfile.A2DP, 1979 BluetoothProfile.STATE_DISCONNECTED, 1980 BluetoothProfile.STATE_CONNECTING); 1981 1982 mLooper.dispatchAll(); 1983 assertThat(mScanManager.mIsConnecting).isTrue(); 1984 } 1985 1986 @Test multipleProfileConnectionStateChanged_updateCountersCorrectly()1987 public void multipleProfileConnectionStateChanged_updateCountersCorrectly() { 1988 doReturn(DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS) 1989 .when(mAdapterService) 1990 .getScanDowngradeDurationMillis(); 1991 assertThat(mScanManager.mIsConnecting).isFalse(); 1992 1993 mScanManager.handleBluetoothProfileConnectionStateChanged( 1994 BluetoothProfile.HEADSET, 1995 BluetoothProfile.STATE_DISCONNECTED, 1996 BluetoothProfile.STATE_CONNECTING); 1997 mScanManager.handleBluetoothProfileConnectionStateChanged( 1998 BluetoothProfile.A2DP, 1999 BluetoothProfile.STATE_DISCONNECTED, 2000 BluetoothProfile.STATE_CONNECTING); 2001 mScanManager.handleBluetoothProfileConnectionStateChanged( 2002 BluetoothProfile.HID_HOST, 2003 BluetoothProfile.STATE_DISCONNECTED, 2004 BluetoothProfile.STATE_CONNECTING); 2005 mLooper.dispatchAll(); 2006 assertThat(mScanManager.mProfilesConnecting).isEqualTo(3); 2007 } 2008 2009 @Test testSetScanPhy()2010 public void testSetScanPhy() { 2011 final boolean isFiltered = false; 2012 final boolean isEmptyFilter = false; 2013 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 2014 SparseIntArray scanModeMap = new SparseIntArray(); 2015 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 2016 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 2017 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 2018 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 2019 2020 for (int i = 0; i < scanModeMap.size(); i++) { 2021 int phy = PHY_LE_CODED; 2022 int scanMode = scanModeMap.keyAt(i); 2023 int expectedScanMode = scanModeMap.get(scanMode); 2024 Log.d( 2025 TAG, 2026 "ScanMode: " 2027 + String.valueOf(scanMode) 2028 + " expectedScanMode: " 2029 + String.valueOf(expectedScanMode)); 2030 2031 // Turn on screen 2032 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 2033 // Create scan client 2034 ScanClient client = 2035 createScanClientWithPhy(i, isFiltered, isEmptyFilter, scanMode, phy); 2036 // Start scan 2037 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 2038 2039 assertThat(client.settings.getPhy()).isEqualTo(phy); 2040 verify(mScanNativeInterface, atLeastOnce()) 2041 .gattSetScanParameters(anyInt(), anyInt(), anyInt(), eq(PHY_LE_CODED_MASK)); 2042 } 2043 } 2044 2045 @Test testSetScanPhyAllSupported()2046 public void testSetScanPhyAllSupported() { 2047 final boolean isFiltered = false; 2048 final boolean isEmptyFilter = false; 2049 // Set scan mode map {original scan mode (ScanMode) : expected scan mode (expectedScanMode)} 2050 SparseIntArray scanModeMap = new SparseIntArray(); 2051 scanModeMap.put(SCAN_MODE_LOW_POWER, SCAN_MODE_LOW_POWER); 2052 scanModeMap.put(SCAN_MODE_BALANCED, SCAN_MODE_BALANCED); 2053 scanModeMap.put(SCAN_MODE_LOW_LATENCY, SCAN_MODE_LOW_LATENCY); 2054 scanModeMap.put(SCAN_MODE_AMBIENT_DISCOVERY, SCAN_MODE_AMBIENT_DISCOVERY); 2055 2056 for (int i = 0; i < scanModeMap.size(); i++) { 2057 int phy = PHY_LE_ALL_SUPPORTED; 2058 int scanMode = scanModeMap.keyAt(i); 2059 int expectedScanMode = scanModeMap.get(scanMode); 2060 int expectedPhy = PHY_LE_1M_MASK; 2061 2062 Log.d(TAG, "ScanMode: " + scanMode + " expectedScanMode: " + expectedScanMode); 2063 2064 // Turn on screen 2065 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 2066 // Create scan client 2067 ScanClient client = 2068 createScanClientWithPhy(i, isFiltered, isEmptyFilter, scanMode, phy); 2069 // Start scan 2070 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 2071 2072 assertThat(client.settings.getPhy()).isEqualTo(phy); 2073 verify(mScanNativeInterface, atLeastOnce()) 2074 .gattSetScanParameters(anyInt(), anyInt(), anyInt(), eq(expectedPhy)); 2075 } 2076 } 2077 2078 @Test 2079 @EnableFlags(Flags.FLAG_LE_SCAN_MSFT_SUPPORT) testMsftScan()2080 public void testMsftScan() { 2081 doReturn(true).when(mScanNativeInterface).gattClientIsMsftSupported(); 2082 doReturn(false).when(mBluetoothAdapterProxy).isOffloadedScanFilteringSupported(); 2083 2084 final boolean isFiltered = true; 2085 final boolean isEmptyFilter = false; 2086 2087 boolean isMsftEnabled = SystemProperties.getBoolean(MSFT_HCI_EXT_ENABLED, false); 2088 SystemProperties.set(MSFT_HCI_EXT_ENABLED, Boolean.toString(true)); 2089 try { 2090 // Create new ScanManager since sysprop and MSFT support are only checked when 2091 // ScanManager is created 2092 mScanManager = 2093 new ScanManager( 2094 mAdapterService, 2095 mScanHelper, 2096 mBluetoothAdapterProxy, 2097 mLooper.getLooper(), 2098 mTimeProvider); 2099 2100 // Turn on screen 2101 sendMessageWaitForProcessed(createScreenOnOffMessage(true)); 2102 // Create scan client 2103 ScanClient client = createScanClient(0, isFiltered, isEmptyFilter, SCAN_MODE_LOW_POWER); 2104 // Start scan 2105 sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); 2106 2107 // Verify MSFT APIs 2108 verify(mScanNativeInterface, atLeastOnce()) 2109 .gattClientMsftAdvMonitorAdd( 2110 any(MsftAdvMonitor.Monitor.class), 2111 any(MsftAdvMonitor.Pattern[].class), 2112 any(MsftAdvMonitor.Address.class), 2113 anyInt()); 2114 verify(mScanNativeInterface, atLeastOnce()).gattClientMsftAdvMonitorEnable(eq(true)); 2115 } finally { 2116 SystemProperties.set(MSFT_HCI_EXT_ENABLED, Boolean.toString(isMsftEnabled)); 2117 } 2118 } 2119 } 2120