1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chromecast.shell; 6 7 import android.media.AudioAttributes; 8 import android.media.AudioFocusRequest; 9 import android.media.AudioManager; 10 import android.os.Build; 11 12 import androidx.annotation.NonNull; 13 14 import org.chromium.base.Log; 15 16 import java.util.HashSet; 17 import java.util.Set; 18 19 /** 20 * Wrapper for Cast code to pass parameter to AudioFocus methods. 21 * This maintains backwards compatibility with old APIs - requestAudioFocus() and 22 * abandonAudioFocus() 23 */ 24 public class CastAudioFocusRequest { 25 private static final String TAG = "CastAudioFocus"; 26 private AudioFocusRequest mAudioFocusRequest; 27 private AudioAttributes mAudioAttributes; 28 private int mFocusGain; 29 private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener; 30 CastAudioFocusRequest(AudioFocusRequest audioFocusRequest)31 CastAudioFocusRequest(AudioFocusRequest audioFocusRequest) { 32 mAudioFocusRequest = audioFocusRequest; 33 } 34 CastAudioFocusRequest(AudioAttributes audioAttributes, int focusGain, AudioManager.OnAudioFocusChangeListener l)35 CastAudioFocusRequest(AudioAttributes audioAttributes, int focusGain, 36 AudioManager.OnAudioFocusChangeListener l) { 37 mAudioAttributes = audioAttributes; 38 mFocusGain = focusGain; 39 mAudioFocusChangeListener = l; 40 } 41 getAudioFocusRequest()42 AudioFocusRequest getAudioFocusRequest() { 43 return mAudioFocusRequest; 44 } 45 getStreamType()46 private int getStreamType() { 47 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 48 if (mAudioAttributes != null) { 49 switch (mAudioAttributes.getContentType()) { 50 case AudioAttributes.CONTENT_TYPE_MOVIE: 51 case AudioAttributes.CONTENT_TYPE_MUSIC: 52 return AudioManager.STREAM_MUSIC; 53 case AudioAttributes.CONTENT_TYPE_SONIFICATION: 54 return AudioManager.STREAM_ALARM; 55 case AudioAttributes.CONTENT_TYPE_SPEECH: 56 return AudioManager.STREAM_VOICE_CALL; 57 case AudioAttributes.CONTENT_TYPE_UNKNOWN: 58 default: 59 return AudioManager.STREAM_SYSTEM; 60 } 61 } 62 } 63 return 0; 64 } 65 setAudioFocusChangeListener(AudioManager.OnAudioFocusChangeListener l)66 void setAudioFocusChangeListener(AudioManager.OnAudioFocusChangeListener l) { 67 mAudioFocusChangeListener = l; 68 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && mAudioFocusRequest != null) { 69 mAudioFocusRequest = new AudioFocusRequest.Builder(mAudioFocusRequest) 70 .setOnAudioFocusChangeListener(mAudioFocusChangeListener) 71 .build(); 72 } 73 } 74 request(AudioManager audioManager)75 int request(AudioManager audioManager) { 76 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 77 return audioManager.requestAudioFocus(mAudioFocusRequest); 78 } else { 79 return audioManager.requestAudioFocus( 80 mAudioFocusChangeListener, getStreamType(), mFocusGain); 81 } 82 } 83 abandon(AudioManager audioManager)84 int abandon(AudioManager audioManager) { 85 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 86 return audioManager.abandonAudioFocusRequest(mAudioFocusRequest); 87 } else { 88 return audioManager.abandonAudioFocus(mAudioFocusChangeListener); 89 } 90 } 91 92 /** 93 * Backwards compatible builder method to create CastAudioFocusRequest object. 94 */ 95 public static class Builder { 96 private AudioAttributes mAudioAttributes; 97 private int mFocusGain; 98 private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener; 99 private Set<Integer> mValidFocusGainValues; 100 Builder()101 public Builder() { 102 mAudioAttributes = null; 103 mFocusGain = 0; 104 mAudioFocusChangeListener = null; 105 mValidFocusGainValues = new HashSet<Integer>(); 106 mValidFocusGainValues.add(AudioManager.AUDIOFOCUS_GAIN); 107 mValidFocusGainValues.add(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 108 mValidFocusGainValues.add(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); 109 mValidFocusGainValues.add(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE); 110 } 111 setAudioAttributes(@onNull AudioAttributes audioAttributes)112 public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes audioAttributes) { 113 mAudioAttributes = audioAttributes; 114 return this; 115 } 116 setFocusGain(int focusGain)117 public @NonNull Builder setFocusGain(int focusGain) { 118 if (mValidFocusGainValues.contains(focusGain)) { 119 mFocusGain = focusGain; 120 } else { 121 Log.e(TAG, "Invalid focus gain value " + focusGain); 122 mFocusGain = AudioManager.AUDIOFOCUS_GAIN; 123 } 124 return this; 125 } 126 setAudioFocusChangeListener( AudioManager.OnAudioFocusChangeListener l)127 public @NonNull Builder setAudioFocusChangeListener( 128 AudioManager.OnAudioFocusChangeListener l) { 129 mAudioFocusChangeListener = l; 130 return this; 131 } 132 build()133 public CastAudioFocusRequest build() { 134 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 135 AudioFocusRequest.Builder builder = new AudioFocusRequest.Builder(mFocusGain); 136 if (mAudioAttributes != null) { 137 builder = builder.setAudioAttributes(mAudioAttributes); 138 } 139 if (mAudioFocusChangeListener != null) { 140 builder = builder.setOnAudioFocusChangeListener(mAudioFocusChangeListener); 141 } 142 AudioFocusRequest audioFocusRequest = builder.build(); 143 return new CastAudioFocusRequest(audioFocusRequest); 144 } else { 145 return new CastAudioFocusRequest( 146 mAudioAttributes, mFocusGain, mAudioFocusChangeListener); 147 } 148 } 149 } 150 } 151