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.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 
    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
    476         public void stop() {
    477             if (mMediaRecorder != null) {
    478                 mMediaRecorder.stop();
    479                 mMediaRecorder.release();
    480                 mMediaRecorder = null;
    481             }
    482             updatePlayPauseButton();
    483         }
    484 
    485         @Override
    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
    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 
    526         public MyUtteranceCompletedListener(String expectedUtteranceId) {
    527             mExpectedUtterance = expectedUtteranceId;
    528         }
    529 
    530         @Override
    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
    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