Home | History | Annotate | Download | only in scoaudiotest
      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 
     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 
    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
    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;
    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 
    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 
    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
    299         public void onClick(View v) {
    300             if (v.getId() == mPlayPauseButtonId) {
    301                 playOrPause();
    302             } else if (v.getId() == mStopButtonId) {
    303                 stop();
    304             }
    305         }
    306 
    307         public void playOrPause() {
    308         }
    309 
    310         public void stop() {
    311         }
    312 
    313         public boolean isPlaying() {
    314             return false;
    315         }
    316 
    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;
    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 
    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
    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
    394         public void stop() {
    395             if (mMediaPlayer != null) {
    396                 mMediaPlayer.stop();
    397                 mMediaPlayer.release();
    398                 mMediaPlayer = null;
    399             }
    400             updatePlayPauseButton();
    401         }
    402 
    403         @Override
    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;
    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
    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 
    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
    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
    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
    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 
    531         public MyUtteranceCompletedListener(String expectedUtteranceId) {
    532             mExpectedUtterance = expectedUtteranceId;
    533         }
    534 
    535         @Override
    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
    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