• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.scoaudiotest;
18 
19 import android.app.Activity;
20 import android.bluetooth.BluetoothAdapter;
21 import android.bluetooth.BluetoothDevice;
22 import android.bluetooth.BluetoothHeadset;
23 import android.bluetooth.BluetoothProfile;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.res.AssetFileDescriptor;
29 import android.media.AudioManager;
30 import android.media.MediaPlayer;
31 import android.media.MediaRecorder;
32 import android.os.Bundle;
33 import android.os.Environment;
34 import android.os.Handler;
35 import android.speech.tts.TextToSpeech;
36 import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
37 import android.util.Log;
38 import android.view.KeyEvent;
39 import android.view.View;
40 import android.view.View.OnClickListener;
41 import android.widget.ArrayAdapter;
42 import android.widget.CheckBox;
43 import android.widget.CompoundButton;
44 import android.widget.CompoundButton.OnCheckedChangeListener;
45 import android.widget.EditText;
46 import android.widget.ImageButton;
47 import android.widget.ImageView;
48 import android.widget.Spinner;
49 import android.widget.TextView;
50 import android.widget.ToggleButton;
51 
52 import java.io.File;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Locale;
56 
57 public 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 
ScoAudioTest()89     public ScoAudioTest() {
90         Log.e(TAG, "contructor");
91     }
92 
93     /** Called when the activity is first created. */
94     @Override
onCreate(Bundle icicle)95     public void onCreate(Bundle icicle) {
96         super.onCreate(icicle);
97 
98         setContentView(R.layout.scoaudiotest);
99 
100         mScoStateTxt = (TextView) findViewById(R.id.scoStateTxt);
101         mVdStateTxt = (TextView) findViewById(R.id.vdStateTxt);
102 
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);
115         TextView name = (TextView) findViewById(R.id.playPause1Text);
116         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 
138         mSpeakText = (EditText) findViewById(R.id.speakTextEdit);
139         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 
146         mModeSpinner = (Spinner) findViewById(R.id.modeSpinner);
147         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
onDestroy()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
onPause()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
onResume()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;
210                 CheckBox box = (CheckBox) findViewById(R.id.useSecondAudioManager);
211                 if (box.isChecked()) {
212                     Log.i(TAG, "Using 2nd audio manager");
213                     mngr = mAudioManager2;
214                 }
215 
216                 if (mForceScoOn) {
217                     Log.e(TAG, "startBluetoothSco() IN");
218                     mngr.startBluetoothSco();
219                     Log.e(TAG, "startBluetoothSco() OUT");
220                 } else {
221                     Log.e(TAG, "stopBluetoothSco() IN");
222                     mngr.stopBluetoothSco();
223                     Log.e(TAG, "stopBluetoothSco() OUT");
224                 }
225             }
226         }
227     };
228 
229     private OnCheckedChangeListener mVoiceDialerChanged
230     = new OnCheckedChangeListener(){
231         @Override
232         public void onCheckedChanged(CompoundButton buttonView,
233                 boolean isChecked) {
234             if (mVoiceDialerOn != isChecked) {
235                 mVoiceDialerOn = isChecked;
236                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
237                     if (mVoiceDialerOn) {
238                         mBluetoothHeadset.startVoiceRecognition(mBluetoothHeadsetDevice);
239                     } else {
240                         mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice);
241                     }
242                 }
243             }
244         }
245     };
246 
247     private OnCheckedChangeListener mTtsToFileChanged
248     = new OnCheckedChangeListener(){
249         @Override
250         public void onCheckedChanged(CompoundButton buttonView,
251                 boolean isChecked) {
252             mTtsToFile = isChecked;
253         }
254     };
255 
256     private class SimpleMediaController implements OnClickListener {
257         int mPlayPauseButtonId;
258         int mStopButtonId;
259         Context mContext;
260         ImageView mPlayPauseButton;
261         int mPlayImageResource;
262         int mPauseImageResource;
263         String mFileNameBase;
264         String mFileName;
265         int mFileResId;
266 
SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName)267         SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
268             mContext = context;
269             mPlayPauseButtonId = playPausebuttonId;
270             mStopButtonId = stopButtonId;
271             mFileNameBase = fileName;
272             mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
273             ImageButton stop = (ImageButton) findViewById(stopButtonId);
274 
275             mPlayPauseButton.setOnClickListener(this);
276             mPlayPauseButton.requestFocus();
277             if (stop != null) {
278                 stop.setOnClickListener(this);
279             }
280         }
281 
SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId)282         SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId) {
283             mContext = context;
284             mPlayPauseButtonId = playPausebuttonId;
285             mStopButtonId = stopButtonId;
286             mFileNameBase = "";
287             mFileResId = fileResId;
288             mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
289             ImageButton stop = (ImageButton) findViewById(stopButtonId);
290 
291             mPlayPauseButton.setOnClickListener(this);
292             mPlayPauseButton.requestFocus();
293             if (stop != null) {
294                 stop.setOnClickListener(this);
295             }
296         }
297 
298         @Override
onClick(View v)299         public void onClick(View v) {
300             if (v.getId() == mPlayPauseButtonId) {
301                 playOrPause();
302             } else if (v.getId() == mStopButtonId) {
303                 stop();
304             }
305         }
306 
playOrPause()307         public void playOrPause() {
308         }
309 
stop()310         public void stop() {
311         }
312 
isPlaying()313         public boolean isPlaying() {
314             return false;
315         }
316 
updatePlayPauseButton()317         public void updatePlayPauseButton() {
318             mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource);
319         }
320     }
321 
322     private class SimplePlayerController extends SimpleMediaController {
323         private MediaPlayer mMediaPlayer;
324         private int mStreamType;
SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream)325         SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream) {
326             super(context, playPausebuttonId, stopButtonId, fileName);
327 
328             mPlayImageResource = android.R.drawable.ic_media_play;
329             mPauseImageResource = android.R.drawable.ic_media_pause;
330             mStreamType = stream;
331             mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
332                         mFileNameBase + "_" + ".wav";
333         }
334 
SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream)335         SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream) {
336             super(context, playPausebuttonId, stopButtonId, fileResId);
337 
338             mPlayImageResource = android.R.drawable.ic_media_play;
339             mPauseImageResource = android.R.drawable.ic_media_pause;
340             mStreamType = stream;
341             mFileName = "";
342         }
343 
344         @Override
playOrPause()345         public void playOrPause() {
346             Log.e(TAG, "playOrPause playing: "+((mMediaPlayer == null)?false:!mMediaPlayer.isPlaying())+
347                     " mMediaPlayer: "+mMediaPlayer+
348                     " mFileName: "+mFileName+
349                     " mLastRecordedFile: "+mLastRecordedFile);
350             if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){
351                 if (mMediaPlayer == null) {
352                     if (mFileName != mLastRecordedFile) {
353                         mFileName = mLastRecordedFile;
354                         Log.e(TAG, "new recorded file: "+mFileName);
355                     }
356                     try {
357                         mMediaPlayer = new MediaPlayer();
358                         if (mFileName.equals("")) {
359                             Log.e(TAG, "Playing from resource");
360                             AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId);
361                             mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
362                             afd.close();
363                         } else {
364                             Log.e(TAG, "Playing file: "+mFileName);
365                             mMediaPlayer.setDataSource(mFileName);
366                         }
367                         mMediaPlayer.setAudioStreamType(mStreamType);
368                         mMediaPlayer.prepare();
369                         mMediaPlayer.setLooping(true);
370                     } catch (Exception ex) {
371                         Log.e(TAG, "mMediaPlayercreate failed:", ex);
372                         mMediaPlayer.release();
373                         mMediaPlayer = null;
374                     }
375 
376                     if (mMediaPlayer != null) {
377                         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
378                             @Override
379                             public void onCompletion(MediaPlayer mp) {
380                                 updatePlayPauseButton();
381                             }
382                         });
383                     }
384                 }
385                 if (mMediaPlayer != null) {
386                     mMediaPlayer.start();
387                 }
388             } else {
389                 mMediaPlayer.pause();
390             }
391             updatePlayPauseButton();
392         }
393         @Override
stop()394         public void stop() {
395             if (mMediaPlayer != null) {
396                 mMediaPlayer.stop();
397                 mMediaPlayer.release();
398                 mMediaPlayer = null;
399             }
400             updatePlayPauseButton();
401         }
402 
403         @Override
isPlaying()404         public boolean isPlaying() {
405             if (mMediaPlayer != null) {
406                 return mMediaPlayer.isPlaying();
407             } else {
408                 return false;
409             }
410         }
411     }
412 
413     private class SimpleRecordController extends SimpleMediaController {
414         private MediaRecorder mMediaRecorder;
415         private int mFileCount = 0;
416         private int mState = 0;
SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName)417         SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
418             super(context, playPausebuttonId, stopButtonId, fileName);
419             Log.e(TAG, "SimpleRecordController cstor");
420             mPlayImageResource = R.drawable.record;
421             mPauseImageResource = R.drawable.stop;
422         }
423 
424         @Override
playOrPause()425         public void playOrPause() {
426             if (mState == 0) {
427                 setup();
428                 try {
429                     mMediaRecorder.start();
430                     mState = 1;
431                 } catch (Exception e) {
432                     Log.e(TAG, "Could start MediaRecorder: ", e);
433                     mMediaRecorder.release();
434                     mMediaRecorder = null;
435                     mState = 0;
436                 }
437             } else {
438                 try {
439                     mMediaRecorder.stop();
440                     mMediaRecorder.reset();
441                 } catch (Exception e) {
442                     Log.e(TAG, "Could not stop MediaRecorder: ", e);
443                     mMediaRecorder.release();
444                     mMediaRecorder = null;
445                 } finally {
446                     mState = 0;
447                 }
448             }
449             updatePlayPauseButton();
450         }
451 
setup()452         public void setup() {
453             Log.e(TAG, "SimpleRecordController setup()");
454             if (mMediaRecorder == null) {
455                 mMediaRecorder = new MediaRecorder();
456             }
457             mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
458             mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
459             mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
460             mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
461                         mFileNameBase + "_" + ++mFileCount + ".amr";
462             mLastRecordedFile = mFileName;
463             Log.e(TAG, "recording to file: "+mLastRecordedFile);
464             mMediaRecorder.setOutputFile(mFileName);
465             try {
466                 mMediaRecorder.prepare();
467             }
468             catch (Exception e) {
469                 Log.e(TAG, "Could not prepare MediaRecorder: ", e);
470                 mMediaRecorder.release();
471                 mMediaRecorder = null;
472             }
473         }
474 
475         @Override
stop()476         public void stop() {
477             if (mMediaRecorder != null) {
478                 try {
479                     mMediaRecorder.stop();
480                 } catch (Exception e) {
481                     Log.e(TAG, "Could not stop MediaRecorder: ", e);
482                 } finally {
483                     mMediaRecorder.release();
484                     mMediaRecorder = null;
485                 }
486             }
487             updatePlayPauseButton();
488         }
489 
490         @Override
isPlaying()491         public boolean isPlaying() {
492             if (mState == 1) {
493                 return true;
494             } else {
495                 return false;
496             }
497         }
498     }
499 
500     class TtsInitListener implements TextToSpeech.OnInitListener {
501         @Override
onInit(int status)502         public void onInit(int status) {
503             // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
504             Log.e(TAG, "onInit for tts");
505             if (status != TextToSpeech.SUCCESS) {
506                 // Initialization failed.
507                 Log.e(TAG, "Could not initialize TextToSpeech.");
508                 return;
509             }
510 
511             if (mTts == null) {
512                 Log.e(TAG, "null tts");
513                 return;
514             }
515 
516             int result = mTts.setLanguage(Locale.US);
517             if (result == TextToSpeech.LANG_MISSING_DATA ||
518                 result == TextToSpeech.LANG_NOT_SUPPORTED) {
519                // Lanuage data is missing or the language is not supported.
520                 Log.e(TAG, "Language is not available.");
521                 return;
522             }
523             mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE));
524             mTtsInited = true;
525          }
526     }
527 
528     class MyUtteranceCompletedListener implements OnUtteranceCompletedListener {
529         private final String mExpectedUtterance;
530 
MyUtteranceCompletedListener(String expectedUtteranceId)531         public MyUtteranceCompletedListener(String expectedUtteranceId) {
532             mExpectedUtterance = expectedUtteranceId;
533         }
534 
535         @Override
onUtteranceCompleted(String utteranceId)536         public void onUtteranceCompleted(String utteranceId) {
537             Log.e(TAG, "onUtteranceCompleted " + utteranceId);
538             if (mTtsToFile) {
539                 if (mSampleFile != null && mSampleFile.exists()) {
540                     MediaPlayer mediaPlayer = new MediaPlayer();
541                     try {
542                         mediaPlayer.setDataSource(mSampleFile.getPath());
543                         mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO);
544                         mediaPlayer.prepare();
545                     } catch (Exception ex) {
546                         Log.e(TAG, "mMediaPlayercreate failed:", ex);
547                         mediaPlayer.release();
548                         mediaPlayer = null;
549                     }
550 
551                     if (mediaPlayer != null) {
552                         mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
553                             @Override
554                             public void onCompletion(MediaPlayer mp) {
555                                 mp.release();
556                                 if (mSampleFile != null && mSampleFile.exists()) {
557                                     mSampleFile.delete();
558                                     mSampleFile = null;
559                                 }
560                               mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
561                               mOriginalVoiceVolume, 0);
562 //                              Debug.stopMethodTracing();
563                             }
564                         });
565                         mediaPlayer.start();
566                     }
567                 } else {
568                     Log.e(TAG, "synthesizeToFile did not create file");
569                 }
570             } else {
571                 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
572                         mOriginalVoiceVolume, 0);
573 //                Debug.stopMethodTracing();
574             }
575 
576             Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume);
577         }
578     }
579 
580 
581     private View.OnKeyListener mSpeakKeyListener
582     = new View.OnKeyListener() {
583         @Override
584         public boolean onKey(View v, int keyCode, KeyEvent event) {
585             if (event.getAction() == KeyEvent.ACTION_DOWN) {
586                 switch (keyCode) {
587                     case KeyEvent.KEYCODE_DPAD_CENTER:
588                     case KeyEvent.KEYCODE_ENTER:
589                         if (!mTtsInited) {
590                             Log.e(TAG, "Tts not inited ");
591                             return false;
592                         }
593                         mOriginalVoiceVolume = mAudioManager.getStreamVolume(
594                                 AudioManager.STREAM_BLUETOOTH_SCO);
595                         Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume);
596                         mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
597                                 mOriginalVoiceVolume/2, 0);
598 
599                         // we now have SCO connection and TTS, so we can start.
600                         mHandler.post(new Runnable() {
601                             @Override
602                             public void run() {
603 //                                Debug.startMethodTracing("tts");
604 
605                                 if (mTtsToFile) {
606                                     if (mSampleFile != null && mSampleFile.exists()) {
607                                         mSampleFile.delete();
608                                         mSampleFile = null;
609                                     }
610                                     mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav");
611                                     mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath());
612                                 } else {
613                                     mTts.speak(mSpeakText.getText().toString(),
614                                         TextToSpeech.QUEUE_FLUSH,
615                                         mTtsParams);
616                                 }
617                             }
618                         });
619                         return true;
620                 }
621             }
622             return false;
623         }
624     };
625 
626     private static final String[] mModeStrings = {
627         "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION"
628     };
629 
630     private Spinner.OnItemSelectedListener mModeChanged
631         = new Spinner.OnItemSelectedListener() {
632         @Override
633         public void onItemSelected(android.widget.AdapterView av, View v,
634                     int position, long id) {
635             if (mCurrentMode != position) {
636                 mCurrentMode = position;
637                 mAudioManager.setMode(mCurrentMode);
638             }
639         }
640 
641         @Override
642         public void onNothingSelected(android.widget.AdapterView av) {
643         }
644     };
645 
646     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
647         new BluetoothProfile.ServiceListener() {
648         @Override
649         public void onServiceConnected(int profile, BluetoothProfile proxy) {
650             mBluetoothHeadset = (BluetoothHeadset) proxy;
651             List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
652             if (deviceList.size() > 0) {
653                 mBluetoothHeadsetDevice = deviceList.get(0);
654             } else {
655                 mBluetoothHeadsetDevice = null;
656             }
657         }
658         @Override
659         public void onServiceDisconnected(int profile) {
660             if (mBluetoothHeadset != null) {
661                 List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
662                 if (devices.size() == 0) {
663                     mBluetoothHeadsetDevice = null;
664                 }
665                 mBluetoothHeadset = null;
666             }
667         }
668     };
669 
670     private int mChangedState = -1;
671     private int mUpdatedState = -1;
672     private int mUpdatedPrevState = -1;
673 
674     private class ScoBroadcastReceiver extends BroadcastReceiver {
675         @Override
onReceive(Context context, Intent intent)676         public void onReceive(Context context, Intent intent) {
677             String action = intent.getAction();
678 
679             if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
680                 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
681                 mVdStateTxt.setText(Integer.toString(state));
682                 Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state);
683             } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) {
684                 mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
685                 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState);
686                 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
687                         " updated: "+Integer.toString(mUpdatedState)+
688                         " prev updated: "+Integer.toString(mUpdatedPrevState));
689             } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
690                 mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
691                 mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
692                 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState);
693                 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
694                         " updated: "+Integer.toString(mUpdatedState)+
695                         " prev updated: "+Integer.toString(mUpdatedPrevState));
696                 if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
697                     mForceScoOn = false;
698                     mScoButton.setChecked(mForceScoOn);
699                     mAudioManager.stopBluetoothSco();
700                 }
701             }
702         }
703     }
704 
705 }
706