Android 10.0 CarAudioService(二)

前言
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(二))