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