Merge "Audio focus: definitive loss of focus removes client from stack"
This commit is contained in:
committed by
Android (Google) Code Review
commit
25e3210eaf
@@ -25,6 +25,7 @@ import android.media.IAudioFocusDispatcher;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -300,16 +301,19 @@ public class FocusRequester {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called synchronized on MediaFocusControl.mAudioFocusLock
|
||||
* Handle the loss of focus resulting from a given focus gain.
|
||||
* @param focusGain the focus gain from which the loss of focus is resulting
|
||||
* @param frWinner the new focus owner
|
||||
* @return true if the focus loss is definitive, false otherwise.
|
||||
*/
|
||||
void handleExternalFocusGain(int focusGain, final FocusRequester fr) {
|
||||
int focusLoss = focusLossForGainRequest(focusGain);
|
||||
handleFocusLoss(focusLoss, fr);
|
||||
@GuardedBy("MediaFocusControl.mAudioFocusLock")
|
||||
boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner) {
|
||||
final int focusLoss = focusLossForGainRequest(focusGain);
|
||||
handleFocusLoss(focusLoss, frWinner);
|
||||
return (focusLoss == AudioManager.AUDIOFOCUS_LOSS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called synchronized on MediaFocusControl.mAudioFocusLock
|
||||
*/
|
||||
@GuardedBy("MediaFocusControl.mAudioFocusLock")
|
||||
void handleFocusGain(int focusGain) {
|
||||
try {
|
||||
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
|
||||
@@ -331,19 +335,15 @@ public class FocusRequester {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called synchronized on MediaFocusControl.mAudioFocusLock
|
||||
*/
|
||||
@GuardedBy("MediaFocusControl.mAudioFocusLock")
|
||||
void handleFocusGainFromRequest(int focusRequestResult) {
|
||||
if (focusRequestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
mFocusController.unduckPlayers(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called synchronized on MediaFocusControl.mAudioFocusLock
|
||||
*/
|
||||
void handleFocusLoss(int focusLoss, @Nullable final FocusRequester fr) {
|
||||
@GuardedBy("MediaFocusControl.mAudioFocusLock")
|
||||
void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner) {
|
||||
try {
|
||||
if (focusLoss != mFocusLossReceived) {
|
||||
mFocusLossReceived = focusLoss;
|
||||
@@ -371,9 +371,9 @@ public class FocusRequester {
|
||||
boolean handled = false;
|
||||
if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
|
||||
&& MediaFocusControl.ENFORCE_DUCKING
|
||||
&& fr != null) {
|
||||
&& frWinner != null) {
|
||||
// candidate for enforcement by the framework
|
||||
if (fr.mCallingUid != this.mCallingUid) {
|
||||
if (frWinner.mCallingUid != this.mCallingUid) {
|
||||
if ((mGrantFlags
|
||||
& AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
|
||||
// the focus loser declared it would pause instead of duck, let it
|
||||
@@ -386,7 +386,7 @@ public class FocusRequester {
|
||||
handled = false;
|
||||
Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK");
|
||||
} else {
|
||||
handled = mFocusController.duckPlayers(fr, this);
|
||||
handled = mFocusController.duckPlayers(frWinner, this);
|
||||
}
|
||||
} // else: the focus change is within the same app, so let the dispatching
|
||||
// happen as if the framework was not involved.
|
||||
|
||||
@@ -32,11 +32,15 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
@@ -146,9 +150,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called synchronized on mAudioFocusLock
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private void notifyTopOfAudioFocusStack() {
|
||||
// notify the top of the stack it gained focus
|
||||
if (!mFocusStack.empty()) {
|
||||
@@ -160,14 +162,24 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
|
||||
/**
|
||||
* Focus is requested, propagate the associated loss throughout the stack.
|
||||
* Will also remove entries in the stack that have just received a definitive loss of focus.
|
||||
* @param focusGain the new focus gain that will later be added at the top of the stack
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private void propagateFocusLossFromGain_syncAf(int focusGain, final FocusRequester fr) {
|
||||
final List<String> clientsToRemove = new LinkedList<String>();
|
||||
// going through the audio focus stack to signal new focus, traversing order doesn't
|
||||
// matter as all entries respond to the same external focus gain
|
||||
Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
|
||||
while(stackIterator.hasNext()) {
|
||||
stackIterator.next().handleExternalFocusGain(focusGain, fr);
|
||||
for (FocusRequester focusLoser : mFocusStack) {
|
||||
final boolean isDefinitiveLoss =
|
||||
focusLoser.handleFocusLossFromGain(focusGain, fr);
|
||||
if (isDefinitiveLoss) {
|
||||
clientsToRemove.add(focusLoser.getClientId());
|
||||
}
|
||||
}
|
||||
for (String clientToRemove : clientsToRemove) {
|
||||
removeFocusStackEntry(clientToRemove, false /*signal*/,
|
||||
true /*notifyFocusFollowers*/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +210,12 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function:
|
||||
* Called synchronized on mAudioFocusLock
|
||||
* Remove a focus listener from the focus stack.
|
||||
* @param clientToRemove the focus listener
|
||||
* @param signal if true and the listener was at the top of the focus stack, i.e. it was holding
|
||||
* focus, notify the next item in the stack it gained focus.
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private void removeFocusStackEntry(String clientToRemove, boolean signal,
|
||||
boolean notifyFocusFollowers) {
|
||||
// is the current top of the focus stack abandoning focus? (because of request, not death)
|
||||
@@ -242,10 +253,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function:
|
||||
* Called synchronized on mAudioFocusLock
|
||||
* Remove focus listeners from the focus stack for a particular client when it has died.
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private void removeFocusStackEntryOnDeath(IBinder cb) {
|
||||
// is the owner of the audio focus part of the client to remove?
|
||||
boolean isTopOfStackForClientToRemove = !mFocusStack.isEmpty() &&
|
||||
@@ -271,10 +281,10 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
|
||||
/**
|
||||
* Helper function for external focus policy:
|
||||
* Called synchronized on mAudioFocusLock
|
||||
* Remove focus listeners from the list of potential focus owners for a particular client when
|
||||
* it has died.
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private void removeFocusEntryForExtPolicy(IBinder cb) {
|
||||
if (mFocusOwnersForFocusPolicy.isEmpty()) {
|
||||
return;
|
||||
@@ -324,6 +334,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
* @return {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED} or
|
||||
* {@link AudioManager#AUDIOFOCUS_REQUEST_DELAYED}
|
||||
*/
|
||||
@GuardedBy("mAudioFocusLock")
|
||||
private int pushBelowLockedFocusOwners(FocusRequester nfr) {
|
||||
int lastLockedFocusOwnerIndex = mFocusStack.size();
|
||||
for (int index = mFocusStack.size()-1; index >= 0; index--) {
|
||||
|
||||
Reference in New Issue
Block a user