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.google.sample.oboe.manualtest;
18 
19 import android.app.Activity;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.PackageInfo;
25 import android.content.pm.PackageManager;
26 import android.graphics.Point;
27 import android.media.AudioManager;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.util.Log;
31 import android.view.Display;
32 import android.view.View;
33 import android.widget.AdapterView;
34 import android.widget.CheckBox;
35 import android.widget.Spinner;
36 import android.widget.TextView;
37 import android.widget.Toast;
38 
39 /**
40  * Select various Audio tests.
41  */
42 
43 public class MainActivity extends Activity {
44 
45     private static final String KEY_TEST_NAME = "test";
46     public static final String VALUE_TEST_NAME_LATENCY = "latency";
47     public static final String VALUE_TEST_NAME_GLITCH = "glitch";
48 
49     static {
50         // Must match name in CMakeLists.txt
51         System.loadLibrary("oboetester");
52     }
53 
54 
55     private Spinner mModeSpinner;
56     private TextView mCallbackSizeEditor;
57     protected TextView mDeviceView;
58     private TextView mVersionTextView;
59     private TextView mBuildTextView;
60     private TextView mBluetoothScoStatusView;
61     private Bundle mBundleFromIntent;
62     private BroadcastReceiver mScoStateReceiver;
63     private CheckBox mWorkaroundsCheckBox;
64     private static String mVersionText;
65 
66     @Override
onCreate(Bundle savedInstanceState)67     protected void onCreate(Bundle savedInstanceState) {
68         super.onCreate(savedInstanceState);
69         setContentView(R.layout.activity_main);
70 
71         logScreenSize();
72 
73         mVersionTextView = (TextView) findViewById(R.id.versionText);
74         mCallbackSizeEditor = (TextView) findViewById(R.id.callbackSize);
75 
76         mDeviceView = (TextView) findViewById(R.id.deviceView);
77         updateNativeAudioUI();
78 
79         // Set mode, eg. MODE_IN_COMMUNICATION
80         mModeSpinner = (Spinner) findViewById(R.id.spinnerAudioMode);
81         mModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
82             @Override
83             public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
84                 long mode = mModeSpinner.getSelectedItemId();
85                 AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
86                 myAudioMgr.setMode((int)mode);
87             }
88 
89             @Override
90             public void onNothingSelected(AdapterView<?> adapterView) {
91             }
92         });
93 
94         try {
95             PackageInfo pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
96             int oboeVersion = OboeAudioStream.getOboeVersionNumber();
97             int oboeMajor = (oboeVersion >> 24) & 0xFF;
98             int oboeMinor = (oboeVersion >> 16) & 0xFF;
99             int oboePatch = oboeVersion & 0xFF;
100             mVersionText = "OboeTester (" + pinfo.versionCode + ") v " + pinfo.versionName
101                     + ", Oboe v " + oboeMajor + "." + oboeMinor + "." + oboePatch;
102             mVersionTextView.setText(mVersionText);
103         } catch (PackageManager.NameNotFoundException e) {
104             mVersionTextView.setText(e.getMessage());
105         }
106 
107         mWorkaroundsCheckBox = (CheckBox) findViewById(R.id.boxEnableWorkarounds);
108         // Turn off workarounds so we can test the underlying API bugs.
109         NativeEngine.setWorkaroundsEnabled(false);
110 
111         mBuildTextView = (TextView) findViewById(R.id.text_build_info);
112         mBuildTextView.setText(Build.DISPLAY);
113 
114         mBluetoothScoStatusView = (TextView) findViewById(R.id.textBluetoothScoStatus);
115         mScoStateReceiver = new BroadcastReceiver() {
116             @Override
117             public void onReceive(Context context, Intent intent) {
118                 int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
119                 if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) {
120                     mBluetoothScoStatusView.setText("CONNECTING");
121                 } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
122                     mBluetoothScoStatusView.setText("CONNECTED");
123                 } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
124                     mBluetoothScoStatusView.setText("DISCONNECTED");
125                 }
126             }
127         };
128 
129         saveIntentBundleForLaterProcessing(getIntent());
130     }
131 
getVersiontext()132     public static String getVersiontext() {
133         return mVersionText;
134     }
135 
registerScoStateReceiver()136     private void registerScoStateReceiver() {
137         registerReceiver(mScoStateReceiver,
138                 new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
139     }
140 
unregisterScoStateReceiver()141     private void unregisterScoStateReceiver() {
142         unregisterReceiver(mScoStateReceiver);
143     }
144 
logScreenSize()145     private void logScreenSize() {
146         Display display = getWindowManager().getDefaultDisplay();
147         Point size = new Point();
148         display.getSize(size);
149         int width = size.x;
150         int height = size.y;
151         Log.i(TestAudioActivity.TAG, "Screen size = " + size.x + " * " + size.y);
152     }
153 
154     @Override
onNewIntent(Intent intent)155     public void onNewIntent(Intent intent) {
156         saveIntentBundleForLaterProcessing(intent);
157     }
158 
159     // This will get processed during onResume.
saveIntentBundleForLaterProcessing(Intent intent)160     private void saveIntentBundleForLaterProcessing(Intent intent) {
161         mBundleFromIntent = intent.getExtras();
162     }
163 
processBundleFromIntent()164     private void processBundleFromIntent() {
165         if (mBundleFromIntent == null) {
166             return;
167         }
168 
169         if (mBundleFromIntent.containsKey(KEY_TEST_NAME)) {
170             String testName = mBundleFromIntent.getString(KEY_TEST_NAME);
171             if (VALUE_TEST_NAME_LATENCY.equals(testName)) {
172                 Intent intent = new Intent(this, RoundTripLatencyActivity.class);
173                 intent.putExtras(mBundleFromIntent);
174                 startActivity(intent);
175             } else if (VALUE_TEST_NAME_GLITCH.equals(testName)) {
176                 Intent intent = new Intent(this, ManualGlitchActivity.class);
177                 intent.putExtras(mBundleFromIntent);
178                 startActivity(intent);
179             }
180         }
181         mBundleFromIntent = null;
182     }
183 
184     @Override
onResume()185     public void onResume(){
186         super.onResume();
187         mWorkaroundsCheckBox.setChecked(NativeEngine.areWorkaroundsEnabled());
188         processBundleFromIntent();
189         registerScoStateReceiver();
190     }
191 
192     @Override
onPause()193     public void onPause(){
194         unregisterScoStateReceiver();
195         super.onPause();
196     }
197 
updateNativeAudioUI()198     private void updateNativeAudioUI() {
199         AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
200         String audioManagerSampleRate = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
201         String audioManagerFramesPerBurst = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
202         mDeviceView.setText("Java AudioManager: rate = " + audioManagerSampleRate +
203                 ", burst = " + audioManagerFramesPerBurst);
204     }
205 
onLaunchTestOutput(View view)206     public void onLaunchTestOutput(View view) {
207         onLaunchTest(TestOutputActivity.class);
208     }
209 
onLaunchTestInput(View view)210     public void onLaunchTestInput(View view) {
211         onLaunchTest(TestInputActivity.class);
212     }
213 
onLaunchTapToTone(View view)214     public void onLaunchTapToTone(View view) {
215         onLaunchTest(TapToToneActivity.class);
216     }
217 
onLaunchRecorder(View view)218     public void onLaunchRecorder(View view) {
219         onLaunchTest(RecorderActivity.class);
220     }
221 
onLaunchEcho(View view)222     public void onLaunchEcho(View view) {
223         onLaunchTest(EchoActivity.class);
224     }
225 
onLaunchRoundTripLatency(View view)226     public void onLaunchRoundTripLatency(View view) {
227         onLaunchTest(RoundTripLatencyActivity.class);
228     }
229 
onLaunchManualGlitchTest(View view)230     public void onLaunchManualGlitchTest(View view) {
231         onLaunchTest(ManualGlitchActivity.class);
232     }
233 
onLaunchAutoGlitchTest(View view)234     public void onLaunchAutoGlitchTest(View view) { onLaunchTest(AutomatedGlitchActivity.class); }
235 
onLaunchTestDisconnect(View view)236     public void onLaunchTestDisconnect(View view) {
237         onLaunchTest(TestDisconnectActivity.class);
238     }
239 
onLaunchTestDataPaths(View view)240     public void onLaunchTestDataPaths(View view) {
241         onLaunchTest(TestDataPathsActivity.class);
242     }
243 
onLaunchTestDeviceReport(View view)244     public void onLaunchTestDeviceReport(View view)  {
245         onLaunchTest(DeviceReportActivity.class);
246     }
247 
onLaunchTest(Class clazz)248     private void onLaunchTest(Class clazz) {
249         updateCallbackSize();
250         Intent intent = new Intent(this, clazz);
251         startActivity(intent);
252     }
253 
onUseCallbackClicked(View view)254     public void onUseCallbackClicked(View view) {
255         CheckBox checkBox = (CheckBox) view;
256         OboeAudioStream.setUseCallback(checkBox.isChecked());
257     }
258 
showErrorToast(String message)259     protected void showErrorToast(String message) {
260         showToast("Error: " + message);
261     }
262 
showToast(final String message)263     protected void showToast(final String message) {
264         runOnUiThread(new Runnable() {
265             @Override
266             public void run() {
267                 Toast.makeText(MainActivity.this,
268                         message,
269                         Toast.LENGTH_SHORT).show();
270             }
271         });
272     }
273 
updateCallbackSize()274     private void updateCallbackSize() {
275         CharSequence chars = mCallbackSizeEditor.getText();
276         String text = chars.toString();
277         int callbackSize = 0;
278         try {
279             callbackSize = Integer.parseInt(text);
280         } catch (NumberFormatException e) {
281             showErrorToast("Badly formated callback size: " + text);
282             mCallbackSizeEditor.setText("0");
283         }
284         OboeAudioStream.setCallbackSize(callbackSize);
285     }
286 
onSetSpeakerphoneOn(View view)287     public void onSetSpeakerphoneOn(View view) {
288         CheckBox checkBox = (CheckBox) view;
289         boolean enabled = checkBox.isChecked();
290         AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
291         myAudioMgr.setSpeakerphoneOn(enabled);
292     }
293 
onStartStopBluetoothSco(View view)294     public void onStartStopBluetoothSco(View view) {
295         CheckBox checkBox = (CheckBox) view;
296         AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
297         if (checkBox.isChecked()) {
298             myAudioMgr.startBluetoothSco();
299         } else {
300             myAudioMgr.stopBluetoothSco();
301         }
302     }
303 
onEnableWorkarounds(View view)304     public void onEnableWorkarounds(View view) {
305         CheckBox checkBox = (CheckBox) view;
306         boolean enabled = checkBox.isChecked();
307         NativeEngine.setWorkaroundsEnabled(enabled);
308     }
309 }
310