AudioTestFragment.java revision d4f4d754a116ef0d88f5aba5558429d9264c0fc8
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.android.car.kitchensink.audio; 18 19import android.car.Car; 20import android.car.CarAppContextManager; 21import android.car.CarAppContextManager.AppContextChangeListener; 22import android.car.CarAppContextManager.AppContextOwnershipChangeListener; 23import android.car.CarNotConnectedException; 24import android.car.media.CarAudioManager; 25import android.content.ComponentName; 26import android.content.Context; 27import android.content.ServiceConnection; 28import android.media.AudioAttributes; 29import android.media.AudioManager; 30import android.os.Bundle; 31import android.os.Handler; 32import android.os.IBinder; 33import android.os.Looper; 34import android.support.v4.app.Fragment; 35import android.util.Log; 36import android.view.LayoutInflater; 37import android.view.View; 38import android.view.View.OnClickListener; 39import android.view.ViewGroup; 40import android.widget.Button; 41import android.widget.CompoundButton; 42import android.widget.CompoundButton.OnCheckedChangeListener; 43import android.widget.RadioGroup; 44import android.widget.TextView; 45import android.widget.ToggleButton; 46 47import com.google.android.car.kitchensink.CarEmulator; 48import com.google.android.car.kitchensink.R; 49import com.google.android.car.kitchensink.audio.AudioPlayer.PlayStateListener; 50 51public class AudioTestFragment extends Fragment { 52 private static final String TAG = "CAR.AUDIO.KS"; 53 private static final boolean DBG = true; 54 55 private AudioManager mAudioManager; 56 private FocusHandler mAudioFocusHandler; 57 private Button mNavPlayOnce; 58 private Button mVrPlayOnce; 59 private Button mSystemPlayOnce; 60 private Button mMediaPlay; 61 private Button mMediaPlayOnce; 62 private Button mMediaStop; 63 private Button mNavStart; 64 private Button mNavEnd; 65 private Button mVrStart; 66 private Button mVrEnd; 67 private Button mRadioStart; 68 private Button mRadioEnd; 69 private Button mSpeakerPhoneOn; 70 private Button mSpeakerPhoneOff; 71 private Button mMicrophoneOn; 72 private Button mMicrophoneOff; 73 private ToggleButton mEnableMocking; 74 private ToggleButton mRejectFocus; 75 76 private AudioPlayer mMusicPlayer; 77 private AudioPlayer mMusicPlayerShort; 78 private AudioPlayer mNavGuidancePlayer; 79 private AudioPlayer mVrPlayer; 80 private AudioPlayer mSystemPlayer; 81 private AudioPlayer[] mAllPlayers; 82 83 private Handler mHandler; 84 private Context mContext; 85 86 private Car mCar; 87 private CarAppContextManager mAppContextManager; 88 private CarAudioManager mCarAudioManager; 89 private AudioAttributes mMusicAudioAttrib; 90 private AudioAttributes mNavAudioAttrib; 91 private AudioAttributes mVrAudioAttrib; 92 private AudioAttributes mRadioAudioAttrib; 93 private AudioAttributes mSystemSoundAudioAttrib; 94 private CarEmulator mCarEmulator; 95 96 private final AudioManager.OnAudioFocusChangeListener mNavFocusListener = 97 new AudioManager.OnAudioFocusChangeListener() { 98 @Override 99 public void onAudioFocusChange(int focusChange) { 100 Log.i(TAG, "Nav focus change:" + focusChange); 101 } 102 }; 103 private final AudioManager.OnAudioFocusChangeListener mVrFocusListener = 104 new AudioManager.OnAudioFocusChangeListener() { 105 @Override 106 public void onAudioFocusChange(int focusChange) { 107 Log.i(TAG, "VR focus change:" + focusChange); 108 } 109 }; 110 private final AudioManager.OnAudioFocusChangeListener mRadioFocusListener = 111 new AudioManager.OnAudioFocusChangeListener() { 112 @Override 113 public void onAudioFocusChange(int focusChange) { 114 Log.i(TAG, "Radio focus change:" + focusChange); 115 } 116 }; 117 118 private final AppContextOwnershipChangeListener mOwnershipListener = 119 new AppContextOwnershipChangeListener() { 120 @Override 121 public void onAppContextOwnershipLoss(int context) { 122 } 123 }; 124 125 private void init() { 126 mContext = getContext(); 127 mHandler = new Handler(Looper.getMainLooper()); 128 mCar = Car.createCar(mContext, new ServiceConnection() { 129 @Override 130 public void onServiceConnected(ComponentName name, IBinder service) { 131 mAppContextManager = 132 (CarAppContextManager) mCar.getCarManager(Car.APP_CONTEXT_SERVICE); 133 mAppContextManager.registerContextListener(new AppContextChangeListener() { 134 @Override 135 public void onAppContextChange(int activeContexts) { 136 } 137 }, CarAppContextManager.APP_CONTEXT_NAVIGATION | 138 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 139 mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE); 140 mMusicAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage( 141 CarAudioManager.CAR_AUDIO_USAGE_MUSIC); 142 mNavAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage( 143 CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE); 144 mVrAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage( 145 CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND); 146 mRadioAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage( 147 CarAudioManager.CAR_AUDIO_USAGE_RADIO); 148 mSystemSoundAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage( 149 CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND); 150 mMusicPlayer = new AudioPlayer(mContext, R.raw.john_harrison_with_the_wichita_state_university_chamber_players_05_summer_mvt_2_adagio, 151 mMusicAudioAttrib); 152 mMusicPlayerShort = new AudioPlayer(mContext, R.raw.ring_classic_01, 153 mMusicAudioAttrib); 154 mNavGuidancePlayer = new AudioPlayer(mContext, R.raw.turnright, 155 mNavAudioAttrib); 156 // no Usage for voice command yet. 157 mVrPlayer = new AudioPlayer(mContext, R.raw.one2six, 158 mVrAudioAttrib); 159 mSystemPlayer = new AudioPlayer(mContext, R.raw.ring_classic_01, 160 mSystemSoundAudioAttrib); 161 mAllPlayers = new AudioPlayer[] { 162 mMusicPlayer, 163 mMusicPlayerShort, 164 mNavGuidancePlayer, 165 mVrPlayer, 166 mSystemPlayer 167 }; 168 } 169 @Override 170 public void onServiceDisconnected(ComponentName name) { 171 } 172 }, Looper.getMainLooper()); 173 mCar.connect(); 174 } 175 176 @Override 177 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { 178 Log.i(TAG, "onCreateView"); 179 init(); 180 View view = inflater.inflate(R.layout.audio, container, false); 181 mAudioManager = (AudioManager) mContext.getSystemService( 182 Context.AUDIO_SERVICE); 183 mAudioFocusHandler = new FocusHandler( 184 (RadioGroup) view.findViewById(R.id.button_focus_request_selection), 185 (Button) view.findViewById(R.id.button_audio_focus_request), 186 (TextView) view.findViewById(R.id.text_audio_focus_state)); 187 mMediaPlay = (Button) view.findViewById(R.id.button_media_play_start); 188 mMediaPlay.setOnClickListener(new OnClickListener() { 189 @Override 190 public void onClick(View v) { 191 mMusicPlayer.start(false, true, AudioManager.AUDIOFOCUS_GAIN); 192 } 193 }); 194 mMediaPlayOnce = (Button) view.findViewById(R.id.button_media_play_once); 195 mMediaPlayOnce.setOnClickListener(new OnClickListener() { 196 @Override 197 public void onClick(View v) { 198 mMusicPlayerShort.start(true, false, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 199 // play only for 1 sec and stop 200 mHandler.postDelayed(new Runnable() { 201 @Override 202 public void run() { 203 mMusicPlayerShort.stop(); 204 } 205 }, 1000); 206 } 207 }); 208 mMediaStop = (Button) view.findViewById(R.id.button_media_play_stop); 209 mMediaStop.setOnClickListener(new OnClickListener() { 210 @Override 211 public void onClick(View v) { 212 mMusicPlayer.stop(); 213 } 214 }); 215 mNavPlayOnce = (Button) view.findViewById(R.id.button_nav_play_once); 216 mNavPlayOnce.setOnClickListener(new OnClickListener() { 217 @Override 218 public void onClick(View v) { 219 if (mAppContextManager == null) { 220 return; 221 } 222 if (DBG) { 223 Log.i(TAG, "Nav start"); 224 } 225 if (!mNavGuidancePlayer.isPlaying()) { 226 mAppContextManager.setActiveContexts(mOwnershipListener, 227 CarAppContextManager.APP_CONTEXT_NAVIGATION); 228 mNavGuidancePlayer.start(true, false, 229 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 230 new PlayStateListener() { 231 @Override 232 public void onCompletion() { 233 mAppContextManager.resetActiveContexts( 234 CarAppContextManager.APP_CONTEXT_NAVIGATION); 235 } 236 }); 237 } 238 } 239 }); 240 mVrPlayOnce = (Button) view.findViewById(R.id.button_vr_play_once); 241 mVrPlayOnce.setOnClickListener(new OnClickListener() { 242 @Override 243 public void onClick(View v) { 244 if (mAppContextManager == null) { 245 return; 246 } 247 if (DBG) { 248 Log.i(TAG, "VR start"); 249 } 250 mAppContextManager.setActiveContexts(mOwnershipListener, 251 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 252 if (!mVrPlayer.isPlaying()) { 253 mVrPlayer.start(true, false, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 254 new PlayStateListener() { 255 @Override 256 public void onCompletion() { 257 mAppContextManager.resetActiveContexts( 258 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 259 } 260 }); 261 } 262 } 263 }); 264 mSystemPlayOnce = (Button) view.findViewById(R.id.button_system_play_once); 265 mSystemPlayOnce.setOnClickListener(new OnClickListener() { 266 @Override 267 public void onClick(View v) { 268 if (DBG) { 269 Log.i(TAG, "System start"); 270 } 271 if (!mSystemPlayer.isPlaying()) { 272 // system sound played without focus 273 mSystemPlayer.start(false, false, 0); 274 } 275 } 276 }); 277 mNavStart = (Button) view.findViewById(R.id.button_nav_start); 278 mNavStart.setOnClickListener(new OnClickListener() { 279 @Override 280 public void onClick(View v) { 281 handleNavStart(); 282 } 283 }); 284 mNavEnd = (Button) view.findViewById(R.id.button_nav_end); 285 mNavEnd.setOnClickListener(new OnClickListener() { 286 @Override 287 public void onClick(View v) { 288 handleNavEnd(); 289 } 290 }); 291 mVrStart = (Button) view.findViewById(R.id.button_vr_start); 292 mVrStart.setOnClickListener(new OnClickListener() { 293 @Override 294 public void onClick(View v) { 295 handleVrStart(); 296 } 297 }); 298 mVrEnd = (Button) view.findViewById(R.id.button_vr_end); 299 mVrEnd.setOnClickListener(new OnClickListener() { 300 @Override 301 public void onClick(View v) { 302 handleVrEnd(); 303 } 304 }); 305 mRadioStart = (Button) view.findViewById(R.id.button_radio_start); 306 mRadioStart.setOnClickListener(new OnClickListener() { 307 @Override 308 public void onClick(View v) { 309 handleRadioStart(); 310 } 311 }); 312 mRadioEnd = (Button) view.findViewById(R.id.button_radio_end); 313 mRadioEnd.setOnClickListener(new OnClickListener() { 314 @Override 315 public void onClick(View v) { 316 handleRadioEnd(); 317 } 318 }); 319 mSpeakerPhoneOn = (Button) view.findViewById(R.id.button_speaker_phone_on); 320 mSpeakerPhoneOn.setOnClickListener(new OnClickListener() { 321 @Override 322 public void onClick(View v) { 323 mAudioManager.setSpeakerphoneOn(true); 324 } 325 }); 326 mSpeakerPhoneOff = (Button) view.findViewById(R.id.button_speaker_phone_off); 327 mSpeakerPhoneOff.setOnClickListener(new OnClickListener() { 328 @Override 329 public void onClick(View v) { 330 mAudioManager.setSpeakerphoneOn(false); 331 } 332 }); 333 mMicrophoneOn = (Button) view.findViewById(R.id.button_microphone_on); 334 mMicrophoneOn.setOnClickListener(new OnClickListener() { 335 @Override 336 public void onClick(View v) { 337 mAudioManager.setMicrophoneMute(false); // Turn the microphone on. 338 } 339 }); 340 mMicrophoneOff = (Button) view.findViewById(R.id.button_microphone_off); 341 mMicrophoneOff.setOnClickListener(new OnClickListener() { 342 @Override 343 public void onClick(View v) { 344 mAudioManager.setMicrophoneMute(true); // Mute the microphone. 345 } 346 }); 347 348 349 mRejectFocus = (ToggleButton) view.findViewById(R.id.button_reject_audio_focus); 350 mRejectFocus.setOnCheckedChangeListener(new OnCheckedChangeListener() { 351 @Override 352 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 353 if (mCarEmulator == null) { 354 return; 355 } 356 if (!mEnableMocking.isChecked()) { 357 return; 358 } 359 if (isChecked) { 360 mCarEmulator.setAudioFocusControl(true); 361 } else { 362 mCarEmulator.setAudioFocusControl(false); 363 } 364 } 365 }); 366 mRejectFocus.setActivated(false); 367 mEnableMocking = (ToggleButton) view.findViewById(R.id.button_mock_audio); 368 mEnableMocking.setOnCheckedChangeListener(new OnCheckedChangeListener() { 369 @Override 370 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 371 if (mCarEmulator == null) { 372 mCarEmulator = new CarEmulator(mCar); 373 } 374 if (isChecked) { 375 mRejectFocus.setActivated(true); 376 mCarEmulator.start(); 377 } else { 378 mRejectFocus.setActivated(false); 379 mCarEmulator.stop(); 380 mCarEmulator = null; 381 } 382 } 383 }); 384 return view; 385 } 386 387 @Override 388 public void onDestroyView() { 389 super.onDestroyView(); 390 Log.i(TAG, "onDestroyView"); 391 if (mCarEmulator != null) { 392 mCarEmulator.setAudioFocusControl(false); 393 mCarEmulator.stop(); 394 } 395 for (AudioPlayer p : mAllPlayers) { 396 p.stop(); 397 } 398 if (mAudioFocusHandler != null) { 399 mAudioFocusHandler.release(); 400 mAudioFocusHandler = null; 401 } 402 if (mAppContextManager != null) { 403 mAppContextManager.resetActiveContexts(CarAppContextManager.APP_CONTEXT_NAVIGATION | 404 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 405 } 406 } 407 408 private void handleNavStart() { 409 if (mAppContextManager == null) { 410 return; 411 } 412 if (mCarAudioManager == null) { 413 return; 414 } 415 if (DBG) { 416 Log.i(TAG, "Nav start"); 417 } 418 mAppContextManager.setActiveContexts(mOwnershipListener, 419 CarAppContextManager.APP_CONTEXT_NAVIGATION); 420 mCarAudioManager.requestAudioFocus(mNavFocusListener, mNavAudioAttrib, 421 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 422 } 423 424 private void handleNavEnd() { 425 if (mAppContextManager == null) { 426 return; 427 } 428 if (mCarAudioManager == null) { 429 return; 430 } 431 if (DBG) { 432 Log.i(TAG, "Nav end"); 433 } 434 mAppContextManager.resetActiveContexts( 435 CarAppContextManager.APP_CONTEXT_NAVIGATION); 436 mCarAudioManager.abandonAudioFocus(mNavFocusListener, mNavAudioAttrib); 437 } 438 439 private void handleVrStart() { 440 if (mAppContextManager == null) { 441 return; 442 } 443 if (mCarAudioManager == null) { 444 return; 445 } 446 if (DBG) { 447 Log.i(TAG, "VR start"); 448 } 449 mAppContextManager.setActiveContexts(mOwnershipListener, 450 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 451 mCarAudioManager.requestAudioFocus(mVrFocusListener, mVrAudioAttrib, 452 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 0); 453 } 454 455 private void handleVrEnd() { 456 if (mAppContextManager == null) { 457 return; 458 } 459 if (mCarAudioManager == null) { 460 return; 461 } 462 if (DBG) { 463 Log.i(TAG, "VR end"); 464 } 465 mAppContextManager.resetActiveContexts( 466 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 467 mCarAudioManager.abandonAudioFocus(mVrFocusListener, mVrAudioAttrib); 468 } 469 470 private void handleRadioStart() { 471 if (mCarAudioManager == null) { 472 return; 473 } 474 if (DBG) { 475 Log.i(TAG, "Radio start"); 476 } 477 mCarAudioManager.requestAudioFocus(mRadioFocusListener, mRadioAudioAttrib, 478 AudioManager.AUDIOFOCUS_GAIN, 0); 479 } 480 481 private void handleRadioEnd() { 482 if (mCarAudioManager == null) { 483 return; 484 } 485 if (DBG) { 486 Log.i(TAG, "Radio end"); 487 } 488 mCarAudioManager.abandonAudioFocus(mRadioFocusListener, mRadioAudioAttrib); 489 } 490 491 private class FocusHandler { 492 private static final String AUDIO_FOCUS_STATE_GAIN = "gain"; 493 private static final String AUDIO_FOCUS_STATE_RELEASED_UNKNOWN = "released / unknown"; 494 495 private final RadioGroup mRequestSelection; 496 private final TextView mText; 497 private final AudioFocusListener mFocusListener; 498 499 public FocusHandler(RadioGroup radioGroup, Button requestButton, TextView text) { 500 mText = text; 501 mRequestSelection = radioGroup; 502 mRequestSelection.check(R.id.focus_gain); 503 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 504 mFocusListener = new AudioFocusListener(); 505 requestButton.setOnClickListener(new OnClickListener() { 506 @Override 507 public void onClick(View v) { 508 int selectedButtonId = mRequestSelection.getCheckedRadioButtonId(); 509 int focusRequest = AudioManager.AUDIOFOCUS_GAIN; 510 if (selectedButtonId == R.id.focus_gain_transient_duck) { 511 focusRequest = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 512 } else if (selectedButtonId == R.id.focus_release) { 513 mAudioManager.abandonAudioFocus(mFocusListener); 514 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 515 return; 516 } 517 int ret = mAudioManager.requestAudioFocus(mFocusListener, 518 AudioManager.STREAM_MUSIC, focusRequest); 519 Log.i(TAG, "requestAudioFocus returned " + ret); 520 if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 521 setFocusText(AUDIO_FOCUS_STATE_GAIN); 522 } 523 } 524 }); 525 } 526 527 public void release() { 528 abandonAudioFocus(); 529 } 530 531 private void abandonAudioFocus() { 532 if (DBG) { 533 Log.i(TAG, "abandonAudioFocus"); 534 } 535 mAudioManager.abandonAudioFocus(mFocusListener); 536 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 537 } 538 539 private void setFocusText(String msg) { 540 mText.setText("focus state:" + msg); 541 } 542 543 private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { 544 @Override 545 public void onAudioFocusChange(int focusChange) { 546 Log.i(TAG, "onAudioFocusChange " + focusChange); 547 if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 548 setFocusText(AUDIO_FOCUS_STATE_GAIN); 549 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 550 setFocusText("loss"); 551 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 552 setFocusText("loss,transient"); 553 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { 554 setFocusText("loss,transient,duck"); 555 } 556 } 557 } 558 } 559} 560