• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.drrickorang.loopback;
18 
19 import android.app.Application;
20 import android.content.Context;
21 import android.content.pm.PackageManager;
22 import android.content.res.Configuration;
23 import android.media.MediaRecorder;
24 import android.os.Build;
25 import android.util.Log;
26 
27 
28 /**
29  * This class maintain global application states, so it also keeps and computes the default
30  * values of all the audio settings.
31  */
32 
33 public class LoopbackApplication extends Application {
34     private static final String TAG = "LoopbackApplication";
35 
36     // here defines all the initial setting values, some get modified in ComputeDefaults()
37     private TestSettings mSettings = new TestSettings(48000 /*samplingRate*/,
38             0 /*playerBufferSizeInBytes*/, 0 /*recorderBuffSizeInBytes*/);
39     private int mChannelIndex = -1;
40     private int mAudioThreadType = Constant.AUDIO_THREAD_TYPE_JAVA; //0:Java, 1:Native (JNI)
41     private int mMicSource = 3; //maps to MediaRecorder.AudioSource.VOICE_RECOGNITION;
42     private int mPerformanceMode = -1; // DEFAULT
43     private int mIgnoreFirstFrames = 0;
44     private int mBufferTestDurationInSeconds = 5;
45     private int mBufferTestWavePlotDurationInSeconds = 7;
46     private int mNumberOfLoadThreads = 4;
47     private boolean mCaptureSysTraceEnabled = false;
48     private boolean mCaptureBugreportEnabled = false;
49     private boolean mCaptureWavSnippetsEnabled = false;
50     private boolean mSoundLevelCalibrationEnabled = false;
51     private int mNumStateCaptures = Constant.DEFAULT_NUM_CAPTURES;
52 
setDefaults()53     public void setDefaults() {
54         // Prefer SLES until buffer test is implemented for AAudio.
55         if (isSafeToUseSles()) {
56             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_NATIVE_SLES;
57         } else if (isSafeToUseAAudio()) {
58             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_NATIVE_AAUDIO;
59         } else {
60             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_JAVA;
61         }
62 
63         computeDefaults();
64     }
65 
getSamplingRate()66     int getSamplingRate() {
67         return mSettings.getSamplingRate();
68     }
69 
setSamplingRate(int samplingRate)70     void setSamplingRate(int samplingRate) {
71         mSettings.setSamplingRate(samplingRate);
72     }
73 
getChannelIndex()74     int getChannelIndex() { return mChannelIndex; }
75 
setChannelIndex(int channelIndex)76     void setChannelIndex(int channelIndex) { mChannelIndex = channelIndex; }
77 
getAudioThreadType()78     int getAudioThreadType() {
79         return mAudioThreadType;
80     }
81 
82 
setAudioThreadType(int audioThreadType)83     void setAudioThreadType(int audioThreadType) {
84         if (isSafeToUseAAudio() && audioThreadType == Constant.AUDIO_THREAD_TYPE_NATIVE_AAUDIO) {
85             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_NATIVE_AAUDIO;
86         } else if (isSafeToUseSles() && (
87                         audioThreadType == Constant.AUDIO_THREAD_TYPE_NATIVE_SLES ||
88                         audioThreadType == Constant.AUDIO_THREAD_TYPE_NATIVE_AAUDIO)) {
89             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_NATIVE_SLES;
90         } else {
91             mAudioThreadType = Constant.AUDIO_THREAD_TYPE_JAVA;
92         }
93     }
94 
95 
getMicSource()96     int getMicSource() {
97         return mMicSource;
98     }
99 
100 
mapMicSource(int threadType, int source)101     int mapMicSource(int threadType, int source) {
102         int mappedSource = 0;
103 
104         //experiment with remote submix
105         if (threadType == Constant.AUDIO_THREAD_TYPE_JAVA) {
106             switch (source) {
107             default:
108             case 0: //DEFAULT
109                 mappedSource = MediaRecorder.AudioSource.DEFAULT;
110                 break;
111             case 1: //MIC
112                 mappedSource = MediaRecorder.AudioSource.MIC;
113                 break;
114             case 2: //CAMCORDER
115                 mappedSource = MediaRecorder.AudioSource.CAMCORDER;
116                 break;
117             case 3: //VOICE_RECOGNITION
118                 mappedSource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
119                 break;
120             case 4: //VOICE_COMMUNICATION
121                 mappedSource = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
122                 break;
123             case 5: //REMOTE_SUBMIX (JAVA ONLY)
124                 mappedSource = MediaRecorder.AudioSource.REMOTE_SUBMIX;
125                 break;
126             case 6: //UNPROCESSED
127                 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
128                     mappedSource = 9 /*MediaRecorder.AudioSource.UNPROCESSED*/;
129                 } else {
130                     mappedSource = MediaRecorder.AudioSource.DEFAULT;
131                 }
132                 break;
133             }
134         } else if (threadType == Constant.AUDIO_THREAD_TYPE_NATIVE_SLES) {
135             // FIXME taken from OpenSLES_AndroidConfiguration.h
136             switch (source) {
137             default:
138             case 0: //DEFAULT
139                 mappedSource = 0x00; //SL_ANDROID_RECORDING_PRESET_NONE
140                 break;
141             case 1: //MIC
142                 mappedSource = 0x01; //SL_ANDROID_RECORDING_PRESET_GENERIC
143                 break;
144             case 2: //CAMCORDER
145                 mappedSource = 0x02; //SL_ANDROID_RECORDING_PRESET_CAMCORDER
146                 break;
147             case 3: //VOICE_RECOGNITION
148                 mappedSource = 0x03; //SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
149                 break;
150             case 4: //VOICE_COMMUNICATION
151                 mappedSource = 0x04; //SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION
152                 break;
153             case 5: //REMOTE_SUBMIX (JAVA ONLY)
154                 mappedSource = 0x00; //SL_ANDROID_RECORDING_PRESET_NONE;
155                 break;
156             case 6: //UNPROCESSED
157                 // FIXME should use >=
158                 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
159                     mappedSource = 0x05; //SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
160                 } else {
161                     mappedSource = 0x00; //SL_ANDROID_RECORDING_PRESET_NONE
162                 }
163                 break;
164             }
165             // Doesn't matter for AUDIO_THREAD_TYPE_NATIVE_AAUDIO.
166         }
167 
168         return mappedSource;
169     }
170 
171 
getMicSourceString(int source)172     String getMicSourceString(int source) {
173         String name = null;
174         String[] myArray = getResources().getStringArray(R.array.mic_source_array);
175 
176         if (myArray != null && source >= 0 && source < myArray.length) {
177             name = myArray[source];
178         }
179         return name;
180     }
181 
setMicSource(int micSource)182     void setMicSource(int micSource) { mMicSource = micSource; }
183 
mapPerformanceMode(int performanceMode)184     int mapPerformanceMode(int performanceMode) {
185         int mappedPerformanceMode = -1;
186 
187         // FIXME taken from OpenSLES_AndroidConfiguration.h
188         switch (performanceMode) {
189         case 0: // NONE
190         case 1: // LATENCY
191         case 2: // LATENCY_EFFECTS
192         case 3: // POWER_SAVING
193             // FIXME should use >=
194             if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
195                 mappedPerformanceMode = performanceMode;
196                 break;
197             }
198             // fall through
199         case -1:
200         default:
201             mappedPerformanceMode = -1;
202             break;
203             }
204 
205         return mappedPerformanceMode;
206     }
207 
208 
getPerformanceMode()209     int getPerformanceMode() {
210         return mPerformanceMode;
211     }
212 
getPerformanceModeString(int performanceMode)213     String getPerformanceModeString(int performanceMode) {
214         String name = null;
215         String[] myArray = getResources().getStringArray(R.array.performance_mode_array);
216 
217         if (myArray != null && performanceMode >= -1 && performanceMode < myArray.length - 1) {
218             name = myArray[performanceMode + 1];
219         }
220         return name;
221     }
222 
223 
setPerformanceMode(int performanceMode)224     void setPerformanceMode(int performanceMode) {
225         mPerformanceMode = performanceMode;
226     }
227 
getIgnoreFirstFrames()228     int getIgnoreFirstFrames() {
229         return mIgnoreFirstFrames;
230     }
231 
setIgnoreFirstFrames(int ignoreFirstFrames)232     void setIgnoreFirstFrames(int ignoreFirstFrames) {
233         mIgnoreFirstFrames = ignoreFirstFrames;
234     }
235 
getPlayerBufferSizeInBytes()236     int getPlayerBufferSizeInBytes() {
237         return mSettings.getPlayerBufferSizeInBytes();
238     }
239 
setPlayerBufferSizeInBytes(int playerBufferSizeInBytes)240     void setPlayerBufferSizeInBytes(int playerBufferSizeInBytes) {
241         mSettings.setPlayerBufferSizeInBytes(playerBufferSizeInBytes);
242     }
243 
244 
getRecorderBufferSizeInBytes()245     int getRecorderBufferSizeInBytes() {
246         return mSettings.getRecorderBufferSizeInBytes();
247     }
248 
249 
setRecorderBufferSizeInBytes(int recorderBufferSizeInBytes)250     void setRecorderBufferSizeInBytes(int recorderBufferSizeInBytes) {
251         mSettings.setRecorderBufferSizeInBytes(recorderBufferSizeInBytes);
252     }
253 
254 
getBufferTestDuration()255     int getBufferTestDuration() {
256         return mBufferTestDurationInSeconds;
257     }
258 
259 
setBufferTestDuration(int bufferTestDurationInSeconds)260     void setBufferTestDuration(int bufferTestDurationInSeconds) {
261         mBufferTestDurationInSeconds = Utilities.clamp(bufferTestDurationInSeconds,
262                 Constant.BUFFER_TEST_DURATION_SECONDS_MIN,
263                 Constant.BUFFER_TEST_DURATION_SECONDS_MAX);
264     }
265 
266 
getBufferTestWavePlotDuration()267     int getBufferTestWavePlotDuration() {
268         return mBufferTestWavePlotDurationInSeconds;
269     }
270 
271 
setBufferTestWavePlotDuration(int bufferTestWavePlotDurationInSeconds)272     void setBufferTestWavePlotDuration(int bufferTestWavePlotDurationInSeconds) {
273         mBufferTestWavePlotDurationInSeconds = Utilities.clamp(bufferTestWavePlotDurationInSeconds,
274                 Constant.BUFFER_TEST_WAVE_PLOT_DURATION_SECONDS_MIN,
275                 Constant.BUFFER_TEST_WAVE_PLOT_DURATION_SECONDS_MAX);
276     }
277 
getNumberOfLoadThreads()278     int getNumberOfLoadThreads() {
279         return mNumberOfLoadThreads;
280     }
281 
setNumberOfLoadThreads(int numberOfLoadThreads)282     void setNumberOfLoadThreads(int numberOfLoadThreads) {
283         mNumberOfLoadThreads = Utilities.clamp(numberOfLoadThreads, Constant.MIN_NUM_LOAD_THREADS,
284                 Constant.MAX_NUM_LOAD_THREADS);
285     }
286 
setNumberOfCaptures(int num)287     public void setNumberOfCaptures (int num) {
288         mNumStateCaptures = Utilities.clamp(num, Constant.MIN_NUM_CAPTURES,
289                 Constant.MAX_NUM_CAPTURES);
290     }
291 
setCaptureSysTraceEnabled(boolean enabled)292     public void setCaptureSysTraceEnabled (boolean enabled) {
293         mCaptureSysTraceEnabled = enabled;
294     }
295 
setCaptureBugreportEnabled(boolean enabled)296     public void setCaptureBugreportEnabled(boolean enabled) {
297         mCaptureBugreportEnabled = enabled;
298     }
299 
setCaptureWavsEnabled(boolean enabled)300     public void setCaptureWavsEnabled(boolean enabled) {
301         mCaptureWavSnippetsEnabled = enabled;
302     }
303 
setSoundLevelCalibrationEnabled(boolean enabled)304     public void setSoundLevelCalibrationEnabled(boolean enabled) {
305         mSoundLevelCalibrationEnabled = enabled;
306     }
307 
isCaptureEnabled()308     public boolean isCaptureEnabled() {
309         return isCaptureSysTraceEnabled() || isCaptureBugreportEnabled();
310     }
311 
isCaptureSysTraceEnabled()312     public boolean isCaptureSysTraceEnabled() {
313         return mCaptureSysTraceEnabled;
314     }
315 
isCaptureBugreportEnabled()316     public boolean isCaptureBugreportEnabled() {
317         return mCaptureBugreportEnabled;
318     }
319 
isSoundLevelCalibrationEnabled()320     public boolean isSoundLevelCalibrationEnabled() {
321         return mSoundLevelCalibrationEnabled;
322     }
323 
getNumStateCaptures()324     public int getNumStateCaptures() {
325         return mNumStateCaptures;
326     }
327 
isCaptureWavSnippetsEnabled()328     public boolean isCaptureWavSnippetsEnabled() {
329         return mCaptureWavSnippetsEnabled;
330     }
331 
332 
333     /** Compute Default audio settings. */
computeDefaults()334     public void computeDefaults() {
335         if (mAudioThreadType == Constant.AUDIO_THREAD_TYPE_NATIVE_SLES ||
336             mAudioThreadType == Constant.AUDIO_THREAD_TYPE_NATIVE_AAUDIO) {
337             mSettings = NativeAudioThread.computeDefaultSettings(
338                     this, mAudioThreadType, mPerformanceMode);
339         } else {
340             mSettings = LoopbackAudioThread.computeDefaultSettings();
341         }
342     }
343 
344 
getSystemInfo()345     String getSystemInfo() {
346         String info = null;
347         try {
348             Context context = getApplicationContext();
349             android.content.pm.PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
350                     context.getPackageName(), 0);
351             int versionCode = packageInfo.versionCode;
352             String versionName = packageInfo.versionName;
353             info = "App ver. " + versionCode + "." + versionName + " | " + Build.MODEL + " | " +
354                     Build.FINGERPRINT;
355         } catch (PackageManager.NameNotFoundException e) {
356             e.printStackTrace();
357         }
358 
359         return info;
360     }
361 
362 
363     /** Check if it's safe to use OpenSL ES. */
isSafeToUseSles()364     static boolean isSafeToUseSles() {
365         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
366     }
367 
368     /** Check if it's safe to use AAudio. */
isSafeToUseAAudio()369     static boolean isSafeToUseAAudio() {
370         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
371     }
372 
373 
374 /*
375     @Override
376     public void onConfigurationChanged(Configuration newConfig) {
377         super.onConfigurationChanged(newConfig);
378     }
379 */
380 
381 
382     @Override
onCreate()383     public void onCreate() {
384         super.onCreate();
385 
386         setDefaults();
387     }
388 
389 
390 /*
391     @Override
392     public void onLowMemory() {
393         super.onLowMemory();
394     }
395 */
396 
397 
398 /*
399     @Override
400     public void onTerminate() {
401         super.onTerminate();
402     }
403 */
404 
405 
log(String msg)406     private static void log(String msg) {
407         Log.v(TAG, msg);
408     }
409 
410 }
411