美文网首页audio
Android 10.0 CarAudioService(二)

Android 10.0 CarAudioService(二)

作者: 棒棒0_0 | 来源:发表于2022-03-26 15:50 被阅读0次

    前言
    1.CarAudioService启动之后调用init()
    2.在init函数中通过AudioManager.getDevice获取了所有的用于输出的Device,然后把这些device中type是BUS的过滤出来
    3.然后调用setupDynamicRouting,这个方法是设置动态路由,前面我们分析了setupDynamicRouting的CarAudioZone部分,接下来,我们分析CarAudioDynamicRouting()

            // Setup dynamic routing rules by usage
            final CarAudioDynamicRouting dynamicRouting = new CarAudioDynamicRouting(mCarAudioZones);
            dynamicRouting.setupAudioDynamicRouting(builder);
    
            // Attach the {@link AudioPolicyVolumeCallback}
            builder.setAudioPolicyVolumeCallback(mAudioPolicyVolumeCallback);
    

    1. CarAudioDynamicRouting()
    首先看构造函数,很简单,只是把前面构建的carAudioZones保存下来

        private final CarAudioZone[] mCarAudioZones;
    
        CarAudioDynamicRouting(CarAudioZone[] carAudioZones) {
            mCarAudioZones = carAudioZones;
        }
    

    2. setupAudioDynamicRouting()
    我们进入dynamicRouting.setupAudioDynamicRouting(builder);来看看。
    两个for循环,外层是mCarAudioZones的循环,我们看内层循环,在上一章节中分析道每一个zone都包含多个CarVolumeGroup,在这里我们拿AudioPolicy的builder和CarVolumeGroup传递给setupAudioDynamicRoutingForGroup(),接下来我们需要分析setupAudioDynamicRoutingForGroup()

        void setupAudioDynamicRouting(AudioPolicy.Builder builder) {
            for (CarAudioZone zone : mCarAudioZones) {
                for (CarVolumeGroup group : zone.getVolumeGroups()) {
                    setupAudioDynamicRoutingForGroup(group, builder);
                }
            }
        }
    

    2.1 setupAudioDynamicRoutingForGroup()
    最外层是一个for循环,首先拿到CarVolumeGroup的busNumber,然后根据busNumber拿到CarAudioDeviceInfo ,拿到CarAudioDeviceInfo 之后,构建AudioFormat 和AudioMixingRule,然后进入第二层for循环,根据busNumber拿到 contextNumber,然后根据contextNumber获取到usages数组,拿到usage之后,便可以mixingRuleBuilder.addRule()

        /**
         * Enumerates all physical buses in a given volume group and attach the mixing rules.
         * @param group {@link CarVolumeGroup} instance to enumerate the buses with
         * @param builder {@link AudioPolicy.Builder} to attach the mixing rules
         */
        private void setupAudioDynamicRoutingForGroup(CarVolumeGroup group,
                AudioPolicy.Builder builder) {
            // Note that one can not register audio mix for same bus more than once.
            for (int busNumber : group.getBusNumbers()) {
                boolean hasContext = false;
                CarAudioDeviceInfo info = group.getCarAudioDeviceInfoForBus(busNumber);
                AudioFormat mixFormat = new AudioFormat.Builder()
                        .setSampleRate(info.getSampleRate())
                        .setEncoding(info.getEncodingFormat())
                        .setChannelMask(info.getChannelCount())
                        .build();
                AudioMixingRule.Builder mixingRuleBuilder = new AudioMixingRule.Builder();
                for (int contextNumber : group.getContextsForBus(busNumber)) {
                    hasContext = true;
                    int[] usages = getUsagesForContext(contextNumber);
                    for (int usage : usages) {
                        mixingRuleBuilder.addRule(
                                new AudioAttributes.Builder().setUsage(usage).build(),
                                AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
                    }
                    Log.d(CarLog.TAG_AUDIO, "Bus number: " + busNumber
                            + " contextNumber: " + contextNumber
                            + " sampleRate: " + info.getSampleRate()
                            + " channels: " + info.getChannelCount()
                            + " usages: " + Arrays.toString(usages));
                }
                if (hasContext) {
                    // It's a valid case that an audio output bus is defined in
                    // audio_policy_configuration and no context is assigned to it.
                    // In such case, do not build a policy mix with zero rules.
                    AudioMix audioMix = new AudioMix.Builder(mixingRuleBuilder.build())
                            .setFormat(mixFormat)
                            .setDevice(info.getAudioDeviceInfo())
                            .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
                            .build();
                    builder.addMix(audioMix);
                }
            }
        }
    

    我们简单总结一下,首先通过传入的mCarAudioZone遍历其中的每个CarAudioZone,每个CarAudioZone又包含一个CarVolumeGroup的集合,遍历CarVolumeGroup里面的每个group,每个group又包含了一个device的集合(contextNumber和busNumber组成的map),这样我们可以通过busNumber获取到contextNumber,又可以根据contextNumber获取到usages数组,其实归根结底,我们就是把AudioAttribute的usage数组和context以及CarAudioDeviceInfo都关联起来。
    AudioMix包含了有usage数组的mixingRuleBuilder和AudioDeviceInfo,这样device与usage数组便对应到一起,在原生的Android里面是通过stream在AudioPolicyManager的Engine中选择device,但是Car的这套逻辑是通过usage和device在上层就配好了,最后addMix就是将audioMix传递到AudioPolicy中,然后通过AudioManager.registerAudioPolicy(mAudioPolicy)注册下去。

    相关文章

      网友评论

        本文标题:Android 10.0 CarAudioService(二)

        本文链接:https://www.haomeiwen.com/subject/pkksjrtx.html