summaryrefslogtreecommitdiffstats
path: root/media/java/android/media/FocusRequester.java
diff options
context:
space:
mode:
Diffstat (limited to 'media/java/android/media/FocusRequester.java')
-rw-r--r--media/java/android/media/FocusRequester.java108
1 files changed, 96 insertions, 12 deletions
diff --git a/media/java/android/media/FocusRequester.java b/media/java/android/media/FocusRequester.java
index 9a39994..bbe5fd2 100644
--- a/media/java/android/media/FocusRequester.java
+++ b/media/java/android/media/FocusRequester.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.NonNull;
import android.media.MediaFocusControl.AudioFocusDeathHandler;
import android.os.IBinder;
import android.util.Log;
@@ -40,24 +41,43 @@ class FocusRequester {
private final String mClientId;
private final String mPackageName;
private final int mCallingUid;
+ private final MediaFocusControl mFocusController; // never null
/**
* the audio focus gain request that caused the addition of this object in the focus stack.
*/
private final int mFocusGainRequest;
/**
+ * the flags associated with the gain request that qualify the type of grant (e.g. accepting
+ * delay vs grant must be immediate)
+ */
+ private final int mGrantFlags;
+ /**
* the audio focus loss received my mFocusDispatcher, is AudioManager.AUDIOFOCUS_NONE if
* it never lost focus.
*/
private int mFocusLossReceived;
/**
- * the stream type associated with the focus request
+ * the audio attributes associated with the focus request
*/
- private final int mStreamType;
+ private final AudioAttributes mAttributes;
- FocusRequester(int streamType, int focusRequest,
+ /**
+ * Class constructor
+ * @param aa
+ * @param focusRequest
+ * @param grantFlags
+ * @param afl
+ * @param source
+ * @param id
+ * @param hdlr
+ * @param pn
+ * @param uid
+ * @param ctlr cannot be null
+ */
+ FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
- String pn, int uid) {
- mStreamType = streamType;
+ String pn, int uid, @NonNull MediaFocusControl ctlr) {
+ mAttributes = aa;
mFocusDispatcher = afl;
mSourceRef = source;
mClientId = id;
@@ -65,7 +85,9 @@ class FocusRequester {
mPackageName = pn;
mCallingUid = uid;
mFocusGainRequest = focusRequest;
+ mGrantFlags = grantFlags;
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
+ mFocusController = ctlr;
}
@@ -77,6 +99,10 @@ class FocusRequester {
}
}
+ boolean isLockedFocusOwner() {
+ return ((mGrantFlags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0);
+ }
+
boolean hasSameBinder(IBinder ib) {
return (mSourceRef != null) && mSourceRef.equals(ib);
}
@@ -93,13 +119,20 @@ class FocusRequester {
return mCallingUid == uid;
}
+ String getClientId() {
+ return mClientId;
+ }
int getGainRequest() {
return mFocusGainRequest;
}
- int getStreamType() {
- return mStreamType;
+ int getGrantFlags() {
+ return mGrantFlags;
+ }
+
+ AudioAttributes getAudioAttributes() {
+ return mAttributes;
}
@@ -134,14 +167,31 @@ class FocusRequester {
return focusChangeToString(mFocusLossReceived);
}
+ private static String flagsToString(int flags) {
+ String msg = new String();
+ if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) != 0) {
+ msg += "DELAY_OK";
+ }
+ if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0) {
+ if (!msg.isEmpty()) { msg += "|"; }
+ msg += "LOCK";
+ }
+ if ((flags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
+ if (!msg.isEmpty()) { msg += "|"; }
+ msg += "PAUSES_ON_DUCKABLE_LOSS";
+ }
+ return msg;
+ }
+
void dump(PrintWriter pw) {
pw.println(" source:" + mSourceRef
+ " -- pack: " + mPackageName
+ " -- client: " + mClientId
+ " -- gain: " + focusGainToString()
+ + " -- flags: " + flagsToString(mGrantFlags)
+ " -- loss: " + focusLossToString()
+ " -- uid: " + mCallingUid
- + " -- stream: " + mStreamType);
+ + " -- attr: " + mAttributes);
}
@@ -204,13 +254,22 @@ class FocusRequester {
}
}
+ /**
+ * Called synchronized on MediaFocusControl.mAudioFocusLock
+ */
void handleExternalFocusGain(int focusGain) {
int focusLoss = focusLossForGainRequest(focusGain);
handleFocusLoss(focusLoss);
}
+ /**
+ * Called synchronized on MediaFocusControl.mAudioFocusLock
+ */
void handleFocusGain(int focusGain) {
try {
+ mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
+ mFocusController.notifyExtPolicyFocusGrant_syncAf(toAudioFocusInfo(),
+ AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
if (mFocusDispatcher != null) {
if (DEBUG) {
Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to "
@@ -218,27 +277,52 @@ class FocusRequester {
}
mFocusDispatcher.dispatchAudioFocusChange(focusGain, mClientId);
}
- mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
} catch (android.os.RemoteException e) {
Log.e(TAG, "Failure to signal gain of audio focus due to: ", e);
}
}
+ /**
+ * Called synchronized on MediaFocusControl.mAudioFocusLock
+ */
void handleFocusLoss(int focusLoss) {
try {
if (focusLoss != mFocusLossReceived) {
+ mFocusLossReceived = focusLoss;
+ // before dispatching a focus loss, check if the following conditions are met:
+ // 1/ the framework is not supposed to notify the focus loser on a DUCK loss
+ // 2/ it is a DUCK loss
+ // 3/ the focus loser isn't flagged as pausing in a DUCK loss
+ // if they are, do not notify the focus loser
+ if (!mFocusController.mustNotifyFocusOwnerOnDuck()
+ && mFocusLossReceived == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
+ && (mGrantFlags
+ & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) == 0) {
+ if (DEBUG) {
+ Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived)
+ + " to " + mClientId + ", to be handled externally");
+ }
+ mFocusController.notifyExtPolicyFocusLoss_syncAf(
+ toAudioFocusInfo(), false /* wasDispatched */);
+ return;
+ }
if (mFocusDispatcher != null) {
if (DEBUG) {
- Log.v(TAG, "dispatching " + focusChangeToString(focusLoss) + " to "
+ Log.v(TAG, "dispatching " + focusChangeToString(mFocusLossReceived) + " to "
+ mClientId);
}
- mFocusDispatcher.dispatchAudioFocusChange(focusLoss, mClientId);
+ mFocusController.notifyExtPolicyFocusLoss_syncAf(
+ toAudioFocusInfo(), true /* wasDispatched */);
+ mFocusDispatcher.dispatchAudioFocusChange(mFocusLossReceived, mClientId);
}
- mFocusLossReceived = focusLoss;
}
} catch (android.os.RemoteException e) {
Log.e(TAG, "Failure to signal loss of audio focus due to:", e);
}
}
+ AudioFocusInfo toAudioFocusInfo() {
+ return new AudioFocusInfo(mAttributes, mClientId, mPackageName,
+ mFocusGainRequest, mFocusLossReceived, mGrantFlags);
+ }
}