blob: 8427d16d97602eb345f9c6840a18a35a263ed2b9 [file] [log] [blame]
Marco Nelissenef02abd2011-08-11 10:41:33 -07001/*
2 * Copyright (C) 2009 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
17package com.android.scoaudiotest;
18
19import android.app.Activity;
20import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothDevice;
22import android.bluetooth.BluetoothHeadset;
23import android.bluetooth.BluetoothProfile;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.res.AssetFileDescriptor;
29import android.media.AudioManager;
30import android.media.MediaPlayer;
31import android.media.MediaRecorder;
32import android.os.Bundle;
33import android.os.Environment;
34import android.os.Handler;
35import android.speech.tts.TextToSpeech;
36import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
37import android.util.Log;
38import android.view.KeyEvent;
39import android.view.View;
40import android.view.View.OnClickListener;
41import android.widget.ArrayAdapter;
42import android.widget.CheckBox;
43import android.widget.CompoundButton;
44import android.widget.CompoundButton.OnCheckedChangeListener;
45import android.widget.EditText;
46import android.widget.ImageButton;
47import android.widget.ImageView;
48import android.widget.Spinner;
49import android.widget.TextView;
50import android.widget.ToggleButton;
51
52import java.io.File;
53import java.util.HashMap;
54import java.util.List;
55import java.util.Locale;
56
57public class ScoAudioTest extends Activity {
58
59 final static String TAG = "ScoAudioTest";
60
61 AudioManager mAudioManager;
62 AudioManager mAudioManager2;
63 boolean mForceScoOn;
64 ToggleButton mScoButton;
65 ToggleButton mVoiceDialerButton;
66 boolean mVoiceDialerOn;
67 String mLastRecordedFile;
68 SimpleMediaController mMediaControllers[] = new SimpleMediaController[2];
69 private TextToSpeech mTts;
70 private HashMap<String, String> mTtsParams;
71 private int mOriginalVoiceVolume;
72 EditText mSpeakText;
73 boolean mTtsInited;
74 private Handler mHandler;
75 private static final String UTTERANCE = "utterance";
76 private static Intent sVoiceCommandIntent;
77 private File mSampleFile;
78 ToggleButton mTtsToFileButton;
79 private boolean mTtsToFile;
80 private int mCurrentMode;
81 Spinner mModeSpinner;
82 private BluetoothHeadset mBluetoothHeadset;
83 private BluetoothDevice mBluetoothHeadsetDevice;
84 TextView mScoStateTxt;
85 TextView mVdStateTxt;
86
87 private final BroadcastReceiver mReceiver = new ScoBroadcastReceiver();
88
89 public ScoAudioTest() {
90 Log.e(TAG, "contructor");
91 }
92
93 /** Called when the activity is first created. */
94 @Override
95 public void onCreate(Bundle icicle) {
96 super.onCreate(icicle);
97
98 setContentView(R.layout.scoaudiotest);
99
Alan Viverette51efddb2017-04-05 10:00:01 -0400100 mScoStateTxt = findViewById(R.id.scoStateTxt);
101 mVdStateTxt = findViewById(R.id.vdStateTxt);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700102
103 IntentFilter intentFilter =
104 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
105 intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
106 intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
107 registerReceiver(mReceiver, intentFilter);
108
109 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
110 mAudioManager2 = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
111 mHandler = new Handler();
112
113 mMediaControllers[0] = new SimplePlayerController(this, R.id.playPause1, R.id.stop1,
114 R.raw.sine440_mo_16b_16k, AudioManager.STREAM_BLUETOOTH_SCO);
Alan Viverette51efddb2017-04-05 10:00:01 -0400115 TextView name = findViewById(R.id.playPause1Text);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700116 name.setText("VOICE_CALL stream");
117
118 mScoButton = (ToggleButton)findViewById(R.id.ForceScoButton);
119 mScoButton.setOnCheckedChangeListener(mForceScoChanged);
120 mForceScoOn = false;
121 mScoButton.setChecked(mForceScoOn);
122
123 mVoiceDialerButton = (ToggleButton)findViewById(R.id.VoiceDialerButton);
124 mVoiceDialerButton.setOnCheckedChangeListener(mVoiceDialerChanged);
125 mVoiceDialerOn = false;
126 mVoiceDialerButton.setChecked(mVoiceDialerOn);
127
128
129 mMediaControllers[1] = new SimpleRecordController(this, R.id.recStop1, 0, "Sco_record_");
130 mTtsInited = false;
131 mTts = new TextToSpeech(this, new TtsInitListener());
132 mTtsParams = new HashMap<String, String>();
133 mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
134 String.valueOf(AudioManager.STREAM_BLUETOOTH_SCO));
135 mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
136 UTTERANCE);
137
Alan Viverette51efddb2017-04-05 10:00:01 -0400138 mSpeakText = findViewById(R.id.speakTextEdit);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700139 mSpeakText.setOnKeyListener(mSpeakKeyListener);
140 mSpeakText.setText("sco audio test sentence");
141 mTtsToFileButton = (ToggleButton)findViewById(R.id.TtsToFileButton);
142 mTtsToFileButton.setOnCheckedChangeListener(mTtsToFileChanged);
143 mTtsToFile = true;
144 mTtsToFileButton.setChecked(mTtsToFile);
145
Alan Viverette51efddb2017-04-05 10:00:01 -0400146 mModeSpinner = findViewById(R.id.modeSpinner);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700147 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
148 android.R.layout.simple_spinner_item, mModeStrings);
149 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
150 mModeSpinner.setAdapter(adapter);
151 mModeSpinner.setOnItemSelectedListener(mModeChanged);
152 mCurrentMode = mAudioManager.getMode();
153 mModeSpinner.setSelection(mCurrentMode);
154
155 mBluetoothHeadsetDevice = null;
156 BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
157 if (btAdapter != null) {
158 btAdapter.getProfileProxy(this, mBluetoothProfileServiceListener,
159 BluetoothProfile.HEADSET);
160 }
161
162 sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND);
163 sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
164 }
165
166 @Override
167 public void onDestroy() {
168 super.onDestroy();
169 mTts.shutdown();
170 unregisterReceiver(mReceiver);
171 if (mBluetoothHeadset != null) {
172 BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
173 if (btAdapter != null) {
174 btAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
175 }
176 }
177 }
178
179 @Override
180 protected void onPause() {
181 super.onPause();
182// mForceScoOn = false;
183// mScoButton.setChecked(mForceScoOn);
184 mMediaControllers[0].stop();
185 mMediaControllers[1].stop();
186 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
187 mOriginalVoiceVolume, 0);
188 }
189
190 @Override
191 protected void onResume() {
192 super.onResume();
193 mLastRecordedFile = "";
194 mMediaControllers[0].mFileName = "";
195 mOriginalVoiceVolume = mAudioManager.getStreamVolume(
196 AudioManager.STREAM_BLUETOOTH_SCO);
197 setVolumeControlStream(AudioManager.STREAM_BLUETOOTH_SCO);
198 mCurrentMode = mAudioManager.getMode();
199 mModeSpinner.setSelection(mCurrentMode);
200 }
201
202 private OnCheckedChangeListener mForceScoChanged
203 = new OnCheckedChangeListener(){
204 @Override
205 public void onCheckedChanged(CompoundButton buttonView,
206 boolean isChecked) {
207 if (mForceScoOn != isChecked) {
208 mForceScoOn = isChecked;
209 AudioManager mngr = mAudioManager;
Eric Laurent1cff3842014-05-15 16:37:29 -0700210 boolean useVirtualCall = false;
Alan Viverette51efddb2017-04-05 10:00:01 -0400211 CheckBox box = findViewById(R.id.useSecondAudioManager);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700212 if (box.isChecked()) {
213 Log.i(TAG, "Using 2nd audio manager");
214 mngr = mAudioManager2;
215 }
Alan Viverette51efddb2017-04-05 10:00:01 -0400216 box = findViewById(R.id.useVirtualCallCheckBox);
Eric Laurent1cff3842014-05-15 16:37:29 -0700217 useVirtualCall = box.isChecked();
Marco Nelissenef02abd2011-08-11 10:41:33 -0700218
219 if (mForceScoOn) {
Eric Laurent1cff3842014-05-15 16:37:29 -0700220 if (useVirtualCall) {
221 Log.e(TAG, "startBluetoothScoVirtualCall() IN");
222 mngr.startBluetoothScoVirtualCall();
223 Log.e(TAG, "startBluetoothScoVirtualCall() OUT");
224 } else {
225 Log.e(TAG, "startBluetoothSco() IN");
226 mngr.startBluetoothSco();
227 Log.e(TAG, "startBluetoothSco() OUT");
228 }
Marco Nelissenef02abd2011-08-11 10:41:33 -0700229 } else {
230 Log.e(TAG, "stopBluetoothSco() IN");
231 mngr.stopBluetoothSco();
232 Log.e(TAG, "stopBluetoothSco() OUT");
233 }
234 }
235 }
236 };
237
238 private OnCheckedChangeListener mVoiceDialerChanged
239 = new OnCheckedChangeListener(){
240 @Override
241 public void onCheckedChanged(CompoundButton buttonView,
242 boolean isChecked) {
243 if (mVoiceDialerOn != isChecked) {
244 mVoiceDialerOn = isChecked;
245 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
246 if (mVoiceDialerOn) {
247 mBluetoothHeadset.startVoiceRecognition(mBluetoothHeadsetDevice);
248 } else {
249 mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice);
250 }
251 }
252 }
253 }
254 };
255
256 private OnCheckedChangeListener mTtsToFileChanged
257 = new OnCheckedChangeListener(){
258 @Override
259 public void onCheckedChanged(CompoundButton buttonView,
260 boolean isChecked) {
261 mTtsToFile = isChecked;
262 }
263 };
264
265 private class SimpleMediaController implements OnClickListener {
266 int mPlayPauseButtonId;
267 int mStopButtonId;
268 Context mContext;
269 ImageView mPlayPauseButton;
270 int mPlayImageResource;
271 int mPauseImageResource;
272 String mFileNameBase;
273 String mFileName;
274 int mFileResId;
275
276 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
277 mContext = context;
278 mPlayPauseButtonId = playPausebuttonId;
279 mStopButtonId = stopButtonId;
280 mFileNameBase = fileName;
Alan Viverette51efddb2017-04-05 10:00:01 -0400281 mPlayPauseButton = findViewById(playPausebuttonId);
282 ImageButton stop = findViewById(stopButtonId);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700283
284 mPlayPauseButton.setOnClickListener(this);
285 mPlayPauseButton.requestFocus();
286 if (stop != null) {
287 stop.setOnClickListener(this);
288 }
289 }
290
291 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId) {
292 mContext = context;
293 mPlayPauseButtonId = playPausebuttonId;
294 mStopButtonId = stopButtonId;
295 mFileNameBase = "";
296 mFileResId = fileResId;
Alan Viverette51efddb2017-04-05 10:00:01 -0400297 mPlayPauseButton = findViewById(playPausebuttonId);
298 ImageButton stop = findViewById(stopButtonId);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700299
300 mPlayPauseButton.setOnClickListener(this);
301 mPlayPauseButton.requestFocus();
302 if (stop != null) {
303 stop.setOnClickListener(this);
304 }
305 }
306
307 @Override
308 public void onClick(View v) {
309 if (v.getId() == mPlayPauseButtonId) {
310 playOrPause();
311 } else if (v.getId() == mStopButtonId) {
312 stop();
313 }
314 }
315
316 public void playOrPause() {
317 }
318
319 public void stop() {
320 }
321
322 public boolean isPlaying() {
323 return false;
324 }
325
326 public void updatePlayPauseButton() {
327 mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource);
328 }
329 }
330
331 private class SimplePlayerController extends SimpleMediaController {
332 private MediaPlayer mMediaPlayer;
333 private int mStreamType;
334 SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream) {
335 super(context, playPausebuttonId, stopButtonId, fileName);
336
337 mPlayImageResource = android.R.drawable.ic_media_play;
338 mPauseImageResource = android.R.drawable.ic_media_pause;
339 mStreamType = stream;
340 mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
341 mFileNameBase + "_" + ".wav";
342 }
343
344 SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream) {
345 super(context, playPausebuttonId, stopButtonId, fileResId);
346
347 mPlayImageResource = android.R.drawable.ic_media_play;
348 mPauseImageResource = android.R.drawable.ic_media_pause;
349 mStreamType = stream;
350 mFileName = "";
351 }
352
353 @Override
354 public void playOrPause() {
355 Log.e(TAG, "playOrPause playing: "+((mMediaPlayer == null)?false:!mMediaPlayer.isPlaying())+
356 " mMediaPlayer: "+mMediaPlayer+
357 " mFileName: "+mFileName+
358 " mLastRecordedFile: "+mLastRecordedFile);
359 if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){
360 if (mMediaPlayer == null) {
361 if (mFileName != mLastRecordedFile) {
362 mFileName = mLastRecordedFile;
363 Log.e(TAG, "new recorded file: "+mFileName);
364 }
365 try {
366 mMediaPlayer = new MediaPlayer();
367 if (mFileName.equals("")) {
368 Log.e(TAG, "Playing from resource");
369 AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId);
370 mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
371 afd.close();
372 } else {
373 Log.e(TAG, "Playing file: "+mFileName);
374 mMediaPlayer.setDataSource(mFileName);
375 }
376 mMediaPlayer.setAudioStreamType(mStreamType);
377 mMediaPlayer.prepare();
378 mMediaPlayer.setLooping(true);
379 } catch (Exception ex) {
380 Log.e(TAG, "mMediaPlayercreate failed:", ex);
381 mMediaPlayer.release();
382 mMediaPlayer = null;
383 }
384
385 if (mMediaPlayer != null) {
386 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
387 @Override
388 public void onCompletion(MediaPlayer mp) {
389 updatePlayPauseButton();
390 }
391 });
392 }
393 }
394 if (mMediaPlayer != null) {
395 mMediaPlayer.start();
396 }
397 } else {
398 mMediaPlayer.pause();
399 }
400 updatePlayPauseButton();
401 }
402 @Override
403 public void stop() {
404 if (mMediaPlayer != null) {
405 mMediaPlayer.stop();
406 mMediaPlayer.release();
407 mMediaPlayer = null;
408 }
409 updatePlayPauseButton();
410 }
411
412 @Override
413 public boolean isPlaying() {
414 if (mMediaPlayer != null) {
415 return mMediaPlayer.isPlaying();
416 } else {
417 return false;
418 }
419 }
420 }
421
422 private class SimpleRecordController extends SimpleMediaController {
423 private MediaRecorder mMediaRecorder;
424 private int mFileCount = 0;
425 private int mState = 0;
426 SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
427 super(context, playPausebuttonId, stopButtonId, fileName);
428 Log.e(TAG, "SimpleRecordController cstor");
429 mPlayImageResource = R.drawable.record;
430 mPauseImageResource = R.drawable.stop;
431 }
432
433 @Override
434 public void playOrPause() {
435 if (mState == 0) {
436 setup();
437 try {
438 mMediaRecorder.start();
439 mState = 1;
440 } catch (Exception e) {
Eric Laurent1b7dba82013-04-19 17:25:03 -0700441 Log.e(TAG, "Could start MediaRecorder: ", e);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700442 mMediaRecorder.release();
443 mMediaRecorder = null;
444 mState = 0;
445 }
446 } else {
447 try {
448 mMediaRecorder.stop();
449 mMediaRecorder.reset();
450 } catch (Exception e) {
Eric Laurent1b7dba82013-04-19 17:25:03 -0700451 Log.e(TAG, "Could not stop MediaRecorder: ", e);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700452 mMediaRecorder.release();
453 mMediaRecorder = null;
454 } finally {
455 mState = 0;
456 }
457 }
458 updatePlayPauseButton();
459 }
460
461 public void setup() {
462 Log.e(TAG, "SimpleRecordController setup()");
463 if (mMediaRecorder == null) {
464 mMediaRecorder = new MediaRecorder();
465 }
466 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
467 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
468 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
469 mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
470 mFileNameBase + "_" + ++mFileCount + ".amr";
471 mLastRecordedFile = mFileName;
472 Log.e(TAG, "recording to file: "+mLastRecordedFile);
473 mMediaRecorder.setOutputFile(mFileName);
474 try {
475 mMediaRecorder.prepare();
476 }
477 catch (Exception e) {
Eric Laurent1b7dba82013-04-19 17:25:03 -0700478 Log.e(TAG, "Could not prepare MediaRecorder: ", e);
Marco Nelissenef02abd2011-08-11 10:41:33 -0700479 mMediaRecorder.release();
480 mMediaRecorder = null;
481 }
482 }
483
484 @Override
485 public void stop() {
486 if (mMediaRecorder != null) {
Eric Laurent1b7dba82013-04-19 17:25:03 -0700487 try {
488 mMediaRecorder.stop();
489 } catch (Exception e) {
490 Log.e(TAG, "Could not stop MediaRecorder: ", e);
491 } finally {
492 mMediaRecorder.release();
493 mMediaRecorder = null;
494 }
Marco Nelissenef02abd2011-08-11 10:41:33 -0700495 }
496 updatePlayPauseButton();
497 }
498
499 @Override
500 public boolean isPlaying() {
501 if (mState == 1) {
502 return true;
503 } else {
504 return false;
505 }
506 }
507 }
508
509 class TtsInitListener implements TextToSpeech.OnInitListener {
510 @Override
511 public void onInit(int status) {
512 // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
513 Log.e(TAG, "onInit for tts");
514 if (status != TextToSpeech.SUCCESS) {
515 // Initialization failed.
516 Log.e(TAG, "Could not initialize TextToSpeech.");
517 return;
518 }
519
520 if (mTts == null) {
521 Log.e(TAG, "null tts");
522 return;
523 }
524
525 int result = mTts.setLanguage(Locale.US);
526 if (result == TextToSpeech.LANG_MISSING_DATA ||
527 result == TextToSpeech.LANG_NOT_SUPPORTED) {
528 // Lanuage data is missing or the language is not supported.
529 Log.e(TAG, "Language is not available.");
530 return;
531 }
532 mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE));
533 mTtsInited = true;
534 }
535 }
536
537 class MyUtteranceCompletedListener implements OnUtteranceCompletedListener {
538 private final String mExpectedUtterance;
539
540 public MyUtteranceCompletedListener(String expectedUtteranceId) {
541 mExpectedUtterance = expectedUtteranceId;
542 }
543
544 @Override
545 public void onUtteranceCompleted(String utteranceId) {
546 Log.e(TAG, "onUtteranceCompleted " + utteranceId);
547 if (mTtsToFile) {
548 if (mSampleFile != null && mSampleFile.exists()) {
549 MediaPlayer mediaPlayer = new MediaPlayer();
550 try {
551 mediaPlayer.setDataSource(mSampleFile.getPath());
552 mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO);
553 mediaPlayer.prepare();
554 } catch (Exception ex) {
555 Log.e(TAG, "mMediaPlayercreate failed:", ex);
556 mediaPlayer.release();
557 mediaPlayer = null;
558 }
559
560 if (mediaPlayer != null) {
561 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
562 @Override
563 public void onCompletion(MediaPlayer mp) {
564 mp.release();
565 if (mSampleFile != null && mSampleFile.exists()) {
566 mSampleFile.delete();
567 mSampleFile = null;
568 }
569 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
570 mOriginalVoiceVolume, 0);
571// Debug.stopMethodTracing();
572 }
573 });
574 mediaPlayer.start();
575 }
576 } else {
577 Log.e(TAG, "synthesizeToFile did not create file");
578 }
579 } else {
580 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
581 mOriginalVoiceVolume, 0);
582// Debug.stopMethodTracing();
583 }
584
585 Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume);
586 }
587 }
588
589
590 private View.OnKeyListener mSpeakKeyListener
591 = new View.OnKeyListener() {
592 @Override
593 public boolean onKey(View v, int keyCode, KeyEvent event) {
594 if (event.getAction() == KeyEvent.ACTION_DOWN) {
595 switch (keyCode) {
596 case KeyEvent.KEYCODE_DPAD_CENTER:
597 case KeyEvent.KEYCODE_ENTER:
598 if (!mTtsInited) {
599 Log.e(TAG, "Tts not inited ");
600 return false;
601 }
602 mOriginalVoiceVolume = mAudioManager.getStreamVolume(
603 AudioManager.STREAM_BLUETOOTH_SCO);
604 Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume);
605 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
606 mOriginalVoiceVolume/2, 0);
607
608 // we now have SCO connection and TTS, so we can start.
609 mHandler.post(new Runnable() {
610 @Override
611 public void run() {
612// Debug.startMethodTracing("tts");
613
614 if (mTtsToFile) {
615 if (mSampleFile != null && mSampleFile.exists()) {
616 mSampleFile.delete();
617 mSampleFile = null;
618 }
619 mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav");
620 mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath());
621 } else {
622 mTts.speak(mSpeakText.getText().toString(),
623 TextToSpeech.QUEUE_FLUSH,
624 mTtsParams);
625 }
626 }
627 });
628 return true;
629 }
630 }
631 return false;
632 }
633 };
634
635 private static final String[] mModeStrings = {
636 "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION"
637 };
638
639 private Spinner.OnItemSelectedListener mModeChanged
640 = new Spinner.OnItemSelectedListener() {
641 @Override
642 public void onItemSelected(android.widget.AdapterView av, View v,
643 int position, long id) {
644 if (mCurrentMode != position) {
645 mCurrentMode = position;
646 mAudioManager.setMode(mCurrentMode);
647 }
648 }
649
650 @Override
651 public void onNothingSelected(android.widget.AdapterView av) {
652 }
653 };
654
655 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
656 new BluetoothProfile.ServiceListener() {
657 @Override
658 public void onServiceConnected(int profile, BluetoothProfile proxy) {
659 mBluetoothHeadset = (BluetoothHeadset) proxy;
660 List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
661 if (deviceList.size() > 0) {
662 mBluetoothHeadsetDevice = deviceList.get(0);
663 } else {
664 mBluetoothHeadsetDevice = null;
665 }
666 }
667 @Override
668 public void onServiceDisconnected(int profile) {
669 if (mBluetoothHeadset != null) {
670 List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
671 if (devices.size() == 0) {
672 mBluetoothHeadsetDevice = null;
673 }
674 mBluetoothHeadset = null;
675 }
676 }
677 };
678
679 private int mChangedState = -1;
680 private int mUpdatedState = -1;
681 private int mUpdatedPrevState = -1;
682
683 private class ScoBroadcastReceiver extends BroadcastReceiver {
684 @Override
685 public void onReceive(Context context, Intent intent) {
686 String action = intent.getAction();
687
688 if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
689 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
690 mVdStateTxt.setText(Integer.toString(state));
691 Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state);
692 } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) {
693 mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
694 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState);
695 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
696 " updated: "+Integer.toString(mUpdatedState)+
697 " prev updated: "+Integer.toString(mUpdatedPrevState));
698 } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
699 mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
700 mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
701 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState);
702 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
703 " updated: "+Integer.toString(mUpdatedState)+
704 " prev updated: "+Integer.toString(mUpdatedPrevState));
705 if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
706 mForceScoOn = false;
707 mScoButton.setChecked(mForceScoOn);
708 mAudioManager.stopBluetoothSco();
709 }
710 }
711 }
712 }
713
714}