前言
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。
(以上,如有问题,欢迎大家指正交流)