1 /* 2 * Copyright 2017 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.mobileer.oboetester; 18 19 import android.content.Context; 20 import android.media.AudioManager; 21 import android.media.audiofx.AcousticEchoCanceler; 22 import android.media.audiofx.AutomaticGainControl; 23 import android.media.audiofx.BassBoost; 24 import android.media.audiofx.LoudnessEnhancer; 25 import android.media.audiofx.NoiseSuppressor; 26 import android.util.AttributeSet; 27 import android.util.Log; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.widget.AdapterView; 31 import android.widget.ArrayAdapter; 32 import android.widget.CheckBox; 33 import android.widget.CompoundButton; 34 import android.widget.LinearLayout; 35 import android.widget.SeekBar; 36 import android.widget.Spinner; 37 import android.widget.TableRow; 38 import android.widget.TextView; 39 40 import com.mobileer.audio_device.AudioDeviceListEntry; 41 import com.mobileer.audio_device.AudioDeviceSpinner; 42 43 import java.util.Locale; 44 45 /** 46 * View for Editing a requested StreamConfiguration 47 * and displaying the actual StreamConfiguration. 48 */ 49 50 public class StreamConfigurationView extends LinearLayout { 51 private static final String TAG = "StreamConfigurationView"; 52 53 protected Spinner mNativeApiSpinner; 54 private TextView mActualNativeApiView; 55 private TextView mActualDeviceIdView; 56 57 private TextView mActualMMapView; 58 private CheckBox mRequestedMMapView; 59 private TextView mActualExclusiveView; 60 private TextView mActualPerformanceView; 61 private Spinner mPerformanceSpinner; 62 private CheckBox mRequestedExclusiveView; 63 private CheckBox mChannelConversionBox; 64 private CheckBox mFormatConversionBox; 65 private Spinner mChannelCountSpinner; 66 private TextView mActualChannelCountView; 67 private Spinner mChannelMaskSpinner; 68 private TextView mActualChannelMaskView; 69 private TextView mActualFormatView; 70 private Spinner mCapacitySpinner; 71 private TextView mActualCapacityView; 72 private TableRow mInputPresetTableRow; 73 private Spinner mInputPresetSpinner; 74 private TextView mActualInputPresetView; 75 76 private TableRow mUsageTableRow; 77 private Spinner mUsageSpinner; 78 private TextView mActualUsageView; 79 80 private TableRow mContentTypeTableRow; 81 private Spinner mContentTypeSpinner; 82 private TextView mActualContentTypeView; 83 84 private TableRow mSpatializationBehaviorTableRow; 85 private Spinner mSpatializationBehaviorSpinner; 86 private TextView mActualSpatializationBehaviorView; 87 88 private Spinner mFormatSpinner; 89 private Spinner mSampleRateSpinner; 90 private Spinner mRateConversionQualitySpinner; 91 private TextView mActualSampleRateView; 92 private LinearLayout mHideableView; 93 94 private AudioDeviceSpinner mDeviceSpinner; 95 private TextView mActualSessionIdView; 96 private CheckBox mRequestAudioEffect; 97 private CheckBox mRequestSessionId; 98 99 private TextView mStreamInfoView; 100 private TextView mStreamStatusView; 101 private TextView mOptionExpander; 102 private String mHideSettingsText; 103 private String mShowSettingsText; 104 105 private LinearLayout mInputEffectsLayout; 106 private LinearLayout mOutputEffectsLayout; 107 108 private CheckBox mAutomaticGainControlCheckBox; 109 private CharSequence mAutomaticGainControlText; 110 private CheckBox mAcousticEchoCancelerCheckBox; 111 private CharSequence mAcousticEchoCancelerText; 112 private CheckBox mNoiseSuppressorCheckBox; 113 private CharSequence mNoiseSuppressorText; 114 private TextView mBassBoostTextView; 115 private SeekBar mBassBoostSeekBar; 116 private TextView mLoudnessEnhancerTextView; 117 private SeekBar mLoudnessEnhancerSeekBar; 118 119 private boolean mIsChannelMaskLastSelected; 120 121 private boolean misOutput; 122 123 private BassBoost mBassBoost; 124 private LoudnessEnhancer mLoudnessEnhancer; 125 private AutomaticGainControl mAutomaticGainControl; 126 private AcousticEchoCanceler mAcousticEchoCanceler; 127 private NoiseSuppressor mNoiseSuppressor; 128 129 // Create an anonymous implementation of OnClickListener 130 private View.OnClickListener mToggleListener = new View.OnClickListener() { 131 public void onClick(View v) { 132 if (mHideableView.isShown()) { 133 hideSettingsView(); 134 } else { 135 showSettingsView(); 136 } 137 } 138 }; 139 yesOrNo(boolean b)140 public static String yesOrNo(boolean b) { 141 return b ? "YES" : "NO"; 142 } 143 updateSettingsViewText()144 private void updateSettingsViewText() { 145 if (mHideableView.isShown()) { 146 mOptionExpander.setText(mHideSettingsText); 147 } else { 148 mOptionExpander.setText(mShowSettingsText); 149 } 150 } 151 showSettingsView()152 public void showSettingsView() { 153 mHideableView.setVisibility(View.VISIBLE); 154 updateSettingsViewText(); 155 } 156 hideSampleRateMenu()157 public void hideSampleRateMenu() { 158 if (mSampleRateSpinner != null) { 159 mSampleRateSpinner.setVisibility(View.GONE); 160 } 161 } 162 hideSettingsView()163 public void hideSettingsView() { 164 mHideableView.setVisibility(View.GONE); 165 updateSettingsViewText(); 166 } 167 StreamConfigurationView(Context context)168 public StreamConfigurationView(Context context) { 169 super(context); 170 initializeViews(context); 171 } 172 StreamConfigurationView(Context context, AttributeSet attrs)173 public StreamConfigurationView(Context context, AttributeSet attrs) { 174 super(context, attrs); 175 initializeViews(context); 176 } 177 StreamConfigurationView(Context context, AttributeSet attrs, int defStyle)178 public StreamConfigurationView(Context context, 179 AttributeSet attrs, 180 int defStyle) { 181 super(context, attrs, defStyle); 182 initializeViews(context); 183 } 184 185 /** 186 * Inflates the views in the layout. 187 * 188 * @param context 189 * the current context for the view. 190 */ initializeViews(Context context)191 private void initializeViews(Context context) { 192 LayoutInflater inflater = (LayoutInflater) context 193 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 194 inflater.inflate(R.layout.stream_config, this); 195 196 mHideSettingsText = getResources().getString(R.string.hint_hide_settings); 197 mShowSettingsText = getResources().getString(R.string.hint_show_settings); 198 199 mHideableView = (LinearLayout) findViewById(R.id.hideableView); 200 201 mOptionExpander = (TextView) findViewById(R.id.toggle_stream_config); 202 mOptionExpander.setOnClickListener(mToggleListener); 203 204 mNativeApiSpinner = (Spinner) findViewById(R.id.spinnerNativeApi); 205 mNativeApiSpinner.setSelection(StreamConfiguration.NATIVE_API_UNSPECIFIED); 206 207 mActualNativeApiView = (TextView) findViewById(R.id.actualNativeApi); 208 209 mActualDeviceIdView = (TextView) findViewById(R.id.actualDeviceId); 210 211 mChannelConversionBox = (CheckBox) findViewById(R.id.checkChannelConversion); 212 213 mFormatConversionBox = (CheckBox) findViewById(R.id.checkFormatConversion); 214 215 mActualMMapView = (TextView) findViewById(R.id.actualMMap); 216 mRequestedMMapView = (CheckBox) findViewById(R.id.requestedMMapEnable); 217 boolean mmapSupported = NativeEngine.isMMapSupported(); 218 mRequestedMMapView.setEnabled(mmapSupported); 219 mRequestedMMapView.setChecked(mmapSupported); 220 221 mActualExclusiveView = (TextView) findViewById(R.id.actualExclusiveMode); 222 mRequestedExclusiveView = (CheckBox) findViewById(R.id.requestedExclusiveMode); 223 224 boolean mmapExclusiveSupported = NativeEngine.isMMapExclusiveSupported(); 225 mRequestedExclusiveView.setEnabled(mmapExclusiveSupported); 226 mRequestedExclusiveView.setChecked(mmapExclusiveSupported); 227 228 mRequestSessionId = (CheckBox) findViewById(R.id.requestSessionId); 229 mActualSessionIdView = (TextView) findViewById(R.id.sessionId); 230 mRequestAudioEffect = (CheckBox) findViewById(R.id.requestAudioEffect); 231 232 mOutputEffectsLayout = (LinearLayout) findViewById(R.id.outputEffects); 233 mInputEffectsLayout = (LinearLayout) findViewById(R.id.inputEffects); 234 235 mRequestAudioEffect.setOnClickListener(new View.OnClickListener() { 236 @Override 237 public void onClick(View view) { 238 onRequestAudioEffectClicked(((CheckBox) view).isChecked()); 239 } 240 }); 241 242 mAutomaticGainControlCheckBox = (CheckBox) findViewById(R.id.checkBoxAutomaticGainControl); 243 mAcousticEchoCancelerCheckBox = (CheckBox) findViewById(R.id.checkBoxAcousticEchoCanceler); 244 mNoiseSuppressorCheckBox = (CheckBox) findViewById(R.id.checkBoxNoiseSuppressor); 245 mBassBoostTextView = (TextView) findViewById(R.id.textBassBoost); 246 mBassBoostSeekBar = (SeekBar) findViewById(R.id.seekBarBassBoost); 247 mLoudnessEnhancerTextView = (TextView) findViewById(R.id.textLoudnessEnhancer); 248 mLoudnessEnhancerSeekBar = (SeekBar) findViewById(R.id.seekBarLoudnessEnhancer); 249 250 mAutomaticGainControlCheckBox.setEnabled(AutomaticGainControl.isAvailable()); 251 mAutomaticGainControlText = mAutomaticGainControlCheckBox.getText(); 252 mAcousticEchoCancelerCheckBox.setEnabled(AcousticEchoCanceler.isAvailable()); 253 mAcousticEchoCancelerText = mAcousticEchoCancelerCheckBox.getText(); 254 mNoiseSuppressorCheckBox.setEnabled(NoiseSuppressor.isAvailable()); 255 mNoiseSuppressorText = mNoiseSuppressorCheckBox.getText(); 256 257 mBassBoostSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 258 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 259 onBassBoostSeekBarChanged(progress); 260 } 261 262 @Override 263 public void onStartTrackingTouch(SeekBar seekBar) { 264 } 265 266 @Override 267 public void onStopTrackingTouch(SeekBar seekBar) { 268 } 269 }); 270 271 mLoudnessEnhancerSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 272 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 273 onLoudnessEnhancerSeekBarChanged(progress); 274 } 275 276 @Override 277 public void onStartTrackingTouch(SeekBar seekBar) { 278 } 279 280 @Override 281 public void onStopTrackingTouch(SeekBar seekBar) { 282 } 283 }); 284 285 mAutomaticGainControlCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 286 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 287 onAutomaticGainControlCheckBoxChanged(isChecked); 288 } 289 }); 290 291 mAcousticEchoCancelerCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 292 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 293 onAcousticEchoCancelerCheckBoxChanged(isChecked); 294 } 295 }); 296 mNoiseSuppressorCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 297 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 298 onNoiseSuppressorCheckBoxChanged(isChecked); 299 } 300 }); 301 302 mActualSampleRateView = (TextView) findViewById(R.id.actualSampleRate); 303 mSampleRateSpinner = (Spinner) findViewById(R.id.spinnerSampleRate); 304 mActualChannelCountView = (TextView) findViewById(R.id.actualChannelCount); 305 mChannelCountSpinner = (Spinner) findViewById(R.id.spinnerChannelCount); 306 mChannelCountSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 307 @Override 308 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 309 onChannelCountSpinnerSelected(); 310 } 311 312 @Override 313 public void onNothingSelected(AdapterView<?> adapterView) { 314 // no-op 315 } 316 }); 317 mActualFormatView = (TextView) findViewById(R.id.actualAudioFormat); 318 mFormatSpinner = (Spinner) findViewById(R.id.spinnerFormat); 319 320 mActualCapacityView = (TextView) findViewById(R.id.actualCapacity); 321 mCapacitySpinner = (Spinner) findViewById(R.id.spinnerCapacity); 322 323 mRateConversionQualitySpinner = (Spinner) findViewById(R.id.spinnerSRCQuality); 324 325 mActualPerformanceView = (TextView) findViewById(R.id.actualPerformanceMode); 326 mPerformanceSpinner = (Spinner) findViewById(R.id.spinnerPerformanceMode); 327 mPerformanceSpinner.setSelection(StreamConfiguration.PERFORMANCE_MODE_LOW_LATENCY 328 - StreamConfiguration.PERFORMANCE_MODE_NONE); 329 330 mInputPresetTableRow = (TableRow) findViewById(R.id.rowInputPreset); 331 mActualInputPresetView = (TextView) findViewById(R.id.actualInputPreset); 332 mInputPresetSpinner = (Spinner) findViewById(R.id.spinnerInputPreset); 333 mInputPresetSpinner.setSelection(2); // TODO need better way to select voice recording default 334 335 mUsageTableRow = (TableRow) findViewById(R.id.rowUsage); 336 mActualUsageView = (TextView) findViewById(R.id.actualUsage); 337 mUsageSpinner = (Spinner) findViewById(R.id.spinnerUsage); 338 339 mContentTypeTableRow = (TableRow) findViewById(R.id.rowContentType); 340 mActualContentTypeView = (TextView) findViewById(R.id.actualContentType); 341 mContentTypeSpinner = (Spinner) findViewById(R.id.spinnerContentType); 342 343 mSpatializationBehaviorTableRow = (TableRow) findViewById(R.id.rowSpatializationBehavior); 344 mActualSpatializationBehaviorView = (TextView) findViewById(R.id.actualSpatializationBehavior); 345 mSpatializationBehaviorSpinner = (Spinner) findViewById(R.id.spinnerSpatializationBehavior); 346 347 mStreamInfoView = (TextView) findViewById(R.id.streamInfo); 348 349 mStreamStatusView = (TextView) findViewById(R.id.statusView); 350 351 mDeviceSpinner = (AudioDeviceSpinner) findViewById(R.id.devices_spinner); 352 353 mActualChannelMaskView = (TextView) findViewById(R.id.actualChannelMask); 354 mChannelMaskSpinner = (Spinner) findViewById(R.id.spinnerChannelMask); 355 ArrayAdapter<String> channelMaskSpinnerArrayAdapter = new ArrayAdapter<String>(context, 356 android.R.layout.simple_spinner_item, 357 StreamConfiguration.getAllChannelMasks()); 358 mChannelMaskSpinner.setAdapter(channelMaskSpinnerArrayAdapter); 359 mChannelMaskSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 360 @Override 361 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 362 onChannelMaskSpinnerSelected(); 363 } 364 365 @Override 366 public void onNothingSelected(AdapterView<?> adapterView) { 367 // no-op 368 } 369 }); 370 371 showSettingsView(); 372 } 373 setOutput(boolean output)374 public void setOutput(boolean output) { 375 misOutput = output; 376 String ioText; 377 if (output) { 378 mDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_OUTPUTS); 379 ioText = "OUTPUT"; 380 } else { 381 mDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_INPUTS); 382 ioText = "INPUT"; 383 } 384 mHideSettingsText = getResources().getString(R.string.hint_hide_settings) + " - " + ioText; 385 mShowSettingsText = getResources().getString(R.string.hint_show_settings) + " - " + ioText; 386 updateSettingsViewText(); 387 388 // Don't show InputPresets for output streams. 389 mInputPresetTableRow.setVisibility(output ? View.GONE : View.VISIBLE); 390 // Don't show Usage and Content Type for input streams. 391 mUsageTableRow.setVisibility(output ? View.VISIBLE : View.GONE); 392 mContentTypeTableRow.setVisibility(output ? View.VISIBLE : View.GONE); 393 } 394 applyToModel(StreamConfiguration config)395 public void applyToModel(StreamConfiguration config) { 396 // Menu position matches actual enum value for these properties. 397 config.setNativeApi(mNativeApiSpinner.getSelectedItemPosition()); 398 config.setFormat(mFormatSpinner.getSelectedItemPosition()); 399 config.setRateConversionQuality(mRateConversionQualitySpinner.getSelectedItemPosition()); 400 401 int id = ((AudioDeviceListEntry) mDeviceSpinner.getSelectedItem()).getId(); 402 config.setDeviceId(id); 403 404 String text = mSampleRateSpinner.getSelectedItem().toString(); 405 int sampleRate = Integer.parseInt(text); 406 config.setSampleRate(sampleRate); 407 408 text = mInputPresetSpinner.getSelectedItem().toString(); 409 int inputPreset = StreamConfiguration.convertTextToInputPreset(text); 410 config.setInputPreset(inputPreset); 411 412 text = mUsageSpinner.getSelectedItem().toString(); 413 int usage = StreamConfiguration.convertTextToUsage(text); 414 config.setUsage(usage); 415 416 text = mContentTypeSpinner.getSelectedItem().toString(); 417 int contentType = StreamConfiguration.convertTextToContentType(text); 418 config.setContentType(contentType); 419 420 text = mSpatializationBehaviorSpinner.getSelectedItem().toString(); 421 int spatializationBehavior = StreamConfiguration.convertTextToSpatializationBehavior(text); 422 config.setSpatializationBehavior(spatializationBehavior); 423 424 // The corresponding channel count of the selected channel mask may be different from 425 // the selected channel count, the last selected will be respected. 426 if (mIsChannelMaskLastSelected) { 427 text = mChannelMaskSpinner.getSelectedItem().toString(); 428 int channelMask = StreamConfiguration.convertTextToChannelMask(text); 429 config.setChannelMask(channelMask); 430 config.setChannelCount(0); 431 Log.d(TAG, String.format(Locale.getDefault(), "Set channel mask as %s(%#x)", text, channelMask)); 432 } else { 433 config.setChannelCount(mChannelCountSpinner.getSelectedItemPosition()); 434 config.setChannelMask(StreamConfiguration.UNSPECIFIED); 435 Log.d(TAG, "Set channel count as " + mChannelCountSpinner.getSelectedItemPosition()); 436 } 437 438 text = mCapacitySpinner.getSelectedItem().toString(); 439 int bufferCapacity = Integer.parseInt(text); 440 config.setBufferCapacityInFrames(bufferCapacity); 441 442 config.setMMap(mRequestedMMapView.isChecked()); 443 config.setChannelConversionAllowed(mChannelConversionBox.isChecked()); 444 config.setFormatConversionAllowed(mFormatConversionBox.isChecked()); 445 config.setSharingMode(mRequestedExclusiveView.isChecked() 446 ? StreamConfiguration.SHARING_MODE_EXCLUSIVE 447 : StreamConfiguration.SHARING_MODE_SHARED); 448 config.setSessionId(mRequestSessionId.isChecked() 449 ? StreamConfiguration.SESSION_ID_ALLOCATE 450 : StreamConfiguration.SESSION_ID_NONE); 451 452 config.setPerformanceMode(mPerformanceSpinner.getSelectedItemPosition() 453 + StreamConfiguration.PERFORMANCE_MODE_NONE); 454 } 455 setChildrenEnabled(boolean enabled)456 public void setChildrenEnabled(boolean enabled) { 457 mNativeApiSpinner.setEnabled(enabled); 458 mPerformanceSpinner.setEnabled(enabled); 459 mRequestedMMapView.setEnabled(enabled && NativeEngine.isMMapSupported()); 460 mRequestedExclusiveView.setEnabled(enabled && NativeEngine.isMMapExclusiveSupported()); 461 mChannelConversionBox.setEnabled(enabled); 462 mFormatConversionBox.setEnabled(enabled); 463 mChannelCountSpinner.setEnabled(enabled); 464 mChannelMaskSpinner.setEnabled(enabled); 465 mCapacitySpinner.setEnabled(enabled); 466 mInputPresetSpinner.setEnabled(enabled); 467 mUsageSpinner.setEnabled(enabled); 468 mContentTypeSpinner.setEnabled(enabled); 469 mFormatSpinner.setEnabled(enabled); 470 mSpatializationBehaviorSpinner.setEnabled(enabled); 471 mSampleRateSpinner.setEnabled(enabled); 472 mRateConversionQualitySpinner.setEnabled(enabled); 473 mDeviceSpinner.setEnabled(enabled); 474 mRequestSessionId.setEnabled(enabled); 475 mRequestAudioEffect.setEnabled(enabled); 476 } 477 478 // This must be called on the UI thread. updateDisplay(StreamConfiguration actualConfiguration)479 void updateDisplay(StreamConfiguration actualConfiguration) { 480 int value; 481 482 value = actualConfiguration.getNativeApi(); 483 mActualNativeApiView.setText(StreamConfiguration.convertNativeApiToText(value)); 484 485 value = actualConfiguration.getDeviceId(); 486 mActualDeviceIdView.setText(String.valueOf(value)); 487 488 mActualMMapView.setText(yesOrNo(actualConfiguration.isMMap())); 489 int sharingMode = actualConfiguration.getSharingMode(); 490 boolean isExclusive = (sharingMode == StreamConfiguration.SHARING_MODE_EXCLUSIVE); 491 mActualExclusiveView.setText(yesOrNo(isExclusive)); 492 493 value = actualConfiguration.getPerformanceMode(); 494 mActualPerformanceView.setText(StreamConfiguration.convertPerformanceModeToText(value)); 495 mActualPerformanceView.requestLayout(); 496 497 value = actualConfiguration.getFormat(); 498 mActualFormatView.setText(StreamConfiguration.convertFormatToText(value)); 499 mActualFormatView.requestLayout(); 500 501 value = actualConfiguration.getInputPreset(); 502 mActualInputPresetView.setText(StreamConfiguration.convertInputPresetToText(value)); 503 mActualInputPresetView.requestLayout(); 504 505 value = actualConfiguration.getUsage(); 506 mActualUsageView.setText(StreamConfiguration.convertUsageToText(value)); 507 mActualUsageView.requestLayout(); 508 509 value = actualConfiguration.getContentType(); 510 mActualContentTypeView.setText(StreamConfiguration.convertContentTypeToText(value)); 511 mActualContentTypeView.requestLayout(); 512 513 value = actualConfiguration.getSpatializationBehavior(); 514 mActualSpatializationBehaviorView.setText(StreamConfiguration.convertSpatializationBehaviorToText(value)); 515 mActualSpatializationBehaviorView.requestLayout(); 516 517 mActualChannelCountView.setText(actualConfiguration.getChannelCount() + ""); 518 mActualSampleRateView.setText(actualConfiguration.getSampleRate() + ""); 519 mActualSessionIdView.setText("S#: " + actualConfiguration.getSessionId()); 520 value = actualConfiguration.getChannelMask(); 521 mActualChannelMaskView.setText(StreamConfiguration.convertChannelMaskToText(value)); 522 mActualCapacityView.setText(actualConfiguration.getBufferCapacityInFrames() + ""); 523 524 boolean isMMap = actualConfiguration.isMMap(); 525 526 String msg = ""; 527 msg += "burst = " + actualConfiguration.getFramesPerBurst(); 528 msg += ", devID = " + actualConfiguration.getDeviceId(); 529 msg += ", " + (actualConfiguration.isMMap() ? "MMAP" : "Legacy"); 530 msg += (isMMap ? ", " + StreamConfiguration.convertSharingModeToText(sharingMode) : ""); 531 532 int hardwareChannelCount = actualConfiguration.getHardwareChannelCount(); 533 int hardwareSampleRate = actualConfiguration.getHardwareSampleRate(); 534 int hardwareFormat = actualConfiguration.getHardwareFormat(); 535 msg += "\nHW: #ch=" + (hardwareChannelCount == 536 StreamConfiguration.UNSPECIFIED ? "?" : hardwareChannelCount); 537 msg += ", SR=" + (hardwareSampleRate == 538 StreamConfiguration.UNSPECIFIED ? "?" : hardwareSampleRate); 539 msg += ", format=" + (hardwareFormat == StreamConfiguration.UNSPECIFIED ? 540 "?" : StreamConfiguration.convertFormatToText(hardwareFormat)); 541 542 mStreamInfoView.setText(msg); 543 544 mHideableView.requestLayout(); 545 } 546 547 // This must be called on the UI thread. setStatusText(String msg)548 public void setStatusText(String msg) { 549 mStreamStatusView.setText(msg); 550 } 551 setExclusiveMode(boolean b)552 public void setExclusiveMode(boolean b) { 553 mRequestedExclusiveView.setChecked(b); 554 } 555 setFormat(int format)556 public void setFormat(int format) { 557 mFormatSpinner.setSelection(format); // position matches format 558 } 559 setFormatConversionAllowed(boolean allowed)560 public void setFormatConversionAllowed(boolean allowed) { 561 mFormatConversionBox.setChecked(allowed); 562 } 563 onChannelCountSpinnerSelected()564 private void onChannelCountSpinnerSelected() { 565 if (mChannelCountSpinner.getSelectedItemPosition() != 0) { 566 mChannelMaskSpinner.setSelection(0); // Override the previous channel mask selection 567 mIsChannelMaskLastSelected = false; 568 } 569 } 570 onChannelMaskSpinnerSelected()571 private void onChannelMaskSpinnerSelected() { 572 if (mChannelMaskSpinner.getSelectedItemPosition() != 0) { 573 mChannelCountSpinner.setSelection(0); // Override the previous channel count selection 574 mIsChannelMaskLastSelected = true; 575 } 576 } 577 onRequestAudioEffectClicked(boolean isChecked)578 private void onRequestAudioEffectClicked(boolean isChecked) { 579 if (isChecked) { 580 mRequestSessionId.setEnabled(false); 581 mRequestSessionId.setChecked(true); 582 if (misOutput) { 583 mOutputEffectsLayout.setVisibility(VISIBLE); 584 } else { 585 mInputEffectsLayout.setVisibility(VISIBLE); 586 } 587 } else { 588 mRequestSessionId.setEnabled(true); 589 if (misOutput) { 590 mOutputEffectsLayout.setVisibility(GONE); 591 } else { 592 mInputEffectsLayout.setVisibility(GONE); 593 } 594 } 595 } 596 setupEffects(int sessionId)597 public void setupEffects(int sessionId) { 598 if (!mRequestAudioEffect.isChecked()) { 599 return; 600 } 601 if (misOutput) { 602 mBassBoost = new BassBoost(0, sessionId); 603 mBassBoost.setStrength((short) mBassBoostSeekBar.getProgress()); 604 mLoudnessEnhancer = new LoudnessEnhancer(sessionId); 605 mLoudnessEnhancer.setTargetGain((short) mLoudnessEnhancerSeekBar.getProgress()); 606 } else { 607 // If AEC is not available, the checkbox will be disabled in initializeViews(). 608 if (mAcousticEchoCancelerCheckBox.isEnabled()) { 609 mAcousticEchoCanceler = AcousticEchoCanceler.create(sessionId); 610 if (mAcousticEchoCanceler != null) { 611 boolean wasOn = mAcousticEchoCanceler.getEnabled(); 612 String text = mAcousticEchoCancelerText + "(" + (wasOn ? "Y" : "N") + ")"; 613 mAcousticEchoCancelerCheckBox.setText(text); 614 mAcousticEchoCanceler.setEnabled(mAcousticEchoCancelerCheckBox.isChecked()); 615 } else { 616 Log.e(TAG, String.format(Locale.getDefault(), "Could not create AcousticEchoCanceler")); 617 } 618 } 619 620 // If AGC is not available, the checkbox will be disabled in initializeViews(). 621 if (mAutomaticGainControlCheckBox.isEnabled()) { 622 mAutomaticGainControl = AutomaticGainControl.create(sessionId); 623 if (mAutomaticGainControl != null) { 624 boolean wasOn = mAutomaticGainControl.getEnabled(); 625 String text = mAutomaticGainControlText + "(" + (wasOn ? "Y" : "N") + ")"; 626 mAutomaticGainControlCheckBox.setText(text); 627 mAutomaticGainControl.setEnabled(mAutomaticGainControlCheckBox.isChecked()); 628 } else { 629 Log.e(TAG, String.format(Locale.getDefault(), "Could not create AutomaticGainControl")); 630 } 631 } 632 633 // If Noise Suppressor is not available, the checkbox will be disabled in initializeViews(). 634 if (mNoiseSuppressorCheckBox.isEnabled()) { 635 mNoiseSuppressor = NoiseSuppressor.create(sessionId); 636 if (mNoiseSuppressor != null) { 637 boolean wasOn = mNoiseSuppressor.getEnabled(); 638 String text = mNoiseSuppressorText + "(" + (wasOn ? "Y" : "N") + ")"; 639 mNoiseSuppressorCheckBox.setText(text); 640 mNoiseSuppressor.setEnabled(mNoiseSuppressorCheckBox.isChecked()); 641 } else { 642 Log.e(TAG, String.format(Locale.getDefault(), "Could not create NoiseSuppressor")); 643 } 644 } 645 } 646 } 647 onLoudnessEnhancerSeekBarChanged(int progress)648 private void onLoudnessEnhancerSeekBarChanged(int progress) { 649 if (mLoudnessEnhancer != null) { 650 mLoudnessEnhancer.setTargetGain(progress); 651 } 652 mLoudnessEnhancerTextView.setText("Loudness Enhancer: " + progress); 653 } 654 onBassBoostSeekBarChanged(int progress)655 private void onBassBoostSeekBarChanged(int progress) { 656 if (mBassBoost != null) { 657 mBassBoost.setStrength((short) progress); 658 } 659 mBassBoostTextView.setText("Bass Boost: " + progress); 660 } 661 onAutomaticGainControlCheckBoxChanged(boolean isChecked)662 private void onAutomaticGainControlCheckBoxChanged(boolean isChecked) { 663 if (mAutomaticGainControlCheckBox.isEnabled() && mAutomaticGainControl != null) { 664 mAutomaticGainControl.setEnabled(isChecked); 665 } 666 } 667 onAcousticEchoCancelerCheckBoxChanged(boolean isChecked)668 private void onAcousticEchoCancelerCheckBoxChanged(boolean isChecked) { 669 if (mAcousticEchoCancelerCheckBox.isEnabled() && mAcousticEchoCanceler != null) { 670 mAcousticEchoCanceler.setEnabled(isChecked); 671 } 672 } 673 onNoiseSuppressorCheckBoxChanged(boolean isChecked)674 private void onNoiseSuppressorCheckBoxChanged(boolean isChecked) { 675 if (mNoiseSuppressorCheckBox.isEnabled() && mNoiseSuppressor != null) { 676 mNoiseSuppressor.setEnabled(isChecked); 677 } 678 } 679 } 680