文章目录
- 正文
- AudioService.java
- MediaFocusControl.java
- AudioService.java
- AudioManager.java
- CarAudioService.java
- AudioPolicy.java
- MediaFocusControl.java
- AudioPolicy.java
- CarAudioService.java
- CarZonesAudioFocus.java
- CarAudioFocus.java
- AudioManager.java
- AudioService.java
- MediaFocusControl.java
- FocusRequester.java
- AudioManager.java
- 参考文章
简单跟一下Android中AudioManager申请焦点的代码流程,顺便记录一下,方便自己查阅。
这里以Android 13的代码分析,而且以车载模式(car模式)跟踪。其实大部分内容跟《》。
记录得有点绕,只是简单走一下流程,不一定适合你看。
正文
前面《》跟过,部分细节就不详说了,直接进入正题。
AudioManager.java
public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest) { return requestAudioFocus(focusRequest, null ); }
requestAudioFocus()
public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) { //略 //注册到mAudioFocusIdListenerMap中,后面查询需要 registerAudioFocusRequest(afr); //略 final String clientId = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()); //BlockingFocusResultReceiver后面会单独关注 final BlockingFocusResultReceiver focusReceiver; synchronized (mFocusRequestsLock) { try { //status为返回状态,如果非车载模式,返回的就是申请焦点成功或失败,但车载模式不同。 //mAudioFocusDispatcher这个重要,有状态回调,需要关注。 //service是AudioService status = service.requestAudioFocus(afr.getAudioAttributes(), afr.getFocusGain(), mICallBack, mAudioFocusDispatcher, clientId, getContext().getOpPackageName(), getContext().getAttributionTag(), afr.getFlags(), ap != null ? ap.cb() : null, sdk); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } //返回的status就是AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) { return status; } //如果开机第一次申请焦点,为null,进行初始化 if (mFocusRequestsAwaitingResult == null) { mFocusRequestsAwaitingResult = new HashMap<String, BlockingFocusResultReceiver>(1); } //创建BlockingFocusResultReceiver, focusReceiver = new BlockingFocusResultReceiver(clientId); //添加到申请结果等待列表,key为clientId后面需要根据key找focusReceiver mFocusRequestsAwaitingResult.put(clientId, focusReceiver); } //延迟200ms,也就等待200ms是否能返回结果。 focusReceiver.waitForResult(EXT_FOCUS_POLICY_TIMEOUT_MS); //延迟已经获取结果的focusReceiver synchronized (mFocusRequestsLock) { //这里是根据clientID移除的 mFocusRequestsAwaitingResult.remove(clientId); } //返回结果焦点申请成功或失败 return focusReceiver.requestResult(); }
这里有几个重点
通过AudioService的requestAudioFocus()申请焦点
传入mAudioFocusDispatcher用于回调焦点申请状态
BlockingFocusResultReceiver等待返回的焦点申请状态
下面先看一下2和3点,1后面进入AudioService中分析。
mAudioFocusDispatcher
对于mAudioFocusDispatcher,之前有介绍过。
这里主要是下面两个回调方法。
第一个之前看过,就是分发焦点变化,然后通知到app层。
第二个方法就是焦点申请结果状态的回调。
private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { @Override public void dispatchAudioFocusChange(int focusChange, String id) { //根据客户端ID查找对应的FocusRequestInfo,这个是一开始注册焦点时放入mAudioFocusIdListenerMap中的。 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, focusChange, 0,id); h.sendMessage(m); } } } @Override public void dispatchFocusResultFromExtPolicy(int requestResult, String clientId) { synchronized (mFocusRequestsLock) { //重点 //先从队列中移除,然后返回对应的BlockingFocusResultReceiver final BlockingFocusResultReceiver focusReceiver = mFocusRequestsAwaitingResult.remove(clientId); //不为null,就通知焦点申请requestResult结果 if (focusReceiver != null) { focusReceiver.notifyResult(requestResult); } else { Log.e(TAG, "dispatchFocusResultFromExtPolicy 3 found no result receiver"); } } } };
BlockingFocusResultReceiver
private static final class BlockingFocusResultReceiver { private final SafeWaitObject mLock = new SafeWaitObject(); @GuardedBy("mLock") private boolean mResultReceived = false; private int mFocusRequestResult = AudioManager.AUDIOFOCUS_REQUEST_FAILED; private final String mFocusClientId; BlockingFocusResultReceiver(String clientId) { mFocusClientId = clientId; } boolean receivedResult() { return mResultReceived; } int requestResult() { return mFocusRequestResult; } void notifyResult(int requestResult) { //更新状态 synchronized (mLock) { mResultReceived = true; mFocusRequestResult = requestResult; //通知解锁 mLock.safeNotify(); } } public void waitForResult(long timeOutMs) { synchronized (mLock) { //如果提前有结果,就直接返回,否则等待200ms if (mResultReceived) { return; } try { mLock.safeWait(timeOutMs); } catch (InterruptedException e) { } } } }
小结一下
车载模式跟非车载模式区别就是上面
车载模式和手机模式(非车载模式)申请流程类似,但返回焦点状态流程不一样
车载模式会之多等待200ms返回结果
好奇,如果当系统卡主,超过200ms返回的结果是啥?
进入AudioService
AudioService.java
requestAudioFocus()
public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb, IAudioFocusDispatcher fd, String clientId, String callingPackageName, String attributionTag, int flags, IAudioPolicyCallback pcb, int sdk) { //非法或权限等检查,略 //是是否有锁住标签,普通app无法设置AudioManager.AUDIOFOCUS_FLAG_LOCK,暂时不关心 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) { if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( android.Manifest.permission.MODIFY_PHONE_STATE)) { final String reason = "Invalid permission to (un)lock audio focus"; mmi.set(MediaMetrics.Property.EARLY_RETURN, reason) .record(); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } } else { // only a registered audio policy can be used to lock focus synchronized (mAudioPolicies) { if (!mAudioPolicies.containsKey(pcb.asBinder())) { final String reason = "Invalid unregistered AudioPolicy to (un)lock audio focus"; mmi.set(MediaMetrics.Property.EARLY_RETURN, reason) .record(); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } } } } //正常下肯定不为null if (callingPackageName == null || clientId == null || aa == null) { final String reason = "Invalid null parameter to request audio focus"; mmi.set(MediaMetrics.Property.EARLY_RETURN, reason) .record(); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } mmi.record(); //最终进入MediaFocusControl return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd, clientId, callingPackageName, attributionTag, flags, sdk, forceFocusDuckingForAccessibility(aa, durationHint, uid), -1 /*testUid, ignored*/); }
MediaFocusControl.java
requestAudioFocus()
大部分跟之前手机模式(非车载模式)流程一样,但由于这里是车载模式,mFocusPolicy不为null,所以走的流程会不一样。
下面说一下不同点。
因为mFocusPolicy不为null,所以afiForExtPolicy也不为null
因为mFocusPolicy不为null,走notifyExtFocusPolicyFocusRequest_syncAf流程,然后判断直接return了。
protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb, IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName, String attributionTag, int flags, int sdk, boolean forceDuck, int testUid) { //略 synchronized(mAudioFocusLock) { //队列中是否过多的FocusRequester,一般不会超过限制 if (mFocusStack.size() > MAX_STACK_SIZE) { return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } //铃声 boolean enteringRingOrCall = !mRingOrCallActive & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0); if (enteringRingOrCall) { mRingOrCallActive = true; } final AudioFocusInfo afiForExtPolicy; //mFocusPolicy是IAudioPolicyCallback对象 //车载模式焦点策略 if (mFocusPolicy != null) { //new一个AudioFocusInfo对象 afiForExtPolicy = new AudioFocusInfo(aa, uid, clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/, flags, sdk); } else { afiForExtPolicy = null; } //是否可以请求焦点 //一般来说通话(或BT或或有申请锁住flag的焦点应用)时,是不允许,否则运行 if (!canReassignAudioFocus()) { //当此时不允许申请焦点时,看是否有延迟焦点标签 if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) { //没有就返回申请失败 return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } else { 设置可以延迟获取焦点标签为true,等通话结束后可以重新获取到焦点 focusGrantDelayed = true; } } //车载模式时焦点车略不为null if (mFocusPolicy != null) { //申请焦点 if (notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, fd, cb)) { return AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY; } else { //申请焦点失败 return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } } //由于车载模式,走了上面,下面的代码不走的。 //略 }
下面关注notifyExtFocusPolicyFocusRequest_syncAf()。
notifyExtFocusPolicyFocusRequest_syncAf()
boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, IAudioFocusDispatcher fd, @NonNull IBinder cb) { //外部(车载模式)焦点计数 synchronized (mExtFocusChangeLock) { afi.setGen(mExtFocusChangeCounter++); } //查询id是否已经在队列中 final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId()); boolean keepTrack = false; //我们这是第一次,不存在,为null if (existingFr != null) { //看是否存在一样的IAudioFocusDispatcher回调 if (!existingFr.hasSameDispatcher(fd)) { existingFr.release(); keepTrack = true; } } else { keepTrack = true; } //为true if (keepTrack) { final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb); try { cb.linkToDeath(hdlr, 0); } catch (RemoteException e) { return false; } //创建FocusRequester并添加到队列中 mFocusOwnersForFocusPolicy.put(afi.getClientId(), new FocusRequester(afi, fd, cb, hdlr, this)); } try { //通知焦点申请 mFocusPolicy.notifyAudioFocusRequest(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED); return true; } catch (RemoteException e) { } return false; }
这里重点
mFocusPolicy.notifyAudioFocusRequest(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
private IAudioPolicyCallback mFocusPolicy = null;
mFocusPolicy是在setFocusPolicy()中赋值的。
setFocusPolicy()
void setFocusPolicy(IAudioPolicyCallback policy, boolean isTestFocusPolicy) {
if (policy == null) {
return;
}
synchronized (mAudioFocusLock) {
if (isTestFocusPolicy) {
mPreviousFocusPolicy = mFocusPolicy;
}
mFocusPolicy = policy;
}
}
上面可以看出mFocusPolicy是其他地方传入的。
而setFocusPolicy的调用是在AudioService.java中的内部类AudioPolicyProxy中。
AudioService.java
AudioPolicyProxy()
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
boolean isVolumeController, IMediaProjection projection) {
super(config);
setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
//这里赋值的。
mPolicyCallback = token;
mHasFocusListener = hasFocusListener;
mIsVolumeController = isVolumeController;
mProjection = projection;
if (mHasFocusListener) {
mMediaFocusControl.addFocusFollower(mPolicyCallback);
if (isFocusPolicy) {
mIsFocusPolicy = true;
mIsTestFocusPolicy = isTestFocusPolicy;
//这里设置policy
mMediaFocusControl.setFocusPolicy(mPolicyCallback, mIsTestFocusPolicy);
}
}
//略
}
而AudioPolicyProxy的初始化在,AudioService.java的registerAudioPolicy()中
registerAudioPolicy()
public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
boolean isVolumeController, IMediaProjection projection) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
//判断是否允许注册
if (!isPolicyRegisterAllowed(policyConfig,
isFocusPolicy || isTestFocusPolicy || hasFocusListener,
isVolumeController,
projection)) {
return null;
}
String regId = null;
synchronized (mAudioPolicies) {
if (mAudioPolicies.containsKey(pcb.asBinder())) {
return null;
}
try {
//初始化AudioPolicyProxy对象
//关注第二个参数pcb,为IAudioPolicyCallback对象。
AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
isFocusPolicy, isTestFocusPolicy, isVolumeController, projection);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
} catch (RemoteException e) {
return null;
} catch (IllegalStateException e) {
return null;
}
}
return regId;
}
registerAudioPolicy()注册时在AudioManager中调用的。
AudioManager.java
registerAudioPolicyStatic()
然后调用的是AudioService中的registerAudioPolicy()。
static int registerAudioPolicyStatic(@NonNull AudioPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
}
final IAudioService service = getService();
try {
MediaProjection projection = policy.getMediaProjection();
//service就是AudioService的代理
//依旧关注第二个参数,policy.cb()
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
policy.hasFocusListener(), policy.isFocusPolicy(), policy.isTestFocusPolicy(),
policy.isVolumeController(),
projection == null ? null : projection.getProjection());
if (regId == null) {
return ERROR;
} else {
policy.setRegistration(regId);
}
// successful registration
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return SUCCESS;
}
重点是第二个参数,policy.cb(),返回的是mPolicyCb
public IAudioPolicyCallback cb() { return mPolicyCb; }
这里先看一下Policy哪里注册的。
registerAudioPolicy()
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int registerAudioPolicy(@NonNull AudioPolicy policy) {
return registerAudioPolicyStatic(policy);
}
这种事car模式(车载模式)下,调用这个注册是在Car的CarAudioService中的。
CarAudioService.java
\packages\services\Car\service\src\com\android\car\audio\CarAudioService.java
setupDynamicRoutingLocked()
private void setupDynamicRoutingLocked() {
final AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
//略
//mFocusHandler需要重点关注
mFocusHandler = CarZonesAudioFocus.createCarZonesAudioFocus(mAudioManager,
mContext.getPackageManager(),
mCarAudioZones,
mCarAudioSettings,
mCarDucking);
Log.w(TAG, "setupDynamicRoutingLocked mFocusHandler : "+mFocusHandler );
//这里mFocusHandler比较重要哈,用于回调状态
builder.setAudioPolicyFocusListener(mFocusHandler);
builder.setIsAudioFocusPolicy(true);
//AudioPolicy的初始化,使用了Build模式
mAudioPolicy = builder.build();
mFocusHandler.setOwningPolicy(this, mAudioPolicy);
//注册到mAudioManager中
int r = mAudioManager.registerAudioPolicy(mAudioPolicy);
if (r != AudioManager.SUCCESS) {
throw new RuntimeException("registerAudioPolicy failed " + r);
}
setupOccupantZoneInfo();
}
mAudioPolicy就是AudioPolicy,这后面跟。
该方法在init()中初始化的。
init()
@Override
public void init() {
synchronized (mImplLock) {
mOccupantZoneService = CarLocalServices.getService(CarOccupantZoneService.class);
Car car = new Car(mContext, /* service= */null, /* handler= */ null);
mOccupantZoneManager = new CarOccupantZoneManager(car, mOccupantZoneService);
//这里判断是否用动态路由
if (mUseDynamicRouting) {
setupDynamicRoutingLocked();
setupHalAudioFocusListenerLocked();
setupHalAudioGainCallbackLocked();
setupAudioConfigurationCallbackLocked();
setupPowerPolicyListener();
} else {
setupLegacyVolumeChangedListener();
}
mAudioManager.setSupportedSystemUsages(SYSTEM_USAGES);
}
restoreMasterMuteState();
}
也就是Car模式下,切设置了使用动态路由,就需要注册mAudioPolicy。
AudioPolicy.java
frameworks\base\media\java\android\media\audiopolicy\AudioPolicy.java
AudioPolicy的初始化使用了Builder模式,因此这里直接看build()方法。
build()
@NonNull
public AudioPolicy build() {
if (mStatusListener != null) {
for (AudioMix mix : mMixes) {
mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
}
}
if (mIsFocusPolicy && mFocusListener == null) {
throw new IllegalStateException("Cannot be a focus policy without "
+ "an AudioPolicyFocusListener");
}
return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
mFocusListener, mStatusListener, mIsFocusPolicy, mIsTestFocusPolicy,
mVolCb, mProjection);
}
AudioPolicy()
private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
AudioPolicyFocusListener fl, AudioPolicyStatusListener sl,
boolean isFocusPolicy, boolean isTestFocusPolicy,
AudioPolicyVolumeCallback vc, @Nullable MediaProjection projection) {
mConfig = config;
mStatus = POLICY_STATUS_UNREGISTERED;
mContext = context;
if (looper == null) {
looper = Looper.getMainLooper();
}
if (looper != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
mFocusListener = fl;
mStatusListener = sl;
mIsFocusPolicy = isFocusPolicy;
mIsTestFocusPolicy = isTestFocusPolicy;
mVolCb = vc;
mProjection = projection;
}
重点关注是传入的mFocusListener。这个参数是使用Build模式传入的,这里略过,但需要这个是用于焦点回调的即可。
当然其他参数也比较重要,这里只挑暂时关注的看哈。
小结
Car模式下,在CarAudioService中初始化并注册AudioPolicy,并传入了mFocusListener
mFocusPolicy是通过AudioPolicy.cb()赋值的,也就是AudioPolicy中的mPolicyCb
MediaFocusControl.java
继续上面,我们说介绍在notifyExtFocusPolicyFocusRequest_syncAf()中
mFocusPolicy.notifyAudioFocusRequest(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
从上面可以知道,mFocusPolicy就是AudioPolicy中的mPolicyCb。
AudioPolicy.java
进入看mPolicyCb变量。
mPolicyCb
其的重写的方法很多,重点关注notifyAudioFocusRequest()
private final IAudioPolicyCallback mPolicyCb = new IAudioPolicyCallback.Stub() {
public void notifyAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
sendMsg(MSG_FOCUS_GRANT, afi, requestResult);
}
public void notifyAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
sendMsg(MSG_FOCUS_LOSS, afi, wasNotified ? 1 : 0);
}
public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
}
public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
}
//略
};
notifyAudioFocusRequest()只是发生了MSG_FOCUS_REQUEST消息。
handleMessage()
private final EventHandler mEventHandler;
private final static int MSG_POLICY_STATUS_CHANGE = 0;
private final static int MSG_FOCUS_GRANT = 1;
private final static int MSG_FOCUS_LOSS = 2;
private final static int MSG_MIX_STATE_UPDATE = 3;
private final static int MSG_FOCUS_REQUEST = 4;
private final static int MSG_FOCUS_ABANDON = 5;
private final static int MSG_VOL_ADJUST = 6;
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:
//是不是很熟悉,CarAudioService中创建和传入的。
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);
} 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);
}
}
}
这里调用了
mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
因此,我们回到Car中的CarAudioService中。
CarAudioService.java
setupDynamicRoutingLocked()
在setupDynamicRoutingLocked()中重点看mFocusHandler的初始化
mFocusHandler = CarZonesAudioFocus.createCarZonesAudioFocus(mAudioManager,
mContext.getPackageManager(),
mCarAudioZones,
mCarAudioSettings,
mCarDucking);
知道,mFocusHandler是CarZonesAudioFocus对象。
CarZonesAudioFocus.java
\packages\services\Car\service\src\com\android\car\audio\CarZonesAudioFocus.java
onAudioFocusRequest()
@Override
public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
int zoneId = getAudioZoneIdForAudioFocusInfo(afi);
//通知焦点回调,这里根据zoneId返回CarAudioFocus
getCarAudioFocusForZoneId(zoneId).onAudioFocusRequest(afi, requestResult);
notifyFocusCallback(new int[]{zoneId});
}
不同zone的焦点配置可能不一样,这里不关注细节。
getCarAudioFocusForZoneId()
@NonNull
private CarAudioFocus getCarAudioFocusForZoneId(int zoneId) {
return mFocusZones.get(zoneId);
}
CarAudioFocus.java
\packages\services\Car\service\src\com\android\car\audio\CarAudioFocus.java
onAudioFocusRequest()
@Override
public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
int response;
AudioPolicy policy;
synchronized (mLock) {
policy = mAudioPolicy;
response = evaluateFocusRequestLocked(afi);
}
//这又回调了AudioManager
mAudioManager.setFocusRequestResult(afi, response, policy);
}
AudioManager.java
setFocusRequestResult.java
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void setFocusRequestResult(@NonNull AudioFocusInfo afi,
@FocusRequestResult int requestResult, @NonNull AudioPolicy ap) {
if (afi == null) {
throw new IllegalArgumentException("Illegal null AudioFocusInfo");
}
if (ap == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy");
}
final IAudioService service = getService();
try {
//调用AudioService.java
service.setFocusRequestResultFromExtPolicy(afi, requestResult, ap.cb());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
AudioService.java
setFocusRequestResultFromExtPolicy()
public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
IAudioPolicyCallback pcb) {
if (afi == null) {
throw new IllegalArgumentException("Illegal null AudioFocusInfo");
}
if (pcb == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy callback");
}
synchronized (mAudioPolicies) {
if (!mAudioPolicies.containsKey(pcb.asBinder())) {
throw new IllegalStateException("Unregistered AudioPolicy for external focus");
}
//进入MediaFocusControl
mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
}
}
MediaFocusControl.java
setFocusRequestResultFromExtPolicy()
void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult) {
synchronized (mExtFocusChangeLock) {
if (afi.getGen() > mExtFocusChangeCounter) {
return;
}
}
final FocusRequester fr;
//失败就移除队列
if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
} else {
fr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
}
//如果不为null,分发结果
if (fr != null) {
fr.dispatchFocusResultFromExtPolicy(requestResult);
}
}
FocusRequester.java
dispatchFocusResultFromExtPolicy()
void dispatchFocusResultFromExtPolicy(int requestResult) {
final IAudioFocusDispatcher fd = mFocusDispatcher;
if (fd == null) {
return;
}
try {
//IAudioFocusDispatcher在AudioManager中有对应的实现类
//也就是请求焦点时传入的mAudioFocusDispatcher
fd.dispatchFocusResultFromExtPolicy(requestResult, mClientId);
} catch (android.os.RemoteException e) {
}
}
mAudioFocusDispatcher前面在AudioManager中有介绍的。
AudioManager.java
mAudioFocusDispatcher
private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
@Override
public void dispatchAudioFocusChange(int focusChange, String id) {
//根据客户端ID查找对应的FocusRequestInfo,这个是一开始注册焦点时放入mAudioFocusIdListenerMap中的。
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, focusChange, 0,id);
h.sendMessage(m);
}
}
}
@Override
public void dispatchFocusResultFromExtPolicy(int requestResult, String clientId) {
synchronized (mFocusRequestsLock) {
//重点
//先从队列中移除,然后返回对应的BlockingFocusResultReceiver
final BlockingFocusResultReceiver focusReceiver =
mFocusRequestsAwaitingResult.remove(clientId);
//不为null,就通知焦点申请requestResult结果
if (focusReceiver != null) {
focusReceiver.notifyResult(requestResult);
} else {
Log.e(TAG, "dispatchFocusResultFromExtPolicy 3 found no result receiver");
}
}
}
};
然后就是进入BlockingFocusResultReceiver中了,最后就是返回焦点申请结果。
至于焦点变化通知,这个后面再单独介绍一下吧。
参考文章
- 《Android 13源码》
