summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt9
-rw-r--r--api/test-current.txt2
-rw-r--r--media/java/android/media/AudioFocusRequest.java56
-rw-r--r--media/java/android/media/AudioManager.java252
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java3
6 files changed, 206 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt
index fb1bb6e84e23..76c9e303125e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20976,8 +20976,6 @@ package android.media {
method public boolean acceptsDelayedFocusGain();
method public android.media.AudioAttributes getAudioAttributes();
method public int getFocusGain();
- method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
- method public android.os.Handler getOnAudioFocusChangeListenerHandler();
method public boolean willPauseWhenDucked();
}
diff --git a/api/system-current.txt b/api/system-current.txt
index a34c2eda8ffd..9480a63dcfa1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -22729,8 +22729,7 @@ package android.media {
method public boolean acceptsDelayedFocusGain();
method public android.media.AudioAttributes getAudioAttributes();
method public int getFocusGain();
- method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
- method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+ method public boolean locksFocus();
method public boolean willPauseWhenDucked();
}
@@ -22741,6 +22740,7 @@ package android.media {
method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+ method public android.media.AudioFocusRequest.Builder setLocksFocus(boolean);
method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
}
@@ -22821,7 +22821,7 @@ package android.media {
public class AudioManager {
method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
- method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+ method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
@@ -22863,7 +22863,8 @@ package android.media {
method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
method public int requestAudioFocus(android.media.AudioFocusRequest);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
+ method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
+ method public int requestAudioFocus(android.media.AudioFocusRequest, android.media.audiopolicy.AudioPolicy);
method public deprecated void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
method public void setMicrophoneMute(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 34544b1db879..bcf23932d847 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -21078,8 +21078,6 @@ package android.media {
method public boolean acceptsDelayedFocusGain();
method public android.media.AudioAttributes getAudioAttributes();
method public int getFocusGain();
- method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
- method public android.os.Handler getOnAudioFocusChangeListenerHandler();
method public boolean willPauseWhenDucked();
}
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 73f912b9e6f5..2e4d199e74ce 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -18,6 +18,7 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.os.Handler;
import android.os.Looper;
@@ -48,7 +49,6 @@ public final class AudioFocusRequest {
private final int mFocusGain;
private final int mFlags;
- //TODO implement use of optional handler
private AudioFocusRequest(OnAudioFocusChangeListener listener, Handler handler,
AudioAttributes attr, int focusGain, int flags) {
mFocusListener = listener;
@@ -77,6 +77,7 @@ public final class AudioFocusRequest {
}
/**
+ * @hide
* Returns the focus change listener set for this {@code AudioFocusRequest}.
* @return null if no {@link AudioManager.OnAudioFocusChangeListener} was set.
*/
@@ -85,6 +86,7 @@ public final class AudioFocusRequest {
}
/**
+ * @hide
* Returns the {@link Handler} to be used for the focus change listener.
* @return the same {@code Handler} set in.
* {@link Builder#setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}, or null
@@ -134,6 +136,18 @@ public final class AudioFocusRequest {
== AudioManager.AUDIOFOCUS_FLAG_DELAY_OK;
}
+ /**
+ * @hide
+ * Returns whether audio focus will be locked (i.e. focus cannot change) as a result of this
+ * focus request being successful.
+ * @return whether this request will lock focus.
+ */
+ @SystemApi
+ public boolean locksFocus() {
+ return (mFlags & AudioManager.AUDIOFOCUS_FLAG_LOCK)
+ == AudioManager.AUDIOFOCUS_FLAG_LOCK;
+ }
+
int getFlags() {
return mFlags;
}
@@ -158,9 +172,16 @@ public final class AudioFocusRequest {
* ...
* mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
* ...
- * mAudioManager.requestAudioFocus(mFocusRequest);
- * ...
- * mAudioManager.abandonAudioFocusRequest(mFocusRequest);
+ * boolean mPlaybackAuthorized = true;;
+ * int res = mAudioManager.requestAudioFocus(mFocusRequest);
+ * if (res == AUDIOFOCUS_REQUEST_FAILED) {
+ * mPlaybackAuthorized = false;
+ * cancelPlayback();
+ * } else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
+ * playbackDelayed();
+ * } else { // res == AUDIOFOCUS_REQUEST_GRANTED
+ * playbackNow();
+ * }
* </pre>
*
*/
@@ -171,6 +192,7 @@ public final class AudioFocusRequest {
private int mFocusGain;
private boolean mPausesOnDuck = false;
private boolean mDelayedFocus = false;
+ private boolean mFocusLocked = false;
/**
* Constructs a new {@code Builder}, and specifies how audio focus
@@ -178,7 +200,8 @@ public final class AudioFocusRequest {
* {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
* {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
* {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
- * <p>By default there is no focus change listener, and the <code>AudioAttributes</code>
+ * <p>By default there is no focus change listener, delayed focus is not supported, ducking
+ * is suitable for the application, and the <code>AudioAttributes</code>
* have a usage of {@link AudioAttributes#USAGE_MEDIA}.
* @param focusGain the type of audio focus gain that will be requested
* @throws IllegalArgumentException thrown when an invalid focus gain type is used
@@ -258,11 +281,11 @@ public final class AudioFocusRequest {
* in {@code AudioTrack}.
* @param attributes the {@link AudioAttributes} for the focus request.
* @return this {@code Builder} instance.
- * @throws IllegalArgumentException thrown when using null for the attributes.
+ * @throws NullPointerException thrown when using null for the attributes.
*/
public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) {
if (attributes == null) {
- throw new IllegalArgumentException("Illegal null AudioAttributes");
+ throw new NullPointerException("Illegal null AudioAttributes");
}
mAttr = attributes;
return this;
@@ -299,6 +322,22 @@ public final class AudioFocusRequest {
}
/**
+ * @hide
+ * Marks this focus request as locking audio focus so granting is temporarily disabled.
+ * This feature can only be used by owners of a registered
+ * {@link android.media.audiopolicy.AudioPolicy} in
+ * {@link AudioManager#requestAudioFocus(AudioFocusRequest, android.media.audiopolicy.AudioPolicy)}.
+ * Setting to false is the same as the default behavior.
+ * @param focusLocked true when locking focus
+ * @return this {@code Builder} instance
+ */
+ @SystemApi
+ public @NonNull Builder setLocksFocus(boolean focusLocked) {
+ mFocusLocked = focusLocked;
+ return this;
+ }
+
+ /**
* Builds a new {@code AudioFocusRequest} instance combining all the information gathered
* by this {@code Builder}'s configuration methods.
* @return the {@code AudioFocusRequest} instance qualified by all the properties set
@@ -313,7 +352,8 @@ public final class AudioFocusRequest {
}
final int flags = 0
| (mDelayedFocus ? AudioManager.AUDIOFOCUS_FLAG_DELAY_OK : 0)
- | (mPausesOnDuck ? AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS : 0);
+ | (mPausesOnDuck ? AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS : 0)
+ | (mFocusLocked ? AudioManager.AUDIOFOCUS_FLAG_LOCK : 0);
return new AudioFocusRequest(mFocusListener, mListenerHandler,
mAttr, mFocusGain, flags);
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f13ccc12692d..c7796cdd4cc4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -18,6 +18,7 @@ package android.media;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -50,9 +51,9 @@ import android.view.KeyEvent;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
/**
* AudioManager provides access to volume and ringer mode control.
@@ -766,7 +767,7 @@ public class AudioManager {
* @see #setStreamVolume(int, int, int)
*/
public void adjustStreamVolume(int streamType, int direction, int flags) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.adjustStreamVolume(streamType, direction, flags,
getContext().getOpPackageName());
@@ -834,7 +835,7 @@ public class AudioManager {
/** @hide */
public void setMasterMute(boolean mute, int flags) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setMasterMute(mute, flags, getContext().getOpPackageName(),
UserHandle.getCallingUserId());
@@ -851,7 +852,7 @@ public class AudioManager {
* @see #setRingerMode(int)
*/
public int getRingerMode() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getRingerModeExternal();
} catch (RemoteException e) {
@@ -871,7 +872,7 @@ public class AudioManager {
if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
return false;
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.isValidRingerMode(ringerMode);
} catch (RemoteException e) {
@@ -887,7 +888,7 @@ public class AudioManager {
* @see #getStreamVolume(int)
*/
public int getStreamMaxVolume(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getStreamMaxVolume(streamType);
} catch (RemoteException e) {
@@ -904,7 +905,7 @@ public class AudioManager {
* @hide
*/
public int getStreamMinVolume(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getStreamMinVolume(streamType);
} catch (RemoteException e) {
@@ -921,7 +922,7 @@ public class AudioManager {
* @see #setStreamVolume(int, int, int)
*/
public int getStreamVolume(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getStreamVolume(streamType);
} catch (RemoteException e) {
@@ -935,7 +936,7 @@ public class AudioManager {
* @hide
*/
public int getLastAudibleStreamVolume(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getLastAudibleStreamVolume(streamType);
} catch (RemoteException e) {
@@ -950,7 +951,7 @@ public class AudioManager {
* @hide
*/
public int getUiSoundsStreamType() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getUiSoundsStreamType();
} catch (RemoteException e) {
@@ -978,7 +979,7 @@ public class AudioManager {
if (!isValidRingerMode(ringerMode)) {
return;
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setRingerModeExternal(ringerMode, getContext().getOpPackageName());
} catch (RemoteException e) {
@@ -1002,7 +1003,7 @@ public class AudioManager {
* @see #isVolumeFixed()
*/
public void setStreamVolume(int streamType, int index, int flags) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
@@ -1079,7 +1080,7 @@ public class AudioManager {
* @see #adjustStreamVolume(int, int, int)
*/
public boolean isStreamMute(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.isStreamMute(streamType);
} catch (RemoteException e) {
@@ -1093,7 +1094,7 @@ public class AudioManager {
* @hide
*/
public boolean isMasterMute() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.isMasterMute();
} catch (RemoteException e) {
@@ -1109,7 +1110,7 @@ public class AudioManager {
* @hide
*/
public void forceVolumeControlStream(int streamType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.forceVolumeControlStream(streamType, mICallBack);
} catch (RemoteException e) {
@@ -1137,7 +1138,7 @@ public class AudioManager {
* current ringer mode that can be queried via {@link #getRingerMode()}.
*/
public boolean shouldVibrate(int vibrateType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.shouldVibrate(vibrateType);
} catch (RemoteException e) {
@@ -1163,7 +1164,7 @@ public class AudioManager {
* current ringer mode that can be queried via {@link #getRingerMode()}.
*/
public int getVibrateSetting(int vibrateType) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getVibrateSetting(vibrateType);
} catch (RemoteException e) {
@@ -1190,7 +1191,7 @@ public class AudioManager {
* current ringer mode that can be queried via {@link #getRingerMode()}.
*/
public void setVibrateSetting(int vibrateType, int vibrateSetting) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setVibrateSetting(vibrateType, vibrateSetting);
} catch (RemoteException e) {
@@ -1208,7 +1209,7 @@ public class AudioManager {
* <var>false</var> to turn it off
*/
public void setSpeakerphoneOn(boolean on){
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setSpeakerphoneOn(on);
} catch (RemoteException e) {
@@ -1222,7 +1223,7 @@ public class AudioManager {
* @return true if speakerphone is on, false if it's off
*/
public boolean isSpeakerphoneOn() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.isSpeakerphoneOn();
} catch (RemoteException e) {
@@ -1362,7 +1363,7 @@ public class AudioManager {
* @see #ACTION_SCO_AUDIO_STATE_UPDATED
*/
public void startBluetoothSco(){
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.startBluetoothSco(mICallBack,
getContext().getApplicationInfo().targetSdkVersion);
@@ -1387,7 +1388,7 @@ public class AudioManager {
* @see #ACTION_SCO_AUDIO_STATE_UPDATED
*/
public void startBluetoothScoVirtualCall() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.startBluetoothScoVirtualCall(mICallBack);
} catch (RemoteException e) {
@@ -1406,7 +1407,7 @@ public class AudioManager {
*/
// Also used for connections started with {@link #startBluetoothScoVirtualCall()}
public void stopBluetoothSco(){
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.stopBluetoothSco(mICallBack);
} catch (RemoteException e) {
@@ -1424,7 +1425,7 @@ public class AudioManager {
* <var>false</var> to not use bluetooth SCO for communications
*/
public void setBluetoothScoOn(boolean on){
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setBluetoothScoOn(on);
} catch (RemoteException e) {
@@ -1439,7 +1440,7 @@ public class AudioManager {
* false if otherwise
*/
public boolean isBluetoothScoOn() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.isBluetoothScoOn();
} catch (RemoteException e) {
@@ -1516,7 +1517,7 @@ public class AudioManager {
* <var>false</var> to turn mute off
*/
public void setMicrophoneMute(boolean on) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setMicrophoneMute(on, getContext().getOpPackageName(),
UserHandle.getCallingUserId());
@@ -1550,7 +1551,7 @@ public class AudioManager {
* it can route the audio appropriately.
*/
public void setMode(int mode) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1566,7 +1567,7 @@ public class AudioManager {
* Returns the current current audio state from the HAL.
*/
public int getMode() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getMode();
} catch (RemoteException e) {
@@ -1703,7 +1704,7 @@ public class AudioManager {
* with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}
*/
public boolean isAudioFocusExclusive() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
} catch (RemoteException e) {
@@ -1869,7 +1870,7 @@ public class AudioManager {
return;
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.playSoundEffect(effectType);
} catch (RemoteException e) {
@@ -1904,7 +1905,7 @@ public class AudioManager {
return;
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.playSoundEffect(effectType);
} catch (RemoteException e) {
@@ -1936,7 +1937,7 @@ public class AudioManager {
return;
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.playSoundEffectVolume(effectType, volume);
} catch (RemoteException e) {
@@ -1958,7 +1959,7 @@ public class AudioManager {
* This method must be called when sound effects are enabled.
*/
public void loadSoundEffects() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.loadSoundEffects();
} catch (RemoteException e) {
@@ -1972,7 +1973,7 @@ public class AudioManager {
* sound effects are disabled.
*/
public void unloadSoundEffects() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.unloadSoundEffects();
} catch (RemoteException e) {
@@ -2058,18 +2059,25 @@ public class AudioManager {
}
/**
- * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
- * to actual listener objects.
+ * Internal class to hold the AudioFocusRequest as well as the Handler for the callback
*/
- private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
- new HashMap<String, OnAudioFocusChangeListener>();
+ private static class FocusRequestInfo {
+ @NonNull final AudioFocusRequest mRequest;
+ @Nullable final Handler mHandler;
+ FocusRequestInfo(@NonNull AudioFocusRequest afr, @Nullable Handler handler) {
+ mRequest = afr;
+ mHandler = handler;
+ }
+ }
+
/**
- * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager
- * instance.
+ * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
+ * to actual listener objects.
*/
- private final Object mFocusListenerLock = new Object();
+ private final ConcurrentHashMap<String, FocusRequestInfo> mAudioFocusIdListenerMap =
+ new ConcurrentHashMap<String, FocusRequestInfo>();
- private OnAudioFocusChangeListener findFocusListener(String id) {
+ private FocusRequestInfo findFocusRequestInfo(String id) {
return mAudioFocusIdListenerMap.get(id);
}
@@ -2110,14 +2118,15 @@ public class AudioManager {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSSG_FOCUS_CHANGE: {
- OnAudioFocusChangeListener listener = null;
- synchronized(mFocusListenerLock) {
- listener = findFocusListener((String)msg.obj);
- }
- if (listener != null) {
- Log.d(TAG, "AudioManager dispatching onAudioFocusChange("
- + msg.arg1 + ") for " + msg.obj);
- listener.onAudioFocusChange(msg.arg1);
+ final FocusRequestInfo fri = findFocusRequestInfo((String)msg.obj);
+ if (fri != null) {
+ final OnAudioFocusChangeListener listener =
+ fri.mRequest.getOnAudioFocusChangeListener();
+ if (listener != null) {
+ Log.d(TAG, "dispatching onAudioFocusChange("
+ + msg.arg1 + ") to " + msg.obj);
+ listener.onAudioFocusChange(msg.arg1);
+ }
}
} break;
case MSSG_RECORDING_CONFIG_CHANGE: {
@@ -2153,13 +2162,22 @@ public class AudioManager {
}
private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
-
+ @Override
public void dispatchAudioFocusChange(int focusChange, String id) {
- final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage(
- MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, id/*obj*/);
- mServiceEventHandlerDelegate.getHandler().sendMessage(m);
+ final FocusRequestInfo fri = findFocusRequestInfo(id);
+ if (fri != null) {
+ final OnAudioFocusChangeListener listener =
+ fri.mRequest.getOnAudioFocusChangeListener();
+ if (listener != null) {
+ final Handler h = (fri.mHandler == null) ?
+ mServiceEventHandlerDelegate.getHandler() : fri.mHandler;
+ final Message m = h.obtainMessage(
+ MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/,
+ id/*obj*/);
+ h.sendMessage(m);
+ }
+ }
}
-
};
private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
@@ -2172,18 +2190,16 @@ public class AudioManager {
/**
* @hide
- * Registers a listener to be called when audio focus changes. Calling this method is optional
- * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it
- * will register the listener as well if it wasn't registered already.
- * @param l the listener to be notified of audio focus changes.
- */
- public void registerAudioFocusListener(OnAudioFocusChangeListener l) {
- synchronized(mFocusListenerLock) {
- if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) {
- return;
- }
- mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l);
- }
+ * Registers a listener to be called when audio focus changes and keeps track of the associated
+ * focus request (including Handler to use for the listener).
+ * @param afr the full request parameters
+ */
+ public void registerAudioFocusRequest(@NonNull AudioFocusRequest afr) {
+ final Handler h = afr.getOnAudioFocusChangeListenerHandler();
+ final FocusRequestInfo fri = new FocusRequestInfo(afr, (h == null) ? null :
+ new ServiceEventHandlerDelegate(h).getHandler());
+ final String key = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener());
+ mAudioFocusIdListenerMap.put(key, fri);
}
/**
@@ -2191,12 +2207,9 @@ public class AudioManager {
* Causes the specified listener to not be called anymore when focus is gained or lost.
* @param l the listener to unregister.
*/
- public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) {
-
+ public void unregisterAudioFocusRequest(OnAudioFocusChangeListener l) {
// remove locally
- synchronized(mFocusListenerLock) {
- mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
- }
+ mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
}
@@ -2307,15 +2320,10 @@ public class AudioManager {
* is requested without building the {@link AudioFocusRequest} with
* {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)} set to
* {@code true}.
- * @throws IllegalArgumentException if passed a null argument
+ * @throws NullPointerException if passed a null argument
*/
public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest) {
- if (focusRequest == null) {
- throw new IllegalArgumentException("Illegal null AudioFocusRequest");
- }
- return requestAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
- focusRequest.getAudioAttributes(),
- focusRequest.getFocusGain(), focusRequest.getFlags(), null /* no AudioPolicy*/);
+ return requestAudioFocus(focusRequest, null /* no AudioPolicy*/);
}
/**
@@ -2402,6 +2410,7 @@ public class AudioManager {
* @return see the description of the same return value in
* {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
* @throws IllegalArgumentException
+ * @deprecated use {@link #requestAudioFocus(AudioFocusRequest, AudioPolicy)}
*/
@SystemApi
public int requestAudioFocus(OnAudioFocusChangeListener l,
@@ -2424,18 +2433,62 @@ public class AudioManager {
throw new IllegalArgumentException(
"Illegal null focus listener when flagged as accepting delayed focus grant");
}
+ if (((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
+ == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) && (l == null)) {
+ throw new IllegalArgumentException(
+ "Illegal null focus listener when flagged as pausing instead of ducking");
+ }
if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) {
throw new IllegalArgumentException(
"Illegal null audio policy when locking audio focus");
}
- int status = AUDIOFOCUS_REQUEST_FAILED;
- registerAudioFocusListener(l);
- IAudioService service = getService();
+ final AudioFocusRequest afr = new AudioFocusRequest.Builder(durationHint)
+ .setOnAudioFocusChangeListener(l, null /* no Handler for this legacy API */)
+ .setAudioAttributes(requestAttributes)
+ .setAcceptsDelayedFocusGain((flags & AUDIOFOCUS_FLAG_DELAY_OK)
+ == AUDIOFOCUS_FLAG_DELAY_OK)
+ .setWillPauseWhenDucked((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
+ == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
+ .setLocksFocus((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK)
+ .build();
+ return requestAudioFocus(afr, ap);
+ }
+
+ /**
+ * @hide
+ * Request or lock audio focus.
+ * This method is to be used by system components that have registered an
+ * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it
+ * so focus granting is temporarily disabled.
+ * @param afr see the description of the same parameter in
+ * {@link #requestAudioFocus(AudioFocusRequest)}
+ * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking
+ * focus, or null.
+ * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * or {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+ * @throws NullPointerException if the AudioFocusRequest is null
+ * @throws IllegalArgumentException when trying to lock focus without an AudioPolicy
+ */
+ @SystemApi
+ public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) {
+ if (afr == null) {
+ throw new NullPointerException("Illegal null AudioFocusRequest");
+ }
+ // this can only be checked now, not during the creation of the AudioFocusRequest instance
+ if (afr.locksFocus() && ap == null) {
+ throw new IllegalArgumentException(
+ "Illegal null audio policy when locking audio focus");
+ }
+ registerAudioFocusRequest(afr);
+ final IAudioService service = getService();
+ final int status;
try {
- status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
- mAudioFocusDispatcher, getIdForAudioFocusListener(l),
- getContext().getOpPackageName() /* package name */, flags,
+ status = service.requestAudioFocus(afr.getAudioAttributes(),
+ afr.getFocusGain(), mICallBack,
+ mAudioFocusDispatcher,
+ getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()),
+ getContext().getOpPackageName() /* package name */, afr.getFlags(),
ap != null ? ap.cb() : null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -2454,7 +2507,7 @@ public class AudioManager {
* media applications resume after a call
*/
public void requestAudioFocusForCall(int streamType, int durationHint) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.requestAudioFocus(new AudioAttributes.Builder()
.setInternalLegacyStreamType(streamType).build(),
@@ -2477,7 +2530,7 @@ public class AudioManager {
* @return
*/
public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
return service.getFocusRampTimeMs(focusGain, attr);
} catch (RemoteException e) {
@@ -2492,7 +2545,7 @@ public class AudioManager {
* Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
*/
public void abandonAudioFocusForCall() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
null /*AudioAttributes, legacy behavior*/);
@@ -2517,12 +2570,13 @@ public class AudioManager {
* @param l the listener with which focus was requested.
* @param aa the {@link AudioAttributes} with which audio focus was requested
* @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * @deprecated use {@link #abandonAudioFocusRequest(AudioFocusRequest)}
*/
@SystemApi
public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
int status = AUDIOFOCUS_REQUEST_FAILED;
- unregisterAudioFocusListener(l);
- IAudioService service = getService();
+ unregisterAudioFocusRequest(l);
+ final IAudioService service = getService();
try {
status = service.abandonAudioFocus(mAudioFocusDispatcher,
getIdForAudioFocusListener(l), aa);
@@ -2730,7 +2784,7 @@ public class AudioManager {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
policy.hasFocusListener());
@@ -2755,7 +2809,7 @@ public class AudioManager {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
}
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.unregisterAudioPolicyAsync(policy.cb());
policy.setRegistration(null);
@@ -2930,7 +2984,7 @@ public class AudioManager {
}
private final IPlaybackConfigDispatcher mPlayCb = new IPlaybackConfigDispatcher.Stub() {
-
+ @Override
public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
synchronized(mPlaybackCallbackLock) {
if (mPlaybackCallbackList != null) {
@@ -3124,7 +3178,7 @@ public class AudioManager {
}
private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
-
+ @Override
public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) {
synchronized(mRecordCallbackLock) {
if (mRecordCallbackList != null) {
@@ -3152,7 +3206,7 @@ public class AudioManager {
* to read and apply restored settings.
*/
public void reloadAudioSettings() {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.reloadAudioSettings();
} catch (RemoteException e) {
@@ -3167,7 +3221,7 @@ public class AudioManager {
* them.
*/
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.avrcpSupportsAbsoluteVolume(address, support);
} catch (RemoteException e) {
@@ -3462,7 +3516,7 @@ public class AudioManager {
* {@hide}
*/
public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.setWiredDeviceConnectionState(type, state, address, name,
mApplicationContext.getOpPackageName());
@@ -3484,7 +3538,7 @@ public class AudioManager {
*/
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state,
int profile) {
- IAudioService service = getService();
+ final IAudioService service = getService();
int delay = 0;
try {
delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile);
@@ -3500,7 +3554,7 @@ public class AudioManager {
* {@hide}
*/
public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) {
- IAudioService service = getService();
+ final IAudioService service = getService();
try {
service.handleBluetoothA2dpDeviceConfigChange(device);
} catch (RemoteException e) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
index e2323386c70c..3a332c67c579 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java
@@ -161,13 +161,11 @@ public class MediaAudioManagerTest extends ActivityInstrumentationTestCase2<Medi
private void setupAudioFocusListener() {
mAudioFocusListener = new AudioFocusListener();
- mAudioManager.registerAudioFocusListener(mAudioFocusListener);
}
private void cleanupAudioFocusListener() {
// clean up
mAudioManager.abandonAudioFocus(mAudioFocusListener);
- mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
}
//----------------------------------
@@ -245,6 +243,5 @@ public class MediaAudioManagerTest extends ActivityInstrumentationTestCase2<Medi
mAudioFocusListener.mFocusChangeCounter + " AudioFocus changes",
mAudioFocusListener.mFocusChangeCounter == ITERATIONS * 2);
mAudioManager.abandonAudioFocus(mAudioFocusListener);
- mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
}
}