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