Android13 AudioManager setFocusRequestResult流程分析

当App调用AudioManager的requestAudioFocus方法申请音频焦点时,会通过AudioPolicy.AudioPolicyFocusListener的方式调用到CarZonesAudioFocus的onAudioFocusRequest方法,经过CarZonesAudioFocus对音频焦点进行仲裁后后,再通过CarAudioFocus的setFocusRequestResult通知AudioManager,这时AudioManager的requestAudioFocus方法才会返回处理结果,接下来我们分析AudioManager的setFocusRequestResult方法:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    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(); //取得IAudioService对象
        try {
            service.setFocusRequestResultFromExtPolicy(afi, requestResult, ap.cb()); //调用IAudioService的setFocusRequestResultFromExtPolicy方法
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

调用IAudioService的setFocusRequestResultFromExtPolicy方法,IAudioService是一个接口,由AudioService实现,因此会调用AudioService的setFocusRequestResultFromExtPolicy方法:

//frameworks/base/service/java/com/android/server/audio/AudioService.java
public class AudioService extends IAudioService.Stub
    private final MediaFocusControl mMediaFocusControl;
    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");
            }
            mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult); //调用MediaFocusControl的setFocusRequestResultFromExtPolicy方法
        }
    }
}

调用MediaFocusControl的setFocusRequestResultFromExtPolicy方法:

//frameworks/base/service/java/com/android/server/audio/MediaFocusControl.java
public class MediaFocusControl implements PlayerFocusEnforcer {
    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()); //获取FocusRequester对象
        } else {
            fr = mFocusOwnersForFocusPolicy.get(afi.getClientId()); //获取FocusRequester对象
        }
        if (fr != null) {
            fr.dispatchFocusResultFromExtPolicy(requestResult); //调用FocusRequester的dispatchFocusResultFromExtPolicy方法
        }
    }
}

调用FocusRequester的dispatchFocusResultFromExtPolicy方法:

//frameworks/base/service/java/com/android/server/audio/FocusRequester.java
public class FocusRequester {
    void dispatchFocusResultFromExtPolicy(int requestResult) {
        final IAudioFocusDispatcher fd = mFocusDispatcher;
        if (fd == null) {
            if (MediaFocusControl.DEBUG) {
                Log.e(TAG, "dispatchFocusResultFromExtPolicy: no focus dispatcher");
            }
            return;
        }
        if (DEBUG) {
            Log.v(TAG, "dispatching result" + requestResult + " to " + mClientId);
        }
        try {
            fd.dispatchFocusResultFromExtPolicy(requestResult, mClientId); //调用IAudioFocusDispatcher的dispatchFocusResultFromExtPolicy方法
        } catch (android.os.RemoteException e) {
            Log.e(TAG, "dispatchFocusResultFromExtPolicy: error talking to focus listener"
                    + mClientId, e);
        }
    }
}

调用IAudioFocusDispatcher的dispatchFocusResultFromExtPolicy方法,IAudioFocusDispatcher是一个接口,由AudioManager实现:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
        @Override
        public void dispatchFocusResultFromExtPolicy(int requestResult, String clientId) {
            synchronized (mFocusRequestsLock) {
                // TODO use generation counter as the key instead
                final BlockingFocusResultReceiver focusReceiver =
                        mFocusRequestsAwaitingResult.remove(clientId); 
                if (focusReceiver != null) {
                    focusReceiver.notifyResult(requestResult); //调用BlockingFocusResultReceiver的notifyResult方法
                } else {
                    Log.e(TAG, "dispatchFocusResultFromExtPolicy found no result receiver");
                }
            }
        }
    };
}

调用BlockingFocusResultReceiver的notifyResult方法,BlockingFocusResultReceiver是AudioManager的内部类:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    private static final class BlockingFocusResultReceiver {
        private final SafeWaitObject mLock = new SafeWaitObject();
        @GuardedBy("mLock")
        private boolean mResultReceived = false;
        // request denied by default (e.g. timeout)
        private int mFocusRequestResult = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        private final String mFocusClientId;
  
        void notifyResult(int requestResult) {
            synchronized (mLock) {
                mResultReceived = true;
                mFocusRequestResult = requestResult;
                mLock.safeNotify(); //调用SafeWaitObject 的safeNotify方法,通知锁
            }
        }
    }
}

在AudioManager的requestAudioFocus方法中调用focusReceiver的waitForResult方法等待上面的Notify:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) {
        if (afr == null) {
            throw new NullPointerException("Illegal null AudioFocusRequest");
        }
        // this can only be checked now, not during the creation of the AudioFocusRequest instance
        if (afr.locksFocus() && ap == null) {
            throw new IllegalArgumentException(
                    "Illegal null audio policy when locking audio focus");
        }
        registerAudioFocusRequest(afr);
        final IAudioService service = getService();
        final int status;
        int sdk;
        try {
            sdk = getContext().getApplicationInfo().targetSdkVersion;
        } catch (NullPointerException e) {
            // some tests don't have a Context
            sdk = Build.VERSION.SDK_INT;
        }


        final String clientId = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener());
        final BlockingFocusResultReceiver focusReceiver;
        synchronized (mFocusRequestsLock) {
            try {
                // TODO status contains result and generation counter for ext policy
                status = service.requestAudioFocus(afr.getAudioAttributes(),
                        afr.getFocusGain(), mICallBack,
                        mAudioFocusDispatcher,
                        clientId,
                        getContext().getOpPackageName() /* package name */,
                        getContext().getAttributionTag(),
                        afr.getFlags(),
                        ap != null ? ap.cb() : null,
                        sdk);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) {
                // default path with no external focus policy
                return status;
            }
            if (mFocusRequestsAwaitingResult == null) {
                mFocusRequestsAwaitingResult =
                        new HashMap<String, BlockingFocusResultReceiver>(1);
            }
            focusReceiver = new BlockingFocusResultReceiver(clientId);
            mFocusRequestsAwaitingResult.put(clientId, focusReceiver);
        }
        focusReceiver.waitForResult(EXT_FOCUS_POLICY_TIMEOUT_MS); 
        if (DEBUG && !focusReceiver.receivedResult()) {
            Log.e(TAG, "requestAudio response from ext policy timed out, denying request");
        }
        synchronized (mFocusRequestsLock) {
            mFocusRequestsAwaitingResult.remove(clientId);
        }
        return focusReceiver.requestResult(); //返回焦点申请结果
    }
}

BlockingFocusResultReceiver的waitForResult方法如下:

public class AudioManager {
    private static final class BlockingFocusResultReceiver {
        private final SafeWaitObject mLock = new SafeWaitObject();
        @GuardedBy("mLock")
        private boolean mResultReceived = false;
        // request denied by default (e.g. timeout)
        private int mFocusRequestResult = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        private final String mFocusClientId;


        public void waitForResult(long timeOutMs) {
            synchronized (mLock) {
                if (mResultReceived) {
                    // the result was received before waiting
                    return;
                }
                try {
                    mLock.safeWait(timeOutMs); //调用SafeWaitObject的safeWait,等待锁
                } catch (InterruptedException e) { }
            }
        }
    }
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值