目录
- 前言
- 正文
- AudioManager.java
- 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
requestAudioFocus()
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源码》