• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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