1 /* 2 * Copyright (C) 2015 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.cts.verifier.audio; 18 19 import android.app.AlertDialog; 20 import android.media.AudioDeviceCallback; 21 import android.media.AudioDeviceInfo; 22 import android.media.AudioManager; 23 import android.media.MediaRecorder; 24 import android.os.Bundle; 25 import android.os.Handler; 26 import android.os.Message; 27 import android.util.Log; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.widget.Button; 31 import android.widget.ProgressBar; 32 import android.widget.SeekBar; 33 import android.widget.TextView; 34 35 import com.android.compatibility.common.util.ResultType; 36 import com.android.compatibility.common.util.ResultUnit; 37 import com.android.cts.verifier.audio.audiolib.AudioSystemFlags; 38 import com.android.cts.verifier.audio.audiolib.StatUtils; 39 import com.android.cts.verifier.audio.audiolib.AudioUtils; 40 import com.android.cts.verifier.CtsVerifierReportLog; 41 import com.android.cts.verifier.PassFailButtons; 42 import com.android.cts.verifier.R; 43 44 import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode; 45 import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix; 46 47 /** 48 * Base class for testing activitiees that require audio loopback hardware.. 49 */ 50 public class AudioLoopbackBaseActivity extends PassFailButtons.Activity { 51 private static final String TAG = "AudioLoopbackBaseActivity"; 52 53 // JNI load 54 static { 55 try { 56 System.loadLibrary("audioloopback_jni"); 57 } catch (UnsatisfiedLinkError e) { 58 Log.e(TAG, "Error loading Audio Loopback JNI library"); 59 Log.e(TAG, "e: " + e); 60 e.printStackTrace(); 61 } 62 63 /* TODO: gracefully fail/notify if the library can't be loaded */ 64 } 65 protected AudioManager mAudioManager; 66 67 // UI 68 TextView mInputDeviceTxt; 69 TextView mOutputDeviceTxt; 70 71 TextView mAudioLevelText; 72 SeekBar mAudioLevelSeekbar; 73 74 TextView mTestPathTxt; 75 76 TextView mResultText; 77 ProgressBar mProgressBar; 78 int mMaxLevel; 79 80 String mYesString; 81 String mNoString; 82 83 // These flags determine the maximum allowed latency 84 private boolean mClaimsProAudio; 85 private boolean mClaimsOutput; 86 private boolean mClaimsInput; 87 88 // Useful info 89 private boolean mSupportsMMAP = AudioUtils.isMMapSupported(); 90 private boolean mSupportsMMAPExclusive = AudioUtils.isMMapExclusiveSupported(); 91 92 // Peripheral(s) 93 boolean mIsPeripheralAttached; // CDD ProAudio section C-1-3 94 AudioDeviceInfo mOutputDevInfo; 95 AudioDeviceInfo mInputDevInfo; 96 97 protected static final int TESTPERIPHERAL_NONE = 0; 98 protected static final int TESTPERIPHERAL_ANALOG_JACK = 1; 99 protected static final int TESTPERIPHERAL_USB = 2; 100 protected static final int TESTPERIPHERAL_DEVICE = 3; // device speaker + mic 101 protected int mTestPeripheral = TESTPERIPHERAL_NONE; 102 103 // Loopback Logic 104 NativeAnalyzerThread mNativeAnalyzerThread = null; 105 106 protected static final int NUM_TEST_PHASES = 5; 107 protected int mTestPhase = 0; 108 109 protected double[] mLatencyMillis = new double[NUM_TEST_PHASES]; 110 protected double[] mConfidence = new double[NUM_TEST_PHASES]; 111 112 protected double mMeanLatencyMillis; 113 protected double mMeanAbsoluteDeviation; 114 protected double mMeanConfidence; 115 116 protected static final double CONFIDENCE_THRESHOLD = 0.6; 117 // impossibly low latencies (indicating something in the test went wrong). 118 protected static final float EPSILON = 1.0f; 119 protected static final double PROAUDIO_RECOMMENDED_LATENCY_MS = 20.0; 120 protected static final double PROAUDIO_RECOMMENDED_USB_LATENCY_MS = 25.0; 121 protected static final double PROAUDIO_MUST_LATENCY_MS = 20.0; 122 protected static final double BASIC_RECOMMENDED_LATENCY_MS = 50.0; 123 protected static final double BASIC_MUST_LATENCY_MS = 800.0; 124 protected double mMustLatency; 125 protected double mRecommendedLatency; 126 127 // The audio stream callback threads should stop and close 128 // in less than a few hundred msec. This is a generous timeout value. 129 private static final int STOP_TEST_TIMEOUT_MSEC = 2 * 1000; 130 131 // 132 // Common UI Handling 133 // connectLoopbackUI()134 private void connectLoopbackUI() { 135 // Connected Device 136 mInputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackInputLbl)); 137 mOutputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackOutputLbl)); 138 139 mAudioLevelText = (TextView)findViewById(R.id.audio_loopback_level_text); 140 mAudioLevelSeekbar = (SeekBar)findViewById(R.id.audio_loopback_level_seekbar); 141 mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 142 mAudioLevelSeekbar.setMax(mMaxLevel); 143 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(0.7 * mMaxLevel), 0); 144 refreshLevel(); 145 146 mAudioLevelSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 147 @Override 148 public void onStopTrackingTouch(SeekBar seekBar) {} 149 150 @Override 151 public void onStartTrackingTouch(SeekBar seekBar) {} 152 153 @Override 154 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 155 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 156 progress, 0); 157 Log.i(TAG,"Level set to: " + progress); 158 refreshLevel(); 159 } 160 }); 161 162 mResultText = (TextView)findViewById(R.id.audio_loopback_results_text); 163 mProgressBar = (ProgressBar)findViewById(R.id.audio_loopback_progress_bar); 164 showWait(false); 165 } 166 167 // 168 // Peripheral Connection Logic 169 // scanPeripheralList(AudioDeviceInfo[] devices)170 protected void scanPeripheralList(AudioDeviceInfo[] devices) { 171 // CDD Section C-1-3: USB port, host-mode support 172 173 // Can't just use the first record because then we will only get 174 // Source OR sink, not both even on devices that are both. 175 mOutputDevInfo = null; 176 mInputDevInfo = null; 177 178 // Any valid peripherals 179 // Do we leave in the Headset test to support a USB-Dongle? 180 for (AudioDeviceInfo devInfo : devices) { 181 if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || // USB Peripheral 182 devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET || // USB dongle+LBPlug 183 devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug? 184 devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback? 185 if (devInfo.isSink()) { 186 mOutputDevInfo = devInfo; 187 } 188 if (devInfo.isSource()) { 189 mInputDevInfo = devInfo; 190 } 191 } else { 192 handleDeviceConnection(devInfo); 193 } 194 } 195 196 // need BOTH input and output to test 197 mIsPeripheralAttached = mOutputDevInfo != null && mInputDevInfo != null; 198 calculateTestPeripheral(); 199 showConnectedAudioPeripheral(); 200 calculateLatencyThresholds(); 201 displayLatencyThresholds(); 202 } 203 handleDeviceConnection(AudioDeviceInfo deviceInfo)204 protected void handleDeviceConnection(AudioDeviceInfo deviceInfo) { 205 // NOP 206 } 207 208 private class ConnectListener extends AudioDeviceCallback { ConnectListener()209 /*package*/ ConnectListener() {} 210 211 // 212 // AudioDevicesManager.OnDeviceConnectionListener 213 // 214 @Override onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)215 public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { 216 scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL)); 217 } 218 219 @Override onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)220 public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { 221 scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL)); 222 } 223 } 224 calculateTestPeripheral()225 protected void calculateTestPeripheral() { 226 if (!mIsPeripheralAttached) { 227 mTestPeripheral = TESTPERIPHERAL_DEVICE; 228 } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || 229 mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) { 230 mTestPeripheral = TESTPERIPHERAL_USB; 231 } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || 232 mInputDevInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { 233 mTestPeripheral = TESTPERIPHERAL_ANALOG_JACK; 234 } else { 235 // Huh? 236 Log.e(TAG, "No valid peripheral found!?"); 237 mTestPeripheral = TESTPERIPHERAL_NONE; 238 } 239 } 240 isPeripheralValidForTest()241 protected boolean isPeripheralValidForTest() { 242 return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK 243 || mTestPeripheral == TESTPERIPHERAL_USB; 244 245 } showConnectedAudioPeripheral()246 protected void showConnectedAudioPeripheral() { 247 mInputDeviceTxt.setText( 248 mInputDevInfo != null ? mInputDevInfo.getProductName().toString() 249 : ""); 250 mOutputDeviceTxt.setText( 251 mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString() 252 : ""); 253 254 String pathName; 255 switch (mTestPeripheral) { 256 case TESTPERIPHERAL_ANALOG_JACK: 257 pathName = "Headset Jack"; 258 break; 259 260 case TESTPERIPHERAL_USB: 261 pathName = "USB"; 262 break; 263 264 case TESTPERIPHERAL_DEVICE: 265 pathName = "Device Speaker + Microphone"; 266 break; 267 268 case TESTPERIPHERAL_NONE: 269 default: 270 pathName = "Error. Unknown Test Path"; 271 break; 272 } 273 mTestPathTxt.setText(pathName); 274 } 275 calculateLatencyThresholds()276 private void calculateLatencyThresholds() { 277 switch (mTestPeripheral) { 278 case TESTPERIPHERAL_ANALOG_JACK: 279 mRecommendedLatency = mClaimsProAudio 280 ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS; 281 mMustLatency = mClaimsProAudio 282 ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_MUST_LATENCY_MS; 283 break; 284 285 case TESTPERIPHERAL_USB: 286 mRecommendedLatency = mClaimsProAudio 287 ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS; 288 mMustLatency = mClaimsProAudio 289 ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_MUST_LATENCY_MS; 290 break; 291 292 case TESTPERIPHERAL_DEVICE: 293 // This isn't a valid case so we won't pass it, but it can be run 294 mRecommendedLatency = mClaimsProAudio 295 ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS; 296 mMustLatency = mClaimsProAudio 297 ? PROAUDIO_RECOMMENDED_LATENCY_MS :BASIC_MUST_LATENCY_MS; 298 break; 299 300 case TESTPERIPHERAL_NONE: 301 default: 302 mRecommendedLatency = BASIC_RECOMMENDED_LATENCY_MS; 303 mMustLatency = BASIC_MUST_LATENCY_MS; 304 break; 305 } 306 } 307 displayLatencyThresholds()308 private void displayLatencyThresholds() { 309 if (isPeripheralValidForTest()) { 310 ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText("" + mMustLatency); 311 ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText( 312 "" + mRecommendedLatency); 313 } else { 314 String naStr = getResources().getString(R.string.audio_proaudio_NA); 315 ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText(naStr); 316 ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(naStr); 317 } 318 } 319 320 /** 321 * refresh Audio Level seekbar and text 322 */ refreshLevel()323 private void refreshLevel() { 324 int currentLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 325 mAudioLevelSeekbar.setProgress(currentLevel); 326 327 String levelText = String.format("%s: %d/%d", 328 getResources().getString(R.string.audio_loopback_level_text), 329 currentLevel, mMaxLevel); 330 mAudioLevelText.setText(levelText); 331 } 332 333 // 334 // show active progress bar 335 // showWait(boolean show)336 protected void showWait(boolean show) { 337 mProgressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 338 } 339 340 // 341 // Common loging 342 // 343 // Schema 344 private static final String KEY_LATENCY = "latency"; 345 private static final String KEY_CONFIDENCE = "confidence"; 346 private static final String KEY_SAMPLE_RATE = "sample_rate"; 347 private static final String KEY_IS_PRO_AUDIO = "is_pro_audio"; 348 private static final String KEY_IS_LOW_LATENCY = "is_low_latency"; 349 private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached"; 350 private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral"; 351 private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral"; 352 private static final String KEY_TEST_PERIPHERAL = "test_peripheral"; 353 private static final String KEY_TEST_MMAP = "supports_mmap"; 354 private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive"; 355 356 @Override getTestId()357 public String getTestId() { 358 return setTestNameSuffix(sCurrentDisplayMode, getClass().getName()); 359 } 360 361 // 362 // Subclasses should call this explicitly. SubClasses should call submit() after their logs 363 // 364 @Override recordTestResults()365 public void recordTestResults() { 366 if (mNativeAnalyzerThread == null) { 367 return; // no results to report 368 } 369 370 CtsVerifierReportLog reportLog = getReportLog(); 371 reportLog.addValue( 372 KEY_LATENCY, 373 mMeanLatencyMillis, 374 ResultType.LOWER_BETTER, 375 ResultUnit.MS); 376 377 reportLog.addValue( 378 KEY_CONFIDENCE, 379 mMeanConfidence, 380 ResultType.HIGHER_BETTER, 381 ResultUnit.NONE); 382 383 reportLog.addValue( 384 KEY_SAMPLE_RATE, 385 mNativeAnalyzerThread.getSampleRate(), 386 ResultType.NEUTRAL, 387 ResultUnit.NONE); 388 389 reportLog.addValue( 390 KEY_IS_LOW_LATENCY, 391 mNativeAnalyzerThread.isLowLatencyStream(), 392 ResultType.NEUTRAL, 393 ResultUnit.NONE); 394 395 reportLog.addValue( 396 KEY_IS_PERIPHERAL_ATTACHED, 397 mIsPeripheralAttached, 398 ResultType.NEUTRAL, 399 ResultUnit.NONE); 400 401 reportLog.addValue( 402 KEY_IS_PRO_AUDIO, 403 mClaimsProAudio, 404 ResultType.NEUTRAL, 405 ResultUnit.NONE); 406 407 reportLog.addValue( 408 KEY_TEST_PERIPHERAL, 409 mTestPeripheral, 410 ResultType.NEUTRAL, 411 ResultUnit.NONE); 412 413 reportLog.addValue( 414 KEY_TEST_MMAP, 415 mSupportsMMAP, 416 ResultType.NEUTRAL, 417 ResultUnit.NONE); 418 419 reportLog.addValue( 420 KEY_TEST_MMAPEXCLUSIVE , 421 mSupportsMMAPExclusive, 422 ResultType.NEUTRAL, 423 ResultUnit.NONE); 424 425 if (mIsPeripheralAttached) { 426 reportLog.addValue( 427 KEY_INPUT_PERIPHERAL_NAME, 428 mInputDevInfo != null ? mInputDevInfo.getProductName().toString() : "None", 429 ResultType.NEUTRAL, 430 ResultUnit.NONE); 431 432 reportLog.addValue( 433 KEY_OUTPUT_PERIPHERAL_NAME, 434 mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString() : "None", 435 ResultType.NEUTRAL, 436 ResultUnit.NONE); 437 } 438 } 439 440 private static final String KEY_LOOPBACK_AVAILABLE = "loopback_available"; recordLoopbackStatus(boolean has)441 private void recordLoopbackStatus(boolean has) { 442 getReportLog().addValue( 443 KEY_LOOPBACK_AVAILABLE, 444 has, 445 ResultType.NEUTRAL, 446 ResultUnit.NONE); 447 } 448 startAudioTest(Handler messageHandler)449 protected void startAudioTest(Handler messageHandler) { 450 getPassButton().setEnabled(false); 451 452 mTestPhase = 0; 453 java.util.Arrays.fill(mLatencyMillis, 0.0); 454 java.util.Arrays.fill(mConfidence, 0.0); 455 456 mNativeAnalyzerThread = new NativeAnalyzerThread(this); 457 if (mNativeAnalyzerThread != null) { 458 mNativeAnalyzerThread.setMessageHandler(messageHandler); 459 // This value matches AAUDIO_INPUT_PRESET_VOICE_RECOGNITION 460 mNativeAnalyzerThread.setInputPreset(MediaRecorder.AudioSource.VOICE_RECOGNITION); 461 startTestPhase(); 462 } else { 463 Log.e(TAG, "Couldn't allocate native analyzer thread"); 464 mResultText.setText(getResources().getString(R.string.audio_loopback_failure)); 465 } 466 } 467 startTestPhase()468 private void startTestPhase() { 469 if (mNativeAnalyzerThread != null) { 470 mNativeAnalyzerThread.startTest(); 471 472 // what is this for? 473 try { 474 Thread.sleep(200); 475 } catch (InterruptedException e) { 476 e.printStackTrace(); 477 } 478 } 479 } 480 handleTestCompletion()481 protected void handleTestCompletion() { 482 mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis); 483 mMeanAbsoluteDeviation = 484 StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis); 485 mMeanConfidence = StatUtils.calculateMean(mConfidence); 486 487 488 String result; 489 if (mMeanConfidence < CONFIDENCE_THRESHOLD) { 490 result = String.format( 491 "Test Finished\nInsufficient Confidence (%.2f < %.2f). No Results.", 492 mMeanConfidence, CONFIDENCE_THRESHOLD); 493 } else { 494 result = String.format( 495 "Test Finished\nMean Latency:%.2f ms (required:%.2f)\n" + 496 "Mean Absolute Deviation: %.2f\n" + 497 " Confidence: %.2f\n" + 498 " Low Latency Path: %s", 499 mMeanLatencyMillis, 500 mMustLatency, 501 mMeanAbsoluteDeviation, 502 mMeanConfidence, 503 mNativeAnalyzerThread.isLowLatencyStream() ? mYesString : mNoString); 504 } 505 506 // Make sure the test thread is finished. It should already be done. 507 if (mNativeAnalyzerThread != null) { 508 try { 509 mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC); 510 } catch (InterruptedException e) { 511 e.printStackTrace(); 512 } 513 } 514 mResultText.setText(result); 515 } 516 handleTestPhaseCompletion()517 protected void handleTestPhaseCompletion() { 518 if (mNativeAnalyzerThread != null && mTestPhase < NUM_TEST_PHASES) { 519 mLatencyMillis[mTestPhase] = mNativeAnalyzerThread.getLatencyMillis(); 520 mConfidence[mTestPhase] = mNativeAnalyzerThread.getConfidence(); 521 522 String result = String.format( 523 "Test %d Finished\nLatency: %.2f ms\nConfidence: %.2f\n", 524 mTestPhase, 525 mLatencyMillis[mTestPhase], 526 mConfidence[mTestPhase]); 527 528 mResultText.setText(result); 529 try { 530 mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC); 531 // Thread.sleep(/*STOP_TEST_TIMEOUT_MSEC*/500); 532 } catch (InterruptedException e) { 533 e.printStackTrace(); 534 } 535 536 mTestPhase++; 537 if (mTestPhase >= NUM_TEST_PHASES) { 538 handleTestCompletion(); 539 } else { 540 startTestPhase(); 541 } 542 } 543 } 544 545 /** 546 * handler for messages from audio thread 547 */ 548 protected Handler mMessageHandler = new Handler() { 549 public void handleMessage(Message msg) { 550 super.handleMessage(msg); 551 switch(msg.what) { 552 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED: 553 Log.v(TAG,"got message native rec started!!"); 554 showWait(true); 555 mResultText.setText(String.format("[phase: %d] - Test Running...", 556 (mTestPhase + 1))); 557 break; 558 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR: 559 Log.v(TAG,"got message native rec can't start!!"); 560 mResultText.setText("Test Error opening streams."); 561 handleTestCompletion(); 562 break; 563 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR: 564 Log.v(TAG,"got message native rec can't start!!"); 565 mResultText.setText("Test Error while recording."); 566 handleTestCompletion(); 567 break; 568 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS: 569 mResultText.setText("Test FAILED due to errors."); 570 handleTestCompletion(); 571 break; 572 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING: 573 Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING"); 574 mResultText.setText(String.format("[phase: %d] - Analyzing ...", 575 mTestPhase + 1)); 576 break; 577 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE: 578 Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE"); 579 handleTestPhaseCompletion(); 580 break; 581 default: 582 break; 583 } 584 } 585 }; 586 587 @Override onCreate(Bundle savedInstanceState)588 protected void onCreate(Bundle savedInstanceState) { 589 super.onCreate(savedInstanceState); 590 591 mClaimsOutput = AudioSystemFlags.claimsOutput(this); 592 mClaimsInput = AudioSystemFlags.claimsInput(this); 593 mClaimsProAudio = AudioSystemFlags.claimsProAudio(this); 594 595 mYesString = getResources().getString(R.string.audio_general_yes); 596 mNoString = getResources().getString(R.string.audio_general_no); 597 598 // Pro Audio 599 ((TextView)findViewById(R.id.audio_loopback_pro_audio)).setText( 600 "" + (mClaimsProAudio ? mYesString : mNoString)); 601 602 // MMAP 603 ((TextView)findViewById(R.id.audio_loopback_mmap)).setText( 604 "" + (mSupportsMMAP ? mYesString : mNoString)); 605 ((TextView)findViewById(R.id.audio_loopback_mmap_exclusive)).setText( 606 "" + (mSupportsMMAPExclusive ? mYesString : mNoString)); 607 608 // Low Latency 609 ((TextView)findViewById(R.id.audio_loopback_low_latency)).setText( 610 "" + (AudioSystemFlags.claimsLowLatencyAudio(this) ? mYesString : mNoString)); 611 612 mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath)); 613 614 mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE); 615 616 mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler()); 617 618 connectLoopbackUI(); 619 620 calculateLatencyThresholds(); 621 displayLatencyThresholds(); 622 } 623 } 624