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 = findViewById(R.id.scoStateTxt); 101 mVdStateTxt = 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 = 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 = 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 = 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 boolean useVirtualCall = false; 211 CheckBox box = findViewById(R.id.useSecondAudioManager); 212 if (box.isChecked()) { 213 Log.i(TAG, "Using 2nd audio manager"); 214 mngr = mAudioManager2; 215 } 216 box = 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 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName)276 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName) { 277 mContext = context; 278 mPlayPauseButtonId = playPausebuttonId; 279 mStopButtonId = stopButtonId; 280 mFileNameBase = fileName; 281 mPlayPauseButton = findViewById(playPausebuttonId); 282 ImageButton stop = findViewById(stopButtonId); 283 284 mPlayPauseButton.setOnClickListener(this); 285 mPlayPauseButton.requestFocus(); 286 if (stop != null) { 287 stop.setOnClickListener(this); 288 } 289 } 290 SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId)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 = findViewById(playPausebuttonId); 298 ImageButton stop = findViewById(stopButtonId); 299 300 mPlayPauseButton.setOnClickListener(this); 301 mPlayPauseButton.requestFocus(); 302 if (stop != null) { 303 stop.setOnClickListener(this); 304 } 305 } 306 307 @Override onClick(View v)308 public void onClick(View v) { 309 if (v.getId() == mPlayPauseButtonId) { 310 playOrPause(); 311 } else if (v.getId() == mStopButtonId) { 312 stop(); 313 } 314 } 315 playOrPause()316 public void playOrPause() { 317 } 318 stop()319 public void stop() { 320 } 321 isPlaying()322 public boolean isPlaying() { 323 return false; 324 } 325 updatePlayPauseButton()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; SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream)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 SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream)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 playOrPause()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 stop()403 public void stop() { 404 if (mMediaPlayer != null) { 405 mMediaPlayer.stop(); 406 mMediaPlayer.release(); 407 mMediaPlayer = null; 408 } 409 updatePlayPauseButton(); 410 } 411 412 @Override isPlaying()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; SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName)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 playOrPause()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 setup()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 stop()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 isPlaying()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 onInit(int status)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 MyUtteranceCompletedListener(String expectedUtteranceId)540 public MyUtteranceCompletedListener(String expectedUtteranceId) { 541 mExpectedUtterance = expectedUtteranceId; 542 } 543 544 @Override onUtteranceCompleted(String utteranceId)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 onReceive(Context context, Intent intent)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