AudioTestFragment.java revision a6521cd799e509b03ecbeea3b05f1dd5c0379387
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.CarNotConnectedException; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.ServiceConnection; 26import android.media.AudioAttributes; 27import android.media.AudioManager; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.Looper; 32import android.support.v4.app.Fragment; 33import android.util.Log; 34import android.view.LayoutInflater; 35import android.view.View; 36import android.view.View.OnClickListener; 37import android.view.ViewGroup; 38import android.widget.Button; 39import android.widget.CompoundButton; 40import android.widget.CompoundButton.OnCheckedChangeListener; 41import android.widget.RadioGroup; 42import android.widget.TextView; 43import android.widget.ToggleButton; 44 45import com.google.android.car.kitchensink.CarEmulator; 46import com.google.android.car.kitchensink.R; 47import com.google.android.car.kitchensink.audio.AudioPlayer.PlayStateListener; 48 49public class AudioTestFragment extends Fragment { 50 private static final String TAG = "AudioTest"; 51 private static final boolean DBG = true; 52 53 private AudioManager mAudioManager; 54 private FocusHandler mAudioFocusHandler; 55 private Button mNavPlayOnce; 56 private Button mVrPlayOnce; 57 private Button mSystemPlayOnce; 58 private Button mMediaPlay; 59 private Button mMediaPlayOnce; 60 private Button mMediaStop; 61 private Button mNavFocusStart; 62 private Button mNavFocusEnd; 63 private Button mVrFocusStart; 64 private Button mVrFocusEnd; 65 private Button mSpeakerPhoneOn; 66 private Button mSpeakerPhoneOff; 67 private Button mMicrophoneOn; 68 private Button mMicrophoneOff; 69 private ToggleButton mEnableMocking; 70 private ToggleButton mRejectFocus; 71 72 private final AudioPlayer mMusicPlayer; 73 private final AudioPlayer mMusicPlayerShort; 74 private final AudioPlayer mNavGuidancePlayer; 75 private final AudioPlayer mVrPlayer; 76 private final AudioPlayer mSystemPlayer; 77 private final AudioPlayer[] mAllPlayers; 78 79 private final Handler mHandler; 80 private final Context mContext; 81 82 private final Car mCar; 83 private CarAppContextManager mAppContextManager; 84 private CarEmulator mCarEmulator; 85 86 public AudioTestFragment(Context context) { 87 mContext = context; 88 mMusicPlayer = new AudioPlayer(mContext, R.raw.john_harrison_with_the_wichita_state_university_chamber_players_05_summer_mvt_2_adagio, 89 (new AudioAttributes.Builder()). 90 setUsage(AudioAttributes.USAGE_MEDIA). 91 setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()); 92 mMusicPlayerShort = new AudioPlayer(mContext, R.raw.ring_classic_01, 93 (new AudioAttributes.Builder()). 94 setUsage(AudioAttributes.USAGE_MEDIA). 95 setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()); 96 mNavGuidancePlayer = new AudioPlayer(mContext, R.raw.turnright, 97 (new AudioAttributes.Builder()). 98 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 99 setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build()); 100 // no Usage for voice command yet. 101 mVrPlayer = new AudioPlayer(mContext, R.raw.one2six, 102 (new AudioAttributes.Builder()). 103 setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION). 104 setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build()); 105 mSystemPlayer = new AudioPlayer(mContext, R.raw.ring_classic_01, 106 (new AudioAttributes.Builder()). 107 setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION). 108 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build()); 109 mAllPlayers = new AudioPlayer[] { 110 mMusicPlayer, 111 mMusicPlayerShort, 112 mNavGuidancePlayer, 113 mVrPlayer, 114 mSystemPlayer 115 }; 116 mHandler = new Handler(Looper.getMainLooper()); 117 mCar = Car.createCar(mContext, new ServiceConnection() { 118 @Override 119 public void onServiceConnected(ComponentName name, IBinder service) { 120 mAppContextManager = 121 (CarAppContextManager) mCar.getCarManager(Car.APP_CONTEXT_SERVICE); 122 mAppContextManager.registerContextListener(new AppContextChangeListener() { 123 124 @Override 125 public void onAppContextOwnershipLoss(int context) { 126 } 127 128 @Override 129 public void onAppContextChange(int activeContexts) { 130 } 131 }, CarAppContextManager.APP_CONTEXT_NAVIGATION | 132 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 133 } 134 @Override 135 public void onServiceDisconnected(ComponentName name) { 136 } 137 }, Looper.getMainLooper()); 138 mCar.connect(); 139 } 140 141 @Override 142 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { 143 Log.i(TAG, "onCreateView"); 144 View view = inflater.inflate(R.layout.audio, container, false); 145 mAudioManager = (AudioManager) mContext.getSystemService( 146 Context.AUDIO_SERVICE); 147 mAudioFocusHandler = new FocusHandler( 148 (RadioGroup) view.findViewById(R.id.button_focus_request_selection), 149 (Button) view.findViewById(R.id.button_audio_focus_request), 150 (TextView) view.findViewById(R.id.text_audio_focus_state)); 151 mMediaPlay = (Button) view.findViewById(R.id.button_media_play_start); 152 mMediaPlay.setOnClickListener(new OnClickListener() { 153 @Override 154 public void onClick(View v) { 155 mMusicPlayer.start(false, true); 156 } 157 }); 158 mMediaPlayOnce = (Button) view.findViewById(R.id.button_media_play_once); 159 mMediaPlayOnce.setOnClickListener(new OnClickListener() { 160 @Override 161 public void onClick(View v) { 162 mMusicPlayerShort.start(true, false); 163 // play only for 1 sec and stop 164 mHandler.postDelayed(new Runnable() { 165 @Override 166 public void run() { 167 mMusicPlayerShort.stop(); 168 } 169 }, 1000); 170 } 171 }); 172 mMediaStop = (Button) view.findViewById(R.id.button_media_play_stop); 173 mMediaStop.setOnClickListener(new OnClickListener() { 174 @Override 175 public void onClick(View v) { 176 mMusicPlayer.stop(); 177 } 178 }); 179 mNavPlayOnce = (Button) view.findViewById(R.id.button_nav_play_once); 180 mNavPlayOnce.setOnClickListener(new OnClickListener() { 181 @Override 182 public void onClick(View v) { 183 if (mAppContextManager == null) { 184 return; 185 } 186 if (DBG) { 187 Log.i(TAG, "Nav start"); 188 } 189 if (!mNavGuidancePlayer.isPlaying()) { 190 mAppContextManager.setActiveContexts( 191 CarAppContextManager.APP_CONTEXT_NAVIGATION); 192 mNavGuidancePlayer.start(true, false, new PlayStateListener() { 193 @Override 194 public void onCompletion() { 195 mAppContextManager.resetActiveContexts( 196 CarAppContextManager.APP_CONTEXT_NAVIGATION); 197 } 198 }); 199 } 200 } 201 }); 202 mVrPlayOnce = (Button) view.findViewById(R.id.button_vr_play_once); 203 mVrPlayOnce.setOnClickListener(new OnClickListener() { 204 @Override 205 public void onClick(View v) { 206 if (mAppContextManager == null) { 207 return; 208 } 209 if (DBG) { 210 Log.i(TAG, "VR start"); 211 } 212 mAppContextManager.setActiveContexts( 213 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 214 if (!mVrPlayer.isPlaying()) { 215 mVrPlayer.start(true, false, new PlayStateListener() { 216 @Override 217 public void onCompletion() { 218 mAppContextManager.resetActiveContexts( 219 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 220 } 221 }); 222 } 223 } 224 }); 225 mSystemPlayOnce = (Button) view.findViewById(R.id.button_system_play_once); 226 mSystemPlayOnce.setOnClickListener(new OnClickListener() { 227 @Override 228 public void onClick(View v) { 229 if (DBG) { 230 Log.i(TAG, "System start"); 231 } 232 if (!mSystemPlayer.isPlaying()) { 233 // system sound played without focus 234 mSystemPlayer.start(false, false); 235 } 236 } 237 }); 238 mNavFocusStart = (Button) view.findViewById(R.id.button_nav_start); 239 mNavFocusStart.setOnClickListener(new OnClickListener() { 240 @Override 241 public void onClick(View v) { 242 if (mAppContextManager == null) { 243 return; 244 } 245 if (DBG) { 246 Log.i(TAG, "Nav focus request"); 247 } 248 mAppContextManager.setActiveContexts( 249 CarAppContextManager.APP_CONTEXT_NAVIGATION); 250 } 251 }); 252 mNavFocusEnd = (Button) view.findViewById(R.id.button_nav_end); 253 mNavFocusEnd.setOnClickListener(new OnClickListener() { 254 @Override 255 public void onClick(View v) { 256 if (mAppContextManager == null) { 257 return; 258 } 259 if (DBG) { 260 Log.i(TAG, "Nav focus release"); 261 } 262 mAppContextManager.resetActiveContexts( 263 CarAppContextManager.APP_CONTEXT_NAVIGATION); 264 } 265 }); 266 mVrFocusStart = (Button) view.findViewById(R.id.button_vr_start); 267 mVrFocusStart.setOnClickListener(new OnClickListener() { 268 @Override 269 public void onClick(View v) { 270 if (mAppContextManager == null) { 271 return; 272 } 273 if (DBG) { 274 Log.i(TAG, "VR request"); 275 } 276 mAppContextManager.setActiveContexts( 277 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 278 } 279 }); 280 mVrFocusEnd = (Button) view.findViewById(R.id.button_vr_end); 281 mVrFocusEnd.setOnClickListener(new OnClickListener() { 282 @Override 283 public void onClick(View v) { 284 if (mAppContextManager == null) { 285 return; 286 } 287 if (DBG) { 288 Log.i(TAG, "VR request"); 289 } 290 mAppContextManager.resetActiveContexts( 291 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 292 } 293 }); 294 mSpeakerPhoneOn = (Button) view.findViewById(R.id.button_speaker_phone_on); 295 mSpeakerPhoneOn.setOnClickListener(new OnClickListener() { 296 @Override 297 public void onClick(View v) { 298 mAudioManager.setSpeakerphoneOn(true); 299 } 300 }); 301 mSpeakerPhoneOff = (Button) view.findViewById(R.id.button_speaker_phone_off); 302 mSpeakerPhoneOff.setOnClickListener(new OnClickListener() { 303 @Override 304 public void onClick(View v) { 305 mAudioManager.setSpeakerphoneOn(false); 306 } 307 }); 308 mMicrophoneOn = (Button) view.findViewById(R.id.button_microphone_on); 309 mMicrophoneOn.setOnClickListener(new OnClickListener() { 310 @Override 311 public void onClick(View v) { 312 mAudioManager.setMicrophoneMute(false); // Turn the microphone on. 313 } 314 }); 315 mMicrophoneOff = (Button) view.findViewById(R.id.button_microphone_off); 316 mMicrophoneOff.setOnClickListener(new OnClickListener() { 317 @Override 318 public void onClick(View v) { 319 mAudioManager.setMicrophoneMute(true); // Mute the microphone. 320 } 321 }); 322 323 324 mRejectFocus = (ToggleButton) view.findViewById(R.id.button_reject_audio_focus); 325 mRejectFocus.setOnCheckedChangeListener(new OnCheckedChangeListener() { 326 @Override 327 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 328 if (mCarEmulator == null) { 329 return; 330 } 331 if (!mEnableMocking.isChecked()) { 332 return; 333 } 334 if (isChecked) { 335 mCarEmulator.setAudioFocusControl(true); 336 } else { 337 mCarEmulator.setAudioFocusControl(false); 338 } 339 } 340 }); 341 mRejectFocus.setActivated(false); 342 mEnableMocking = (ToggleButton) view.findViewById(R.id.button_mock_audio); 343 mEnableMocking.setOnCheckedChangeListener(new OnCheckedChangeListener() { 344 @Override 345 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 346 if (mCarEmulator == null) { 347 mCarEmulator = new CarEmulator(mCar); 348 } 349 if (isChecked) { 350 mRejectFocus.setActivated(true); 351 mCarEmulator.start(); 352 } else { 353 mRejectFocus.setActivated(false); 354 mCarEmulator.stop(); 355 mCarEmulator = null; 356 } 357 } 358 }); 359 return view; 360 } 361 362 @Override 363 public void onDestroyView() { 364 Log.i(TAG, "onDestroyView"); 365 super.onDestroyView(); 366 if (mCarEmulator != null) { 367 mCarEmulator.setAudioFocusControl(false); 368 mCarEmulator.stop(); 369 } 370 for (AudioPlayer p : mAllPlayers) { 371 p.stop(); 372 } 373 if (mAudioFocusHandler != null) { 374 mAudioFocusHandler.release(); 375 mAudioFocusHandler = null; 376 } 377 if (mAppContextManager != null) { 378 mAppContextManager.resetActiveContexts(CarAppContextManager.APP_CONTEXT_NAVIGATION | 379 CarAppContextManager.APP_CONTEXT_VOICE_COMMAND); 380 } 381 } 382 383 private class FocusHandler { 384 private static final String AUDIO_FOCUS_STATE_GAIN = "gain"; 385 private static final String AUDIO_FOCUS_STATE_RELEASED_UNKNOWN = "released / unknown"; 386 387 private final RadioGroup mRequestSelection; 388 private final TextView mText; 389 private final AudioFocusListener mFocusListener; 390 391 public FocusHandler(RadioGroup radioGroup, Button requestButton, TextView text) { 392 mText = text; 393 mRequestSelection = radioGroup; 394 mRequestSelection.check(R.id.focus_gain); 395 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 396 mFocusListener = new AudioFocusListener(); 397 requestButton.setOnClickListener(new OnClickListener() { 398 @Override 399 public void onClick(View v) { 400 int selectedButtonId = mRequestSelection.getCheckedRadioButtonId(); 401 int focusRequest = AudioManager.AUDIOFOCUS_GAIN; 402 if (selectedButtonId == R.id.focus_gain_transient_duck) { 403 focusRequest = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 404 } else if (selectedButtonId == R.id.focus_release) { 405 mAudioManager.abandonAudioFocus(mFocusListener); 406 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 407 return; 408 } 409 int ret = mAudioManager.requestAudioFocus(mFocusListener, 410 AudioManager.STREAM_MUSIC, focusRequest); 411 Log.i(TAG, "requestAudioFocus returned " + ret); 412 if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 413 setFocusText(AUDIO_FOCUS_STATE_GAIN); 414 } 415 } 416 }); 417 } 418 419 public void release() { 420 abandonAudioFocus(); 421 } 422 423 private void abandonAudioFocus() { 424 if (DBG) { 425 Log.i(TAG, "abandonAudioFocus"); 426 } 427 mAudioManager.abandonAudioFocus(mFocusListener); 428 setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN); 429 } 430 431 private void setFocusText(String msg) { 432 mText.setText("focus state:" + msg); 433 } 434 435 private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { 436 @Override 437 public void onAudioFocusChange(int focusChange) { 438 Log.i(TAG, "onAudioFocusChange " + focusChange); 439 if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 440 setFocusText(AUDIO_FOCUS_STATE_GAIN); 441 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 442 setFocusText("loss"); 443 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 444 setFocusText("loss,transient"); 445 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { 446 setFocusText("loss,transient,duck"); 447 } 448 } 449 } 450 } 451} 452