Android10.0AudioManager之getDevices(二)

前言

Android10.0AudioManager之getDevices(一)我们分析了获取Audioport以及AudioPatch的过程,今天继续

正文

通过AudioPolicyManager我们拿到了AudioPort和AudioPatch,那么回到AudioManager的updateAudioPortCache的 1.1.3

                for (int i = 0; i < newPatches.size(); i++) {
                    for (int j = 0; j < newPatches.get(i).sources().length; j++) {
                        AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j],
                                                                   newPorts);
                        newPatches.get(i).sources()[j] = portCfg;
                    }
                    for (int j = 0; j < newPatches.get(i).sinks().length; j++) {
                        AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j],
                                                                   newPorts);
                        newPatches.get(i).sinks()[j] = portCfg;
                    }
                }

我们从代码看这部分逻辑是重新赋值newPatches.get(i).sources()[j]和newPatches.get(i).sinks()[j],那么source和sink是什么呢?
我们在分析Android10.0audio_policy_configuration.xml解析的时候,我们分析过mSupportedDevices,它就是这里的sink,它的类型是,DeviceDescriptor : public AudioPort, public AudioPortConfig。我们从继承关系上看即继承了AudioPort又继承了AudioPortConfig。而source是SwAudioOutputDescriptor,也是继承了AudioPortConfig。这部分逻辑可参照AudioPolicyManager的initialize()中的setOutputDevices

uint32_t AudioPolicyManager::setOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
                                              const DeviceVector &devices,
                                              bool force,
                                              int delayMs,
                                              audio_patch_handle_t *patchHandle,
                                              bool requiresMuteCheck)
{
    ALOGV("%s device %s delayMs %d", __func__, devices.toString().c_str(), delayMs);
    uint32_t muteWaitMs;

    if (outputDesc->isDuplicated()) {
        muteWaitMs = setOutputDevices(outputDesc->subOutput1(), devices, force, delayMs,
                nullptr /* patchHandle */, requiresMuteCheck);
        muteWaitMs += setOutputDevices(outputDesc->subOutput2(), devices, force, delayMs,
                nullptr /* patchHandle */, requiresMuteCheck);
        return muteWaitMs;
    }

    // filter devices according to output selected
    DeviceVector filteredDevices = outputDesc->filterSupportedDevices(devices);
    DeviceVector prevDevices = outputDesc->devices();

    // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
    // output profile or if new device is not supported AND previous device(s) is(are) still
    // available (otherwise reset device must be done on the output)
    if (!devices.isEmpty() && filteredDevices.isEmpty() &&
            !mAvailableOutputDevices.filter(prevDevices).empty()) {
        ALOGV("%s: unsupported device %s for output", __func__, devices.toString().c_str());
        return 0;
    }

    ALOGV("setOutputDevices() prevDevice %s", prevDevices.toString().c_str());

    if (!filteredDevices.isEmpty()) {
        outputDesc->setDevices(filteredDevices);
    }

    // if the outputs are not materially active, there is no need to mute.
    if (requiresMuteCheck) {
        muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevices, delayMs);
    } else {
        ALOGV("%s: suppressing checkDeviceMuteStrategies", __func__);
        muteWaitMs = 0;
    }

    // Do not change the routing if:
    //      the requested device is AUDIO_DEVICE_NONE
    //      OR the requested device is the same as current device
    //  AND force is not specified
    //  AND the output is connected by a valid audio patch.
    // Doing this check here allows the caller to call setOutputDevices() without conditions
    if ((filteredDevices.isEmpty() || filteredDevices == prevDevices) &&
            !force && outputDesc->getPatchHandle() != 0) {
        ALOGV("%s setting same device %s or null device, force=%d, patch handle=%d", __func__,
              filteredDevices.toString().c_str(), force, outputDesc->getPatchHandle());
        return muteWaitMs;
    }

    ALOGV("%s changing device to %s", __func__, filteredDevices.toString().c_str());

    // do the routing
    if (filteredDevices.isEmpty()) {
        resetOutputDevice(outputDesc, delayMs, NULL);
    } else {
        PatchBuilder patchBuilder;
        patchBuilder.addSource(outputDesc);
        ALOG_ASSERT(filteredDevices.size() <= AUDIO_PATCH_PORTS_MAX, "Too many sink ports");
        for (const auto &filteredDevice : filteredDevices) {
            patchBuilder.addSource(filteredDevice);
        }

        installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
    }

    // update stream volumes according to new device
    applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);

    return muteWaitMs;
}

其中patchBuilder构建的时候,addSource与addSource传入的便是SwAudioOutputDescriptor和outputDesc->filterSupportedDevices(devices)
这块就不多说了,继续看

            if (ports != null) {
                ports.clear();
                ports.addAll(sAudioPortsCached);
            }
            if (patches != null) {
                patches.clear();
                patches.addAll(sAudioPatchesCached);
            }

由于我们传入的patches为null这里只操作ports,到此java层就通过jni在AudioPolicyManager中拿到了AudioPort,并在java层重新封装了。我们继续filterDevicePorts(ports, devices);也就是上文说的1.2,这里ports是我们从native层获取的,devices是我们要最终拿到的

    private static void filterDevicePorts(ArrayList<AudioPort> ports,
                                          ArrayList<AudioDevicePort> devices) {
        devices.clear();
        for (int i = 0; i < ports.size(); i++) {
            if (ports.get(i) instanceof AudioDevicePort) {
                devices.add((AudioDevicePort)ports.get(i));
            }
        }
    }

代码不是很复杂,只是从AudioPort中过滤出AudioDevicePort,也就是过滤出type为AUDIO_PORT_TYPE_DEVICE的。
回到最后一步infoListFromPortList(ports, flags)

   private static AudioDeviceInfo[]
        infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags) {

        // figure out how many AudioDeviceInfo we need space for...
        int numRecs = 0;
        for (AudioDevicePort port : ports) {
            if (checkTypes(port) && checkFlags(port, flags)) {
                numRecs++;
            }
        }

        // Now load them up...
        AudioDeviceInfo[] deviceList = new AudioDeviceInfo[numRecs];
        int slot = 0;
        for (AudioDevicePort port : ports) {
            if (checkTypes(port) && checkFlags(port, flags)) {
                deviceList[slot++] = new AudioDeviceInfo(port);
            }
        }

        return deviceList;
    }

第一次过滤拿到数量,因为我们知道AudioDevicePort 分output和input,所以这里先根据flag过滤出数量,然后我们再组装我们要的AudioDeviceInfo,最终返回AudioDeviceInfo的lists。

总结

到此,我们AudioManager的getDevices就分析完成了,从AudioManager经过AudioSystem到jni最终再AudioPolicyManager中拿到我们要的AudioPort和AudioPatch,然后再AudioManager根据flag中过滤组装成我们需要的AudioDeviceInfo的list。
(以上,如有问题,欢迎大家指正交流)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

轻量级LZ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值