Android R- CarAudioService之registerAudioPolicy动态注册(三)

11 篇文章 28 订阅
6 篇文章 15 订阅

前言

最近又隔了好久没有更新了,实在抱歉,简单总结下之前的分析,前面分析了car_audio_configuration.xml的组成以及CarAudioServic如何解析car_audio_configuration.xml和AudioPolicy的构建。其实在CarAudioService中构建完AudioPolicy后就是registerAudioPolicy过程了,今天我们重点看下这部分的源码。

正文

首先简单看下时序图:
在这里插入图片描述
代码setupDynamicRoutingLocked这里我们也七七八八分析差不多了。剩下的就是registerAudioPolicy了

    private void setupDynamicRoutingLocked() {
        final AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
        builder.setLooper(Looper.getMainLooper());
		.......

        // Attach the {@link AudioPolicyVolumeCallback}
        //注册了volume的callback会截断AudioService中adjustVolume的逻辑
        builder.setAudioPolicyVolumeCallback(mAudioPolicyVolumeCallback);

        if (sUseCarAudioFocus) {
            // Configure our AudioPolicy to handle focus events.
            // This gives us the ability to decide which audio focus requests to accept and bypasses
            // the framework ducking logic.
            mFocusHandler = new CarZonesAudioFocus(mAudioManager,
                    mContext.getPackageManager(),
                    mCarAudioZones,
                    mCarAudioSettings, ENABLE_DELAYED_AUDIO_FOCUS);
            //如下两句代码会截断MediaFocusControl中的音频焦点处理逻辑
            builder.setAudioPolicyFocusListener(mFocusHandler);
            builder.setIsAudioFocusPolicy(true);
        }

        mAudioPolicy = builder.build();
		.......
		//注册AudioPolicy
        int r = mAudioManager.registerAudioPolicy(mAudioPolicy);
        if (r != AudioManager.SUCCESS) {
            throw new RuntimeException("registerAudioPolicy failed " + r);
        }
    }

我们继续看下AudioManager中的registerAudioPolicy:

    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public int registerAudioPolicy(@NonNull AudioPolicy policy) {
        return registerAudioPolicyStatic(policy);
    }

函数比较简单,只是简单的一个权限检查,注意这个是一个hide并且system的API,也就是第三方应用是无法调用的,只有定制的系统应用才可使用,继续看下registerAudioPolicyStatic:

    static int registerAudioPolicyStatic(@NonNull AudioPolicy policy) {
        if (policy == null) {
            throw new IllegalArgumentException("Illegal null AudioPolicy argument");
        }
        //拿到AudioService
        final IAudioService service = getService();
        try {
        	// 投屏、录屏相关的,我们在CarAudioService中看到是没有设置的,因此暂不关注
            MediaProjection projection = policy.getMediaProjection();
            //调用AudioService的registerAudioPolicy
            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;
    }

这里简单说下registerAudioPolicy的几个参数:

  • policy.getConfig() 这个是在创建AudioPolicy的时候AudioPolicy内部创建的主要处理AudioMix的。
  • policy.cb() 即 IAudioPolicyCallback,处理AudioPolicy回调的包括音量以及AudioFocus.
  • policy.hasFocusListener() 是否set过setAudioPolicyFocusListener
  • policy.isFocusPolicy() 是否sett过setIsAudioFocusPolicy
  • policy.isTestFocusPolicy() 是否set过setTestFocusPolicy(默认false)
  • policy.isVolumeController()是否set过setAudioPolicyVolumeCallback

到这里AudioManager的部分就结束了。剩下就是AudioService了。我们继续分析AudioService中的registerAudioPolicy
代码很长,摘录核心部分如下:

    public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
            boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
            boolean isVolumeController, IMediaProjection projection) {
			 ......
            try {
            	//创建内部类AudioPolicyProxy
                AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
                        isFocusPolicy, isTestFocusPolicy, isVolumeController, projection);    
                pcb.asBinder().linkToDeath(app, 0/*flags*/);
                regId = app.getRegistrationId();
                //将所有register进来的AudioPolicy放到mAudioPolicies这个map中
                mAudioPolicies.put(pcb.asBinder(), app);
            } catch (RemoteException e) {
                // audio policy owner has already died!
                Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
                        " binder death", e);
                return null;
            } catch (IllegalStateException e) {
                Slog.w(TAG, "Audio policy registration failed for binder " + pcb, e);
                return null;
            }
        }
        return regId;
    }

这里主要就是new一个内部类AudioPolicyProxy,我们继续看下AudioPolicyProxy内部的实现逻辑,代码很长,只有一句主要的核心代码就是

 int status = connectMixes();

connectMixes实际就是将我们设置好的AudioPolicy注册下去到native的AudioPolicy中

        @AudioSystem.AudioSystemError int connectMixes() {
            final long identity = Binder.clearCallingIdentity();
            int status = AudioSystem.registerPolicyMixes(mMixes, true);
            Binder.restoreCallingIdentity(identity);
            return status;
        }

到此AudioPolicy在java层注册逻辑就结束了,后面就是通过JNI到native的逻辑了。

总结

简单总结下这部分逻辑:

  1. 首先CarAudioService将构建好的AudioPolicy注册到AudioService中。
  2. AudioService中同时创建一个AudioPolicyProxy的内部类,并将注册进来的AudioPolicy放到mAudioPolicies中维护。
  3. AudioPolicyProxy在构建的时候会解析AudioPolicy里面的部分参数,比如Volume相关的以及AudioFocus相关的listner并与AudioService中部分模块关联起来。
  4. connectMixes将AudioPolicy继续通过AudioSystem注册下去。
  5. 注册成功将结果反馈给AudioPolicy。

下一章我们开始分析native层的registerAudioPolicy过程,欢迎大家沟通交流喜欢就关注一波吧

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

轻量级LZ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值