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); 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); 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); 470 mMediaRecorder.release(); 471 mMediaRecorder = null; 472 } 473 } 474 475 @Override stop()476 public void stop() { 477 if (mMediaRecorder != null) { 478 try { 479 mMediaRecorder.stop(); 480 } catch (Exception e) { 481 Log.e(TAG, "Could not stop MediaRecorder: ", e); 482 } finally { 483 mMediaRecorder.release(); 484 mMediaRecorder = null; 485 } 486 } 487 updatePlayPauseButton(); 488 } 489 490 @Override isPlaying()491 public boolean isPlaying() { 492 if (mState == 1) { 493 return true; 494 } else { 495 return false; 496 } 497 } 498 } 499 500 class TtsInitListener implements TextToSpeech.OnInitListener { 501 @Override onInit(int status)502 public void onInit(int status) { 503 // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR. 504 Log.e(TAG, "onInit for tts"); 505 if (status != TextToSpeech.SUCCESS) { 506 // Initialization failed. 507 Log.e(TAG, "Could not initialize TextToSpeech."); 508 return; 509 } 510 511 if (mTts == null) { 512 Log.e(TAG, "null tts"); 513 return; 514 } 515 516 int result = mTts.setLanguage(Locale.US); 517 if (result == TextToSpeech.LANG_MISSING_DATA || 518 result == TextToSpeech.LANG_NOT_SUPPORTED) { 519 // Lanuage data is missing or the language is not supported. 520 Log.e(TAG, "Language is not available."); 521 return; 522 } 523 mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE)); 524 mTtsInited = true; 525 } 526 } 527 528 class MyUtteranceCompletedListener implements OnUtteranceCompletedListener { 529 private final String mExpectedUtterance; 530 MyUtteranceCompletedListener(String expectedUtteranceId)531 public MyUtteranceCompletedListener(String expectedUtteranceId) { 532 mExpectedUtterance = expectedUtteranceId; 533 } 534 535 @Override onUtteranceCompleted(String utteranceId)536 public void onUtteranceCompleted(String utteranceId) { 537 Log.e(TAG, "onUtteranceCompleted " + utteranceId); 538 if (mTtsToFile) { 539 if (mSampleFile != null && mSampleFile.exists()) { 540 MediaPlayer mediaPlayer = new MediaPlayer(); 541 try { 542 mediaPlayer.setDataSource(mSampleFile.getPath()); 543 mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO); 544 mediaPlayer.prepare(); 545 } catch (Exception ex) { 546 Log.e(TAG, "mMediaPlayercreate failed:", ex); 547 mediaPlayer.release(); 548 mediaPlayer = null; 549 } 550 551 if (mediaPlayer != null) { 552 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 553 @Override 554 public void onCompletion(MediaPlayer mp) { 555 mp.release(); 556 if (mSampleFile != null && mSampleFile.exists()) { 557 mSampleFile.delete(); 558 mSampleFile = null; 559 } 560 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 561 mOriginalVoiceVolume, 0); 562 // Debug.stopMethodTracing(); 563 } 564 }); 565 mediaPlayer.start(); 566 } 567 } else { 568 Log.e(TAG, "synthesizeToFile did not create file"); 569 } 570 } else { 571 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 572 mOriginalVoiceVolume, 0); 573 // Debug.stopMethodTracing(); 574 } 575 576 Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume); 577 } 578 } 579 580 581 private View.OnKeyListener mSpeakKeyListener 582 = new View.OnKeyListener() { 583 @Override 584 public boolean onKey(View v, int keyCode, KeyEvent event) { 585 if (event.getAction() == KeyEvent.ACTION_DOWN) { 586 switch (keyCode) { 587 case KeyEvent.KEYCODE_DPAD_CENTER: 588 case KeyEvent.KEYCODE_ENTER: 589 if (!mTtsInited) { 590 Log.e(TAG, "Tts not inited "); 591 return false; 592 } 593 mOriginalVoiceVolume = mAudioManager.getStreamVolume( 594 AudioManager.STREAM_BLUETOOTH_SCO); 595 Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume); 596 mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 597 mOriginalVoiceVolume/2, 0); 598 599 // we now have SCO connection and TTS, so we can start. 600 mHandler.post(new Runnable() { 601 @Override 602 public void run() { 603 // Debug.startMethodTracing("tts"); 604 605 if (mTtsToFile) { 606 if (mSampleFile != null && mSampleFile.exists()) { 607 mSampleFile.delete(); 608 mSampleFile = null; 609 } 610 mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav"); 611 mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath()); 612 } else { 613 mTts.speak(mSpeakText.getText().toString(), 614 TextToSpeech.QUEUE_FLUSH, 615 mTtsParams); 616 } 617 } 618 }); 619 return true; 620 } 621 } 622 return false; 623 } 624 }; 625 626 private static final String[] mModeStrings = { 627 "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION" 628 }; 629 630 private Spinner.OnItemSelectedListener mModeChanged 631 = new Spinner.OnItemSelectedListener() { 632 @Override 633 public void onItemSelected(android.widget.AdapterView av, View v, 634 int position, long id) { 635 if (mCurrentMode != position) { 636 mCurrentMode = position; 637 mAudioManager.setMode(mCurrentMode); 638 } 639 } 640 641 @Override 642 public void onNothingSelected(android.widget.AdapterView av) { 643 } 644 }; 645 646 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 647 new BluetoothProfile.ServiceListener() { 648 @Override 649 public void onServiceConnected(int profile, BluetoothProfile proxy) { 650 mBluetoothHeadset = (BluetoothHeadset) proxy; 651 List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); 652 if (deviceList.size() > 0) { 653 mBluetoothHeadsetDevice = deviceList.get(0); 654 } else { 655 mBluetoothHeadsetDevice = null; 656 } 657 } 658 @Override 659 public void onServiceDisconnected(int profile) { 660 if (mBluetoothHeadset != null) { 661 List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices(); 662 if (devices.size() == 0) { 663 mBluetoothHeadsetDevice = null; 664 } 665 mBluetoothHeadset = null; 666 } 667 } 668 }; 669 670 private int mChangedState = -1; 671 private int mUpdatedState = -1; 672 private int mUpdatedPrevState = -1; 673 674 private class ScoBroadcastReceiver extends BroadcastReceiver { 675 @Override onReceive(Context context, Intent intent)676 public void onReceive(Context context, Intent intent) { 677 String action = intent.getAction(); 678 679 if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 680 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 681 mVdStateTxt.setText(Integer.toString(state)); 682 Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state); 683 } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) { 684 mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); 685 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState); 686 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ 687 " updated: "+Integer.toString(mUpdatedState)+ 688 " prev updated: "+Integer.toString(mUpdatedPrevState)); 689 } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { 690 mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); 691 mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1); 692 Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState); 693 mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ 694 " updated: "+Integer.toString(mUpdatedState)+ 695 " prev updated: "+Integer.toString(mUpdatedPrevState)); 696 if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { 697 mForceScoOn = false; 698 mScoButton.setChecked(mForceScoOn); 699 mAudioManager.stopBluetoothSco(); 700 } 701 } 702 } 703 } 704 705 } 706