Android 10.0 CarAudioService(二)

前言
1.CarAudioService啟動(dòng)之后調(diào)用init()
2.在init函數(shù)中通過(guò)AudioManager.getDevice獲取了所有的用于輸出的Device,然后把這些device中type是BUS的過(guò)濾出來(lái)
3.然后調(diào)用setupDynamicRouting,這個(gè)方法是設(shè)置動(dòng)態(tài)路由,前面我們分析了setupDynamicRouting的CarAudioZone部分,接下來(lái),我們分析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()
首先看構(gòu)造函數(shù),很簡(jiǎn)單,只是把前面構(gòu)建的carAudioZones保存下來(lái)

    private final CarAudioZone[] mCarAudioZones;

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

2. setupAudioDynamicRouting()
我們進(jìn)入dynamicRouting.setupAudioDynamicRouting(builder);來(lái)看看。
兩個(gè)for循環(huán),外層是mCarAudioZones的循環(huán),我們看內(nèi)層循環(huán),在上一章節(jié)中分析道每一個(gè)zone都包含多個(gè)CarVolumeGroup,在這里我們拿AudioPolicy的builder和CarVolumeGroup傳遞給setupAudioDynamicRoutingForGroup(),接下來(lái)我們需要分析setupAudioDynamicRoutingForGroup()

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

2.1 setupAudioDynamicRoutingForGroup()
最外層是一個(gè)for循環(huán),首先拿到CarVolumeGroup的busNumber,然后根據(jù)busNumber拿到CarAudioDeviceInfo ,拿到CarAudioDeviceInfo 之后,構(gòu)建AudioFormat 和AudioMixingRule,然后進(jìn)入第二層for循環(huán),根據(jù)busNumber拿到 contextNumber,然后根據(jù)contextNumber獲取到usages數(shù)組,拿到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);
            }
        }
    }

我們簡(jiǎn)單總結(jié)一下,首先通過(guò)傳入的mCarAudioZone遍歷其中的每個(gè)CarAudioZone,每個(gè)CarAudioZone又包含一個(gè)CarVolumeGroup的集合,遍歷CarVolumeGroup里面的每個(gè)group,每個(gè)group又包含了一個(gè)device的集合(contextNumber和busNumber組成的map),這樣我們可以通過(guò)busNumber獲取到contextNumber,又可以根據(jù)contextNumber獲取到usages數(shù)組,其實(shí)歸根結(jié)底,我們就是把AudioAttribute的usage數(shù)組和context以及CarAudioDeviceInfo都關(guān)聯(lián)起來(lái)。
AudioMix包含了有usage數(shù)組的mixingRuleBuilder和AudioDeviceInfo,這樣device與usage數(shù)組便對(duì)應(yīng)到一起,在原生的Android里面是通過(guò)stream在AudioPolicyManager的Engine中選擇device,但是Car的這套邏輯是通過(guò)usage和device在上層就配好了,最后addMix就是將audioMix傳遞到AudioPolicy中,然后通過(guò)AudioManager.registerAudioPolicy(mAudioPolicy)注冊(cè)下去。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容