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.Manifest; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.media.audiofx.AcousticEchoCanceler; 23 import android.media.audiofx.AutomaticGainControl; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.os.Environment; 27 import android.support.annotation.NonNull; 28 import android.support.v4.app.ActivityCompat; 29 import android.support.v4.content.FileProvider; 30 import android.view.View; 31 import android.widget.RadioButton; 32 import android.widget.Toast; 33 34 import java.io.File; 35 import java.io.IOException; 36 37 /** 38 * Test Oboe Capture 39 */ 40 41 public class TestInputActivity extends TestAudioActivity 42 implements ActivityCompat.OnRequestPermissionsResultCallback { 43 44 private static final int AUDIO_ECHO_REQUEST = 0; 45 protected AudioInputTester mAudioInputTester; 46 private static final int NUM_VOLUME_BARS = 4; 47 private VolumeBarView[] mVolumeBars = new VolumeBarView[NUM_VOLUME_BARS]; 48 private InputMarginView mInputMarginView; 49 private int mInputMarginBursts = 0; 50 private WorkloadView mWorkloadView; 51 setMinimumFramesBeforeRead(int frames)52 public native void setMinimumFramesBeforeRead(int frames); saveWaveFile(String absolutePath)53 public native int saveWaveFile(String absolutePath); 54 isOutput()55 @Override boolean isOutput() { return false; } 56 57 @Override inflateActivity()58 protected void inflateActivity() { 59 setContentView(R.layout.activity_test_input); 60 61 BufferSizeView bufferSizeView = findViewById(R.id.buffer_size_view); 62 bufferSizeView.setVisibility(View.GONE); 63 } 64 65 @Override onCreate(Bundle savedInstanceState)66 protected void onCreate(Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 69 mVolumeBars[0] = (VolumeBarView) findViewById(R.id.volumeBar0); 70 mVolumeBars[1] = (VolumeBarView) findViewById(R.id.volumeBar1); 71 mVolumeBars[2] = (VolumeBarView) findViewById(R.id.volumeBar2); 72 mVolumeBars[3] = (VolumeBarView) findViewById(R.id.volumeBar3); 73 74 mInputMarginView = (InputMarginView) findViewById(R.id.input_margin_view); 75 76 updateEnabledWidgets(); 77 78 mAudioInputTester = addAudioInputTester(); 79 80 mWorkloadView = (WorkloadView) findViewById(R.id.workload_view); 81 if (mWorkloadView != null) { 82 mWorkloadView.setAudioStreamTester(mAudioInputTester); 83 } 84 } 85 86 @Override getActivityType()87 int getActivityType() { 88 return ACTIVITY_TEST_INPUT; 89 } 90 91 @Override resetConfiguration()92 protected void resetConfiguration() { 93 super.resetConfiguration(); 94 mAudioInputTester.reset(); 95 } 96 97 @Override updateStreamDisplay()98 void updateStreamDisplay() { 99 int numChannels = mAudioInputTester.getCurrentAudioStream().getChannelCount(); 100 if (numChannels > NUM_VOLUME_BARS) { 101 numChannels = NUM_VOLUME_BARS; 102 } 103 for (int i = 0; i < numChannels; i++) { 104 if (mVolumeBars[i] == null) break; 105 double level = mAudioInputTester.getPeakLevel(i); 106 mVolumeBars[i].setVolume((float) level); 107 } 108 } 109 resetVolumeBars()110 void resetVolumeBars() { 111 for (int i = 0; i < mVolumeBars.length; i++) { 112 if (mVolumeBars[i] == null) break; 113 mVolumeBars[i].setVolume((float) 0.0); 114 } 115 } 116 setMinimumBurstsBeforeRead(int numBursts)117 void setMinimumBurstsBeforeRead(int numBursts) { 118 int framesPerBurst = mAudioInputTester.getCurrentAudioStream().getFramesPerBurst(); 119 if (framesPerBurst > 0) { 120 setMinimumFramesBeforeRead(numBursts * framesPerBurst); 121 } 122 } 123 124 @Override openAudio()125 public void openAudio() throws IOException { 126 if (!isRecordPermissionGranted()){ 127 requestRecordPermission(); 128 return; 129 } 130 super.openAudio(); 131 setMinimumBurstsBeforeRead(mInputMarginBursts); 132 resetVolumeBars(); 133 } 134 135 @Override stopAudio()136 public void stopAudio() { 137 super.stopAudio(); 138 resetVolumeBars(); 139 } 140 141 @Override toastPauseError(int result)142 protected void toastPauseError(int result) { 143 showToast("Pause not implemented. Returned " + result); 144 } 145 isRecordPermissionGranted()146 private boolean isRecordPermissionGranted() { 147 return (ActivityCompat.checkSelfPermission(this, 148 Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED); 149 } 150 requestRecordPermission()151 private void requestRecordPermission(){ 152 ActivityCompat.requestPermissions( 153 this, 154 new String[]{Manifest.permission.RECORD_AUDIO}, 155 AUDIO_ECHO_REQUEST); 156 } 157 158 @Override onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)159 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 160 @NonNull int[] grantResults) { 161 162 if (AUDIO_ECHO_REQUEST != requestCode) { 163 super.onRequestPermissionsResult(requestCode, permissions, grantResults); 164 return; 165 } 166 167 if (grantResults.length != 1 || 168 grantResults[0] != PackageManager.PERMISSION_GRANTED) { 169 170 Toast.makeText(getApplicationContext(), 171 getString(R.string.need_record_audio_permission), 172 Toast.LENGTH_SHORT) 173 .show(); 174 } else { 175 // Permission was granted 176 try { 177 super.openAudio(); 178 } catch (IOException e) { 179 showErrorToast(e.getMessage()); 180 } 181 } 182 } 183 setupAGC(int sessionId)184 public void setupAGC(int sessionId) { 185 AutomaticGainControl effect = AutomaticGainControl.create(sessionId); 186 } 187 setupAEC(int sessionId)188 public void setupAEC(int sessionId) { 189 AcousticEchoCanceler effect = AcousticEchoCanceler.create(sessionId); 190 } 191 192 @Override setupEffects(int sessionId)193 public void setupEffects(int sessionId) { 194 setupAEC(sessionId); 195 } 196 saveWaveFile(File file)197 protected int saveWaveFile(File file) { 198 // Pass filename to native to write WAV file 199 int result = saveWaveFile(file.getAbsolutePath()); 200 if (result < 0) { 201 showErrorToast("Save returned " + result); 202 } else { 203 showToast("Saved " + result + " bytes."); 204 } 205 return result; 206 } 207 getWaveTag()208 String getWaveTag() { 209 return "input"; 210 } 211 212 @NonNull createFileName()213 private File createFileName() { 214 // Get directory and filename 215 File dir = getExternalFilesDir(Environment.DIRECTORY_MUSIC); 216 return new File(dir, "oboe_" + getWaveTag() + "_" + AutomatedTestRunner.getTimestampString() + ".wav"); 217 } 218 shareWaveFile()219 public void shareWaveFile() { 220 // Share WAVE file via GMail, Drive or other method. 221 File file = createFileName(); 222 int result = saveWaveFile(file); 223 if (result > 0) { 224 Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); 225 sharingIntent.setType("audio/wav"); 226 String subjectText = file.getName(); 227 sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subjectText); 228 Uri uri = FileProvider.getUriForFile(this, 229 BuildConfig.APPLICATION_ID + ".provider", 230 file); 231 sharingIntent.putExtra(Intent.EXTRA_STREAM, uri); 232 sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 233 startActivity(Intent.createChooser(sharingIntent, "Share WAV using:")); 234 } 235 } 236 onShareFile(View view)237 public void onShareFile(View view) { 238 shareWaveFile(); 239 } 240 onMarginBoxClicked(View view)241 public void onMarginBoxClicked(View view) { 242 RadioButton radioButton = (RadioButton) view; 243 String text = (String) radioButton.getText(); 244 mInputMarginBursts = Integer.parseInt(text); 245 setMinimumBurstsBeforeRead(mInputMarginBursts); 246 } 247 } 248