BluetoothStressTest.java revision e1d666b632608a2f708cb3df06c796e16d5d1717
1/* 2 * Copyright (C) 2010 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 17package android.bluetooth; 18 19import java.io.BufferedWriter; 20import java.io.File; 21import java.io.FileWriter; 22import java.io.IOException; 23 24import android.app.Instrumentation; 25import android.content.BroadcastReceiver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.os.Environment; 30import android.test.InstrumentationTestCase; 31import android.util.Log; 32 33public class BluetoothStressTest extends InstrumentationTestCase { 34 private static final String TAG = "BluetoothStressTest"; 35 private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt"; 36 37 /** 38 * Timeout for {@link BluetoothAdapter#disable()} in ms. 39 */ 40 private static final int DISABLE_TIMEOUT = 5000; 41 42 /** 43 * Timeout for {@link BluetoothAdapter#enable()} in ms. 44 */ 45 private static final int ENABLE_TIMEOUT = 20000; 46 47 /** 48 * Timeout for {@link BluetoothAdapter#setScanMode(int)} in ms. 49 */ 50 private static final int SET_SCAN_MODE_TIMEOUT = 5000; 51 52 /** 53 * Timeout for {@link BluetoothAdapter#startDiscovery()} in ms. 54 */ 55 private static final int START_DISCOVERY_TIMEOUT = 5000; 56 57 /** 58 * Timeout for {@link BluetoothAdapter#cancelDiscovery()} in ms. 59 */ 60 private static final int CANCEL_DISCOVERY_TIMEOUT = 5000; 61 62 private static final int DISCOVERY_STARTED_FLAG = 1; 63 private static final int DISCOVERY_FINISHED_FLAG = 1 << 1; 64 private static final int SCAN_MODE_NONE_FLAG = 1 << 2; 65 private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3; 66 private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4; 67 private static final int STATE_OFF_FLAG = 1 << 5; 68 private static final int STATE_TURNING_ON_FLAG = 1 << 6; 69 private static final int STATE_ON_FLAG = 1 << 7; 70 private static final int STATE_TURNING_OFF_FLAG = 1 << 8; 71 72 /** 73 * Time between polls in ms. 74 */ 75 private static final int POLL_TIME = 100; 76 77 private Context mContext; 78 79 private Instrumentation mInstrumentation; 80 81 private BufferedWriter mOutputWriter; 82 83 private class BluetoothReceiver extends BroadcastReceiver { 84 private int mFiredFlags = 0; 85 86 @Override 87 public void onReceive(Context context, Intent intent) { 88 synchronized (this) { 89 if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) { 90 mFiredFlags |= DISCOVERY_STARTED_FLAG; 91 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) { 92 mFiredFlags |= DISCOVERY_FINISHED_FLAG; 93 } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) { 94 int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 95 BluetoothAdapter.ERROR); 96 assertNotSame(mode, BluetoothAdapter.ERROR); 97 switch (mode) { 98 case BluetoothAdapter.SCAN_MODE_NONE: 99 mFiredFlags |= SCAN_MODE_NONE_FLAG; 100 break; 101 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 102 mFiredFlags |= SCAN_MODE_CONNECTABLE_FLAG; 103 break; 104 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 105 mFiredFlags |= SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG; 106 break; 107 } 108 } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { 109 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 110 BluetoothAdapter.ERROR); 111 assertNotSame(state, BluetoothAdapter.ERROR); 112 switch (state) { 113 case BluetoothAdapter.STATE_OFF: 114 mFiredFlags |= STATE_OFF_FLAG; 115 break; 116 case BluetoothAdapter.STATE_TURNING_ON: 117 mFiredFlags |= STATE_TURNING_ON_FLAG; 118 break; 119 case BluetoothAdapter.STATE_ON: 120 mFiredFlags |= STATE_ON_FLAG; 121 break; 122 case BluetoothAdapter.STATE_TURNING_OFF: 123 mFiredFlags |= STATE_TURNING_OFF_FLAG; 124 break; 125 } 126 } 127 } 128 } 129 130 public int getFiredFlags() { 131 synchronized (this) { 132 return mFiredFlags; 133 } 134 } 135 136 public void resetFiredFlags() { 137 synchronized (this) { 138 mFiredFlags = 0; 139 } 140 } 141 } 142 143 private BluetoothReceiver mReceiver = new BluetoothReceiver(); 144 145 @Override 146 protected void setUp() throws Exception { 147 super.setUp(); 148 149 mInstrumentation = getInstrumentation(); 150 mContext = mInstrumentation.getTargetContext(); 151 152 try { 153 mOutputWriter = new BufferedWriter(new FileWriter(new File( 154 Environment.getExternalStorageDirectory(), OUTPUT_FILE), true)); 155 } catch (IOException e) { 156 Log.w(TAG, "Test output file could not be opened", e); 157 mOutputWriter = null; 158 } 159 160 IntentFilter filter = new IntentFilter(); 161 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 162 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 163 filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 164 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 165 mContext.registerReceiver(mReceiver, filter); 166 } 167 168 @Override 169 protected void tearDown() throws Exception { 170 super.tearDown(); 171 172 mContext.unregisterReceiver(mReceiver); 173 174 if (mOutputWriter != null) { 175 try { 176 mOutputWriter.close(); 177 } catch (IOException e) { 178 Log.w(TAG, "Test output file could not be closed", e); 179 } 180 } 181 } 182 183 public void testEnable() { 184 int iterations = BluetoothTestRunner.sEnableIterations; 185 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 186 187 for (int i = 0; i < iterations; i++) { 188 writeOutput("enable iteration " + (i + 1) + " of " + iterations); 189 enable(adapter); 190 disable(adapter); 191 } 192 } 193 194 public void testDiscoverable() { 195 int iterations = BluetoothTestRunner.sDiscoverableIterations; 196 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 197 enable(adapter); 198 199 for (int i = 0; i < iterations; i++) { 200 writeOutput("discoverable iteration " + (i + 1) + " of " + iterations); 201 discoverable(adapter); 202 undiscoverable(adapter); 203 } 204 205 disable(adapter); 206 } 207 208 public void testScan() { 209 int iterations = BluetoothTestRunner.sScanIterations; 210 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 211 enable(adapter); 212 213 for (int i = 0; i < iterations; i++) { 214 writeOutput("scan iteration " + (i + 1) + " of " + iterations); 215 startScan(adapter); 216 stopScan(adapter); 217 } 218 219 disable(adapter); 220 } 221 222 private void disable(BluetoothAdapter adapter) { 223 int mask = STATE_TURNING_OFF_FLAG | STATE_OFF_FLAG | SCAN_MODE_NONE_FLAG; 224 mReceiver.resetFiredFlags(); 225 226 int state = adapter.getState(); 227 switch (state) { 228 case BluetoothAdapter.STATE_OFF: 229 assertFalse(adapter.isEnabled()); 230 return; 231 case BluetoothAdapter.STATE_ON: 232 assertTrue(adapter.isEnabled()); 233 assertTrue(adapter.disable()); 234 break; 235 case BluetoothAdapter.STATE_TURNING_ON: 236 assertFalse(adapter.isEnabled()); 237 assertTrue(adapter.disable()); 238 break; 239 case BluetoothAdapter.STATE_TURNING_OFF: 240 assertFalse(adapter.isEnabled()); 241 mask = 0; // Don't check for received intents since we might have missed them. 242 break; 243 default: 244 fail("disable() invalid state: state=" + state); 245 } 246 247 long s = System.currentTimeMillis(); 248 while (System.currentTimeMillis() - s < DISABLE_TIMEOUT) { 249 state = adapter.getState(); 250 if (state == BluetoothAdapter.STATE_OFF) { 251 assertFalse(adapter.isEnabled()); 252 if ((mReceiver.getFiredFlags() & mask) == mask) { 253 mReceiver.resetFiredFlags(); 254 writeOutput(String.format("disable() completed in %d ms", 255 (System.currentTimeMillis() - s))); 256 return; 257 } 258 } else { 259 assertFalse(adapter.isEnabled()); 260 assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state); 261 } 262 sleep(POLL_TIME); 263 } 264 265 int firedFlags = mReceiver.getFiredFlags(); 266 mReceiver.resetFiredFlags(); 267 fail(String.format("disable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)", 268 state, BluetoothAdapter.STATE_OFF, firedFlags, mask)); 269 } 270 271 private void enable(BluetoothAdapter adapter) { 272 int mask = STATE_TURNING_ON_FLAG | STATE_ON_FLAG | SCAN_MODE_CONNECTABLE_FLAG; 273 mReceiver.resetFiredFlags(); 274 275 int state = adapter.getState(); 276 switch (state) { 277 case BluetoothAdapter.STATE_ON: 278 assertTrue(adapter.isEnabled()); 279 return; 280 case BluetoothAdapter.STATE_OFF: 281 case BluetoothAdapter.STATE_TURNING_OFF: 282 assertFalse(adapter.isEnabled()); 283 assertTrue(adapter.enable()); 284 break; 285 case BluetoothAdapter.STATE_TURNING_ON: 286 assertFalse(adapter.isEnabled()); 287 mask = 0; // Don't check for received intents since we might have missed them. 288 break; 289 default: 290 fail("enable() invalid state: state=" + state); 291 } 292 293 long s = System.currentTimeMillis(); 294 while (System.currentTimeMillis() - s < ENABLE_TIMEOUT) { 295 state = adapter.getState(); 296 if (state == BluetoothAdapter.STATE_ON) { 297 assertTrue(adapter.isEnabled()); 298 if ((mReceiver.getFiredFlags() & mask) == mask) { 299 mReceiver.resetFiredFlags(); 300 writeOutput(String.format("enable() completed in %d ms", 301 (System.currentTimeMillis() - s))); 302 return; 303 } 304 } else { 305 assertFalse(adapter.isEnabled()); 306 assertEquals(BluetoothAdapter.STATE_TURNING_ON, state); 307 } 308 sleep(POLL_TIME); 309 } 310 311 int firedFlags = mReceiver.getFiredFlags(); 312 mReceiver.resetFiredFlags(); 313 fail(String.format("enable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)", 314 state, BluetoothAdapter.STATE_ON, firedFlags, mask)); 315 } 316 317 private void discoverable(BluetoothAdapter adapter) { 318 int mask = SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG; 319 mReceiver.resetFiredFlags(); 320 321 if (!adapter.isEnabled()) { 322 fail("discoverable() bluetooth not enabled"); 323 } 324 325 int scanMode = adapter.getScanMode(); 326 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { 327 return; 328 } 329 330 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE); 331 assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)); 332 333 long s = System.currentTimeMillis(); 334 while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) { 335 scanMode = adapter.getScanMode(); 336 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { 337 if ((mReceiver.getFiredFlags() & mask) == mask) { 338 mReceiver.resetFiredFlags(); 339 writeOutput(String.format("discoverable() completed in %d ms", 340 (System.currentTimeMillis() - s))); 341 return; 342 } 343 } else { 344 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE); 345 } 346 sleep(POLL_TIME); 347 } 348 349 int firedFlags = mReceiver.getFiredFlags(); 350 mReceiver.resetFiredFlags(); 351 fail(String.format("discoverable() timeout: scanMode=%d (expected %d), flags=0x%x " 352 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 353 firedFlags, mask)); 354 } 355 356 private void undiscoverable(BluetoothAdapter adapter) { 357 int mask = SCAN_MODE_CONNECTABLE_FLAG; 358 mReceiver.resetFiredFlags(); 359 360 if (!adapter.isEnabled()) { 361 fail("undiscoverable() bluetooth not enabled"); 362 } 363 364 int scanMode = adapter.getScanMode(); 365 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) { 366 return; 367 } 368 369 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); 370 assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE)); 371 372 long s = System.currentTimeMillis(); 373 while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) { 374 scanMode = adapter.getScanMode(); 375 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) { 376 if ((mReceiver.getFiredFlags() & mask) == mask) { 377 mReceiver.resetFiredFlags(); 378 writeOutput(String.format("undiscoverable() completed in %d ms", 379 (System.currentTimeMillis() - s))); 380 return; 381 } 382 } else { 383 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); 384 } 385 sleep(POLL_TIME); 386 } 387 388 int firedFlags = mReceiver.getFiredFlags(); 389 mReceiver.resetFiredFlags(); 390 fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d), flags=0x%x " 391 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE, firedFlags, 392 mask)); 393 } 394 395 private void startScan(BluetoothAdapter adapter) { 396 int mask = DISCOVERY_STARTED_FLAG; 397 mReceiver.resetFiredFlags(); 398 399 if (!adapter.isEnabled()) { 400 fail("startScan() bluetooth not enabled"); 401 } 402 403 if (adapter.isDiscovering()) { 404 return; 405 } 406 407 assertTrue(adapter.startDiscovery()); 408 409 long s = System.currentTimeMillis(); 410 while (System.currentTimeMillis() - s < START_DISCOVERY_TIMEOUT) { 411 if (adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) { 412 mReceiver.resetFiredFlags(); 413 writeOutput(String.format("startScan() completed in %d ms", 414 (System.currentTimeMillis() - s))); 415 return; 416 } 417 sleep(POLL_TIME); 418 } 419 420 int firedFlags = mReceiver.getFiredFlags(); 421 mReceiver.resetFiredFlags(); 422 fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)", 423 adapter.isDiscovering(), firedFlags, mask)); 424 } 425 426 private void stopScan(BluetoothAdapter adapter) { 427 int mask = DISCOVERY_FINISHED_FLAG; 428 mReceiver.resetFiredFlags(); 429 430 if (!adapter.isEnabled()) { 431 fail("stopScan() bluetooth not enabled"); 432 } 433 434 if (!adapter.isDiscovering()) { 435 return; 436 } 437 438 // TODO: put assertTrue() around cancelDiscovery() once it starts 439 // returning true. 440 adapter.cancelDiscovery(); 441 442 long s = System.currentTimeMillis(); 443 while (System.currentTimeMillis() - s < CANCEL_DISCOVERY_TIMEOUT) { 444 if (!adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) { 445 mReceiver.resetFiredFlags(); 446 writeOutput(String.format("stopScan() completed in %d ms", 447 (System.currentTimeMillis() - s))); 448 return; 449 } 450 sleep(POLL_TIME); 451 } 452 453 int firedFlags = mReceiver.getFiredFlags(); 454 mReceiver.resetFiredFlags(); 455 fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)", 456 adapter.isDiscovering(), firedFlags, mask)); 457 458 } 459 460 private void writeOutput(String s) { 461 if (mOutputWriter == null) { 462 return; 463 } 464 try { 465 Log.i(TAG, s); 466 mOutputWriter.write(s + "\n"); 467 mOutputWriter.flush(); 468 } catch (IOException e) { 469 Log.w(TAG, "Could not write to output file", e); 470 } 471 } 472 473 private void sleep(long time) { 474 try { 475 Thread.sleep(time); 476 } catch (InterruptedException e) { 477 } 478 } 479} 480