Android P的音频架构(三)音频焦点逻辑

一、申请音频焦点的简单用法

private AudioManager mAudioManager;
private AudioAttributes mNavAudioAttrib;

mAudioManager = (AudioManager) mContext.getSystemService( Context.AUDIO_SERVICE );

mNavAudioAttrib = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .build();

try {
   
    AudioFocusRequest naviFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
            .setOnAudioFocusChangeListener(mNavFocusListener)
            .setAudioAttributes(mNavAudioAttrib)
            .setFocusGain(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK).build();
    //申请音频焦点,得到返回结果
    int result = mAudioManager.requestAudioFocus(naviFocusRequest);
} catch (Exception e) {
   
    Log.e(TAG, "Failed to set active focus", e);
}

private final AudioManager.OnAudioFocusChangeListener mNavFocusListener = new AudioManager.OnAudioFocusChangeListener() {
   
   @Override
   public void onAudioFocusChange(int focusChange) {
   
       Log.i(TAG, "Nav focus change:" + focusChange);
       if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
   
            setFocusText(AUDIO_FOCUS_STATE_GAIN);
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
   
            setFocusText("loss");
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
   
            setFocusText("loss,transient");
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
   
            setFocusText("loss,transient,duck");
        }
   }
};

二、系统源码解析

相关源码:
\frameworks\base\media\java\android\media\AudioManager.java
\frameworks\base\services\core\java\com\android\server\audio\AudioService.java
\frameworks\base\services\core\java\com\android\server\audio\MediaFocusControl.java
\frameworks\base\services\core\java\com\android\server\audio\FocusRequester.java

关键接口:
mAudioManager.requestAudioFocus(naviFocusRequest);

    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    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;
       
       	//1.申请音频焦点是多线程异步操作,需要同步锁
        synchronized (mFocusRequestsLock) {
   
            try {
   
            	//2.开始申请音频焦点,status为申请结果;分为内部策略和外部策略
                // TODO status contains result and generation counter for ext policy
                status = service.requestAudioFocus(afr.getAudioAttributes(),
                        afr.getFocusGain(), mICallBack,
                        mAudioFocusDispatcher,
                        clientId,
                        getContext().getOpPackageName() /* package name */, afr.getFlags(),
                        ap != null ? ap.cb() : null,
                        sdk);
            } catch (RemoteException e) {
   
                throw e.rethrowFromSystemServer();
            }
            //3.音频焦点支持外部策略,这里两种结果:一是内部策略,直接返回申请音频焦点的结果status;二是外部策略,返回AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY,申请焦点的结果则由外部策略发送mAudioManager.setFocusRequestResult()来通知。
            if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) {
   
                // default path with no external focus policy
                //如果是内部策略,则直接返回音频焦点结果
                return status;
            }
            //4.外部策略所用的Map,用于保存多个线程申请音频焦点的情况
            if (mFocusRequestsAwaitingResult == null) {
   
                mFocusRequestsAwaitingResult =
                        new HashMap<String, BlockingFocusResultReceiver>(
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaolin2016

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值