Focus gain sends focus loss through the focus stack
When a new focus owner lands on the stack, don't just make the previous top of the stack lose focus, propagate the loss throughout the stack. Only dispatch focus loss on focus loss state change Remove canDispatchFocus() method as it now doesn't need to be known (and shouldn't be known) outside of the implementation. Fix error where the focus code for a focus gain request should always be a focus loss code. Bug 8315302 Change-Id: I92c8f51fdcc090851d34d00fefed916e25da40c1
This commit is contained in:
@@ -37,9 +37,10 @@ class FocusRequester {
|
||||
|
||||
// on purpose not using this classe's name, as it will only be used from MediaFocusControl
|
||||
private static final String TAG = "MediaFocusControl";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private AudioFocusDeathHandler mDeathHandler;
|
||||
private final IAudioFocusDispatcher mFocusDispatcher;
|
||||
private final IAudioFocusDispatcher mFocusDispatcher; // may be null
|
||||
private final IBinder mSourceRef;
|
||||
private final String mClientId;
|
||||
private final String mPackageName;
|
||||
@@ -73,10 +74,6 @@ class FocusRequester {
|
||||
}
|
||||
|
||||
|
||||
boolean canDispatchFocus() {
|
||||
return (mFocusDispatcher != null);
|
||||
}
|
||||
|
||||
boolean hasSameClient(String otherClient) {
|
||||
try {
|
||||
return mClientId.compareTo(otherClient) == 0;
|
||||
@@ -197,7 +194,7 @@ class FocusRequester {
|
||||
switch(mFocusLossReceived) {
|
||||
case AUDIOFOCUS_NONE:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
|
||||
return AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
|
||||
return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
@@ -210,20 +207,19 @@ class FocusRequester {
|
||||
}
|
||||
|
||||
void handleExternalFocusGain(int focusGain) {
|
||||
try {
|
||||
int focusLoss = focusLossForGainRequest(focusGain);
|
||||
if (focusLoss != mFocusLossReceived) {
|
||||
mFocusDispatcher.dispatchAudioFocusChange(focusLoss, mClientId);
|
||||
mFocusLossReceived = focusLoss;
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
Log.e(TAG, "Failure to signal loss of focus: ", e);
|
||||
}
|
||||
int focusLoss = focusLossForGainRequest(focusGain);
|
||||
handleFocusLoss(focusLoss);
|
||||
}
|
||||
|
||||
void handleFocusGain(int focusGain) {
|
||||
try {
|
||||
mFocusDispatcher.dispatchAudioFocusChange(focusGain, mClientId);
|
||||
if (mFocusDispatcher != null) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to "
|
||||
+ mClientId);
|
||||
}
|
||||
mFocusDispatcher.dispatchAudioFocusChange(focusGain, mClientId);
|
||||
}
|
||||
mFocusLossReceived = AUDIOFOCUS_NONE;
|
||||
} catch (android.os.RemoteException e) {
|
||||
Log.e(TAG, "Failure to signal gain of audio focus due to: ", e);
|
||||
@@ -232,9 +228,16 @@ class FocusRequester {
|
||||
|
||||
void handleFocusLoss(int focusLoss) {
|
||||
try {
|
||||
mFocusDispatcher.dispatchAudioFocusChange(
|
||||
focusLoss, mClientId);
|
||||
mFocusLossReceived = focusLoss;
|
||||
if (focusLoss != mFocusLossReceived) {
|
||||
if (mFocusDispatcher != null) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "dispatching " + focusChangeToString(focusLoss) + " to "
|
||||
+ mClientId);
|
||||
}
|
||||
mFocusDispatcher.dispatchAudioFocusChange(focusLoss, mClientId);
|
||||
}
|
||||
mFocusLossReceived = focusLoss;
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
Log.e(TAG, "Failure to signal loss of audio focus due to:", e);
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ public class MediaFocusControl implements OnFinished {
|
||||
*/
|
||||
protected void discardAudioFocusOwner() {
|
||||
synchronized(mAudioFocusLock) {
|
||||
if (!mFocusStack.empty() && mFocusStack.peek().canDispatchFocus()) {
|
||||
if (!mFocusStack.empty()) {
|
||||
// notify the current focus owner it lost focus after removing it from stack
|
||||
final FocusRequester exFocusOwner = mFocusStack.pop();
|
||||
exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS);
|
||||
@@ -280,13 +280,26 @@ public class MediaFocusControl implements OnFinished {
|
||||
|
||||
private void notifyTopOfAudioFocusStack() {
|
||||
// notify the top of the stack it gained focus
|
||||
if (!mFocusStack.empty() && mFocusStack.peek().canDispatchFocus()) {
|
||||
if (!mFocusStack.empty()) {
|
||||
if (canReassignAudioFocus()) {
|
||||
mFocusStack.peek().handleFocusGain(AudioManager.AUDIOFOCUS_GAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus is requested, propagate the associated loss throughout the stack.
|
||||
* @param focusGain the new focus gain that will later be added at the top of the stack
|
||||
*/
|
||||
private void propagateFocusLossFromGain_syncAf(int focusGain) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
private final Stack<FocusRequester> mFocusStack = new Stack<FocusRequester>();
|
||||
|
||||
/**
|
||||
@@ -462,14 +475,14 @@ public class MediaFocusControl implements OnFinished {
|
||||
fr.release();
|
||||
}
|
||||
|
||||
// notify current top of stack it is losing focus
|
||||
if (!mFocusStack.empty() && mFocusStack.peek().canDispatchFocus()) {
|
||||
mFocusStack.peek().handleExternalFocusGain(focusChangeHint);
|
||||
}
|
||||
|
||||
// focus requester might already be somewhere below in the stack, remove it
|
||||
removeFocusStackEntry(clientId, false /* signal */);
|
||||
|
||||
// propagate the focus change through the stack
|
||||
if (!mFocusStack.empty()) {
|
||||
propagateFocusLossFromGain_syncAf(focusChangeHint);
|
||||
}
|
||||
|
||||
// push focus requester at the top of the audio focus stack
|
||||
mFocusStack.push(new FocusRequester(mainStreamType, focusChangeHint, fd, cb,
|
||||
clientId, afdh, callingPackageName, Binder.getCallingUid()));
|
||||
|
||||
Reference in New Issue
Block a user