Merge "APM: support product strategy routing"

am: 2c76260fb4

Change-Id: I9e96bef513f9b9c5467cdc8ca24f0e8635b819fc
gugelfrei
Jean-Michel Trivi 5 years ago committed by android-build-merger
commit deee129099

@ -1525,6 +1525,35 @@ status_t AudioSystem::setRttEnabled(bool enabled)
return aps->setRttEnabled(enabled);
}
status_t AudioSystem::setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
return aps->setPreferredDeviceForStrategy(strategy, device);
}
status_t AudioSystem::removePreferredDeviceForStrategy(product_strategy_t strategy)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
return aps->removePreferredDeviceForStrategy(strategy);
}
status_t AudioSystem::getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
return aps->getPreferredDeviceForStrategy(strategy, device);
}
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(

@ -104,7 +104,10 @@ enum {
GET_VOLUME_GROUP_FOR_ATTRIBUTES,
SET_ALLOWED_CAPTURE_POLICY,
MOVE_EFFECTS_TO_IO,
SET_RTT_ENABLED
SET_RTT_ENABLED,
SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
};
#define MAX_ITEMS_PER_LIST 1024
@ -1284,6 +1287,55 @@ public:
}
return static_cast<status_t>(reply.readInt32());
}
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeUint32(static_cast<uint32_t>(strategy));
status_t status = device.writeToParcel(&data);
if (status != NO_ERROR) {
return BAD_VALUE;
}
status = remote()->transact(SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
data, &reply);
if (status != NO_ERROR) {
return status;
}
return static_cast<status_t>(reply.readInt32());
}
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeUint32(static_cast<uint32_t>(strategy));
status_t status = remote()->transact(REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
data, &reply);
if (status != NO_ERROR) {
return status;
}
return static_cast<status_t>(reply.readInt32());
}
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeUint32(static_cast<uint32_t>(strategy));
status_t status = remote()->transact(GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
data, &reply);
if (status != NO_ERROR) {
return status;
}
status = device.readFromParcel(&reply);
if (status != NO_ERROR) {
return status;
}
return static_cast<status_t>(reply.readInt32());
}
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@ -1346,7 +1398,10 @@ status_t BnAudioPolicyService::onTransact(
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
case SET_RTT_ENABLED: {
case SET_RTT_ENABLED:
case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@ -2369,6 +2424,40 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
}
case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
AudioDeviceTypeAddr device;
status_t status = device.readFromParcel((Parcel*)&data);
if (status != NO_ERROR) {
return status;
}
status = setPreferredDeviceForStrategy(strategy, device);
reply->writeInt32(status);
return NO_ERROR;
}
case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
status_t status = removePreferredDeviceForStrategy(strategy);
reply->writeInt32(status);
return NO_ERROR;
}
case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
AudioDeviceTypeAddr device;
status_t status = getPreferredDeviceForStrategy(strategy, device);
status_t marshall_status = device.writeToParcel(reply);
if (marshall_status != NO_ERROR) {
return marshall_status;
}
reply->writeInt32(status);
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -403,6 +403,17 @@ public:
*/
static status_t setAudioHalPids(const std::vector<pid_t>& pids);
static status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device);
static status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
static status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
static status_t getDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
// ----------------------------------------------------------------------------
class AudioVolumeGroupCallback : public RefBase

@ -223,6 +223,14 @@ public:
volume_group_t &volumeGroup) = 0;
virtual status_t setRttEnabled(bool enabled) = 0;
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) = 0;
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) = 0;
};

@ -37,6 +37,8 @@ struct AudioDeviceTypeAddr : public Parcelable {
bool equals(const AudioDeviceTypeAddr& other) const;
AudioDeviceTypeAddr& operator= (const AudioDeviceTypeAddr&) = default;
void reset();
status_t readFromParcel(const Parcel *parcel) override;

@ -271,6 +271,14 @@ public:
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup) = 0;
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) = 0;
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) = 0;
};

@ -93,6 +93,13 @@ public:
void dump(String8 *dst) const override;
status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) override;
status_t removePreferredDeviceForStrategy(product_strategy_t strategy) override;
status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) const override;
engineConfig::ParsingResult loadAudioPolicyEngineConfig();
@ -124,6 +131,7 @@ private:
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
VolumeGroupMap mVolumeGroups;
LastRemovableMediaDevices mLastRemovableMediaDevices;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */

@ -28,6 +28,7 @@
#include <utils/String8.h>
#include <media/AudioAttributes.h>
#include <media/AudioContainers.h>
#include <media/AudioPolicy.h>
namespace android {
@ -163,4 +164,10 @@ private:
product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t, AudioDeviceTypeAddr>
{
public:
void dump(String8 *dst, int spaces = 0) const;
};
} // namespace android

@ -283,9 +283,57 @@ status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
return NO_ERROR;
}
status_t EngineBase::setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device)
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
ALOGE("%s invalid strategy %u", __func__, strategy);
return BAD_VALUE;
}
mProductStrategyPreferredDevices[strategy] = device;
return NO_ERROR;
}
status_t EngineBase::removePreferredDeviceForStrategy(product_strategy_t strategy)
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
ALOGE("%s invalid strategy %u", __func__, strategy);
return BAD_VALUE;
}
if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
// no preferred device was set
return NAME_NOT_FOUND;
}
return NO_ERROR;
}
status_t EngineBase::getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) const
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
ALOGE("%s unknown strategy %u", __func__, strategy);
return BAD_VALUE;
}
// preferred device for this strategy?
auto devIt = mProductStrategyPreferredDevices.find(strategy);
if (devIt == mProductStrategyPreferredDevices.end()) {
ALOGV("%s no preferred device for strategy %u", __func__, strategy);
return NAME_NOT_FOUND;
}
device = devIt->second;
return NO_ERROR;
}
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);
mProductStrategyPreferredDevices.dump(dst, 2);
mVolumeGroups.dump(dst, 2);
}

@ -310,5 +310,15 @@ void ProductStrategyMap::dump(String8 *dst, int spaces) const
}
}
void ProductStrategyPreferredRoutingMap::dump(android::String8* dst, int spaces) const {
dst->appendFormat("\n%*sPreferred devices per product strategy dump:", spaces, "");
for (const auto& iter : *this) {
dst->appendFormat("\n%*sStrategy %u dev:%08x addr:%s",
spaces + 2, "",
(uint32_t) iter.first,
iter.second.mType, iter.second.mAddress.c_str());
}
dst->appendFormat("\n");
}
}

@ -292,6 +292,39 @@ public:
*/
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
/**
* @brief setPreferredDeviceForStrategy sets the default device to be used for a
* strategy when available
* @param strategy the audio strategy whose routing will be affected
* @param device the audio device to route to when available
* @return BAD_VALUE if the strategy is invalid,
* or NO_ERROR if the preferred device was set
*/
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) = 0;
/**
* @brief removePreferredDeviceForStrategy removes the preferred device previously set
* for the given strategy
* @param strategy the audio strategy whose routing will be affected
* @return BAD_VALUE if the strategy is invalid,
* or NO_ERROR if the preferred device was removed
*/
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
/**
* @brief getPreferredDeviceForStrategy queries which device is set as the
* preferred device for the given strategy
* @param strategy the strategy to query
* @param device returns configured as the preferred device if one was set
* @return BAD_VALUE if the strategy is invalid,
* or NAME_NOT_FOUND if no preferred device was set
* or NO_ERROR if the device parameter was initialized to the preferred device
*/
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) const = 0;
virtual void dump(String8 *dst) const = 0;
protected:

@ -604,7 +604,7 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
void Engine::updateDeviceSelectionCache()
{
for (const auto &iter : getProductStrategies()) {
const auto &strategy = iter.second;
const auto& strategy = iter.second;
auto devices = getDevicesForProductStrategy(strategy->getId());
mDevicesForStrategies[strategy->getId()] = devices;
strategy->setDeviceTypes(devices.types());
@ -612,14 +612,30 @@ void Engine::updateDeviceSelectionCache()
}
}
DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const
{
DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
// check if this strategy has a preferred device that is available,
// if yes, give priority to it
AudioDeviceTypeAddr preferredStrategyDevice;
const status_t status = getPreferredDeviceForStrategy(strategy, preferredStrategyDevice);
if (status == NO_ERROR) {
// there is a preferred device, is it available?
sp<DeviceDescriptor> preferredAvailableDevDescr = availableOutputDevices.getDevice(
preferredStrategyDevice.mType,
String8(preferredStrategyDevice.mAddress.c_str()),
AUDIO_FORMAT_DEFAULT);
if (preferredAvailableDevDescr != nullptr) {
ALOGVV("%s using pref device 0x%08x/%s for strategy %u", __FUNCTION__,
preferredStrategyDevice.mType, preferredStrategyDevice.mAddress, strategy);
return DeviceVector(preferredAvailableDevDescr);
}
}
DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices,
availableInputDevices, outputs);

@ -794,27 +794,11 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
//FIXME: workaround for truncated touch sounds
// to be removed when the problem is handled by system UI
uint32_t delayMs = 0;
uint32_t waitMs = 0;
if (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) {
delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
}
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
waitMs = updateCallRouting(newDevices, delayMs);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
// As done in setDeviceConnectionState, we could also fix default device issue by
// preventing the force re-routing in case of default dev that distinguishes on address.
// Let's give back to engine full device choice decision however.
waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
}
if (forceVolumeReeval && !newDevices.isEmpty()) {
applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
}
}
updateCallAndOutputRouting(forceVolumeReeval, delayMs);
for (const auto& activeDesc : mInputs.getActiveInputs()) {
auto newDevice = getNewInputDevice(activeDesc);
@ -3084,6 +3068,72 @@ status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
return res;
}
status_t AudioPolicyManager::setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) {
ALOGI("%s() strategy=%d device=%08x addr=%s", __FUNCTION__,
strategy, device.mType, device.mAddress.c_str());
// strategy preferred device is only for output devices
if (!audio_is_output_device(device.mType)) {
ALOGE("%s() device=%08x is NOT an output device", __FUNCTION__, device.mType);
return BAD_VALUE;
}
status_t status = mEngine->setPreferredDeviceForStrategy(strategy, device);
if (status != NO_ERROR) {
ALOGW("Engine could not set preferred device %08x %s for strategy %d",
device.mType, device.mAddress.c_str(), strategy);
return status;
}
checkForDeviceAndOutputChanges();
updateCallAndOutputRouting();
return NO_ERROR;
}
void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs)
{
uint32_t waitMs = 0;
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
waitMs = updateCallRouting(newDevices, delayMs);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
// As done in setDeviceConnectionState, we could also fix default device issue by
// preventing the force re-routing in case of default dev that distinguishes on address.
// Let's give back to engine full device choice decision however.
waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
}
if (forceVolumeReeval && !newDevices.isEmpty()) {
applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
}
}
}
status_t AudioPolicyManager::removePreferredDeviceForStrategy(product_strategy_t strategy)
{
ALOGI("%s() strategy=%d", __FUNCTION__, strategy);
status_t status = mEngine->removePreferredDeviceForStrategy(strategy);
if (status != NO_ERROR) {
ALOGW("Engine could not remove preferred device for strategy %d", strategy);
return status;
}
checkForDeviceAndOutputChanges();
updateCallAndOutputRouting();
return NO_ERROR;
}
status_t AudioPolicyManager::getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device) {
return mEngine->getPreferredDeviceForStrategy(strategy, device);
}
void AudioPolicyManager::dump(String8 *dst) const
{
dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@ -5056,6 +5106,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr
DeviceVector oldDevices = mEngine->getOutputDevicesForAttributes(attr, 0, true /*fromCache*/);
DeviceVector newDevices = mEngine->getOutputDevicesForAttributes(attr, 0, false /*fromCache*/);
SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);

@ -258,6 +258,12 @@ public:
const Vector<AudioDeviceTypeAddr>& devices);
virtual status_t removeUidDeviceAffinities(uid_t uid);
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device);
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId,
@ -496,12 +502,18 @@ protected:
// close an input.
void closeInput(audio_io_handle_t input);
// runs all the checks required for accomodating changes in devices and outputs
// runs all the checks required for accommodating changes in devices and outputs
// if 'onOutputsChecked' callback is provided, it is executed after the outputs
// check via 'checkOutputForAllStrategies'. If the callback returns 'true',
// A2DP suspend status is rechecked.
void checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked = nullptr);
/**
* @brief updates routing for all outputs (including call if call in progress).
* @param delayMs delay for unmuting if required
*/
void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
/**
* @brief checkOutputForAttributes checks and if necessary changes outputs used for the
* given audio attributes.

@ -1325,4 +1325,33 @@ status_t AudioPolicyService::setRttEnabled(bool enabled)
return NO_ERROR;
}
status_t AudioPolicyService::setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->setPreferredDeviceForStrategy(strategy, device);
}
status_t AudioPolicyService::removePreferredDeviceForStrategy(product_strategy_t strategy)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->removePreferredDeviceForStrategy(strategy);
}
status_t AudioPolicyService::getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getPreferredDeviceForStrategy(strategy, device);
}
} // namespace android

@ -224,6 +224,15 @@ public:
virtual status_t removeUidDeviceAffinities(uid_t uid);
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device);
virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);

Loading…
Cancel
Save