From 147f5c318877c4fa8afa8e97208c109abf58c1cd Mon Sep 17 00:00:00 2001 From: jiabin Date: Wed, 7 Aug 2019 14:43:33 -0700 Subject: [PATCH 1/5] Return DeviceDescriptor or DeviceVector in Engine. To remove the limit on the number of audio device types, there is a need to remove the return value as a combination of audio_devices_t. Using DeviceDescriptor or DeviceVector in Engine is a starting point. Test: audiopolicy_tests, smoke test Test: CTS for AudioTrack, AudioRecord, AudioManager Bug: 135621476 Change-Id: I0d87fd76385629e6e6b74cdd37dbd334ae02c04f Merged-In: I0d87fd76385629e6e6b74cdd37dbd334ae02c04f --- .../include/DeviceDescriptor.h | 7 + .../src/DeviceDescriptor.cpp | 33 +- .../audiopolicy/enginedefault/src/Engine.cpp | 497 ++++++++---------- .../audiopolicy/enginedefault/src/Engine.h | 11 +- 4 files changed, 262 insertions(+), 286 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index 33e506f1b7..c7c1feed46 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -116,6 +116,13 @@ public: DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const; audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const; + DeviceVector getFirstDevicesFromTypes(std::vector orderedTypes) const; + sp getFirstExistingDevice(std::vector orderedTypes) const; + + // If there are devices with the given type and the devices to add is not empty, + // remove all the devices with the given type and add all the devices to add. + void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd); + bool contains(const sp& item) const { return indexOf(item) >= 0; } /** diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index c996cbf4e3..e395caa6b0 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -255,7 +255,6 @@ DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN; if ((isOutput == curIsOutput) && ((type & curType) != 0)) { devices.add(itemAt(i)); - type &= ~curType; ALOGV("DeviceVector::%s() for type %08x found %p", __func__, itemAt(i)->type(), itemAt(i).get()); } @@ -273,6 +272,38 @@ sp DeviceVector::getDeviceFromTagName(const String8 &tagName) return nullptr; } +DeviceVector DeviceVector::getFirstDevicesFromTypes( + std::vector orderedTypes) const +{ + DeviceVector devices; + for (auto deviceType : orderedTypes) { + if (!(devices = getDevicesFromTypeMask(deviceType)).isEmpty()) { + break; + } + } + return devices; +} + +sp DeviceVector::getFirstExistingDevice( + std::vector orderedTypes) const { + sp device; + for (auto deviceType : orderedTypes) { + if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) { + break; + } + } + return device; +} + +void DeviceVector::replaceDevicesByType( + audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) { + DeviceVector devicesToRemove = getDevicesFromTypeMask(typeToRemove); + if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) { + remove(devicesToRemove); + add(devicesToAdd); + } +} + void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const { if (isEmpty()) { diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index c602f3a19e..cbc46d5324 100644 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -136,27 +136,23 @@ status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced return EngineBase::setForceUse(usage, config); } -audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, - DeviceVector availableOutputDevices, - DeviceVector availableInputDevices, - const SwAudioOutputCollection &outputs, - uint32_t outputDeviceTypesToIgnore) const +DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy, + DeviceVector availableOutputDevices, + DeviceVector availableInputDevices, + const SwAudioOutputCollection &outputs) const { - uint32_t device = AUDIO_DEVICE_NONE; - uint32_t availableOutputDevicesType = - availableOutputDevices.types() & ~outputDeviceTypesToIgnore; + DeviceVector devices; switch (strategy) { case STRATEGY_TRANSMITTED_THROUGH_SPEAKER: - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; + devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER); break; case STRATEGY_SONIFICATION_RESPECTFUL: if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) { - device = getDeviceForStrategyInt( - STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + devices = getDevicesForStrategyInt( + STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs); } else { bool media_active_locally = outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC), @@ -165,17 +161,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, toVolumeSource(AUDIO_STREAM_ACCESSIBILITY), SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY); // routing is same as media without the "remote" device - device = getDeviceForStrategyInt(STRATEGY_MEDIA, + availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_REMOTE_SUBMIX)); + devices = getDevicesForStrategyInt(STRATEGY_MEDIA, availableOutputDevices, - availableInputDevices, outputs, - AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore); + availableInputDevices, outputs); // if no media is playing on the device, check for mandatory use of "safe" speaker // when media would have played on speaker, and the safe speaker path is available - if (!media_active_locally - && (device & AUDIO_DEVICE_OUT_SPEAKER) - && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { - device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; - device &= ~AUDIO_DEVICE_OUT_SPEAKER; + if (!media_active_locally) { + devices.replaceDevicesByType( + AUDIO_DEVICE_OUT_SPEAKER, + availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_SPEAKER_SAFE)); } } break; @@ -183,9 +180,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, case STRATEGY_DTMF: if (!isInCall()) { // when off call, DTMF strategy follows the same rules as MEDIA strategy - device = getDeviceForStrategyInt( - STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + devices = getDevicesForStrategyInt( + STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs); break; } // when in call, DTMF and PHONE strategies follow the same rules @@ -197,24 +193,27 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, // - cannot route from voice call RX OR // - audio HAL version is < 3.0 and TX device is on the primary HW module if (getPhoneState() == AUDIO_MODE_IN_CALL) { - audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); + audio_devices_t txDevice = getDeviceForInputSource( + AUDIO_SOURCE_VOICE_COMMUNICATION)->type(); sp primaryOutput = outputs.getPrimaryOutput(); - audio_devices_t availPrimaryInputDevices = - availableInputDevices.getDeviceTypesFromHwModule(primaryOutput->getModuleHandle()); + DeviceVector availPrimaryInputDevices = + availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle()); // TODO: getPrimaryOutput return only devices from first module in // audio_policy_configuration.xml, hearing aid is not there, but it's // a primary device // FIXME: this is not the right way of solving this problem - audio_devices_t availPrimaryOutputDevices = - (primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) & - availableOutputDevices.types(); - - if (((availableInputDevices.types() & - AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) || - (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) && - (primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) { - availableOutputDevicesType = availPrimaryOutputDevices; + DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask( + primaryOutput->supportedDevices().types()); + availPrimaryOutputDevices.add( + availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID)); + + if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX, + String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) || + ((availPrimaryInputDevices.getDevice( + txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) && + (primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) { + availableOutputDevices = availPrimaryOutputDevices; } } // for phone strategy, we first consider the forced use and then the available devices by @@ -222,49 +221,40 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) { case AUDIO_POLICY_FORCE_BT_SCO: if (!isInCall() || strategy != STRATEGY_DTMF) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; - if (device) break; + devices = availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT); + if (!devices.isEmpty()) break; } - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; - if (device) break; + devices = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO}); + if (!devices.isEmpty()) break; // if SCO device is requested but no SCO device is available, fall back to default case FALLTHROUGH_INTENDED; default: // FORCE_NONE - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID; - if (device) break; + devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID); + if (!devices.isEmpty()) break; // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP if (!isInCall() && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && outputs.isA2dpSupported()) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; - if (device) break; + devices = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}); + if (!devices.isEmpty()) break; } - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; - if (device) break; + devices = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET, + AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET, + AUDIO_DEVICE_OUT_USB_DEVICE}); + if (!devices.isEmpty()) break; if (!isInCall()) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; - if (device) break; + devices = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, + AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET}); + if (!devices.isEmpty()) break; } - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE; + devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE); break; case AUDIO_POLICY_FORCE_SPEAKER: @@ -273,22 +263,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, if (!isInCall() && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && outputs.isA2dpSupported()) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; - if (device) break; + devices = availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER); + if (!devices.isEmpty()) break; } if (!isInCall()) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; - if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; - if (device) break; + devices = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE, + AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL, + AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET}); + if (!devices.isEmpty()) break; } - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; + devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER); break; } break; @@ -298,9 +284,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, // If incall, just select the STRATEGY_PHONE device if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) { - device = getDeviceForStrategyInt( - STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + devices = getDevicesForStrategyInt( + STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs); break; } FALLTHROUGH_INTENDED; @@ -313,41 +298,37 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, if ((strategy == STRATEGY_SONIFICATION) || (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; + devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER); } // if SCO headset is connected and we are told to use it, play ringtone over // speaker and BT SCO - if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) { - uint32_t device2 = AUDIO_DEVICE_NONE; - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; - } + if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) { + DeviceVector devices2; + devices2 = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, + AUDIO_DEVICE_OUT_BLUETOOTH_SCO}); // Use ONLY Bluetooth SCO output when ringing in vibration mode if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) && (strategy == STRATEGY_ENFORCED_AUDIBLE))) { if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING) == AUDIO_POLICY_FORCE_BT_SCO) { - if (device2 != AUDIO_DEVICE_NONE) { - device = device2; + if (!devices2.isEmpty()) { + devices = devices2; break; } } } // Use both Bluetooth SCO and phone default output when ringing in normal mode if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) { - if ((strategy == STRATEGY_SONIFICATION) && - (device & AUDIO_DEVICE_OUT_SPEAKER) && - (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { - device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; - device &= ~AUDIO_DEVICE_OUT_SPEAKER; + if (strategy == STRATEGY_SONIFICATION) { + devices.replaceDevicesByType( + AUDIO_DEVICE_OUT_SPEAKER, + availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_SPEAKER_SAFE)); } - if (device2 != AUDIO_DEVICE_NONE) { - device |= device2; + if (!devices2.isEmpty()) { + devices.add(devices2); break; } } @@ -361,25 +342,20 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, // compressed format as they would likely not be mixed and dropped. for (size_t i = 0; i < outputs.size(); i++) { sp desc = outputs.valueAt(i); - audio_devices_t devices = desc->devices().types() & - (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC); - if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) && - devices != AUDIO_DEVICE_NONE) { - availableOutputDevicesType = availableOutputDevices.types() & ~devices; + if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat)) { + availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF + | AUDIO_DEVICE_OUT_HDMI_ARC)); } } - availableOutputDevices = - availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType); if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) || outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) { - return getDeviceForStrategyInt( - STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + return getDevicesForStrategyInt( + STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs); } if (isInCall()) { - return getDeviceForStrategyInt( - STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + return getDevicesForStrategyInt( + STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs); } } // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA @@ -388,128 +364,116 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now case STRATEGY_REROUTING: case STRATEGY_MEDIA: { - uint32_t device2 = AUDIO_DEVICE_NONE; + DeviceVector devices2; if (strategy != STRATEGY_SONIFICATION) { // no sonification on remote submix (e.g. WFD) - if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, - String8("0"), AUDIO_FORMAT_DEFAULT) != 0) { - device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; + sp remoteSubmix; + if ((remoteSubmix = availableOutputDevices.getDevice( + AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"), + AUDIO_FORMAT_DEFAULT)) != nullptr) { + devices2.add(remoteSubmix); } } if (isInCall() && (strategy == STRATEGY_MEDIA)) { - device = getDeviceForStrategyInt( - STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, - outputDeviceTypesToIgnore); + devices = getDevicesForStrategyInt( + STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs); break; } // FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261). - if ((device2 == AUDIO_DEVICE_NONE) && + if ((devices2.isEmpty()) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID; + devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID); } - if ((device2 == AUDIO_DEVICE_NONE) && + if ((devices2.isEmpty()) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && outputs.isA2dpSupported()) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; - } + devices2 = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}); } - if ((device2 == AUDIO_DEVICE_NONE) && + if ((devices2.isEmpty()) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET; + devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER); } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; + if (devices2.isEmpty()) { + devices2 = availableOutputDevices.getFirstDevicesFromTypes({ + AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_LINE, + AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET, + AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE, + AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET}); } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; - } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; - } - if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { + if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) { // no sonification on aux digital (e.g. HDMI) - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; + devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL); } - if ((device2 == AUDIO_DEVICE_NONE) && + if ((devices2.isEmpty()) && (getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; + devices2 = availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET); } - if (device2 == AUDIO_DEVICE_NONE) { - device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; + if (devices2.isEmpty()) { + devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER); } - int device3 = AUDIO_DEVICE_NONE; + DeviceVector devices3; if (strategy == STRATEGY_MEDIA) { // ARC, SPDIF and AUX_LINE can co-exist with others. - device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC; - device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF); - device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE); + devices3 = availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE); } - device2 |= device3; + devices2.add(devices3); // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise - device |= device2; + devices.add(devices2); // If hdmi system audio mode is on, remove speaker out of output list. if ((strategy == STRATEGY_MEDIA) && (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) == AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { - device &= ~AUDIO_DEVICE_OUT_SPEAKER; + devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER)); } // for STRATEGY_SONIFICATION: // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead - if ((strategy == STRATEGY_SONIFICATION) && - (device & AUDIO_DEVICE_OUT_SPEAKER) && - (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { - device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; - device &= ~AUDIO_DEVICE_OUT_SPEAKER; + if (strategy == STRATEGY_SONIFICATION) { + devices.replaceDevicesByType( + AUDIO_DEVICE_OUT_SPEAKER, + availableOutputDevices.getDevicesFromTypeMask( + AUDIO_DEVICE_OUT_SPEAKER_SAFE)); } } break; default: - ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); + ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy); break; } - if (device == AUDIO_DEVICE_NONE) { - ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy); - device = getApmObserver()->getDefaultOutputDevice()->type(); - ALOGE_IF(device == AUDIO_DEVICE_NONE, - "getDeviceForStrategy() no default device defined"); + if (devices.isEmpty()) { + ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy); + sp defaultOutputDevice = getApmObserver()->getDefaultOutputDevice(); + if (defaultOutputDevice != nullptr) { + devices.add(defaultOutputDevice); + } + ALOGE_IF(devices.isEmpty(), + "getDevicesForStrategy() no default device defined"); } - ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); - return device; + + ALOGVV("getDevices" + "ForStrategy() strategy %d, device %x", strategy, devices.types()); + return devices; } -audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const +sp Engine::getDeviceForInputSource(audio_source_t inputSource) const { const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices(); const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices(); const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs(); - audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; + DeviceVector availableDevices = availableInputDevices; sp primaryOutput = outputs.getPrimaryOutput(); - audio_devices_t availablePrimaryDeviceTypes = availableInputDevices.getDeviceTypesFromHwModule( - primaryOutput->getModuleHandle()) & ~AUDIO_DEVICE_BIT_IN; - uint32_t device = AUDIO_DEVICE_NONE; + DeviceVector availablePrimaryDevices = availableInputDevices.getDevicesFromHwModule( + primaryOutput->getModuleHandle()); + sp device; // when a call is active, force device selection to match source VOICE_COMMUNICATION // for most other input sources to avoid rerouting call TX audio @@ -532,57 +496,47 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons switch (inputSource) { case AUDIO_SOURCE_DEFAULT: case AUDIO_SOURCE_MIC: - if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) { - device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP; - } else if ((getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) && - (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) { - device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { - device = AUDIO_DEVICE_IN_WIRED_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { - device = AUDIO_DEVICE_IN_USB_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { - device = AUDIO_DEVICE_IN_USB_DEVICE; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; - } - break; + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT); + if (device != nullptr) break; + if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) { + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT); + if (device != nullptr) break; + } + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET, + AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC}); + break; case AUDIO_SOURCE_VOICE_COMMUNICATION: // Allow only use of devices on primary input if in call and HAL does not support routing // to voice call path. if ((getPhoneState() == AUDIO_MODE_IN_CALL) && - (availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) { - availableDeviceTypes = availablePrimaryDeviceTypes; + (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX, + String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) { + availableDevices = availablePrimaryDevices; } switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) { case AUDIO_POLICY_FORCE_BT_SCO: // if SCO device is requested but no SCO device is available, fall back to default case - if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { - device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT); + if (device != nullptr) { break; } FALLTHROUGH_INTENDED; default: // FORCE_NONE - if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { - device = AUDIO_DEVICE_IN_WIRED_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { - device = AUDIO_DEVICE_IN_USB_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { - device = AUDIO_DEVICE_IN_USB_DEVICE; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; - } + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET, + AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC}); break; case AUDIO_POLICY_FORCE_SPEAKER: - if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { - device = AUDIO_DEVICE_IN_BACK_MIC; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; - } + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC}); break; } break; @@ -591,77 +545,60 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons case AUDIO_SOURCE_UNPROCESSED: case AUDIO_SOURCE_HOTWORD: if (inputSource == AUDIO_SOURCE_HOTWORD) { - availableDeviceTypes = availablePrimaryDeviceTypes; - } - if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO && - availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { - device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { - device = AUDIO_DEVICE_IN_WIRED_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { - device = AUDIO_DEVICE_IN_USB_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { - device = AUDIO_DEVICE_IN_USB_DEVICE; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; + availableDevices = availablePrimaryDevices; + } + if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) { + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT); + if (device != nullptr) break; } + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET, + AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC}); break; case AUDIO_SOURCE_CAMCORDER: - if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { - device = AUDIO_DEVICE_IN_BACK_MIC; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { - // This is specifically for a device without built-in mic - device = AUDIO_DEVICE_IN_USB_DEVICE; - } + // For a device without built-in mic, adding usb device + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC, + AUDIO_DEVICE_IN_USB_DEVICE}); break; case AUDIO_SOURCE_VOICE_DOWNLINK: case AUDIO_SOURCE_VOICE_CALL: case AUDIO_SOURCE_VOICE_UPLINK: - if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { - device = AUDIO_DEVICE_IN_VOICE_CALL; - } + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT); break; case AUDIO_SOURCE_VOICE_PERFORMANCE: - if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { - device = AUDIO_DEVICE_IN_WIRED_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { - device = AUDIO_DEVICE_IN_USB_HEADSET; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { - device = AUDIO_DEVICE_IN_USB_DEVICE; - } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { - device = AUDIO_DEVICE_IN_BUILTIN_MIC; - } + device = availableDevices.getFirstExistingDevice({ + AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET, + AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC}); break; case AUDIO_SOURCE_REMOTE_SUBMIX: - if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { - device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; - } + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT); break; case AUDIO_SOURCE_FM_TUNER: - if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) { - device = AUDIO_DEVICE_IN_FM_TUNER; - } + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT); break; case AUDIO_SOURCE_ECHO_REFERENCE: - if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) { - device = AUDIO_DEVICE_IN_ECHO_REFERENCE; - } + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT); break; default: ALOGW("getDeviceForInputSource() invalid input source %d", inputSource); break; } - if (device == AUDIO_DEVICE_NONE) { + if (device == nullptr) { ALOGV("getDeviceForInputSource() no device found for source %d", inputSource); - if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) { - device = AUDIO_DEVICE_IN_STUB; - } - ALOGE_IF(device == AUDIO_DEVICE_NONE, + device = availableDevices.getDevice( + AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT); + ALOGE_IF(device == nullptr, "getDeviceForInputSource() no default device defined"); } - ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); + ALOGV_IF(device != nullptr, + "getDeviceForInputSource()input source %d, device %08x", + inputSource, device->type()); return device; } @@ -684,11 +621,9 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) c auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ? mLegacyStrategyMap.at(strategy) : STRATEGY_NONE; - audio_devices_t devices = getDeviceForStrategyInt(legacyStrategy, - availableOutputDevices, - availableInputDevices, outputs, - (uint32_t)AUDIO_DEVICE_NONE); - return availableOutputDevices.getDevicesFromTypeMask(devices); + return getDevicesForStrategyInt(legacyStrategy, + availableOutputDevices, + availableInputDevices, outputs); } DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes, @@ -747,17 +682,21 @@ sp Engine::getInputDeviceForAttributes(const audio_attributes_ if (device != nullptr) { return device; } - audio_devices_t deviceType = getDeviceForInputSource(attr.source); - if (audio_is_remote_submix_device(deviceType)) { - address = "0"; - std::size_t pos; - std::string tags { attr.tags }; - if ((pos = tags.find("addr=")) != std::string::npos) { - address = tags.substr(pos + std::strlen("addr=")); - } + device = getDeviceForInputSource(attr.source); + if (device == nullptr || !audio_is_remote_submix_device(device->type())) { + // Return immediately if the device is null or it is not a remote submix device. + return device; + } + + // For remote submix device, try to find the device by address. + address = "0"; + std::size_t pos; + std::string tags { attr.tags }; + if ((pos = tags.find("addr=")) != std::string::npos) { + address = tags.substr(pos + std::strlen("addr=")); } - return availableInputDevices.getDevice(deviceType, + return availableInputDevices.getDevice(device->type(), String8(address.c_str()), AUDIO_FORMAT_DEFAULT); } diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h index dd1b680c63..4360c6fe66 100644 --- a/services/audiopolicy/enginedefault/src/Engine.h +++ b/services/audiopolicy/enginedefault/src/Engine.h @@ -73,15 +73,14 @@ private: status_t setDefaultDevice(audio_devices_t device); - audio_devices_t getDeviceForStrategyInt(legacy_strategy strategy, - DeviceVector availableOutputDevices, - DeviceVector availableInputDevices, - const SwAudioOutputCollection &outputs, - uint32_t outputDeviceTypesToIgnore) const; + DeviceVector getDevicesForStrategyInt(legacy_strategy strategy, + DeviceVector availableOutputDevices, + DeviceVector availableInputDevices, + const SwAudioOutputCollection &outputs) const; DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const; - audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const; + sp getDeviceForInputSource(audio_source_t inputSource) const; DeviceStrategyMap mDevicesForStrategies; From 59a8759e91d4cd806026fd95e329e9a9d2b14313 Mon Sep 17 00:00:00 2001 From: jiabin Date: Tue, 13 Aug 2019 15:17:08 -0700 Subject: [PATCH 2/5] Preparation for moving AudioProfile to libaudiofoundation. Copy AudioProfile from audio policy to libaudiofoundation. Note that AudioProfile in libaudiofoundation has not been added into the make file as it needs some more change to make it work. Doing this just to make a cleaner diff for later change. Rename AudioProfile in managerdefinitions folder as AudioProfileVector since AudioProfile will be moved to libaudiofoundation. Bug: 135621476 Test: make Change-Id: I13ac067317648bbfd8d3960d16a1ea56ded83011 Merged-In: I13ac067317648bbfd8d3960d16a1ea56ded83011 --- .../libaudiofoundation}/AudioProfile.cpp | 0 .../include/media/AudioProfile.h | 142 +++++ .../common/managerdefinitions/Android.bp | 2 +- .../managerdefinitions/include/AudioPort.h | 2 +- .../{AudioProfile.h => AudioProfileVector.h} | 0 .../src/AudioProfileVector.cpp | 587 ++++++++++++++++++ .../managerdefault/AudioPolicyManager.h | 2 +- 7 files changed, 732 insertions(+), 3 deletions(-) rename {services/audiopolicy/common/managerdefinitions/src => media/libaudiofoundation}/AudioProfile.cpp (100%) create mode 100644 media/libaudiofoundation/include/media/AudioProfile.h rename services/audiopolicy/common/managerdefinitions/include/{AudioProfile.h => AudioProfileVector.h} (100%) create mode 100644 services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp similarity index 100% rename from services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp rename to media/libaudiofoundation/AudioProfile.cpp diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h new file mode 100644 index 0000000000..606e17b1b7 --- /dev/null +++ b/media/libaudiofoundation/include/media/AudioProfile.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if 0 +#pragma once + +#include +#include +#include +#include + +#include "policy.h" + +namespace android { + +class AudioProfile : public virtual RefBase +{ +public: + static sp createFullDynamic(); + + AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); + AudioProfile(audio_format_t format, + const ChannelMaskSet &channelMasks, + const SampleRateSet &samplingRateCollection); + + audio_format_t getFormat() const { return mFormat; } + const ChannelMaskSet &getChannels() const { return mChannelMasks; } + const SampleRateSet &getSampleRates() const { return mSamplingRates; } + void setChannels(const ChannelMaskSet &channelMasks); + void setSampleRates(const SampleRateSet &sampleRates); + + void clear(); + bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); } + bool supportsChannels(audio_channel_mask_t channels) const + { + return mChannelMasks.count(channels) != 0; + } + bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; } + + status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const; + status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask, + audio_channel_mask_t &updatedChannelMask, + audio_port_type_t portType, + audio_port_role_t portRole) const; + status_t checkCompatibleSamplingRate(uint32_t samplingRate, + uint32_t &updatedSamplingRate) const; + + bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; } + bool hasValidRates() const { return !mSamplingRates.empty(); } + bool hasValidChannels() const { return !mChannelMasks.empty(); } + + void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; } + bool isDynamicChannels() const { return mIsDynamicChannels; } + + void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; } + bool isDynamicRate() const { return mIsDynamicRate; } + + void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; } + bool isDynamicFormat() const { return mIsDynamicFormat; } + + bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; } + + void dump(String8 *dst, int spaces) const; + +private: + String8 mName; + audio_format_t mFormat; + ChannelMaskSet mChannelMasks; + SampleRateSet mSamplingRates; + + bool mIsDynamicFormat = false; + bool mIsDynamicChannels = false; + bool mIsDynamicRate = false; +}; + + +class AudioProfileVector : public std::vector > +{ +public: + ssize_t add(const sp &profile); + // This API is intended to be used by the policy manager once retrieving capabilities + // for a profile with dynamic format, rate and channels attributes + ssize_t addProfileFromHal(const sp &profileToAdd); + void appendProfiles(const AudioProfileVector& audioProfiles) { + insert(end(), audioProfiles.begin(), audioProfiles.end()); + } + + status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, + audio_format_t format) const; + status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, + audio_format_t &format, + audio_port_type_t portType, + audio_port_role_t portRole) const; + void clearProfiles(); + // Assuming that this profile vector contains input profiles, + // find the best matching config from 'outputProfiles', according to + // the given preferences for audio formats and channel masks. + // Note: std::vectors are used because specialized containers for formats + // and channels can be sorted and use their own ordering. + status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles, + const std::vector& preferredFormats, // order: most pref -> least pref + const std::vector& preferredOutputChannels, + bool preferHigherSamplingRates, + audio_config_base *bestOutputConfig) const; + + sp getFirstValidProfile() const; + sp getFirstValidProfileFor(audio_format_t format) const; + bool hasValidProfile() const { return getFirstValidProfile() != 0; } + + FormatVector getSupportedFormats() const; + bool hasDynamicChannelsFor(audio_format_t format) const; + bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } + bool hasDynamicProfile() const; + bool hasDynamicRateFor(audio_format_t format) const; + + // One audio profile will be added for each format supported by Audio HAL + void setFormats(const FormatVector &formats); + + void dump(String8 *dst, int spaces) const; + +private: + sp getProfileFor(audio_format_t format) const; + void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format); + void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format); +}; + +bool operator == (const AudioProfile &left, const AudioProfile &right); + +} // namespace android +#endif diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp index ebfba832a8..71d5789d18 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.bp +++ b/services/audiopolicy/common/managerdefinitions/Android.bp @@ -8,7 +8,7 @@ cc_library_static { "src/AudioPatch.cpp", "src/AudioPolicyMix.cpp", "src/AudioPort.cpp", - "src/AudioProfile.cpp", + "src/AudioProfileVector.cpp", "src/AudioRoute.cpp", "src/ClientDescriptor.cpp", "src/DeviceDescriptor.cpp", diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h index 641cebfce4..ccbf2f3be2 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h @@ -17,7 +17,7 @@ #pragma once #include "AudioCollections.h" -#include "AudioProfile.h" +#include "AudioProfileVector.h" #include "HandleGenerator.h" #include #include diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h similarity index 100% rename from services/audiopolicy/common/managerdefinitions/include/AudioProfile.h rename to services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp new file mode 100644 index 0000000000..b0503bb33b --- /dev/null +++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#define LOG_TAG "APM::AudioProfile" +//#define LOG_NDEBUG 0 + +#include +#include +#include + +#include "AudioPort.h" +#include "AudioProfileVector.h" +#include "HwModule.h" +#include "TypeConverter.h" + +namespace android { + +bool operator == (const AudioProfile &left, const AudioProfile &compareTo) +{ + return (left.getFormat() == compareTo.getFormat()) && + (left.getChannels() == compareTo.getChannels()) && + (left.getSampleRates() == compareTo.getSampleRates()); +} + +static AudioProfile* createFullDynamicImpl() +{ + AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat, + ChannelMaskSet(), SampleRateSet()); + dynamicProfile->setDynamicFormat(true); + dynamicProfile->setDynamicChannels(true); + dynamicProfile->setDynamicRate(true); + return dynamicProfile; +} + +// static +sp AudioProfile::createFullDynamic() +{ + static sp dynamicProfile = createFullDynamicImpl(); + return dynamicProfile; +} + +AudioProfile::AudioProfile(audio_format_t format, + audio_channel_mask_t channelMasks, + uint32_t samplingRate) : + mName(String8("")), + mFormat(format) +{ + mChannelMasks.insert(channelMasks); + mSamplingRates.insert(samplingRate); +} + +AudioProfile::AudioProfile(audio_format_t format, + const ChannelMaskSet &channelMasks, + const SampleRateSet &samplingRateCollection) : + mName(String8("")), + mFormat(format), + mChannelMasks(channelMasks), + mSamplingRates(samplingRateCollection) {} + +void AudioProfile::setChannels(const ChannelMaskSet &channelMasks) +{ + if (mIsDynamicChannels) { + mChannelMasks = channelMasks; + } +} + +void AudioProfile::setSampleRates(const SampleRateSet &sampleRates) +{ + if (mIsDynamicRate) { + mSamplingRates = sampleRates; + } +} + +void AudioProfile::clear() +{ + if (mIsDynamicChannels) { + mChannelMasks.clear(); + } + if (mIsDynamicRate) { + mSamplingRates.clear(); + } +} + +status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, + audio_format_t format) const +{ + if (audio_formats_match(format, mFormat) && + supportsChannels(channelMask) && + supportsRate(samplingRate)) { + return NO_ERROR; + } + return BAD_VALUE; +} + +status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, + uint32_t &updatedSamplingRate) const +{ + ALOG_ASSERT(samplingRate > 0); + + if (mSamplingRates.empty()) { + updatedSamplingRate = samplingRate; + return NO_ERROR; + } + + // Search for the closest supported sampling rate that is above (preferred) + // or below (acceptable) the desired sampling rate, within a permitted ratio. + // The sampling rates are sorted in ascending order. + auto desiredRate = mSamplingRates.lower_bound(samplingRate); + + // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. + if (desiredRate != mSamplingRates.end()) { + if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { + updatedSamplingRate = *desiredRate; + return NO_ERROR; + } + } + // But if we have to up-sample from a lower sampling rate, that's OK. + if (desiredRate != mSamplingRates.begin()) { + uint32_t candidate = *(--desiredRate); + if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { + updatedSamplingRate = candidate; + return NO_ERROR; + } + } + // leave updatedSamplingRate unmodified + return BAD_VALUE; +} + +status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, + audio_channel_mask_t &updatedChannelMask, + audio_port_type_t portType, + audio_port_role_t portRole) const +{ + if (mChannelMasks.empty()) { + updatedChannelMask = channelMask; + return NO_ERROR; + } + const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK; + const bool isIndex = audio_channel_mask_get_representation(channelMask) + == AUDIO_CHANNEL_REPRESENTATION_INDEX; + const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); + int bestMatch = 0; + for (const auto &supported : mChannelMasks) { + if (supported == channelMask) { + // Exact matches always taken. + updatedChannelMask = channelMask; + return NO_ERROR; + } + + // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support + if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { + // Approximate (best) match: + // The match score measures how well the supported channel mask matches the + // desired mask, where increasing-is-better. + // + // TODO: Some tweaks may be needed. + // Should be a static function of the data processing library. + // + // In priority: + // match score = 1000 if legacy channel conversion equivalent (always prefer this) + // OR + // match score += 100 if the channel mask representations match + // match score += number of channels matched. + // match score += 100 if the channel mask representations DO NOT match + // but the profile has positional channel mask and less than 2 channels. + // This is for audio HAL convention to not list index masks for less than 2 channels + // + // If there are no matched channels, the mask may still be accepted + // but the playback or record will be silent. + const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) + == AUDIO_CHANNEL_REPRESENTATION_INDEX); + const uint32_t supportedChannelCount = audio_channel_count_from_in_mask(supported); + int match; + if (isIndex && isSupportedIndex) { + // index equivalence + match = 100 + __builtin_popcount( + audio_channel_mask_get_bits(channelMask) + & audio_channel_mask_get_bits(supported)); + } else if (isIndex && !isSupportedIndex) { + const uint32_t equivalentBits = (1 << supportedChannelCount) - 1 ; + match = __builtin_popcount( + audio_channel_mask_get_bits(channelMask) & equivalentBits); + if (supportedChannelCount <= FCC_2) { + match += 100; + } + } else if (!isIndex && isSupportedIndex) { + const uint32_t equivalentBits = (1 << channelCount) - 1; + match = __builtin_popcount( + equivalentBits & audio_channel_mask_get_bits(supported)); + } else { + // positional equivalence + match = 100 + __builtin_popcount( + audio_channel_mask_get_bits(channelMask) + & audio_channel_mask_get_bits(supported)); + switch (supported) { + case AUDIO_CHANNEL_IN_FRONT_BACK: + case AUDIO_CHANNEL_IN_STEREO: + if (channelMask == AUDIO_CHANNEL_IN_MONO) { + match = 1000; + } + break; + case AUDIO_CHANNEL_IN_MONO: + if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK + || channelMask == AUDIO_CHANNEL_IN_STEREO) { + match = 1000; + } + break; + default: + break; + } + } + if (match > bestMatch) { + bestMatch = match; + updatedChannelMask = supported; + } + } + } + return bestMatch > 0 ? NO_ERROR : BAD_VALUE; +} + +void AudioProfile::dump(String8 *dst, int spaces) const +{ + dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", + mIsDynamicChannels ? "[dynamic channels]" : "", + mIsDynamicRate ? "[dynamic rates]" : ""); + if (mName.length() != 0) { + dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string()); + } + std::string formatLiteral; + if (FormatConverter::toString(mFormat, formatLiteral)) { + dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str()); + } + if (!mSamplingRates.empty()) { + dst->appendFormat("%*s- sampling rates:", spaces, ""); + for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) { + dst->appendFormat("%d", *it); + dst->append(++it == mSamplingRates.end() ? "" : ", "); + } + dst->append("\n"); + } + + if (!mChannelMasks.empty()) { + dst->appendFormat("%*s- channel masks:", spaces, ""); + for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) { + dst->appendFormat("0x%04x", *it); + dst->append(++it == mChannelMasks.end() ? "" : ", "); + } + dst->append("\n"); + } +} + +ssize_t AudioProfileVector::add(const sp &profile) +{ + ssize_t index = size(); + push_back(profile); + // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. + std::sort(begin(), end(), + [](const sp & a, const sp & b) + { + return AudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0; + }); + return index; +} + +ssize_t AudioProfileVector::addProfileFromHal(const sp &profileToAdd) +{ + // Check valid profile to add: + if (!profileToAdd->hasValidFormat()) { + return -1; + } + if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { + FormatVector formats; + formats.push_back(profileToAdd->getFormat()); + setFormats(FormatVector(formats)); + return 0; + } + if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { + setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); + return 0; + } + if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { + setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); + return 0; + } + // Go through the list of profile to avoid duplicates + for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { + const sp &profile = at(profileIndex); + if (profile->isValid() && profile == profileToAdd) { + // Nothing to do + return profileIndex; + } + } + profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal + return add(profileToAdd); +} + +status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, + audio_channel_mask_t channelMask, + audio_format_t format) const +{ + if (empty()) { + return NO_ERROR; + } + + for (const auto& profile : *this) { + if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { + return NO_ERROR; + } + } + return BAD_VALUE; +} + +status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, + audio_channel_mask_t &channelMask, + audio_format_t &format, + audio_port_type_t portType, + audio_port_role_t portRole) const +{ + if (empty()) { + return NO_ERROR; + } + + const bool checkInexact = // when port is input and format is linear pcm + portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK + && audio_is_linear_pcm(format); + + // iterate from best format to worst format (reverse order) + for (ssize_t i = size() - 1; i >= 0 ; --i) { + const sp profile = at(i); + audio_format_t formatToCompare = profile->getFormat(); + if (formatToCompare == format || + (checkInexact + && formatToCompare != AUDIO_FORMAT_DEFAULT + && audio_is_linear_pcm(formatToCompare))) { + // Compatible profile has been found, checks if this profile has compatible + // rate and channels as well + audio_channel_mask_t updatedChannels; + uint32_t updatedRate; + if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, + portType, portRole) == NO_ERROR && + profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { + // for inexact checks we take the first linear pcm format due to sorting. + format = formatToCompare; + channelMask = updatedChannels; + samplingRate = updatedRate; + return NO_ERROR; + } + } + } + return BAD_VALUE; +} + +void AudioProfileVector::clearProfiles() +{ + for (auto it = begin(); it != end();) { + if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) { + it = erase(it); + } else { + (*it)->clear(); + ++it; + } + } +} + +// Returns an intersection between two possibly unsorted vectors and the contents of 'order'. +// The result is ordered according to 'order'. +template +std::vector intersectFilterAndOrder( + const T& input1, const T& input2, const Order& order) +{ + std::set set1{input1.begin(), input1.end()}; + std::set set2{input2.begin(), input2.end()}; + std::set common; + std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), + std::inserter(common, common.begin())); + std::vector result; + for (const auto& e : order) { + if (common.find(e) != common.end()) result.push_back(e); + } + return result; +} + +// Intersect two possibly unsorted vectors, return common elements according to 'comp' ordering. +// 'comp' is a comparator function. +template +std::vector intersectAndOrder( + const T& input1, const T& input2, Compare comp) +{ + std::set set1{input1.begin(), input1.end(), comp}; + std::set set2{input2.begin(), input2.end(), comp}; + std::vector result; + std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), + std::back_inserter(result), comp); + return result; +} + +status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles, + const std::vector& preferredFormats, + const std::vector& preferredOutputChannels, + bool preferHigherSamplingRates, + audio_config_base *bestOutputConfig) const +{ + auto formats = intersectFilterAndOrder(getSupportedFormats(), + outputProfiles.getSupportedFormats(), preferredFormats); + // Pick the best compatible profile. + for (const auto& f : formats) { + sp inputProfile = getFirstValidProfileFor(f); + sp outputProfile = outputProfiles.getFirstValidProfileFor(f); + if (inputProfile == nullptr || outputProfile == nullptr) { + continue; + } + auto channels = intersectFilterAndOrder(asOutMask(inputProfile->getChannels()), + outputProfile->getChannels(), preferredOutputChannels); + if (channels.empty()) { + continue; + } + auto sampleRates = preferHigherSamplingRates ? + intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(), + std::greater()) : + intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(), + std::less()); + if (sampleRates.empty()) { + continue; + } + ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.", + __func__, *channels.begin(), *sampleRates.begin(), f); + bestOutputConfig->format = f; + bestOutputConfig->sample_rate = *sampleRates.begin(); + bestOutputConfig->channel_mask = *channels.begin(); + return NO_ERROR; + } + return BAD_VALUE; +} + +sp AudioProfileVector::getFirstValidProfile() const +{ + for (const auto &profile : *this) { + if (profile->isValid()) { + return profile; + } + } + return nullptr; +} + +sp AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const +{ + for (const auto &profile : *this) { + if (profile->isValid() && profile->getFormat() == format) { + return profile; + } + } + return nullptr; +} + +FormatVector AudioProfileVector::getSupportedFormats() const +{ + FormatVector supportedFormats; + for (const auto &profile : *this) { + if (profile->hasValidFormat()) { + supportedFormats.push_back(profile->getFormat()); + } + } + return supportedFormats; +} + +bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const +{ + for (const auto &profile : *this) { + if (profile->getFormat() == format && profile->isDynamicChannels()) { + return true; + } + } + return false; +} + +bool AudioProfileVector::hasDynamicProfile() const +{ + for (const auto &profile : *this) { + if (profile->isDynamic()) { + return true; + } + } + return false; +} + +bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const +{ + for (const auto &profile : *this) { + if (profile->getFormat() == format && profile->isDynamicRate()) { + return true; + } + } + return false; +} + +void AudioProfileVector::setFormats(const FormatVector &formats) +{ + // Only allow to change the format of dynamic profile + sp dynamicFormatProfile = getProfileFor(gDynamicFormat); + if (dynamicFormatProfile == 0) { + return; + } + for (const auto &format : formats) { + sp profile = new AudioProfile(format, + dynamicFormatProfile->getChannels(), + dynamicFormatProfile->getSampleRates()); + profile->setDynamicFormat(true); + profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); + profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); + add(profile); + } +} + +void AudioProfileVector::dump(String8 *dst, int spaces) const +{ + dst->appendFormat("%*s- Profiles:\n", spaces, ""); + for (size_t i = 0; i < size(); i++) { + dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i); + at(i)->dump(dst, spaces + 8); + } +} + +sp AudioProfileVector::getProfileFor(audio_format_t format) const +{ + for (const auto &profile : *this) { + if (profile->getFormat() == format) { + return profile; + } + } + return nullptr; +} + +void AudioProfileVector::setSampleRatesFor( + const SampleRateSet &sampleRates, audio_format_t format) +{ + for (const auto &profile : *this) { + if (profile->getFormat() == format && profile->isDynamicRate()) { + if (profile->hasValidRates()) { + // Need to create a new profile with same format + sp profileToAdd = new AudioProfile(format, profile->getChannels(), + sampleRates); + profileToAdd->setDynamicFormat(true); // need to set to allow cleaning + add(profileToAdd); + } else { + profile->setSampleRates(sampleRates); + } + return; + } + } +} + +void AudioProfileVector::setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format) +{ + for (const auto &profile : *this) { + if (profile->getFormat() == format && profile->isDynamicChannels()) { + if (profile->hasValidChannels()) { + // Need to create a new profile with same format + sp profileToAdd = new AudioProfile(format, channelMasks, + profile->getSampleRates()); + profileToAdd->setDynamicFormat(true); // need to set to allow cleaning + add(profileToAdd); + } else { + profile->setChannels(channelMasks); + } + return; + } + } +} + +} // namespace android diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 02c6171593..4270aa87be 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include From b677643c52cec078ae2f25eeabb6350f6b32010a Mon Sep 17 00:00:00 2001 From: jiabin Date: Mon, 19 Aug 2019 10:10:17 -0700 Subject: [PATCH 3/5] Make AudioProfile as a common class and create AudioProfileVectorBase. AudioProfile is a class that contains information for an audio profile. AudioProfileVectorBase is a base class that contains operations for a vector of audio profiles. AudioProfileVector derives from AudioProfileVectorBase and contains policy related stuff. Bug: 135621476 Test: CTS for AudioRecord, AudioTrack, AudioManager Test: audio smoke test, audiopolicy_tests Test: dumpsys media.audio_policy Change-Id: Ic2e08efcc5efa99e499a931811b7042fbd5ddf04 Merged-In: Ic2e08efcc5efa99e499a931811b7042fbd5ddf04 --- media/libaudiofoundation/Android.bp | 3 + media/libaudiofoundation/AudioProfile.cpp | 449 ++---------------- .../include/media/AudioProfile.h | 72 +-- .../include/AudioPolicyConfig.h | 5 +- .../include/AudioProfileVector.h | 105 +--- .../managerdefinitions/include/IOProfile.h | 1 + .../managerdefinitions/src/AudioPort.cpp | 4 +- .../src/AudioProfileVector.cpp | 229 ++------- .../managerdefinitions/src/Serializer.cpp | 4 +- 9 files changed, 115 insertions(+), 757 deletions(-) diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp index 5045d8762f..2ea2c10f08 100644 --- a/media/libaudiofoundation/Android.bp +++ b/media/libaudiofoundation/Android.bp @@ -10,17 +10,20 @@ cc_library_shared { srcs: [ "AudioGain.cpp", + "AudioProfile.cpp", ], shared_libs: [ "libbase", "libbinder", "liblog", + "libmedia_helper", "libutils", ], header_libs: [ "libaudio_system_headers", + "libaudioclient_headers", "libaudiofoundation_headers", ], diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp index d1082e8a77..aaaa7d16cb 100644 --- a/media/libaudiofoundation/AudioProfile.cpp +++ b/media/libaudiofoundation/AudioProfile.cpp @@ -14,34 +14,30 @@ * limitations under the License. */ -#include #include -#include -#define LOG_TAG "APM::AudioProfile" +#define LOG_TAG "AudioProfile" //#define LOG_NDEBUG 0 +#include #include -#include +#include +#include #include -#include "AudioPort.h" -#include "AudioProfile.h" -#include "HwModule.h" -#include "TypeConverter.h" - namespace android { -bool operator == (const AudioProfile &left, const AudioProfile &compareTo) +bool operator == (const AudioProfile &left, const AudioProfile &right) { - return (left.getFormat() == compareTo.getFormat()) && - (left.getChannels() == compareTo.getChannels()) && - (left.getSampleRates() == compareTo.getSampleRates()); + return (left.getFormat() == right.getFormat()) && + (left.getChannels() == right.getChannels()) && + (left.getSampleRates() == right.getSampleRates()); } -static AudioProfile* createFullDynamicImpl() +// static +sp AudioProfile::createFullDynamic(audio_format_t dynamicFormat) { - AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat, + AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat, ChannelMaskSet(), SampleRateSet()); dynamicProfile->setDynamicFormat(true); dynamicProfile->setDynamicChannels(true); @@ -49,17 +45,10 @@ static AudioProfile* createFullDynamicImpl() return dynamicProfile; } -// static -sp AudioProfile::createFullDynamic() -{ - static sp dynamicProfile = createFullDynamicImpl(); - return dynamicProfile; -} - AudioProfile::AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate) : - mName(String8("")), + mName(""), mFormat(format) { mChannelMasks.insert(channelMasks); @@ -69,7 +58,7 @@ AudioProfile::AudioProfile(audio_format_t format, AudioProfile::AudioProfile(audio_format_t format, const ChannelMaskSet &channelMasks, const SampleRateSet &samplingRateCollection) : - mName(String8("")), + mName(""), mFormat(format), mChannelMasks(channelMasks), mSamplingRates(samplingRateCollection) {} @@ -98,276 +87,45 @@ void AudioProfile::clear() } } -status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, - audio_format_t format) const -{ - if (audio_formats_match(format, mFormat) && - supportsChannels(channelMask) && - supportsRate(samplingRate)) { - return NO_ERROR; - } - return BAD_VALUE; -} - -status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, - uint32_t &updatedSamplingRate) const -{ - ALOG_ASSERT(samplingRate > 0); - - if (mSamplingRates.empty()) { - updatedSamplingRate = samplingRate; - return NO_ERROR; - } - - // Search for the closest supported sampling rate that is above (preferred) - // or below (acceptable) the desired sampling rate, within a permitted ratio. - // The sampling rates are sorted in ascending order. - auto desiredRate = mSamplingRates.lower_bound(samplingRate); - - // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. - if (desiredRate != mSamplingRates.end()) { - if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { - updatedSamplingRate = *desiredRate; - return NO_ERROR; - } - } - // But if we have to up-sample from a lower sampling rate, that's OK. - if (desiredRate != mSamplingRates.begin()) { - uint32_t candidate = *(--desiredRate); - if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { - updatedSamplingRate = candidate; - return NO_ERROR; - } - } - // leave updatedSamplingRate unmodified - return BAD_VALUE; -} - -status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, - audio_channel_mask_t &updatedChannelMask, - audio_port_type_t portType, - audio_port_role_t portRole) const -{ - if (mChannelMasks.empty()) { - updatedChannelMask = channelMask; - return NO_ERROR; - } - const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK; - const bool isIndex = audio_channel_mask_get_representation(channelMask) - == AUDIO_CHANNEL_REPRESENTATION_INDEX; - const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); - int bestMatch = 0; - for (const auto &supported : mChannelMasks) { - if (supported == channelMask) { - // Exact matches always taken. - updatedChannelMask = channelMask; - return NO_ERROR; - } - - // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support - if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { - // Approximate (best) match: - // The match score measures how well the supported channel mask matches the - // desired mask, where increasing-is-better. - // - // TODO: Some tweaks may be needed. - // Should be a static function of the data processing library. - // - // In priority: - // match score = 1000 if legacy channel conversion equivalent (always prefer this) - // OR - // match score += 100 if the channel mask representations match - // match score += number of channels matched. - // match score += 100 if the channel mask representations DO NOT match - // but the profile has positional channel mask and less than 2 channels. - // This is for audio HAL convention to not list index masks for less than 2 channels - // - // If there are no matched channels, the mask may still be accepted - // but the playback or record will be silent. - const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) - == AUDIO_CHANNEL_REPRESENTATION_INDEX); - const uint32_t supportedChannelCount = audio_channel_count_from_in_mask(supported); - int match; - if (isIndex && isSupportedIndex) { - // index equivalence - match = 100 + __builtin_popcount( - audio_channel_mask_get_bits(channelMask) - & audio_channel_mask_get_bits(supported)); - } else if (isIndex && !isSupportedIndex) { - const uint32_t equivalentBits = (1 << supportedChannelCount) - 1 ; - match = __builtin_popcount( - audio_channel_mask_get_bits(channelMask) & equivalentBits); - if (supportedChannelCount <= FCC_2) { - match += 100; - } - } else if (!isIndex && isSupportedIndex) { - const uint32_t equivalentBits = (1 << channelCount) - 1; - match = __builtin_popcount( - equivalentBits & audio_channel_mask_get_bits(supported)); - } else { - // positional equivalence - match = 100 + __builtin_popcount( - audio_channel_mask_get_bits(channelMask) - & audio_channel_mask_get_bits(supported)); - switch (supported) { - case AUDIO_CHANNEL_IN_FRONT_BACK: - case AUDIO_CHANNEL_IN_STEREO: - if (channelMask == AUDIO_CHANNEL_IN_MONO) { - match = 1000; - } - break; - case AUDIO_CHANNEL_IN_MONO: - if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK - || channelMask == AUDIO_CHANNEL_IN_STEREO) { - match = 1000; - } - break; - default: - break; - } - } - if (match > bestMatch) { - bestMatch = match; - updatedChannelMask = supported; - } - } - } - return bestMatch > 0 ? NO_ERROR : BAD_VALUE; -} - -void AudioProfile::dump(String8 *dst, int spaces) const +void AudioProfile::dump(std::string *dst, int spaces) const { - dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", + dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", mIsDynamicChannels ? "[dynamic channels]" : "", - mIsDynamicRate ? "[dynamic rates]" : ""); + mIsDynamicRate ? "[dynamic rates]" : "")); if (mName.length() != 0) { - dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string()); + dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str())); } std::string formatLiteral; if (FormatConverter::toString(mFormat, formatLiteral)) { - dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str()); + dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str())); } if (!mSamplingRates.empty()) { - dst->appendFormat("%*s- sampling rates:", spaces, ""); + dst->append(base::StringPrintf("%*s- sampling rates:", spaces, "")); for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) { - dst->appendFormat("%d", *it); + dst->append(base::StringPrintf("%d", *it)); dst->append(++it == mSamplingRates.end() ? "" : ", "); } dst->append("\n"); } if (!mChannelMasks.empty()) { - dst->appendFormat("%*s- channel masks:", spaces, ""); + dst->append(base::StringPrintf("%*s- channel masks:", spaces, "")); for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) { - dst->appendFormat("0x%04x", *it); + dst->append(base::StringPrintf("0x%04x", *it)); dst->append(++it == mChannelMasks.end() ? "" : ", "); } dst->append("\n"); } } -ssize_t AudioProfileVector::add(const sp &profile) +ssize_t AudioProfileVectorBase::add(const sp &profile) { ssize_t index = size(); push_back(profile); - // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. - std::sort(begin(), end(), - [](const sp & a, const sp & b) - { - return AudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0; - }); return index; } -ssize_t AudioProfileVector::addProfileFromHal(const sp &profileToAdd) -{ - // Check valid profile to add: - if (!profileToAdd->hasValidFormat()) { - return -1; - } - if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { - FormatVector formats; - formats.push_back(profileToAdd->getFormat()); - setFormats(FormatVector(formats)); - return 0; - } - if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { - setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); - return 0; - } - if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { - setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); - return 0; - } - // Go through the list of profile to avoid duplicates - for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { - const sp &profile = at(profileIndex); - if (profile->isValid() && profile == profileToAdd) { - // Nothing to do - return profileIndex; - } - } - profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal - return add(profileToAdd); -} - -status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, - audio_channel_mask_t channelMask, - audio_format_t format) const -{ - if (empty()) { - return NO_ERROR; - } - - for (const auto& profile : *this) { - if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { - return NO_ERROR; - } - } - return BAD_VALUE; -} - -status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, - audio_channel_mask_t &channelMask, - audio_format_t &format, - audio_port_type_t portType, - audio_port_role_t portRole) const -{ - if (empty()) { - return NO_ERROR; - } - - const bool checkInexact = // when port is input and format is linear pcm - portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK - && audio_is_linear_pcm(format); - - // iterate from best format to worst format (reverse order) - for (ssize_t i = size() - 1; i >= 0 ; --i) { - const sp profile = at(i); - audio_format_t formatToCompare = profile->getFormat(); - if (formatToCompare == format || - (checkInexact - && formatToCompare != AUDIO_FORMAT_DEFAULT - && audio_is_linear_pcm(formatToCompare))) { - // Compatible profile has been found, checks if this profile has compatible - // rate and channels as well - audio_channel_mask_t updatedChannels; - uint32_t updatedRate; - if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, - portType, portRole) == NO_ERROR && - profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { - // for inexact checks we take the first linear pcm format due to sorting. - format = formatToCompare; - channelMask = updatedChannels; - samplingRate = updatedRate; - return NO_ERROR; - } - } - } - return BAD_VALUE; -} - -void AudioProfileVector::clearProfiles() +void AudioProfileVectorBase::clearProfiles() { for (auto it = begin(); it != end();) { if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) { @@ -379,77 +137,7 @@ void AudioProfileVector::clearProfiles() } } -// Returns an intersection between two possibly unsorted vectors and the contents of 'order'. -// The result is ordered according to 'order'. -template -std::vector intersectFilterAndOrder( - const T& input1, const T& input2, const Order& order) -{ - std::set set1{input1.begin(), input1.end()}; - std::set set2{input2.begin(), input2.end()}; - std::set common; - std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), - std::inserter(common, common.begin())); - std::vector result; - for (const auto& e : order) { - if (common.find(e) != common.end()) result.push_back(e); - } - return result; -} - -// Intersect two possibly unsorted vectors, return common elements according to 'comp' ordering. -// 'comp' is a comparator function. -template -std::vector intersectAndOrder( - const T& input1, const T& input2, Compare comp) -{ - std::set set1{input1.begin(), input1.end(), comp}; - std::set set2{input2.begin(), input2.end(), comp}; - std::vector result; - std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), - std::back_inserter(result), comp); - return result; -} - -status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles, - const std::vector& preferredFormats, - const std::vector& preferredOutputChannels, - bool preferHigherSamplingRates, - audio_config_base *bestOutputConfig) const -{ - auto formats = intersectFilterAndOrder(getSupportedFormats(), - outputProfiles.getSupportedFormats(), preferredFormats); - // Pick the best compatible profile. - for (const auto& f : formats) { - sp inputProfile = getFirstValidProfileFor(f); - sp outputProfile = outputProfiles.getFirstValidProfileFor(f); - if (inputProfile == nullptr || outputProfile == nullptr) { - continue; - } - auto channels = intersectFilterAndOrder(asOutMask(inputProfile->getChannels()), - outputProfile->getChannels(), preferredOutputChannels); - if (channels.empty()) { - continue; - } - auto sampleRates = preferHigherSamplingRates ? - intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(), - std::greater()) : - intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(), - std::less()); - if (sampleRates.empty()) { - continue; - } - ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.", - __func__, *channels.begin(), *sampleRates.begin(), f); - bestOutputConfig->format = f; - bestOutputConfig->sample_rate = *sampleRates.begin(); - bestOutputConfig->channel_mask = *channels.begin(); - return NO_ERROR; - } - return BAD_VALUE; -} - -sp AudioProfileVector::getFirstValidProfile() const +sp AudioProfileVectorBase::getFirstValidProfile() const { for (const auto &profile : *this) { if (profile->isValid()) { @@ -459,7 +147,7 @@ sp AudioProfileVector::getFirstValidProfile() const return nullptr; } -sp AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const +sp AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const { for (const auto &profile : *this) { if (profile->isValid() && profile->getFormat() == format) { @@ -469,7 +157,7 @@ sp AudioProfileVector::getFirstValidProfileFor(audio_format_t form return nullptr; } -FormatVector AudioProfileVector::getSupportedFormats() const +FormatVector AudioProfileVectorBase::getSupportedFormats() const { FormatVector supportedFormats; for (const auto &profile : *this) { @@ -480,7 +168,7 @@ FormatVector AudioProfileVector::getSupportedFormats() const return supportedFormats; } -bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const +bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const { for (const auto &profile : *this) { if (profile->getFormat() == format && profile->isDynamicChannels()) { @@ -490,97 +178,44 @@ bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const return false; } -bool AudioProfileVector::hasDynamicProfile() const +bool AudioProfileVectorBase::hasDynamicFormat() const { for (const auto &profile : *this) { - if (profile->isDynamic()) { + if (profile->isDynamicFormat()) { return true; } } return false; } -bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const +bool AudioProfileVectorBase::hasDynamicProfile() const { for (const auto &profile : *this) { - if (profile->getFormat() == format && profile->isDynamicRate()) { + if (profile->isDynamic()) { return true; } } return false; } -void AudioProfileVector::setFormats(const FormatVector &formats) -{ - // Only allow to change the format of dynamic profile - sp dynamicFormatProfile = getProfileFor(gDynamicFormat); - if (dynamicFormatProfile == 0) { - return; - } - for (const auto &format : formats) { - sp profile = new AudioProfile(format, - dynamicFormatProfile->getChannels(), - dynamicFormatProfile->getSampleRates()); - profile->setDynamicFormat(true); - profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); - profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); - add(profile); - } -} - -void AudioProfileVector::dump(String8 *dst, int spaces) const -{ - dst->appendFormat("%*s- Profiles:\n", spaces, ""); - for (size_t i = 0; i < size(); i++) { - dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i); - at(i)->dump(dst, spaces + 8); - } -} - -sp AudioProfileVector::getProfileFor(audio_format_t format) const -{ - for (const auto &profile : *this) { - if (profile->getFormat() == format) { - return profile; - } - } - return nullptr; -} - -void AudioProfileVector::setSampleRatesFor( - const SampleRateSet &sampleRates, audio_format_t format) +bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const { for (const auto &profile : *this) { if (profile->getFormat() == format && profile->isDynamicRate()) { - if (profile->hasValidRates()) { - // Need to create a new profile with same format - sp profileToAdd = new AudioProfile(format, profile->getChannels(), - sampleRates); - profileToAdd->setDynamicFormat(true); // need to set to allow cleaning - add(profileToAdd); - } else { - profile->setSampleRates(sampleRates); - } - return; + return true; } } + return false; } -void AudioProfileVector::setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format) +void AudioProfileVectorBase::dump(std::string *dst, int spaces) const { - for (const auto &profile : *this) { - if (profile->getFormat() == format && profile->isDynamicChannels()) { - if (profile->hasValidChannels()) { - // Need to create a new profile with same format - sp profileToAdd = new AudioProfile(format, channelMasks, - profile->getSampleRates()); - profileToAdd->setDynamicFormat(true); // need to set to allow cleaning - add(profileToAdd); - } else { - profile->setChannels(channelMasks); - } - return; - } + dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, "")); + for (size_t i = 0; i < size(); i++) { + dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i)); + std::string profileStr; + at(i)->dump(&profileStr, spaces + 8); + dst->append(profileStr); } } diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h index 606e17b1b7..20f35eb8a1 100644 --- a/media/libaudiofoundation/include/media/AudioProfile.h +++ b/media/libaudiofoundation/include/media/AudioProfile.h @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#if 0 + #pragma once +#include +#include + #include #include #include -#include - -#include "policy.h" namespace android { -class AudioProfile : public virtual RefBase +class AudioProfile final : public RefBase { public: - static sp createFullDynamic(); + static sp createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT); AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); AudioProfile(audio_format_t format, @@ -49,14 +49,6 @@ public: } bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; } - status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const; - status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask, - audio_channel_mask_t &updatedChannelMask, - audio_port_type_t portType, - audio_port_role_t portRole) const; - status_t checkCompatibleSamplingRate(uint32_t samplingRate, - uint32_t &updatedSamplingRate) const; - bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; } bool hasValidRates() const { return !mSamplingRates.empty(); } bool hasValidChannels() const { return !mChannelMasks.empty(); } @@ -72,11 +64,11 @@ public: bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; } - void dump(String8 *dst, int spaces) const; + void dump(std::string *dst, int spaces) const; private: - String8 mName; - audio_format_t mFormat; + std::string mName; + audio_format_t mFormat; // The format for an audio profile should only be set when initialized. ChannelMaskSet mChannelMasks; SampleRateSet mSamplingRates; @@ -85,35 +77,16 @@ private: bool mIsDynamicRate = false; }; - -class AudioProfileVector : public std::vector > +class AudioProfileVectorBase : public std::vector > { public: - ssize_t add(const sp &profile); - // This API is intended to be used by the policy manager once retrieving capabilities - // for a profile with dynamic format, rate and channels attributes - ssize_t addProfileFromHal(const sp &profileToAdd); - void appendProfiles(const AudioProfileVector& audioProfiles) { - insert(end(), audioProfiles.begin(), audioProfiles.end()); - } + virtual ~AudioProfileVectorBase() = default; + + virtual ssize_t add(const sp &profile); - status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, - audio_format_t format) const; - status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, - audio_format_t &format, - audio_port_type_t portType, - audio_port_role_t portRole) const; - void clearProfiles(); - // Assuming that this profile vector contains input profiles, - // find the best matching config from 'outputProfiles', according to - // the given preferences for audio formats and channel masks. - // Note: std::vectors are used because specialized containers for formats - // and channels can be sorted and use their own ordering. - status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles, - const std::vector& preferredFormats, // order: most pref -> least pref - const std::vector& preferredOutputChannels, - bool preferHigherSamplingRates, - audio_config_base *bestOutputConfig) const; + // If the profile is dynamic format and has valid format, it will be removed when doing + // clearProfiles(). Otherwise, AudioProfile::clear() will be called. + virtual void clearProfiles(); sp getFirstValidProfile() const; sp getFirstValidProfileFor(audio_format_t format) const; @@ -121,22 +94,13 @@ public: FormatVector getSupportedFormats() const; bool hasDynamicChannelsFor(audio_format_t format) const; - bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } + bool hasDynamicFormat() const; bool hasDynamicProfile() const; bool hasDynamicRateFor(audio_format_t format) const; - // One audio profile will be added for each format supported by Audio HAL - void setFormats(const FormatVector &formats); - - void dump(String8 *dst, int spaces) const; - -private: - sp getProfileFor(audio_format_t format) const; - void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format); - void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format); + virtual void dump(std::string *dst, int spaces) const; }; bool operator == (const AudioProfile &left, const AudioProfile &right); } // namespace android -#endif diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h index 31c5041927..9816bc1c2c 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace android { @@ -118,9 +119,9 @@ public: mSource = "AudioPolicyConfig::setDefault"; mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix; mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER); - mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic()); + mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat)); sp defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC); - defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic()); + defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat)); sp micProfile = new AudioProfile( AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000); defaultInputDevice->addAudioProfile(micProfile); diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h index ea56729827..2e7328d437 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h @@ -16,126 +16,53 @@ #pragma once -#include +#include #include -#include -#include - -#include "policy.h" namespace android { -class AudioProfile : public virtual RefBase -{ +class AudioProfileVector : public AudioProfileVectorBase { public: - static sp createFullDynamic(); - - AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); - AudioProfile(audio_format_t format, - const ChannelMaskSet &channelMasks, - const SampleRateSet &samplingRateCollection); - - audio_format_t getFormat() const { return mFormat; } - const ChannelMaskSet &getChannels() const { return mChannelMasks; } - const SampleRateSet &getSampleRates() const { return mSamplingRates; } - void setChannels(const ChannelMaskSet &channelMasks); - void setSampleRates(const SampleRateSet &sampleRates); - - void clear(); - bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); } - bool supportsChannels(audio_channel_mask_t channels) const - { - return mChannelMasks.count(channels) != 0; - } - bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; } - - status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const; - status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask, - audio_channel_mask_t &updatedChannelMask, - audio_port_type_t portType, - audio_port_role_t portRole) const; - status_t checkCompatibleSamplingRate(uint32_t samplingRate, - uint32_t &updatedSamplingRate) const; + virtual ~AudioProfileVector() = default; - bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; } - bool hasValidRates() const { return !mSamplingRates.empty(); } - bool hasValidChannels() const { return !mChannelMasks.empty(); } + ssize_t add(const sp &profile) override; - void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; } - bool isDynamicChannels() const { return mIsDynamicChannels; } - - void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; } - bool isDynamicRate() const { return mIsDynamicRate; } - - void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; } - bool isDynamicFormat() const { return mIsDynamicFormat; } - - bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; } - - void dump(String8 *dst, int spaces) const; - -private: - String8 mName; - audio_format_t mFormat; - ChannelMaskSet mChannelMasks; - SampleRateSet mSamplingRates; - - bool mIsDynamicFormat = false; - bool mIsDynamicChannels = false; - bool mIsDynamicRate = false; -}; - - -class AudioProfileVector : public std::vector > -{ -public: - ssize_t add(const sp &profile); // This API is intended to be used by the policy manager once retrieving capabilities // for a profile with dynamic format, rate and channels attributes ssize_t addProfileFromHal(const sp &profileToAdd); - void appendProfiles(const AudioProfileVector& audioProfiles) { + void appendProfiles(const AudioProfileVectorBase& audioProfiles) { insert(end(), audioProfiles.begin(), audioProfiles.end()); } - status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, + status_t checkExactProfile(const uint32_t samplingRate, + audio_channel_mask_t channelMask, audio_format_t format) const; - status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, + + status_t checkCompatibleProfile(uint32_t &samplingRate, + audio_channel_mask_t &channelMask, audio_format_t &format, audio_port_type_t portType, audio_port_role_t portRole) const; - void clearProfiles(); + // Assuming that this profile vector contains input profiles, // find the best matching config from 'outputProfiles', according to // the given preferences for audio formats and channel masks. // Note: std::vectors are used because specialized containers for formats // and channels can be sorted and use their own ordering. - status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles, - const std::vector& preferredFormats, // order: most pref -> least pref - const std::vector& preferredOutputChannels, + status_t findBestMatchingOutputConfig( + const AudioProfileVector &outputProfiles, + const std::vector &preferredFormats, // order: most pref -> least pref + const std::vector &preferredOutputChannels, bool preferHigherSamplingRates, audio_config_base *bestOutputConfig) const; - sp getFirstValidProfile() const; - sp getFirstValidProfileFor(audio_format_t format) const; - bool hasValidProfile() const { return getFirstValidProfile() != 0; } - - FormatVector getSupportedFormats() const; - bool hasDynamicChannelsFor(audio_format_t format) const; - bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } - bool hasDynamicProfile() const; - bool hasDynamicRateFor(audio_format_t format) const; - // One audio profile will be added for each format supported by Audio HAL void setFormats(const FormatVector &formats); - void dump(String8 *dst, int spaces) const; - private: sp getProfileFor(audio_format_t format) const; void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format); void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format); }; -bool operator == (const AudioProfile &left, const AudioProfile &right); - -} // namespace android +} // namespace android \ No newline at end of file diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h index e0b56d4793..d9900943c8 100644 --- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h +++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h @@ -18,6 +18,7 @@ #include "AudioPort.h" #include "DeviceDescriptor.h" +#include "policy.h" #include #include diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index ff32284796..c8376097c0 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -342,7 +342,9 @@ void AudioPort::dump(String8 *dst, int spaces, bool verbose) const dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string()); } if (verbose) { - mProfiles.dump(dst, spaces); + std::string profilesStr; + mProfiles.dump(&profilesStr, spaces); + dst->append(profilesStr.c_str()); if (mGains.size() != 0) { dst->appendFormat("%*s- gains:\n", spaces, ""); diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp index b0503bb33b..c17df37c0a 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp @@ -28,93 +28,29 @@ #include "AudioPort.h" #include "AudioProfileVector.h" #include "HwModule.h" -#include "TypeConverter.h" +#include "policy.h" namespace android { -bool operator == (const AudioProfile &left, const AudioProfile &compareTo) +status_t checkExact(const sp &audioProfile, uint32_t samplingRate, + audio_channel_mask_t channelMask, audio_format_t format) { - return (left.getFormat() == compareTo.getFormat()) && - (left.getChannels() == compareTo.getChannels()) && - (left.getSampleRates() == compareTo.getSampleRates()); -} - -static AudioProfile* createFullDynamicImpl() -{ - AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat, - ChannelMaskSet(), SampleRateSet()); - dynamicProfile->setDynamicFormat(true); - dynamicProfile->setDynamicChannels(true); - dynamicProfile->setDynamicRate(true); - return dynamicProfile; -} - -// static -sp AudioProfile::createFullDynamic() -{ - static sp dynamicProfile = createFullDynamicImpl(); - return dynamicProfile; -} - -AudioProfile::AudioProfile(audio_format_t format, - audio_channel_mask_t channelMasks, - uint32_t samplingRate) : - mName(String8("")), - mFormat(format) -{ - mChannelMasks.insert(channelMasks); - mSamplingRates.insert(samplingRate); -} - -AudioProfile::AudioProfile(audio_format_t format, - const ChannelMaskSet &channelMasks, - const SampleRateSet &samplingRateCollection) : - mName(String8("")), - mFormat(format), - mChannelMasks(channelMasks), - mSamplingRates(samplingRateCollection) {} - -void AudioProfile::setChannels(const ChannelMaskSet &channelMasks) -{ - if (mIsDynamicChannels) { - mChannelMasks = channelMasks; - } -} - -void AudioProfile::setSampleRates(const SampleRateSet &sampleRates) -{ - if (mIsDynamicRate) { - mSamplingRates = sampleRates; - } -} - -void AudioProfile::clear() -{ - if (mIsDynamicChannels) { - mChannelMasks.clear(); - } - if (mIsDynamicRate) { - mSamplingRates.clear(); - } -} - -status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, - audio_format_t format) const -{ - if (audio_formats_match(format, mFormat) && - supportsChannels(channelMask) && - supportsRate(samplingRate)) { + if (audio_formats_match(format, audioProfile->getFormat()) && + audioProfile->supportsChannels(channelMask) && + audioProfile->supportsRate(samplingRate)) { return NO_ERROR; } return BAD_VALUE; } -status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, - uint32_t &updatedSamplingRate) const +status_t checkCompatibleSamplingRate(const sp &audioProfile, + uint32_t samplingRate, + uint32_t &updatedSamplingRate) { ALOG_ASSERT(samplingRate > 0); - if (mSamplingRates.empty()) { + const SampleRateSet sampleRates = audioProfile->getSampleRates(); + if (sampleRates.empty()) { updatedSamplingRate = samplingRate; return NO_ERROR; } @@ -122,17 +58,17 @@ status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, // Search for the closest supported sampling rate that is above (preferred) // or below (acceptable) the desired sampling rate, within a permitted ratio. // The sampling rates are sorted in ascending order. - auto desiredRate = mSamplingRates.lower_bound(samplingRate); + auto desiredRate = sampleRates.lower_bound(samplingRate); // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. - if (desiredRate != mSamplingRates.end()) { + if (desiredRate != sampleRates.end()) { if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { updatedSamplingRate = *desiredRate; return NO_ERROR; } } // But if we have to up-sample from a lower sampling rate, that's OK. - if (desiredRate != mSamplingRates.begin()) { + if (desiredRate != sampleRates.begin()) { uint32_t candidate = *(--desiredRate); if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { updatedSamplingRate = candidate; @@ -143,12 +79,14 @@ status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, return BAD_VALUE; } -status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, - audio_channel_mask_t &updatedChannelMask, - audio_port_type_t portType, - audio_port_role_t portRole) const +status_t checkCompatibleChannelMask(const sp &audioProfile, + audio_channel_mask_t channelMask, + audio_channel_mask_t &updatedChannelMask, + audio_port_type_t portType, + audio_port_role_t portRole) { - if (mChannelMasks.empty()) { + const ChannelMaskSet channelMasks = audioProfile->getChannels(); + if (channelMasks.empty()) { updatedChannelMask = channelMask; return NO_ERROR; } @@ -157,7 +95,7 @@ status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMa == AUDIO_CHANNEL_REPRESENTATION_INDEX; const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); int bestMatch = 0; - for (const auto &supported : mChannelMasks) { + for (const auto &supported : channelMasks) { if (supported == channelMask) { // Exact matches always taken. updatedChannelMask = channelMask; @@ -235,37 +173,6 @@ status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMa return bestMatch > 0 ? NO_ERROR : BAD_VALUE; } -void AudioProfile::dump(String8 *dst, int spaces) const -{ - dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", - mIsDynamicChannels ? "[dynamic channels]" : "", - mIsDynamicRate ? "[dynamic rates]" : ""); - if (mName.length() != 0) { - dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string()); - } - std::string formatLiteral; - if (FormatConverter::toString(mFormat, formatLiteral)) { - dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str()); - } - if (!mSamplingRates.empty()) { - dst->appendFormat("%*s- sampling rates:", spaces, ""); - for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) { - dst->appendFormat("%d", *it); - dst->append(++it == mSamplingRates.end() ? "" : ", "); - } - dst->append("\n"); - } - - if (!mChannelMasks.empty()) { - dst->appendFormat("%*s- channel masks:", spaces, ""); - for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) { - dst->appendFormat("0x%04x", *it); - dst->append(++it == mChannelMasks.end() ? "" : ", "); - } - dst->append("\n"); - } -} - ssize_t AudioProfileVector::add(const sp &profile) { ssize_t index = size(); @@ -311,7 +218,7 @@ ssize_t AudioProfileVector::addProfileFromHal(const sp &profileToA return add(profileToAdd); } -status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, +status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate, audio_channel_mask_t channelMask, audio_format_t format) const { @@ -320,7 +227,7 @@ status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, } for (const auto& profile : *this) { - if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { + if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) { return NO_ERROR; } } @@ -353,9 +260,9 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, // rate and channels as well audio_channel_mask_t updatedChannels; uint32_t updatedRate; - if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, - portType, portRole) == NO_ERROR && - profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { + if (checkCompatibleChannelMask(profile, channelMask, updatedChannels, + portType, portRole) == NO_ERROR && + checkCompatibleSamplingRate(profile, samplingRate, updatedRate) == NO_ERROR) { // for inexact checks we take the first linear pcm format due to sorting. format = formatToCompare; channelMask = updatedChannels; @@ -367,18 +274,6 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, return BAD_VALUE; } -void AudioProfileVector::clearProfiles() -{ - for (auto it = begin(); it != end();) { - if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) { - it = erase(it); - } else { - (*it)->clear(); - ++it; - } - } -} - // Returns an intersection between two possibly unsorted vectors and the contents of 'order'. // The result is ordered according to 'order'. template @@ -449,67 +344,6 @@ status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVect return BAD_VALUE; } -sp AudioProfileVector::getFirstValidProfile() const -{ - for (const auto &profile : *this) { - if (profile->isValid()) { - return profile; - } - } - return nullptr; -} - -sp AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const -{ - for (const auto &profile : *this) { - if (profile->isValid() && profile->getFormat() == format) { - return profile; - } - } - return nullptr; -} - -FormatVector AudioProfileVector::getSupportedFormats() const -{ - FormatVector supportedFormats; - for (const auto &profile : *this) { - if (profile->hasValidFormat()) { - supportedFormats.push_back(profile->getFormat()); - } - } - return supportedFormats; -} - -bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const -{ - for (const auto &profile : *this) { - if (profile->getFormat() == format && profile->isDynamicChannels()) { - return true; - } - } - return false; -} - -bool AudioProfileVector::hasDynamicProfile() const -{ - for (const auto &profile : *this) { - if (profile->isDynamic()) { - return true; - } - } - return false; -} - -bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const -{ - for (const auto &profile : *this) { - if (profile->getFormat() == format && profile->isDynamicRate()) { - return true; - } - } - return false; -} - void AudioProfileVector::setFormats(const FormatVector &formats) { // Only allow to change the format of dynamic profile @@ -528,15 +362,6 @@ void AudioProfileVector::setFormats(const FormatVector &formats) } } -void AudioProfileVector::dump(String8 *dst, int spaces) const -{ - dst->appendFormat("%*s- Profiles:\n", spaces, ""); - for (size_t i = 0; i < size(); i++) { - dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i); - at(i)->dump(dst, spaces + 8); - } -} - sp AudioProfileVector::getProfileFor(audio_format_t format) const { for (const auto &profile : *this) { diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp index c699aa733b..09cbe1a4f6 100644 --- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp @@ -438,7 +438,7 @@ Return MixPortTraits::deserialize(const xmlNode *child, return Status::fromStatusT(status); } if (profiles.empty()) { - profiles.add(AudioProfile::createFullDynamic()); + profiles.add(AudioProfile::createFullDynamic(gDynamicFormat)); } mixPort->setAudioProfiles(profiles); @@ -522,7 +522,7 @@ Return DevicePortTraits::deserialize(const xmlNode *c return Status::fromStatusT(status); } if (profiles.empty()) { - profiles.add(AudioProfile::createFullDynamic()); + profiles.add(AudioProfile::createFullDynamic(gDynamicFormat)); } deviceDesc->setAudioProfiles(profiles); From 736ffc105e64398dfa789bec3be880c7a1809761 Mon Sep 17 00:00:00 2001 From: jiabin Date: Mon, 19 Aug 2019 14:14:57 -0700 Subject: [PATCH 4/5] Copy AudioPort.h to libaudiofoundation. Copy AudioPort.h from audio policy to libaudiofoundation and name it as AudioPortBase.h. Note that AudioPortBase has not been added into the make file as it needs some more change to make it work. Doing this just to make a cleaner diff for later change. Bug: 135621476 Test: make Change-Id: I6cd1a53e889340c7fefffdd5832854016cd733ee Merged-In: I6cd1a53e889340c7fefffdd5832854016cd733ee --- .../include/media/AudioPortBase.h | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 media/libaudiofoundation/include/media/AudioPortBase.h diff --git a/media/libaudiofoundation/include/media/AudioPortBase.h b/media/libaudiofoundation/include/media/AudioPortBase.h new file mode 100644 index 0000000000..f5d92e6165 --- /dev/null +++ b/media/libaudiofoundation/include/media/AudioPortBase.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if 0 +#pragma once + +#include "AudioCollections.h" +#include "AudioProfile.h" +#include "HandleGenerator.h" +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class HwModule; +class AudioRoute; + +class AudioPort : public virtual RefBase, private HandleGenerator +{ +public: + AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) : + mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {} + + virtual ~AudioPort() {} + + void setName(const String8 &name) { mName = name; } + const String8 &getName() const { return mName; } + + audio_port_type_t getType() const { return mType; } + audio_port_role_t getRole() const { return mRole; } + + virtual const String8 getTagName() const = 0; + + void setGains(const AudioGains &gains) { mGains = gains; } + const AudioGains &getGains() const { return mGains; } + + virtual void setFlags(uint32_t flags) + { + //force direct flag if offload flag is set: offloading implies a direct output stream + // and all common behaviors are driven by checking only the direct flag + // this should normally be set appropriately in the policy configuration file + if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { + flags |= AUDIO_OUTPUT_FLAG_DIRECT; + } + mFlags = flags; + } + uint32_t getFlags() const { return mFlags; } + + virtual void attach(const sp& module); + virtual void detach(); + bool isAttached() { return mModule != 0; } + + // Audio port IDs are in a different namespace than AudioFlinger unique IDs + static audio_port_handle_t getNextUniqueId(); + + virtual void toAudioPort(struct audio_port *port) const; + + virtual void importAudioPort(const sp& port, bool force = false); + + void addAudioProfile(const sp &profile) { mProfiles.add(profile); } + + void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; } + AudioProfileVector &getAudioProfiles() { return mProfiles; } + + bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); } + + bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); } + + // searches for an exact match + virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const; + + // searches for a compatible match, currently implemented for input + // parameters are input|output, returned value is the best match. + status_t checkCompatibleAudioProfile(uint32_t &samplingRate, + audio_channel_mask_t &channelMask, + audio_format_t &format) const + { + return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole); + } + + void clearAudioProfiles() { return mProfiles.clearProfiles(); } + + status_t checkGain(const struct audio_gain_config *gainConfig, int index) const; + + void pickAudioProfile(uint32_t &samplingRate, + audio_channel_mask_t &channelMask, + audio_format_t &format) const; + + static const audio_format_t sPcmFormatCompareTable[]; + + static int compareFormats(audio_format_t format1, audio_format_t format2); + + // Used to select an audio HAL output stream with a sample format providing the + // less degradation for a given AudioTrack sample format. + static bool isBetterFormatMatch(audio_format_t newFormat, + audio_format_t currentFormat, + audio_format_t targetFormat); + static uint32_t formatDistance(audio_format_t format1, + audio_format_t format2); + static const uint32_t kFormatDistanceMax = 4; + + audio_module_handle_t getModuleHandle() const; + uint32_t getModuleVersionMajor() const; + const char *getModuleName() const; + sp getModule() const { return mModule; } + + bool useInputChannelMask() const + { + return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) || + ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK)); + } + + inline bool isDirectOutput() const + { + return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && + (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)); + } + + void addRoute(const sp &route) { mRoutes.add(route); } + const AudioRouteVector &getRoutes() const { return mRoutes; } + + void dump(String8 *dst, int spaces, bool verbose = true) const; + + void log(const char* indent) const; + + AudioGains mGains; // gain controllers + +private: + void pickChannelMask(audio_channel_mask_t &channelMask, + const ChannelMaskSet &channelMasks) const; + void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const; + + sp mModule; // audio HW module exposing this I/O stream + String8 mName; + audio_port_type_t mType; + audio_port_role_t mRole; + uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...). + AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels) + AudioRouteVector mRoutes; // Routes involving this port +}; + +class AudioPortConfig : public virtual RefBase +{ +public: + status_t applyAudioPortConfig(const struct audio_port_config *config, + struct audio_port_config *backupConfig = NULL); + virtual void toAudioPortConfig(struct audio_port_config *dstConfig, + const struct audio_port_config *srcConfig = NULL) const = 0; + virtual sp getAudioPort() const = 0; + virtual bool hasSameHwModuleAs(const sp& other) const { + return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) && + (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle()); + } + bool hasGainController(bool canUseForVolume = false) const; + + unsigned int mSamplingRate = 0u; + audio_format_t mFormat = AUDIO_FORMAT_INVALID; + audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE; + struct audio_gain_config mGain = { .index = -1 }; + union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE }; +}; + +} // namespace android +#endif From eaf09f089a42f7a7ea39339e93b358b37b58956f Mon Sep 17 00:00:00 2001 From: jiabin Date: Mon, 19 Aug 2019 15:08:30 -0700 Subject: [PATCH 5/5] Add AudioPortFoundation, AudioPortBase and AudioPortConfigBase. The purpose of this change is to make a generic AudioPort class that could be used by vendor. 1. Add AudioPortFoundation and AudioPortBase. AudioPortFoundation contains generic members of an audio port. AudioPortBase is a template class that derives from AudioPortFoundation. It takes audio profile vector as a template parameters. That makes it more feasible to use customized audio profile stuff as needed. In audio policy, AudioPort derives from AudioPortBase and contain policy related stuff. 2. Add AudioPortConfigBase. AudioPortConfigBase contains generic members of an audio port config. AudioPortConfig derives from AudioPortConfigBase and contains policy related stuff. 3. Use std::string instead of String8 in AudioPort and AudioPortConfig. Bug: 135621476 Test: CTS for AudioRecord, AudioTrack, AudioManager, RoutingTest Test: audiopolicy_tests, AudioServiceHostTest audio smoke test Test: dumpsys media.audio_policy Change-Id: I05611b7067c18006660de2c678acd56bdd34010a Merged-In: I05611b7067c18006660de2c678acd56bdd34010a --- media/libaudiofoundation/Android.bp | 1 + media/libaudiofoundation/AudioPortBase.cpp | 87 +++++++++ .../include/media/AudioPortBase.h | 177 +++++++----------- .../include/AudioCollections.h | 2 +- .../include/AudioPolicyConfig.h | 4 +- .../managerdefinitions/include/AudioPort.h | 64 ++----- .../include/DeviceDescriptor.h | 10 +- .../managerdefinitions/include/HwModule.h | 10 +- .../managerdefinitions/include/IOProfile.h | 8 +- .../src/AudioCollections.cpp | 2 +- .../src/AudioInputDescriptor.cpp | 6 +- .../src/AudioOutputDescriptor.cpp | 6 +- .../managerdefinitions/src/AudioPort.cpp | 78 +------- .../managerdefinitions/src/AudioRoute.cpp | 8 +- .../src/DeviceDescriptor.cpp | 16 +- .../managerdefinitions/src/HwModule.cpp | 22 +-- .../managerdefinitions/src/IOProfile.cpp | 4 +- .../managerdefinitions/src/Serializer.cpp | 14 +- .../audiopolicy/enginedefault/src/Engine.cpp | 2 +- .../managerdefault/AudioPolicyManager.cpp | 53 +++--- .../tests/audiopolicymanager_tests.cpp | 9 +- 21 files changed, 258 insertions(+), 325 deletions(-) create mode 100644 media/libaudiofoundation/AudioPortBase.cpp diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp index 2ea2c10f08..c91b79e93b 100644 --- a/media/libaudiofoundation/Android.bp +++ b/media/libaudiofoundation/Android.bp @@ -10,6 +10,7 @@ cc_library_shared { srcs: [ "AudioGain.cpp", + "AudioPortBase.cpp", "AudioProfile.cpp", ], diff --git a/media/libaudiofoundation/AudioPortBase.cpp b/media/libaudiofoundation/AudioPortBase.cpp new file mode 100644 index 0000000000..922a82cfd7 --- /dev/null +++ b/media/libaudiofoundation/AudioPortBase.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +namespace android { + +void AudioPortFoundation::toAudioPort(struct audio_port *port) const { + // TODO: update this function once audio_port structure reflects the new profile definition. + // For compatibility reason: flatening the AudioProfile into audio_port structure. + FormatSet flatenedFormats; + SampleRateSet flatenedRates; + ChannelMaskSet flatenedChannels; + for (const auto& profile : *getAudioProfileVectorBase()) { + if (profile->isValid()) { + audio_format_t formatToExport = profile->getFormat(); + const SampleRateSet &ratesToExport = profile->getSampleRates(); + const ChannelMaskSet &channelsToExport = profile->getChannels(); + + flatenedFormats.insert(formatToExport); + flatenedRates.insert(ratesToExport.begin(), ratesToExport.end()); + flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end()); + + if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES || + flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS || + flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) { + ALOGE("%s: bailing out: cannot export profiles to port config", __func__); + return; + } + } + } + port->role = mRole; + port->type = mType; + strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN); + port->num_sample_rates = flatenedRates.size(); + port->num_channel_masks = flatenedChannels.size(); + port->num_formats = flatenedFormats.size(); + std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates); + std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks); + std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats); + + ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); + + port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS); + for (size_t i = 0; i < port->num_gains; i++) { + port->gains[i] = mGains[i]->getGain(); + } +} + +void AudioPortFoundation::dump(std::string *dst, int spaces, bool verbose) const { + if (!mName.empty()) { + dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str())); + } + if (verbose) { + std::string profilesStr; + getAudioProfileVectorBase()->dump(&profilesStr, spaces); + dst->append(profilesStr); + + if (mGains.size() != 0) { + dst->append(base::StringPrintf("%*s- gains:\n", spaces, "")); + for (size_t i = 0; i < mGains.size(); i++) { + std::string gainStr; + mGains[i]->dump(&gainStr, spaces + 2, i); + dst->append(gainStr); + } + } + } +} + +} \ No newline at end of file diff --git a/media/libaudiofoundation/include/media/AudioPortBase.h b/media/libaudiofoundation/include/media/AudioPortBase.h index f5d92e6165..5812c2ca1a 100644 --- a/media/libaudiofoundation/include/media/AudioPortBase.h +++ b/media/libaudiofoundation/include/media/AudioPortBase.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,113 +13,57 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#if 0 + #pragma once -#include "AudioCollections.h" -#include "AudioProfile.h" -#include "HandleGenerator.h" +#include + #include -#include -#include -#include +#include #include +#include #include #include namespace android { -class HwModule; -class AudioRoute; - -class AudioPort : public virtual RefBase, private HandleGenerator +class AudioPortFoundation : public virtual RefBase { public: - AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) : - mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {} + AudioPortFoundation(const std::string& name, audio_port_type_t type, audio_port_role_t role) : + mName(name), mType(type), mRole(role) {} - virtual ~AudioPort() {} + virtual ~AudioPortFoundation() = default; - void setName(const String8 &name) { mName = name; } - const String8 &getName() const { return mName; } + void setName(const std::string &name) { mName = name; } + const std::string &getName() const { return mName; } audio_port_type_t getType() const { return mType; } audio_port_role_t getRole() const { return mRole; } - virtual const String8 getTagName() const = 0; + virtual const std::string getTagName() const = 0; void setGains(const AudioGains &gains) { mGains = gains; } const AudioGains &getGains() const { return mGains; } - virtual void setFlags(uint32_t flags) - { - //force direct flag if offload flag is set: offloading implies a direct output stream - // and all common behaviors are driven by checking only the direct flag - // this should normally be set appropriately in the policy configuration file - if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { - flags |= AUDIO_OUTPUT_FLAG_DIRECT; - } - mFlags = flags; - } - uint32_t getFlags() const { return mFlags; } - - virtual void attach(const sp& module); - virtual void detach(); - bool isAttached() { return mModule != 0; } - - // Audio port IDs are in a different namespace than AudioFlinger unique IDs - static audio_port_handle_t getNextUniqueId(); - virtual void toAudioPort(struct audio_port *port) const; - virtual void importAudioPort(const sp& port, bool force = false); - - void addAudioProfile(const sp &profile) { mProfiles.add(profile); } - - void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; } - AudioProfileVector &getAudioProfiles() { return mProfiles; } - - bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); } - - bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); } - - // searches for an exact match - virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const; - - // searches for a compatible match, currently implemented for input - // parameters are input|output, returned value is the best match. - status_t checkCompatibleAudioProfile(uint32_t &samplingRate, - audio_channel_mask_t &channelMask, - audio_format_t &format) const - { - return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole); + virtual AudioProfileVectorBase* getAudioProfileVectorBase() const = 0; + virtual void addAudioProfile(const sp &profile) { + getAudioProfileVectorBase()->add(profile); + } + virtual void clearAudioProfiles() { + getAudioProfileVectorBase()->clearProfiles(); } - void clearAudioProfiles() { return mProfiles.clearProfiles(); } - - status_t checkGain(const struct audio_gain_config *gainConfig, int index) const; - - void pickAudioProfile(uint32_t &samplingRate, - audio_channel_mask_t &channelMask, - audio_format_t &format) const; - - static const audio_format_t sPcmFormatCompareTable[]; - - static int compareFormats(audio_format_t format1, audio_format_t format2); - - // Used to select an audio HAL output stream with a sample format providing the - // less degradation for a given AudioTrack sample format. - static bool isBetterFormatMatch(audio_format_t newFormat, - audio_format_t currentFormat, - audio_format_t targetFormat); - static uint32_t formatDistance(audio_format_t format1, - audio_format_t format2); - static const uint32_t kFormatDistanceMax = 4; + bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); } - audio_module_handle_t getModuleHandle() const; - uint32_t getModuleVersionMajor() const; - const char *getModuleName() const; - sp getModule() const { return mModule; } + status_t checkGain(const struct audio_gain_config *gainConfig, int index) const { + if (index < 0 || (size_t)index >= mGains.size()) { + return BAD_VALUE; + } + return mGains[index]->checkConfig(gainConfig); + } bool useInputChannelMask() const { @@ -127,55 +71,60 @@ public: ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK)); } - inline bool isDirectOutput() const - { - return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && - (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)); - } + void dump(std::string *dst, int spaces, bool verbose = true) const; - void addRoute(const sp &route) { mRoutes.add(route); } - const AudioRouteVector &getRoutes() const { return mRoutes; } + AudioGains mGains; // gain controllers +protected: + std::string mName; + audio_port_type_t mType; + audio_port_role_t mRole; +}; - void dump(String8 *dst, int spaces, bool verbose = true) const; +template ::value>::type> +class AudioPortBase : public AudioPortFoundation +{ +public: + AudioPortBase(const std::string& name, audio_port_type_t type, audio_port_role_t role) : + AudioPortFoundation(name, type, role) {} - void log(const char* indent) const; + virtual ~AudioPortBase() {} - AudioGains mGains; // gain controllers + AudioProfileVectorBase* getAudioProfileVectorBase() const override { + return static_cast(const_cast(&mProfiles)); + } -private: - void pickChannelMask(audio_channel_mask_t &channelMask, - const ChannelMaskSet &channelMasks) const; - void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const; + void addAudioProfile(const sp &profile) override { mProfiles.add(profile); } + void clearAudioProfiles() override { return mProfiles.clearProfiles(); } - sp mModule; // audio HW module exposing this I/O stream - String8 mName; - audio_port_type_t mType; - audio_port_role_t mRole; - uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...). - AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels) - AudioRouteVector mRoutes; // Routes involving this port + void setAudioProfiles(const ProfileVector &profiles) { mProfiles = profiles; } + ProfileVector &getAudioProfiles() { return mProfiles; } + +protected: + ProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels) }; -class AudioPortConfig : public virtual RefBase + +class AudioPortConfigBase : public virtual RefBase { public: - status_t applyAudioPortConfig(const struct audio_port_config *config, - struct audio_port_config *backupConfig = NULL); + virtual ~AudioPortConfigBase() = default; + + virtual status_t applyAudioPortConfig(const struct audio_port_config *config, + struct audio_port_config *backupConfig = NULL) = 0; virtual void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const = 0; - virtual sp getAudioPort() const = 0; - virtual bool hasSameHwModuleAs(const sp& other) const { - return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) && - (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle()); - } - bool hasGainController(bool canUseForVolume = false) const; + unsigned int getSamplingRate() const { return mSamplingRate; } + audio_format_t getFormat() const { return mFormat; } + audio_channel_mask_t getChannelMask() const { return mChannelMask; } + +protected: unsigned int mSamplingRate = 0u; audio_format_t mFormat = AUDIO_FORMAT_INVALID; audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE; struct audio_gain_config mGain = { .index = -1 }; - union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE }; }; } // namespace android -#endif diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h index a948ea91a1..646ef31d2b 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h @@ -31,7 +31,7 @@ class AudioRoute; class AudioPortVector : public Vector > { public: - sp findByTagName(const String8 &tagName) const; + sp findByTagName(const std::string &tagName) const; }; diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h index 9816bc1c2c..c17f308b95 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h @@ -133,14 +133,14 @@ public: mDefaultOutputDevice->attach(module); defaultInputDevice->attach(module); - sp outProfile = new OutputProfile(String8("primary")); + sp outProfile = new OutputProfile("primary"); outProfile->addAudioProfile( new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100)); outProfile->addSupportedDevice(mDefaultOutputDevice); outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY); module->addOutputProfile(outProfile); - sp inProfile = new InputProfile(String8("primary")); + sp inProfile = new InputProfile("primary"); inProfile->addAudioProfile(micProfile); inProfile->addSupportedDevice(defaultInputDevice); module->addInputProfile(inProfile); diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h index ccbf2f3be2..c26bffc499 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h @@ -20,6 +20,7 @@ #include "AudioProfileVector.h" #include "HandleGenerator.h" #include +#include #include #include #include @@ -32,25 +33,15 @@ namespace android { class HwModule; class AudioRoute; -class AudioPort : public virtual RefBase, private HandleGenerator +class AudioPort : public virtual RefBase, public AudioPortBase, + private HandleGenerator { public: - AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) : - mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {} + AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) : + AudioPortBase(name, type, role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {} virtual ~AudioPort() {} - void setName(const String8 &name) { mName = name; } - const String8 &getName() const { return mName; } - - audio_port_type_t getType() const { return mType; } - audio_port_role_t getRole() const { return mRole; } - - virtual const String8 getTagName() const = 0; - - void setGains(const AudioGains &gains) { mGains = gains; } - const AudioGains &getGains() const { return mGains; } - virtual void setFlags(uint32_t flags) { //force direct flag if offload flag is set: offloading implies a direct output stream @@ -70,18 +61,9 @@ public: // Audio port IDs are in a different namespace than AudioFlinger unique IDs static audio_port_handle_t getNextUniqueId(); - virtual void toAudioPort(struct audio_port *port) const; - virtual void importAudioPort(const sp& port, bool force = false); - void addAudioProfile(const sp &profile) { mProfiles.add(profile); } - - void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; } - AudioProfileVector &getAudioProfiles() { return mProfiles; } - - bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); } - - bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); } + bool hasDynamicAudioProfile() const { return getAudioProfileVectorBase()->hasDynamicProfile(); } // searches for an exact match virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const; @@ -95,10 +77,6 @@ public: return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole); } - void clearAudioProfiles() { return mProfiles.clearProfiles(); } - - status_t checkGain(const struct audio_gain_config *gainConfig, int index) const; - void pickAudioProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, audio_format_t &format) const; @@ -121,12 +99,6 @@ public: const char *getModuleName() const; sp getModule() const { return mModule; } - bool useInputChannelMask() const - { - return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) || - ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK)); - } - inline bool isDirectOutput() const { return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && @@ -136,44 +108,36 @@ public: void addRoute(const sp &route) { mRoutes.add(route); } const AudioRouteVector &getRoutes() const { return mRoutes; } - void dump(String8 *dst, int spaces, bool verbose = true) const; - void log(const char* indent) const; - AudioGains mGains; // gain controllers - private: void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelMaskSet &channelMasks) const; void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const; - sp mModule; // audio HW module exposing this I/O stream - String8 mName; - audio_port_type_t mType; - audio_port_role_t mRole; uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...). - AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels) + sp mModule; // audio HW module exposing this I/O stream AudioRouteVector mRoutes; // Routes involving this port }; -class AudioPortConfig : public virtual RefBase +class AudioPortConfig : public AudioPortConfigBase { public: status_t applyAudioPortConfig(const struct audio_port_config *config, - struct audio_port_config *backupConfig = NULL); + struct audio_port_config *backupConfig = NULL) override; + virtual void toAudioPortConfig(struct audio_port_config *dstConfig, - const struct audio_port_config *srcConfig = NULL) const = 0; + const struct audio_port_config *srcConfig = NULL) const override; + virtual sp getAudioPort() const = 0; + virtual bool hasSameHwModuleAs(const sp& other) const { return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) && (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle()); } + bool hasGainController(bool canUseForVolume = false) const; - unsigned int mSamplingRate = 0u; - audio_format_t mFormat = AUDIO_FORMAT_INVALID; - audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE; - struct audio_gain_config mGain = { .index = -1 }; union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE }; }; diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index c7c1feed46..c2f1d93953 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -30,13 +30,13 @@ class DeviceDescriptor : public AudioPort, public AudioPortConfig { public: // Note that empty name refers by convention to a generic device. - explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8("")); + explicit DeviceDescriptor(audio_devices_t type, const std::string &tagName = ""); DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats, - const String8 &tagName = String8("")); + const std::string &tagName = ""); virtual ~DeviceDescriptor() {} - virtual const String8 getTagName() const { return mTagName; } + virtual const std::string getTagName() const { return mTagName; } audio_devices_t type() const { return mDeviceType; } String8 address() const { return mAddress; } @@ -75,7 +75,7 @@ public: private: String8 mAddress{""}; - String8 mTagName; // Unique human readable identifier for a device port found in conf file. + std::string mTagName; // Unique human readable identifier for a device port found in conf file. audio_devices_t mDeviceType; FormatVector mEncodedFormats; audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE; @@ -112,7 +112,7 @@ public: * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr. */ sp getDeviceFromId(audio_port_handle_t id) const; - sp getDeviceFromTagName(const String8 &tagName) const; + sp getDeviceFromTagName(const std::string &tagName) const; DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const; audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const; diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h index eb34da448a..65c886a560 100644 --- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h +++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h @@ -82,17 +82,17 @@ public: status_t addInputProfile(const sp &profile); status_t addProfile(const sp &profile); - status_t addOutputProfile(const String8& name, const audio_config_t *config, + status_t addOutputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address); - status_t removeOutputProfile(const String8& name); - status_t addInputProfile(const String8& name, const audio_config_t *config, + status_t removeOutputProfile(const std::string& name); + status_t addInputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address); - status_t removeInputProfile(const String8& name); + status_t removeInputProfile(const std::string& name); audio_module_handle_t getHandle() const { return mHandle; } void setHandle(audio_module_handle_t handle); - sp findPortByTagName(const String8 &tagName) const + sp findPortByTagName(const std::string &tagName) const { return mPorts.findByTagName(tagName); } diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h index d9900943c8..419dd350fa 100644 --- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h +++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h @@ -34,7 +34,7 @@ class HwModule; class IOProfile : public AudioPort { public: - IOProfile(const String8 &name, audio_port_role_t role) + IOProfile(const std::string &name, audio_port_role_t role) : AudioPort(name, AUDIO_PORT_TYPE_MIX, role), maxOpenCount(1), curOpenCount(0), @@ -42,7 +42,7 @@ public: curActiveCount(0) {} // For a Profile aka MixPort, tag name and name are equivalent. - virtual const String8 getTagName() const { return getName(); } + virtual const std::string getTagName() const { return getName(); } // FIXME: this is needed because shared MMAP stream clients use the same audio session. // Once capture clients are tracked individually and not per session this can be removed @@ -184,13 +184,13 @@ private: class InputProfile : public IOProfile { public: - explicit InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {} + explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {} }; class OutputProfile : public IOProfile { public: - explicit OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {} + explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {} }; } // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp index e8cf485616..b391a09645 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp @@ -24,7 +24,7 @@ namespace android { -sp AudioPortVector::findByTagName(const String8 &tagName) const +sp AudioPortVector::findByTagName(const std::string &tagName) const { for (const auto& port : *this) { if (port->getTagName() == tagName) { diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp index a9b87e3f59..7cb2e10a2b 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp @@ -34,8 +34,8 @@ AudioInputDescriptor::AudioInputDescriptor(const sp& profile, { if (profile != NULL) { profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); - if (profile->mGains.size() > 0) { - profile->mGains[0]->getDefaultConfig(&mGain); + if (profile->getGains().size() > 0) { + profile->getGains()[0]->getDefaultConfig(&mGain); } } } @@ -212,7 +212,7 @@ status_t AudioInputDescriptor::open(const audio_config_t *config, mDevice = device; ALOGV("opening input for device %s profile %p name %s", - mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string()); + mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str()); audio_devices_t deviceType = mDevice->type(); diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 49524b09fd..6f0c3f501b 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -40,8 +40,8 @@ AudioOutputDescriptor::AudioOutputDescriptor(const sp& port, { if (mPort.get() != nullptr) { mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); - if (mPort->mGains.size() > 0) { - mPort->mGains[0]->getDefaultConfig(&mGain); + if (mPort->getGains().size() > 0) { + mPort->getGains()[0]->getDefaultConfig(&mGain); } } } @@ -483,7 +483,7 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config, mFlags = (audio_output_flags_t)(mFlags | flags); ALOGV("opening output for device %s profile %p name %s", - mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string()); + mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str()); status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(), output, diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index c8376097c0..decfad1b7c 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -30,7 +30,7 @@ namespace android { // --- AudioPort class implementation void AudioPort::attach(const sp& module) { - ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string()); + ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.c_str()); mModule = module; } @@ -60,49 +60,6 @@ const char *AudioPort::getModuleName() const return mModule != 0 ? mModule->getName() : "invalid module"; } -void AudioPort::toAudioPort(struct audio_port *port) const -{ - // TODO: update this function once audio_port structure reflects the new profile definition. - // For compatibility reason: flatening the AudioProfile into audio_port structure. - FormatSet flatenedFormats; - SampleRateSet flatenedRates; - ChannelMaskSet flatenedChannels; - for (const auto& profile : mProfiles) { - if (profile->isValid()) { - audio_format_t formatToExport = profile->getFormat(); - const SampleRateSet &ratesToExport = profile->getSampleRates(); - const ChannelMaskSet &channelsToExport = profile->getChannels(); - - flatenedFormats.insert(formatToExport); - flatenedRates.insert(ratesToExport.begin(), ratesToExport.end()); - flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end()); - - if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES || - flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS || - flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) { - ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__); - return; - } - } - } - port->role = mRole; - port->type = mType; - strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN); - port->num_sample_rates = flatenedRates.size(); - port->num_channel_masks = flatenedChannels.size(); - port->num_formats = flatenedFormats.size(); - std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates); - std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks); - std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats); - - ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); - - port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS); - for (size_t i = 0; i < port->num_gains; i++) { - port->gains[i] = mGains[i]->getGain(); - } -} - void AudioPort::importAudioPort(const sp& port, bool force __unused) { for (const auto& profileToImport : port->mProfiles) { @@ -324,42 +281,13 @@ void AudioPort::pickAudioProfile(uint32_t &samplingRate, } } } - ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(), + ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.c_str(), samplingRate, channelMask, format); } -status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const -{ - if (index < 0 || (size_t)index >= mGains.size()) { - return BAD_VALUE; - } - return mGains[index]->checkConfig(gainConfig); -} - -void AudioPort::dump(String8 *dst, int spaces, bool verbose) const -{ - if (!mName.isEmpty()) { - dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string()); - } - if (verbose) { - std::string profilesStr; - mProfiles.dump(&profilesStr, spaces); - dst->append(profilesStr.c_str()); - - if (mGains.size() != 0) { - dst->appendFormat("%*s- gains:\n", spaces, ""); - for (size_t i = 0; i < mGains.size(); i++) { - std::string gainStr; - mGains[i]->dump(&gainStr, spaces + 2, i); - dst->append(gainStr.c_str()); - } - } - } -} - void AudioPort::log(const char* indent) const { - ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); + ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole); } // --- AudioPortConfig class implementation diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp index 92cbe4eb30..0f35ff8990 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp @@ -26,11 +26,11 @@ namespace android void AudioRoute::dump(String8 *dst, int spaces) const { dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix"); - dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().string()); + dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().c_str()); if (mSources.size() != 0) { dst->appendFormat("%*s- Sources: \n", spaces, ""); for (size_t i = 0; i < mSources.size(); i++) { - dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().string()); + dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().c_str()); } } dst->append("\n"); @@ -41,10 +41,10 @@ bool AudioRoute::supportsPatch(const sp &srcPort, const sp if (mSink == 0 || dstPort == 0 || dstPort != mSink) { return false; } - ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string()); + ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str()); for (const auto &sourcePort : mSources) { if (sourcePort == srcPort) { - ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string()); + ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str()); return true; } } diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index e395caa6b0..018636dca1 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -26,14 +26,14 @@ namespace android { -DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) : +DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagName) : DeviceDescriptor(type, FormatVector{}, tagName) { } DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats, - const String8 &tagName) : - AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE, + const std::string &tagName) : + AudioPort("", AUDIO_PORT_TYPE_DEVICE, audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE), mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats) @@ -262,7 +262,7 @@ DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const return devices; } -sp DeviceVector::getDeviceFromTagName(const String8 &tagName) const +sp DeviceVector::getDeviceFromTagName(const std::string &tagName) const { for (const auto& device : *this) { if (device->getTagName() == tagName) { @@ -374,8 +374,8 @@ void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) c if (mId != 0) { dst->appendFormat("%*s- id: %2d\n", spaces, "", mId); } - if (!mTagName.isEmpty()) { - dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string()); + if (!mTagName.empty()) { + dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str()); } dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str()); @@ -383,7 +383,9 @@ void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) c if (mAddress.size() != 0) { dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string()); } - AudioPort::dump(dst, spaces, verbose); + std::string portStr; + AudioPort::dump(&portStr, spaces, verbose); + dst->append(portStr.c_str()); } std::string DeviceDescriptor::toString() const diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp index 99e282e872..c232775f12 100644 --- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp @@ -41,7 +41,7 @@ HwModule::~HwModule() } } -status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config, +status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address) { sp profile = new OutputProfile(name); @@ -95,7 +95,7 @@ void HwModule::setProfiles(const IOProfileCollection &profiles) } } -status_t HwModule::removeOutputProfile(const String8& name) +status_t HwModule::removeOutputProfile(const std::string& name) { for (size_t i = 0; i < mOutputProfiles.size(); i++) { if (mOutputProfiles[i]->getName() == name) { @@ -110,7 +110,7 @@ status_t HwModule::removeOutputProfile(const String8& name) return NO_ERROR; } -status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config, +status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address) { sp profile = new InputProfile(name); @@ -125,12 +125,12 @@ status_t HwModule::addInputProfile(const String8& name, const audio_config_t *co profile->addSupportedDevice(devDesc); ALOGV("addInputProfile() name %s rate %d mask 0x%08x", - name.string(), config->sample_rate, config->channel_mask); + name.c_str(), config->sample_rate, config->channel_mask); return addInputProfile(profile); } -status_t HwModule::removeInputProfile(const String8& name) +status_t HwModule::removeInputProfile(const std::string& name) { for (size_t i = 0; i < mInputProfiles.size(); i++) { if (mInputProfiles[i]->getName() == name) { @@ -193,13 +193,13 @@ void HwModule::refreshSupportedDevices() } DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route); if (sourceDevicesForRoute.isEmpty()) { - ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); + ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str()); continue; } sourceDevices.add(sourceDevicesForRoute); } if (sourceDevices.isEmpty()) { - ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); + ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str()); continue; } stream->setSupportedDevices(sourceDevices); @@ -214,7 +214,7 @@ void HwModule::refreshSupportedDevices() } sp sinkDevice = getRouteSinkDevice(route); if (sinkDevice == 0) { - ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string()); + ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str()); continue; } sinkDevices.add(sinkDevice); @@ -335,7 +335,7 @@ sp HwModuleCollection::getDeviceDescriptor(const audio_devices if (allowToCreate) { moduleDevice->attach(hwModule); moduleDevice->setAddress(devAddress); - moduleDevice->setName(String8(name)); + moduleDevice->setName(name); } return moduleDevice; } @@ -359,8 +359,8 @@ sp HwModuleCollection::createDevice(const audio_devices_t type address); return nullptr; } - sp device = new DeviceDescriptor(type, String8(name)); - device->setName(String8(name)); + sp device = new DeviceDescriptor(type, name); + device->setName(name); device->setAddress(String8(address)); device->setEncodedFormat(encodedFormat); diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp index aefe557508..bf1a0f7182 100644 --- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp @@ -107,7 +107,9 @@ bool IOProfile::isCompatibleProfile(const DeviceVector &devices, void IOProfile::dump(String8 *dst) const { - AudioPort::dump(dst, 4); + std::string portStr; + AudioPort::dump(&portStr, 4); + dst->append(portStr.c_str()); dst->appendFormat(" - flags: 0x%04x", getFlags()); std::string flagsLiteral; diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp index 09cbe1a4f6..707169b10b 100644 --- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp @@ -430,7 +430,7 @@ Return MixPortTraits::deserialize(const xmlNode *child, audio_port_role_t portRole = (role == Attributes::roleSource) ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; - Element mixPort = new IOProfile(String8(name.c_str()), portRole); + Element mixPort = new IOProfile(name, portRole); AudioProfileTraits::Collection profiles; status_t status = deserializeCollection(child, &profiles, NULL); @@ -508,7 +508,7 @@ Return DevicePortTraits::deserialize(const xmlNode *c if (!encodedFormatsLiteral.empty()) { encodedFormats = formatsFromString(encodedFormatsLiteral, " "); } - Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str())); + Element deviceDesc = new DeviceDescriptor(type, encodedFormats, name); std::string address = getXmlAttribute(cur, Attributes::address); if (!address.empty()) { @@ -532,7 +532,7 @@ Return DevicePortTraits::deserialize(const xmlNode *c return Status::fromStatusT(status); } ALOGV("%s: adding device tag %s type %08x address %s", __func__, - deviceDesc->getName().string(), type, deviceDesc->address().string()); + deviceDesc->getName().c_str(), type, deviceDesc->address().string()); return deviceDesc; } @@ -555,7 +555,7 @@ Return RouteTraits::deserialize(const xmlNode *cur, PtrSer return Status::fromStatusT(BAD_VALUE); } // Convert Sink name to port pointer - sp sink = ctx->findPortByTagName(String8(sinkAttr.c_str())); + sp sink = ctx->findPortByTagName(sinkAttr); if (sink == NULL) { ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str()); return Status::fromStatusT(BAD_VALUE); @@ -574,7 +574,7 @@ Return RouteTraits::deserialize(const xmlNode *cur, PtrSer char *devTag = strtok(sourcesLiteral.get(), ","); while (devTag != NULL) { if (strlen(devTag) != 0) { - sp source = ctx->findPortByTagName(String8(devTag)); + sp source = ctx->findPortByTagName(devTag); if (source == NULL) { ALOGE("%s: no source found with name=%s", __func__, devTag); return Status::fromStatusT(BAD_VALUE); @@ -648,7 +648,7 @@ Return ModuleTraits::deserialize(const xmlNode *cur, PtrS ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, reinterpret_cast(attachedDevice.get())); sp device = module->getDeclaredDevices(). - getDeviceFromTagName(String8(reinterpret_cast( + getDeviceFromTagName(std::string(reinterpret_cast( attachedDevice.get()))); ctx->addAvailableDevice(device); } @@ -663,7 +663,7 @@ Return ModuleTraits::deserialize(const xmlNode *cur, PtrS ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, reinterpret_cast(defaultOutputDevice.get())); sp device = module->getDeclaredDevices().getDeviceFromTagName( - String8(reinterpret_cast(defaultOutputDevice.get()))); + std::string(reinterpret_cast(defaultOutputDevice.get()))); if (device != 0 && ctx->getDefaultOutputDevice() == 0) { ctx->setDefaultOutputDevice(device); ALOGV("%s: default is %08x", diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index cbc46d5324..b895c2feec 100644 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -342,7 +342,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy, // compressed format as they would likely not be mixed and dropped. for (size_t i = 0; i < outputs.size(); i++) { sp desc = outputs.valueAt(i); - if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat)) { + if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) { availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask( AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC)); diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 630091e569..28eb2635e1 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -1206,9 +1206,9 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices( if (!desc->isDuplicated() && (profile == desc->mProfile)) { // reuse direct output if currently open by the same client // and configured with same parameters - if ((config->sample_rate == desc->mSamplingRate) && - (config->format == desc->mFormat) && - (channelMask == desc->mChannelMask) && + if ((config->sample_rate == desc->getSamplingRate()) && + (config->format == desc->getFormat()) && + (channelMask == desc->getChannelMask()) && (session == desc->mDirectClientSession)) { desc->mDirectOpenCount++; ALOGI("%s reusing direct output %d for session %d", __func__, @@ -1248,13 +1248,13 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices( // only accept an output with the requested parameters if (status != NO_ERROR || - (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) || - (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) || - (channelMask != 0 && channelMask != outputDesc->mChannelMask)) { + (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) || + (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) || + (channelMask != 0 && channelMask != outputDesc->getChannelMask())) { ALOGV("%s failed opening direct output: output %d sample rate %d %d," "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate, - outputDesc->mSamplingRate, config->format, outputDesc->mFormat, - channelMask, outputDesc->mChannelMask); + outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(), + channelMask, outputDesc->getChannelMask()); if (output != AUDIO_IO_HANDLE_NONE) { outputDesc->close(); } @@ -1525,13 +1525,13 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVectormChannelMask & AUDIO_CHANNEL_HAPTIC_ALL); + outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL); if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) { continue; } if (outputHapticChannelCount >= hapticChannelCount - && format == outputDesc->mFormat - && samplingRate == outputDesc->mSamplingRate) { + && format == outputDesc->getFormat() + && samplingRate == outputDesc->getSamplingRate()) { currentMatchCriteria[0] = outputHapticChannelCount; } @@ -1539,12 +1539,13 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVectormFlags & functionalFlags); // channel mask and channel count match - uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask); + uint32_t outputChannelCount = audio_channel_count_from_out_mask( + outputDesc->getChannelMask()); if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 && channelCount <= outputChannelCount) { if ((audio_channel_mask_get_representation(channelMask) == - audio_channel_mask_get_representation(outputDesc->mChannelMask)) && - ((channelMask & outputDesc->mChannelMask) == channelMask)) { + audio_channel_mask_get_representation(outputDesc->getChannelMask())) && + ((channelMask & outputDesc->getChannelMask()) == channelMask)) { currentMatchCriteria[2] = outputChannelCount; } currentMatchCriteria[3] = outputChannelCount; @@ -1552,8 +1553,8 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector SAMPLE_RATE_HZ_DEFAULT && - samplingRate <= outputDesc->mSamplingRate) { - currentMatchCriteria[4] = outputDesc->mSamplingRate; + samplingRate <= outputDesc->getSamplingRate()) { + currentMatchCriteria[4] = outputDesc->getSamplingRate(); } // performance flags match @@ -1563,7 +1564,7 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVectormFormat); + AudioPort::formatDistance(format, outputDesc->getFormat()); } // primary output match @@ -2922,9 +2923,9 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector& mixes) // stereo and let audio flinger do the channel conversion if needed. outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO; - rSubmixModule->addOutputProfile(address, &outputConfig, + rSubmixModule->addOutputProfile(address.c_str(), &outputConfig, AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address); - rSubmixModule->addInputProfile(address, &inputConfig, + rSubmixModule->addInputProfile(address.c_str(), &inputConfig, AUDIO_DEVICE_IN_REMOTE_SUBMIX, address); if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable, @@ -3020,8 +3021,8 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector mixes) } } } - rSubmixModule->removeOutputProfile(address); - rSubmixModule->removeInputProfile(address); + rSubmixModule->removeOutputProfile(address.c_str()); + rSubmixModule->removeInputProfile(address.c_str()); } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) { if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) { @@ -3233,7 +3234,7 @@ bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& conf ALOGV("%s() profile %sfound with name: %s, " "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x", __FUNCTION__, profile != 0 ? "" : "NOT ", - (profile != 0 ? profile->getTagName().string() : "null"), + (profile != 0 ? profile->getTagName().c_str() : "null"), config.sample_rate, config.format, config.channel_mask, output_flags); return (profile != 0); } @@ -3897,7 +3898,7 @@ status_t AudioPolicyManager::connectAudioSource(const sp if (srcDevice->hasSameHwModuleAs(sinkDevice) && srcDevice->getModuleVersionMajor() >= 3 && sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) && - srcDevice->getAudioPort()->mGains.size() > 0) { + srcDevice->getAudioPort()->getGains().size() > 0) { ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__); // TODO: may explicitly specify whether we should use HW or SW patch // create patch between src device and output device @@ -4137,7 +4138,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat for (size_t i = 0; i < hdmiOutputDevices.size(); i++) { // Simulate reconnection to update enabled surround sound formats. String8 address = hdmiOutputDevices[i]->address(); - String8 name = hdmiOutputDevices[i]->getName(); + std::string name = hdmiOutputDevices[i]->getName(); status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, address.c_str(), @@ -4159,7 +4160,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat for (size_t i = 0; i < hdmiInputDevices.size(); i++) { // Simulate reconnection to update enabled surround sound formats. String8 address = hdmiInputDevices[i]->address(); - String8 name = hdmiInputDevices[i]->getName(); + std::string name = hdmiInputDevices[i]->getName(); status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, address.c_str(), @@ -4642,7 +4643,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp& d } ALOGV("opening output for device %08x with params %s profile %p name %s", - deviceType, address.string(), profile.get(), profile->getName().string()); + deviceType, address.string(), profile.get(), profile->getName().c_str()); desc = new SwAudioOutputDescriptor(profile, mpClientInterface); audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; status_t status = desc->open(nullptr, DeviceVector(device), diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp index e10a7167f8..975ce8fd08 100644 --- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp +++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp @@ -317,12 +317,11 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) { mMsdOutputDevice->attach(msdModule); mMsdInputDevice->attach(msdModule); - sp msdOutputProfile = new OutputProfile(String8("msd input")); + sp msdOutputProfile = new OutputProfile("msd input"); msdOutputProfile->addAudioProfile(pcmOutputProfile); msdOutputProfile->addSupportedDevice(mMsdOutputDevice); msdModule->addOutputProfile(msdOutputProfile); - sp msdCompressedOutputProfile = - new OutputProfile(String8("msd compressed input")); + sp msdCompressedOutputProfile = new OutputProfile("msd compressed input"); msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile); msdCompressedOutputProfile->setFlags( AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | @@ -330,7 +329,7 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) { msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice); msdModule->addOutputProfile(msdCompressedOutputProfile); - sp msdInputProfile = new InputProfile(String8("msd output")); + sp msdInputProfile = new InputProfile("msd output"); msdInputProfile->addAudioProfile(pcmInputProfile); msdInputProfile->addSupportedDevice(mMsdInputDevice); msdModule->addInputProfile(msdInputProfile); @@ -340,7 +339,7 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) { sp dtsOutputProfile = new AudioProfile( AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000); config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile); - sp primaryEncodedOutputProfile = new OutputProfile(String8("encoded")); + sp primaryEncodedOutputProfile = new OutputProfile("encoded"); primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile); primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT); primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());