首先看AudioManager的abandonAudioFocusRequest方法:
//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
......
public int abandonAudioFocusRequest(@NonNull AudioFocusRequest focusRequest) {
if (focusRequest == null) {
throw new IllegalArgumentException("Illegal null AudioFocusRequest");
}
return abandonAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
focusRequest.getAudioAttributes());
}
public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
int status = AUDIOFOCUS_REQUEST_FAILED;
unregisterAudioFocusRequest(l);
final IAudioService service = getService();
try {
status = service.abandonAudioFocus(mAudioFocusDispatcher,
getIdForAudioFocusListener(l), aa, getContext().getOpPackageName()); //调用AudioService的abandonAudioFocus方法
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return status;
}
......
}
AudioService.abandonAudioFocus
在AudioManager的abandonAudioFocus方法中调用AudioService的abandonAudioFocus:
//frameworks/base/service/java/com/android/server/audio/AudioService.java
public class AudioService extends IAudioService.Stub
implements AccessibilityManager.TouchExplorationStateChangeListener,
AccessibilityManager.AccessibilityServicesStateChangeListener {
......
private final MediaFocusControl mMediaFocusControl;
......
public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
String callingPackageName) {
return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
}
......
}
MediaFocusControl.abandonAudioFocus
在AudioService的abandonAudioFocus中调用MediaFocusControl的abandonAudioFocus。
public class MediaFocusControl implements PlayerFocusEnforcer {
......
protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
String callingPackageName) {
// AudioAttributes are currently ignored, to be used for zones / a11y
mEventLogger.log((new AudioEventLogger.StringEvent(
"abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
+ " clientId=" + clientId))
.printLog(TAG));
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
// external focus policy?
if (mFocusPolicy != null) {
final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
0 /*flags*/, 0 /* sdk n/a here*/);
if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) { //如果是外部音频焦点策略,通过AudioPolicy.AudioPolicyFocusListener调用到CarZonesAudioFocus
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
}
boolean exitingRingOrCall = mRingOrCallActive
& (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
if (exitingRingOrCall) { mRingOrCallActive = false; }
removeFocusStackEntry(clientId, true /*signal*/, true /*notifyFocusFollowers*/);
if (ENFORCE_MUTING_FOR_RING_OR_CALL & exitingRingOrCall) {
runAudioCheckerForRingOrCallAsync(false/*enteringRingOrCall*/);
}
}
} catch (java.util.ConcurrentModificationException cme) {
// Catching this exception here is temporary. It is here just to prevent
// a crash seen when the "Silent" notification is played. This is believed to be fixed
// but this try catch block is left just to be safe.
Log.e(TAG, "FATAL EXCEPTION AudioFocus abandonAudioFocus() caused " + cme);
cme.printStackTrace();
}
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
......
}
notifyExtFocusPolicyFocusAbandon_syncAf
如果是外部音频焦点策略,调用notifyExtFocusPolicyFocusAbandon_syncAf方法:
//frameworks/base/service/java/com/android/server/audio/MediaFocusControl.java
public class MediaFocusControl implements PlayerFocusEnforcer {
@Nullable private IAudioPolicyCallback mFocusPolicy = null;
boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
if (mFocusPolicy == null) {
return false;
}
final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
if (fr != null) {
fr.release();
}
try {
//oneway
mFocusPolicy.notifyAudioFocusAbandon(afi); //调用IAudioPolicyCallback的notifyAudioFocusAbandon方法
} catch (RemoteException e) {
Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback "
+ mFocusPolicy.asBinder(), e);
}
return true;
}
}
IAudioPolicyCallback的notifyAudioFocusAbandon方法,IAudioPolicyCallback是一个接口,其实现在AudioPolicy中:
//frameworks/base/media/java/android/media/audiopolicy/AudioPolicy.java
public class AudioPolicy {
private final IAudioPolicyCallback mPolicyCb = new IAudioPolicyCallback.Stub() {
public void notifyAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
sendMsg(MSG_FOCUS_GRANT, afi, requestResult);
if (DEBUG) {
Log.v(TAG, "notifyAudioFocusGrant: pack=" + afi.getPackageName() + " client="
+ afi.getClientId() + "reqRes=" + requestResult);
}
}
public void notifyAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
sendMsg(MSG_FOCUS_LOSS, afi, wasNotified ? 1 : 0);
if (DEBUG) {
Log.v(TAG, "notifyAudioFocusLoss: pack=" + afi.getPackageName() + " client="
+ afi.getClientId() + "wasNotified=" + wasNotified);
}
}
public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
if (DEBUG) {
Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
+ afi.getClientId() + " gen=" + afi.getGen());
}
}
public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */); //发送MSG_FOCUS_ABANDON消息
if (DEBUG) {
Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
+ afi.getClientId());
}
}
public void notifyMixStateUpdate(String regId, int state) {
for (AudioMix mix : mConfig.getMixes()) {
if (mix.getRegistration().equals(regId)) {
mix.mMixState = state;
sendMsg(MSG_MIX_STATE_UPDATE, mix, 0/*ignored*/);
if (DEBUG) {
Log.v(TAG, "notifyMixStateUpdate: regId=" + regId + " state=" + state);
}
}
}
}
public void notifyVolumeAdjust(int adjustment) {
sendMsg(MSG_VOL_ADJUST, null /* ignored */, adjustment);
if (DEBUG) {
Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
}
}
public void notifyUnregistration() {
setRegistration(null);
}
}
}
发送MSG_FOCUS_ABANDON消息,在EventHandler中会处理这个消息:
//frameworks/base/media/java/android/media/audiopolicy/AudioPolicy.java
public class AudioPolicy {
private AudioPolicyFocusListener mFocusListener;
private class EventHandler extends Handler {
public EventHandler(AudioPolicy ap, Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_POLICY_STATUS_CHANGE:
onPolicyStatusChange();
break;
case MSG_FOCUS_GRANT:
if (mFocusListener != null) {
mFocusListener.onAudioFocusGrant(
(AudioFocusInfo) msg.obj, msg.arg1);
}
break;
case MSG_FOCUS_LOSS:
if (mFocusListener != null) {
mFocusListener.onAudioFocusLoss(
(AudioFocusInfo) msg.obj, msg.arg1 != 0);
}
break;
case MSG_MIX_STATE_UPDATE:
if (mStatusListener != null) {
mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
}
break;
case MSG_FOCUS_REQUEST:
if (mFocusListener != null) {
mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
} else { // should never be null, but don't crash
Log.e(TAG, "Invalid null focus listener for focus request event");
}
break;
case MSG_FOCUS_ABANDON:
if (mFocusListener != null) { // should never be null
mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj); //调用AudioPolicyFocusListener的onAudioFocusAbandon方法
} else { // should never be null, but don't crash
Log.e(TAG, "Invalid null focus listener for focus abandon event");
}
break;
case MSG_VOL_ADJUST:
if (mVolCb != null) {
mVolCb.onVolumeAdjustment(msg.arg1);
} else { // should never be null, but don't crash
Log.e(TAG, "Invalid null volume event");
}
break;
default:
Log.e(TAG, "Unknown event " + msg.what);
}
}
}
}
调用AudioPolicyFocusListener的onAudioFocusAbandon方法,AudioPolicyFocusListener是一个接口,由CarZonesAudioFocus实现,因此会调用CarZonesAudioFocus的onAudioFocusAbandon方法:
待更新