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 ScoAudioTest()89 public ScoAudioTest() { 90 Log.e(TAG, "contructor"); 91 } 92 93 /** Called when the activity is first created. */ 94 @Override onCreate(Bundle icicle)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 onDestroy()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 onPause()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 onResume()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 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName)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 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId)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 onClick(View v)299 public void onClick(View v) { 300 if (v.getId() == mPlayPauseButtonId) { 301 playOrPause(); 302 } else if (v.getId() == mStopButtonId) { 303 stop(); 304 } 305 } 306 playOrPause()307 public void playOrPause() { 308 } 309 stop()310 public void stop() { 311 } 312 isPlaying()313 public boolean isPlaying() { 314 return false; 315 } 316 updatePlayPauseButton()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; SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream)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 SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream)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 playOrPause()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 stop()394 public void stop() { 395 if (mMediaPlayer != null) { 396 mMediaPlayer.stop(); 397 mMediaPlayer.release(); 398 mMediaPlayer = null; 399 } 400 updatePlayPauseButton(); 401 } 402 403 @Override isPlaying()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; SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName)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 playOrPause()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 setup()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 stop()476 public void stop() { 477 if (mMediaRecorder != null) { 478 mMediaRecorder.stop(); 479 mMediaRecorder.release(); 480 mMediaRecorder = null; 481 } 482 updatePlayPauseButton(); 483 } 484 485 @Override isPlaying()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 onInit(int status)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 MyUtteranceCompletedListener(String expectedUtteranceId)526 public MyUtteranceCompletedListener(String expectedUtteranceId) { 527 mExpectedUtterance = expectedUtteranceId; 528 } 529 530 @Override onUtteranceCompleted(String utteranceId)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 onReceive(Context context, Intent intent)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