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
17package com.android.scoaudiotest;
18
19import android.app.Activity;
20import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothDevice;
22import android.bluetooth.BluetoothHeadset;
23import android.bluetooth.BluetoothProfile;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.res.AssetFileDescriptor;
29import android.media.AudioManager;
30import android.media.MediaPlayer;
31import android.media.MediaRecorder;
32import android.os.Bundle;
33import android.os.Environment;
34import android.os.Handler;
35import android.speech.tts.TextToSpeech;
36import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
37import android.util.Log;
38import android.view.KeyEvent;
39import android.view.View;
40import android.view.View.OnClickListener;
41import android.widget.ArrayAdapter;
42import android.widget.CheckBox;
43import android.widget.CompoundButton;
44import android.widget.CompoundButton.OnCheckedChangeListener;
45import android.widget.EditText;
46import android.widget.ImageButton;
47import android.widget.ImageView;
48import android.widget.Spinner;
49import android.widget.TextView;
50import android.widget.ToggleButton;
51
52import java.io.File;
53import java.util.HashMap;
54import java.util.List;
55import java.util.Locale;
56
57public class ScoAudioTest extends Activity {
58
59    final static String TAG = "ScoAudioTest";
60
61    AudioManager mAudioManager;
62    AudioManager mAudioManager2;
63    boolean mForceScoOn;
64    ToggleButton mScoButton;
65    ToggleButton mVoiceDialerButton;
66    boolean mVoiceDialerOn;
67    String mLastRecordedFile;
68    SimpleMediaController mMediaControllers[] = new SimpleMediaController[2];
69    private TextToSpeech mTts;
70    private HashMap<String, String> mTtsParams;
71    private int mOriginalVoiceVolume;
72    EditText mSpeakText;
73    boolean mTtsInited;
74    private Handler mHandler;
75    private static final String UTTERANCE = "utterance";
76    private static Intent sVoiceCommandIntent;
77    private File mSampleFile;
78    ToggleButton mTtsToFileButton;
79    private boolean mTtsToFile;
80    private int mCurrentMode;
81    Spinner mModeSpinner;
82    private BluetoothHeadset mBluetoothHeadset;
83    private BluetoothDevice mBluetoothHeadsetDevice;
84    TextView mScoStateTxt;
85    TextView mVdStateTxt;
86
87    private final BroadcastReceiver mReceiver = new ScoBroadcastReceiver();
88
89    public ScoAudioTest() {
90        Log.e(TAG, "contructor");
91    }
92
93    /** Called when the activity is first created. */
94    @Override
95    public void onCreate(Bundle icicle) {
96        super.onCreate(icicle);
97
98        setContentView(R.layout.scoaudiotest);
99
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