FileDocCategorySizeDatePackage
ScoAudioTest.javaAPI DocAndroid 5.1 API28838Thu Mar 12 22:22:30 GMT 2015com.android.scoaudiotest

ScoAudioTest.java

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.scoaudiotest;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ToggleButton;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

public class ScoAudioTest extends Activity {

    final static String TAG = "ScoAudioTest";
    
    AudioManager mAudioManager;
    AudioManager mAudioManager2;
    boolean mForceScoOn;
    ToggleButton mScoButton;
    ToggleButton mVoiceDialerButton;
    boolean mVoiceDialerOn;
    String mLastRecordedFile;
    SimpleMediaController mMediaControllers[] = new SimpleMediaController[2];
    private TextToSpeech mTts;
    private HashMap<String, String> mTtsParams;
    private int mOriginalVoiceVolume;
    EditText mSpeakText;
    boolean mTtsInited;
    private Handler mHandler;
    private static final String UTTERANCE = "utterance";
    private static Intent sVoiceCommandIntent;
    private File mSampleFile;
    ToggleButton mTtsToFileButton;
    private boolean mTtsToFile;
    private int mCurrentMode;
    Spinner mModeSpinner;
    private BluetoothHeadset mBluetoothHeadset;
    private BluetoothDevice mBluetoothHeadsetDevice;
    TextView mScoStateTxt;
    TextView mVdStateTxt;
    
    private final BroadcastReceiver mReceiver = new ScoBroadcastReceiver();

    public ScoAudioTest() {
        Log.e(TAG, "contructor");
    }
        
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        
        setContentView(R.layout.scoaudiotest);

        mScoStateTxt = (TextView) findViewById(R.id.scoStateTxt);
        mVdStateTxt = (TextView) findViewById(R.id.vdStateTxt);

        IntentFilter intentFilter =
            new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
        intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
        registerReceiver(mReceiver, intentFilter);

        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        mAudioManager2 = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        mHandler = new Handler();
        
        mMediaControllers[0] = new SimplePlayerController(this, R.id.playPause1, R.id.stop1,
                R.raw.sine440_mo_16b_16k, AudioManager.STREAM_BLUETOOTH_SCO);
        TextView name = (TextView) findViewById(R.id.playPause1Text);
        name.setText("VOICE_CALL stream");
        
        mScoButton = (ToggleButton)findViewById(R.id.ForceScoButton);
        mScoButton.setOnCheckedChangeListener(mForceScoChanged);
        mForceScoOn = false;
        mScoButton.setChecked(mForceScoOn);

        mVoiceDialerButton = (ToggleButton)findViewById(R.id.VoiceDialerButton);
        mVoiceDialerButton.setOnCheckedChangeListener(mVoiceDialerChanged);
        mVoiceDialerOn = false;
        mVoiceDialerButton.setChecked(mVoiceDialerOn);

        
        mMediaControllers[1] = new SimpleRecordController(this, R.id.recStop1, 0, "Sco_record_");
        mTtsInited = false;
        mTts = new TextToSpeech(this, new TtsInitListener());
        mTtsParams = new HashMap<String, String>();
        mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
                String.valueOf(AudioManager.STREAM_BLUETOOTH_SCO));
        mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
                UTTERANCE);

        mSpeakText = (EditText) findViewById(R.id.speakTextEdit);        
        mSpeakText.setOnKeyListener(mSpeakKeyListener);
        mSpeakText.setText("sco audio test sentence");
        mTtsToFileButton = (ToggleButton)findViewById(R.id.TtsToFileButton);
        mTtsToFileButton.setOnCheckedChangeListener(mTtsToFileChanged);
        mTtsToFile = true;
        mTtsToFileButton.setChecked(mTtsToFile);

        mModeSpinner = (Spinner) findViewById(R.id.modeSpinner);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, mModeStrings);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mModeSpinner.setAdapter(adapter);
        mModeSpinner.setOnItemSelectedListener(mModeChanged);
        mCurrentMode = mAudioManager.getMode();
        mModeSpinner.setSelection(mCurrentMode);

        mBluetoothHeadsetDevice = null;
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        if (btAdapter != null) {
            btAdapter.getProfileProxy(this, mBluetoothProfileServiceListener,
                                    BluetoothProfile.HEADSET);
        }

        sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND);
        sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mTts.shutdown();
        unregisterReceiver(mReceiver);
        if (mBluetoothHeadset != null) {
            BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
            if (btAdapter != null) {
                btAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
            }
        }
    }
    
    @Override
    protected void onPause() {
        super.onPause();
//        mForceScoOn = false;
//        mScoButton.setChecked(mForceScoOn);
        mMediaControllers[0].stop();        
        mMediaControllers[1].stop();
        mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
                mOriginalVoiceVolume, 0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mLastRecordedFile = "";
        mMediaControllers[0].mFileName = "";
        mOriginalVoiceVolume = mAudioManager.getStreamVolume(
                AudioManager.STREAM_BLUETOOTH_SCO);
        setVolumeControlStream(AudioManager.STREAM_BLUETOOTH_SCO);
        mCurrentMode = mAudioManager.getMode();
        mModeSpinner.setSelection(mCurrentMode);
    }

    private OnCheckedChangeListener mForceScoChanged
    = new OnCheckedChangeListener(){
        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            if (mForceScoOn != isChecked) {
                mForceScoOn = isChecked;
                AudioManager mngr = mAudioManager;
                boolean useVirtualCall = false;
                CheckBox box = (CheckBox) findViewById(R.id.useSecondAudioManager);
                if (box.isChecked()) {
                    Log.i(TAG, "Using 2nd audio manager");
                    mngr = mAudioManager2;
                }
                box = (CheckBox) findViewById(R.id.useVirtualCallCheckBox);
                useVirtualCall = box.isChecked();

                if (mForceScoOn) {
                    if (useVirtualCall) {
                        Log.e(TAG, "startBluetoothScoVirtualCall() IN");
                        mngr.startBluetoothScoVirtualCall();
                        Log.e(TAG, "startBluetoothScoVirtualCall() OUT");
                    } else {
                        Log.e(TAG, "startBluetoothSco() IN");
                        mngr.startBluetoothSco();
                        Log.e(TAG, "startBluetoothSco() OUT");
                    }
                } else {
                    Log.e(TAG, "stopBluetoothSco() IN");
                    mngr.stopBluetoothSco();
                    Log.e(TAG, "stopBluetoothSco() OUT");
                }
            }
        }
    };

    private OnCheckedChangeListener mVoiceDialerChanged
    = new OnCheckedChangeListener(){
        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            if (mVoiceDialerOn != isChecked) {
                mVoiceDialerOn = isChecked;
                if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
                    if (mVoiceDialerOn) {
                        mBluetoothHeadset.startVoiceRecognition(mBluetoothHeadsetDevice);
                    } else {
                        mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice);                        
                    }
                }
            }
        }
    };

    private OnCheckedChangeListener mTtsToFileChanged
    = new OnCheckedChangeListener(){
        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            mTtsToFile = isChecked;
        }
    };

    private class SimpleMediaController implements OnClickListener {
        int mPlayPauseButtonId;
        int mStopButtonId;
        Context mContext;
        ImageView mPlayPauseButton;
        int mPlayImageResource;
        int mPauseImageResource;
        String mFileNameBase;
        String mFileName;
        int mFileResId;
        
        SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
            mContext = context;
            mPlayPauseButtonId = playPausebuttonId;
            mStopButtonId = stopButtonId;
            mFileNameBase = fileName;
            mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
            ImageButton stop = (ImageButton) findViewById(stopButtonId);

            mPlayPauseButton.setOnClickListener(this);
            mPlayPauseButton.requestFocus();
            if (stop != null) {
                stop.setOnClickListener(this);
            }
        }

        SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId) {
            mContext = context;
            mPlayPauseButtonId = playPausebuttonId;
            mStopButtonId = stopButtonId;
            mFileNameBase = "";
            mFileResId = fileResId;
            mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
            ImageButton stop = (ImageButton) findViewById(stopButtonId);

            mPlayPauseButton.setOnClickListener(this);
            mPlayPauseButton.requestFocus();
            if (stop != null) {
                stop.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            if (v.getId() == mPlayPauseButtonId) {
                playOrPause();
            } else if (v.getId() == mStopButtonId) {
                stop();
            }
        }
        
        public void playOrPause() {
        }
        
        public void stop() {
        }

        public boolean isPlaying() {
            return false;
        }

        public void updatePlayPauseButton() {
            mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource);
        }
    }
    
    private class SimplePlayerController extends SimpleMediaController {
        private MediaPlayer mMediaPlayer;
        private int mStreamType;
        SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream) {
            super(context, playPausebuttonId, stopButtonId, fileName);
            
            mPlayImageResource = android.R.drawable.ic_media_play;
            mPauseImageResource = android.R.drawable.ic_media_pause;
            mStreamType = stream;
            mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
                        mFileNameBase + "_" + ".wav";
        }

        SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream) {
            super(context, playPausebuttonId, stopButtonId, fileResId);
            
            mPlayImageResource = android.R.drawable.ic_media_play;
            mPauseImageResource = android.R.drawable.ic_media_pause;
            mStreamType = stream;
            mFileName = "";
        }

        @Override
        public void playOrPause() {
            Log.e(TAG, "playOrPause playing: "+((mMediaPlayer == null)?false:!mMediaPlayer.isPlaying())+
                    " mMediaPlayer: "+mMediaPlayer+
                    " mFileName: "+mFileName+
                    " mLastRecordedFile: "+mLastRecordedFile);
            if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){
                if (mMediaPlayer == null) {
                    if (mFileName != mLastRecordedFile) {
                        mFileName = mLastRecordedFile;
                        Log.e(TAG, "new recorded file: "+mFileName);
                    }
                    try {
                        mMediaPlayer = new MediaPlayer();
                        if (mFileName.equals("")) {
                            Log.e(TAG, "Playing from resource");
                            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId);
                            mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                            afd.close();
                        } else {
                            Log.e(TAG, "Playing file: "+mFileName);
                            mMediaPlayer.setDataSource(mFileName);
                        }
                        mMediaPlayer.setAudioStreamType(mStreamType);
                        mMediaPlayer.prepare();
                        mMediaPlayer.setLooping(true);
                    } catch (Exception ex) {
                        Log.e(TAG, "mMediaPlayercreate failed:", ex);
                        mMediaPlayer.release();
                        mMediaPlayer = null;
                    }

                    if (mMediaPlayer != null) {
                        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mp) {
                                updatePlayPauseButton();
                            }
                        });
                    }
                }
                if (mMediaPlayer != null) {
                    mMediaPlayer.start();
                }
            } else {
                mMediaPlayer.pause();
            }
            updatePlayPauseButton();
        }
        @Override
        public void stop() {
            if (mMediaPlayer != null) {
                mMediaPlayer.stop();
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
            updatePlayPauseButton();
        }
        
        @Override
        public boolean isPlaying() {
            if (mMediaPlayer != null) {
                return mMediaPlayer.isPlaying();
            } else {
                return false;                
            }
        }
    }
    
    private class SimpleRecordController extends SimpleMediaController {
        private MediaRecorder mMediaRecorder;
        private int mFileCount = 0;
        private int mState = 0;
        SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName) {
            super(context, playPausebuttonId, stopButtonId, fileName);
            Log.e(TAG, "SimpleRecordController cstor");
            mPlayImageResource = R.drawable.record;
            mPauseImageResource = R.drawable.stop;
        }
       
        @Override
        public void playOrPause() {
            if (mState == 0) {
                setup();
                try {
                    mMediaRecorder.start();
                    mState = 1;
                } catch (Exception e) {
                    Log.e(TAG, "Could start MediaRecorder: ", e);
                    mMediaRecorder.release();
                    mMediaRecorder = null;
                    mState = 0;
                }
            } else {
                try {
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                } catch (Exception e) {
                    Log.e(TAG, "Could not stop MediaRecorder: ", e);
                    mMediaRecorder.release();
                    mMediaRecorder = null;
                } finally {
                    mState = 0;
                }
            }
            updatePlayPauseButton();
        }

        public void setup() {
            Log.e(TAG, "SimpleRecordController setup()");
            if (mMediaRecorder == null) {
                mMediaRecorder = new MediaRecorder();
            }
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" +
                        mFileNameBase + "_" + ++mFileCount + ".amr";
            mLastRecordedFile = mFileName;
            Log.e(TAG, "recording to file: "+mLastRecordedFile);
            mMediaRecorder.setOutputFile(mFileName);
            try {
                mMediaRecorder.prepare();
            }
            catch (Exception e) {
                Log.e(TAG, "Could not prepare MediaRecorder: ", e);
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        }
        
        @Override
        public void stop() {
            if (mMediaRecorder != null) {
                try {
                    mMediaRecorder.stop();
                } catch (Exception e) {
                    Log.e(TAG, "Could not stop MediaRecorder: ", e);
                } finally {
                    mMediaRecorder.release();
                    mMediaRecorder = null;
                }
            }
            updatePlayPauseButton();
        }

        @Override
        public boolean isPlaying() {
            if (mState == 1) {
                return true;
            } else {
                return false;                
            }
        }
    }
    
    class TtsInitListener implements TextToSpeech.OnInitListener {
        @Override
        public void onInit(int status) {
            // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
            Log.e(TAG, "onInit for tts");
            if (status != TextToSpeech.SUCCESS) {
                // Initialization failed.
                Log.e(TAG, "Could not initialize TextToSpeech.");
                return;
            }

            if (mTts == null) {
                Log.e(TAG, "null tts");
                return;
            }

            int result = mTts.setLanguage(Locale.US);
            if (result == TextToSpeech.LANG_MISSING_DATA ||
                result == TextToSpeech.LANG_NOT_SUPPORTED) {
               // Lanuage data is missing or the language is not supported.
                Log.e(TAG, "Language is not available.");
                return;
            }
            mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE));
            mTtsInited = true;
         }
    }

    class MyUtteranceCompletedListener implements OnUtteranceCompletedListener {
        private final String mExpectedUtterance;
        
        public MyUtteranceCompletedListener(String expectedUtteranceId) {
            mExpectedUtterance = expectedUtteranceId;
        }
        
        @Override
        public void onUtteranceCompleted(String utteranceId) {
            Log.e(TAG, "onUtteranceCompleted " + utteranceId);
            if (mTtsToFile) {
                if (mSampleFile != null && mSampleFile.exists()) {
                    MediaPlayer mediaPlayer = new MediaPlayer();
                    try {
                        mediaPlayer.setDataSource(mSampleFile.getPath());
                        mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO);
                        mediaPlayer.prepare();
                    } catch (Exception ex) {
                        Log.e(TAG, "mMediaPlayercreate failed:", ex);
                        mediaPlayer.release();
                        mediaPlayer = null;
                    }
    
                    if (mediaPlayer != null) {
                        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mp) {
                                mp.release();
                                if (mSampleFile != null && mSampleFile.exists()) {
                                    mSampleFile.delete();
                                    mSampleFile = null;
                                }
                              mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
                              mOriginalVoiceVolume, 0);
//                              Debug.stopMethodTracing();
                            }
                        });
                        mediaPlayer.start();
                    }
                } else {
                    Log.e(TAG, "synthesizeToFile did not create file");
                }
            } else {
                mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
                        mOriginalVoiceVolume, 0);
//                Debug.stopMethodTracing();
            }
            
            Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume);
        }
    }

    
    private View.OnKeyListener mSpeakKeyListener
    = new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                switch (keyCode) {
                    case KeyEvent.KEYCODE_DPAD_CENTER:
                    case KeyEvent.KEYCODE_ENTER:
                        if (!mTtsInited) {
                            Log.e(TAG, "Tts not inited ");
                            return false;
                        }
                        mOriginalVoiceVolume = mAudioManager.getStreamVolume(
                                AudioManager.STREAM_BLUETOOTH_SCO);
                        Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume);
                        mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO,
                                mOriginalVoiceVolume/2, 0);

                        // we now have SCO connection and TTS, so we can start.
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
//                                Debug.startMethodTracing("tts");

                                if (mTtsToFile) {
                                    if (mSampleFile != null && mSampleFile.exists()) {
                                        mSampleFile.delete();
                                        mSampleFile = null;
                                    }
                                    mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav");
                                    mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath());
                                } else {
                                    mTts.speak(mSpeakText.getText().toString(),
                                        TextToSpeech.QUEUE_FLUSH,
                                        mTtsParams);
                                }
                            }
                        });
                        return true;
                }
            }
            return false;
        }
    };
    
    private static final String[] mModeStrings = {
        "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION"
    };
    
    private Spinner.OnItemSelectedListener mModeChanged
        = new Spinner.OnItemSelectedListener() {
        @Override
        public void onItemSelected(android.widget.AdapterView av, View v,
                    int position, long id) {
            if (mCurrentMode != position) {
                mCurrentMode = position;
                mAudioManager.setMode(mCurrentMode);
            }
        }
        
        @Override
        public void onNothingSelected(android.widget.AdapterView av) {
        }
    };

    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
        new BluetoothProfile.ServiceListener() {
        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            mBluetoothHeadset = (BluetoothHeadset) proxy;
            List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
            if (deviceList.size() > 0) {
                mBluetoothHeadsetDevice = deviceList.get(0);
            } else {
                mBluetoothHeadsetDevice = null;
            }
        }
        @Override
        public void onServiceDisconnected(int profile) {
            if (mBluetoothHeadset != null) {
                List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
                if (devices.size() == 0) {
                    mBluetoothHeadsetDevice = null;
                }
                mBluetoothHeadset = null;
            }
        }
    };

    private int mChangedState = -1;
    private int mUpdatedState = -1;
    private int mUpdatedPrevState = -1;
    
    private class ScoBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
                mVdStateTxt.setText(Integer.toString(state));
                Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state);
            } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) {
                mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
                Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState);
                mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ 
                        " updated: "+Integer.toString(mUpdatedState)+
                        " prev updated: "+Integer.toString(mUpdatedPrevState));
            } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
                mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
                mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
                Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState);
                mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ 
                        " updated: "+Integer.toString(mUpdatedState)+
                        " prev updated: "+Integer.toString(mUpdatedPrevState));
                if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
                    mForceScoOn = false;
                    mScoButton.setChecked(mForceScoOn);
                    mAudioManager.stopBluetoothSco();
                }
            }
        }
    }

}