• 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.toString());
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.toString());
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.toString());
470                 mMediaRecorder.release();
471                 mMediaRecorder = null;
472             }
473         }
474 
475         @Override
stop()476         public void stop() {
477             if (mMediaRecorder != null) {
478                 mMediaRecorder.stop();
479                 mMediaRecorder.release();
480                 mMediaRecorder = null;
481             }
482             updatePlayPauseButton();
483         }
484 
485         @Override
isPlaying()486         public boolean isPlaying() {
487             if (mState == 1) {
488                 return true;
489             } else {
490                 return false;
491             }
492         }
493     }
494 
495     class TtsInitListener implements TextToSpeech.OnInitListener {
496         @Override
onInit(int status)497         public void onInit(int status) {
498             // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
499             Log.e(TAG, "onInit for tts");
500             if (status != TextToSpeech.SUCCESS) {
501                 // Initialization failed.
502                 Log.e(TAG, "Could not initialize TextToSpeech.");
503                 return;
504             }
505 
506             if (mTts == null) {
507                 Log.e(TAG, "null tts");
508                 return;
509             }
510 
511             int result = mTts.setLanguage(Locale.US);
512             if (result == TextToSpeech.LANG_MISSING_DATA ||
513                 result == TextToSpeech.LANG_NOT_SUPPORTED) {
514                // Lanuage data is missing or the language is not supported.
515                 Log.e(TAG, "Language is not available.");
516                 return;
517             }
518             mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE));
519             mTtsInited = true;
520          }
521     }
522 
523     class MyUtteranceCompletedListener implements OnUtteranceCompletedListener {
524         private final String mExpectedUtterance;
525 
MyUtteranceCompletedListener(String expectedUtteranceId)526         public MyUtteranceCompletedListener(String expectedUtteranceId) {
527             mExpectedUtterance = expectedUtteranceId;
528         }
529 
530         @Override
onUtteranceCompleted(String utteranceId)531         public void onUtteranceCompleted(String utteranceId) {
532             Log.e(TAG, "onUtteranceCompleted " + utteranceId);
533             if (mTtsToFile) {
534                 if (mSampleFile != null && mSampleFile.exists()) {
535                     MediaPlayer mediaPlayer = new MediaPlayer();
536                     try {
537                         mediaPlayer.setDataSource(mSampleFile.getPath());
538                         mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO);
539                         mediaPlayer.prepare();
540                     } catch (Exception ex) {
541                         Log.e(TAG, "mMediaPlayercreate failed:", ex);
542                         mediaPlayer.release();
543                         mediaPlayer = null;
544                     }
545 
546                     if (mediaPlayer != null) {
547                         mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
548                             @Override
549                             public void onCompletion(MediaPlayer mp) {
550                                 mp.release();
551                                 if (mSampleFile != null && mSampleFile.exists()) {
552                                     mSampleFile.delete();
553                                     mSampleFile = null;
554                                 }
555                               mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
556                               mOriginalVoiceVolume, 0);
557 //                              Debug.stopMethodTracing();
558                             }
559                         });
560                         mediaPlayer.start();
561                     }
562                 } else {
563                     Log.e(TAG, "synthesizeToFile did not create file");
564                 }
565             } else {
566                 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
567                         mOriginalVoiceVolume, 0);
568 //                Debug.stopMethodTracing();
569             }
570 
571             Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume);
572         }
573     }
574 
575 
576     private View.OnKeyListener mSpeakKeyListener
577     = new View.OnKeyListener() {
578         @Override
579         public boolean onKey(View v, int keyCode, KeyEvent event) {
580             if (event.getAction() == KeyEvent.ACTION_DOWN) {
581                 switch (keyCode) {
582                     case KeyEvent.KEYCODE_DPAD_CENTER:
583                     case KeyEvent.KEYCODE_ENTER:
584                         if (!mTtsInited) {
585                             Log.e(TAG, "Tts not inited ");
586                             return false;
587                         }
588                         mOriginalVoiceVolume = mAudioManager.getStreamVolume(
589                                 AudioManager.STREAM_BLUETOOTH_SCO);
590                         Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume);
591                         mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
592                                 mOriginalVoiceVolume/2, 0);
593 
594                         // we now have SCO connection and TTS, so we can start.
595                         mHandler.post(new Runnable() {
596                             @Override
597                             public void run() {
598 //                                Debug.startMethodTracing("tts");
599 
600                                 if (mTtsToFile) {
601                                     if (mSampleFile != null && mSampleFile.exists()) {
602                                         mSampleFile.delete();
603                                         mSampleFile = null;
604                                     }
605                                     mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav");
606                                     mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath());
607                                 } else {
608                                     mTts.speak(mSpeakText.getText().toString(),
609                                         TextToSpeech.QUEUE_FLUSH,
610                                         mTtsParams);
611                                 }
612                             }
613                         });
614                         return true;
615                 }
616             }
617             return false;
618         }
619     };
620 
621     private static final String[] mModeStrings = {
622         "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION"
623     };
624 
625     private Spinner.OnItemSelectedListener mModeChanged
626         = new Spinner.OnItemSelectedListener() {
627         @Override
628         public void onItemSelected(android.widget.AdapterView av, View v,
629                     int position, long id) {
630             if (mCurrentMode != position) {
631                 mCurrentMode = position;
632                 mAudioManager.setMode(mCurrentMode);
633             }
634         }
635 
636         @Override
637         public void onNothingSelected(android.widget.AdapterView av) {
638         }
639     };
640 
641     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
642         new BluetoothProfile.ServiceListener() {
643         @Override
644         public void onServiceConnected(int profile, BluetoothProfile proxy) {
645             mBluetoothHeadset = (BluetoothHeadset) proxy;
646             List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
647             if (deviceList.size() > 0) {
648                 mBluetoothHeadsetDevice = deviceList.get(0);
649             } else {
650                 mBluetoothHeadsetDevice = null;
651             }
652         }
653         @Override
654         public void onServiceDisconnected(int profile) {
655             if (mBluetoothHeadset != null) {
656                 List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
657                 if (devices.size() == 0) {
658                     mBluetoothHeadsetDevice = null;
659                 }
660                 mBluetoothHeadset = null;
661             }
662         }
663     };
664 
665     private int mChangedState = -1;
666     private int mUpdatedState = -1;
667     private int mUpdatedPrevState = -1;
668 
669     private class ScoBroadcastReceiver extends BroadcastReceiver {
670         @Override
onReceive(Context context, Intent intent)671         public void onReceive(Context context, Intent intent) {
672             String action = intent.getAction();
673 
674             if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
675                 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
676                 mVdStateTxt.setText(Integer.toString(state));
677                 Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state);
678             } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) {
679                 mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
680                 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState);
681                 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
682                         " updated: "+Integer.toString(mUpdatedState)+
683                         " prev updated: "+Integer.toString(mUpdatedPrevState));
684             } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
685                 mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
686                 mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
687                 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState);
688                 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+
689                         " updated: "+Integer.toString(mUpdatedState)+
690                         " prev updated: "+Integer.toString(mUpdatedPrevState));
691                 if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
692                     mForceScoOn = false;
693                     mScoButton.setChecked(mForceScoOn);
694                     mAudioManager.stopBluetoothSco();
695                 }
696             }
697         }
698     }
699 
700 }
701