Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28d09f06 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: improve accessibility volume

Fix some regressions caused by the introduction of accessibility
stream type and strategy in M.

- change the way ACCESSIBILITY usage maps to a given strategy: always map
to strategy ACCESSIBILITY but implement a specific device selection for
strategy ACCESSIBILITY in getDeviceForStrategy(). This makes sure that
accessibility prompts always use ACCESSIBILITY stream type.

- optimize getDeviceForStrategy() to avoid reloading the list of outputs
and devices from the observer when called recursively.

-  make sure that all volume APIs also take into account ACCESSIBILITY stream
when called for MUSIC stream. Generalize the concept of matching strategies
for straqegies that should be considered equivalent for volume control.
Modifications in:
- initStreamVolume()
- setStreamVolumeIndex()
- isStreamActive()
- getDevicesForStream()

Bug: 25067903
Bug: 25616373
Change-Id: Id8c7dd3231f79572b278407bc73186fc42dcc028
parent 9322ba85
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -142,6 +142,8 @@ routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t
{
{
    const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
    const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();


    //FIXME: getStrategyForUsage() should return STRATEGY_ACCESSIBILITY and getDeviceForStrategy()
    // should be implemented accordingly for STRATEGY_ACCESSIBILITY
    if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
    if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
            (outputs.isStreamActive(AUDIO_STREAM_RING) ||
            (outputs.isStreamActive(AUDIO_STREAM_RING) ||
             outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
             outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
+44 −21
Original line number Original line Diff line number Diff line
@@ -195,18 +195,9 @@ routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream)


routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
{
{
    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();

    // usage to strategy mapping
    // usage to strategy mapping
    switch (usage) {
    switch (usage) {
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
                outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
            return STRATEGY_SONIFICATION;
        }
        if (isInCall()) {
            return STRATEGY_PHONE;
        }
        return STRATEGY_ACCESSIBILITY;
        return STRATEGY_ACCESSIBILITY;


    case AUDIO_USAGE_MEDIA:
    case AUDIO_USAGE_MEDIA:
@@ -245,6 +236,17 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const


    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();


    return getDeviceForStrategyInt(strategy, (DeviceVector&)availableOutputDevices,
                                   availableInputDevices, outputs);
}



audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
                                                DeviceVector &availableOutputDevices,
                                                const DeviceVector &availableInputDevices,
                                                const SwAudioOutputCollection &outputs) const
{
    uint32_t device = AUDIO_DEVICE_NONE;
    uint32_t device = AUDIO_DEVICE_NONE;
    uint32_t availableOutputDevicesType = availableOutputDevices.types();
    uint32_t availableOutputDevicesType = availableOutputDevices.types();


@@ -260,14 +262,16 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const


    case STRATEGY_SONIFICATION_RESPECTFUL:
    case STRATEGY_SONIFICATION_RESPECTFUL:
        if (isInCall()) {
        if (isInCall()) {
            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
            device = getDeviceForStrategyInt(
                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
        } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
        } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
                SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
                SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing on a remote device, use the the sonification behavior.
            // while media is playing on a remote device, use the the sonification behavior.
            // Note that we test this usecase before testing if media is playing because
            // Note that we test this usecase before testing if media is playing because
            //   the isStreamActive() method only informs about the activity of a stream, not
            //   the isStreamActive() method only informs about the activity of a stream, not
            //   if it's for local playback. Note also that we use the same delay between both tests
            //   if it's for local playback. Note also that we use the same delay between both tests
            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
            device = getDeviceForStrategyInt(
                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //other acoustic safety mechanisms for notification
            //other acoustic safety mechanisms for notification
            if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
            if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
@@ -275,12 +279,15 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
                device &= ~AUDIO_DEVICE_OUT_SPEAKER;
                device &= ~AUDIO_DEVICE_OUT_SPEAKER;
            }
            }
        } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
        } else if (outputs.isStreamActive(
                                AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing (or has recently played), use the same device
            // while media is playing (or has recently played), use the same device
            device = getDeviceForStrategy(STRATEGY_MEDIA);
            device = getDeviceForStrategyInt(
                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
        } else {
        } else {
            // when media is not playing anymore, fall back on the sonification behavior
            // when media is not playing anymore, fall back on the sonification behavior
            device = getDeviceForStrategy(STRATEGY_SONIFICATION);
            device = getDeviceForStrategyInt(
                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //other acoustic safety mechanisms for notification
            //other acoustic safety mechanisms for notification
            if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
            if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
@@ -294,7 +301,8 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
    case STRATEGY_DTMF:
    case STRATEGY_DTMF:
        if (!isInCall()) {
        if (!isInCall()) {
            // when off call, DTMF strategy follows the same rules as MEDIA strategy
            // when off call, DTMF strategy follows the same rules as MEDIA strategy
            device = getDeviceForStrategy(STRATEGY_MEDIA);
            device = getDeviceForStrategyInt(
                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
            break;
            break;
        }
        }
        // when in call, DTMF and PHONE strategies follow the same rules
        // when in call, DTMF and PHONE strategies follow the same rules
@@ -321,8 +329,8 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
                availableOutputDevicesType = availPrimaryOutputDevices;
                availableOutputDevicesType = availPrimaryOutputDevices;
            }
            }
        }
        }
        // for phone strategy, we first consider the forced use and then the available devices by order
        // for phone strategy, we first consider the forced use and then the available devices by
        // of priority
        // order of priority
        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
        switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
        case AUDIO_POLICY_FORCE_BT_SCO:
        case AUDIO_POLICY_FORCE_BT_SCO:
            if (!isInCall() || strategy != STRATEGY_DTMF) {
            if (!isInCall() || strategy != STRATEGY_DTMF) {
@@ -408,7 +416,8 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
        // handleIncallSonification().
        // handleIncallSonification().
        if (isInCall()) {
        if (isInCall()) {
            device = getDeviceForStrategy(STRATEGY_PHONE);
            device = getDeviceForStrategyInt(
                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
            break;
            break;
        }
        }
        // FALL THROUGH
        // FALL THROUGH
@@ -429,7 +438,6 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
        // The second device used for sonification is the same as the device used by media strategy
        // The second device used for sonification is the same as the device used by media strategy
        // FALL THROUGH
        // FALL THROUGH


    // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
    case STRATEGY_ACCESSIBILITY:
    case STRATEGY_ACCESSIBILITY:
        if (strategy == STRATEGY_ACCESSIBILITY) {
        if (strategy == STRATEGY_ACCESSIBILITY) {
            // do not route accessibility prompts to a digital output currently configured with a
            // do not route accessibility prompts to a digital output currently configured with a
@@ -443,20 +451,35 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
                    availableOutputDevicesType = availableOutputDevices.types() & ~devices;
                    availableOutputDevicesType = availableOutputDevices.types() & ~devices;
                }
                }
            }
            }
            availableOutputDevices =
                    availableOutputDevices.getDevicesFromType(availableOutputDevicesType);
            if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
                    outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
                return getDeviceForStrategyInt(
                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
            }
            if (isInCall()) {
                return getDeviceForStrategyInt(
                        STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
            }
        }
        }
        // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
        // FALL THROUGH
        // FALL THROUGH


    // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
    case STRATEGY_REROUTING:
    case STRATEGY_REROUTING:
    case STRATEGY_MEDIA: {
    case STRATEGY_MEDIA: {
        uint32_t device2 = AUDIO_DEVICE_NONE;
        uint32_t device2 = AUDIO_DEVICE_NONE;
        if (strategy != STRATEGY_SONIFICATION) {
        if (strategy != STRATEGY_SONIFICATION) {
            // no sonification on remote submix (e.g. WFD)
            // no sonification on remote submix (e.g. WFD)
            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                                                 String8("0")) != 0) {
                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
            }
            }
        }
        }
        if (isInCall() && (strategy == STRATEGY_MEDIA)) {
        if (isInCall() && (strategy == STRATEGY_MEDIA)) {
            device = getDeviceForStrategy(STRATEGY_PHONE);
            device = getDeviceForStrategyInt(
                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
            break;
            break;
        }
        }
        if ((device2 == AUDIO_DEVICE_NONE) &&
        if ((device2 == AUDIO_DEVICE_NONE) &&
+4 −0
Original line number Original line Diff line number Diff line
@@ -125,6 +125,10 @@ private:
    routing_strategy getStrategyForStream(audio_stream_type_t stream);
    routing_strategy getStrategyForStream(audio_stream_type_t stream);
    routing_strategy getStrategyForUsage(audio_usage_t usage);
    routing_strategy getStrategyForUsage(audio_usage_t usage);
    audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
    audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
    audio_devices_t getDeviceForStrategyInt(routing_strategy strategy,
                                            DeviceVector &availableOutputDevices,
                                            const DeviceVector &availableInputDevices,
                                            const SwAudioOutputCollection &outputs) const;
    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
    audio_mode_t mPhoneState;  /**< current phone state. */
    audio_mode_t mPhoneState;  /**< current phone state. */


+79 −60
Original line number Original line Diff line number Diff line
@@ -1794,8 +1794,15 @@ void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
{
{
    ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
    ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
    mVolumeCurves->initStreamVolume(stream, indexMin, indexMax);
    mVolumeCurves->initStreamVolume(stream, indexMin, indexMax);
    if (stream == AUDIO_STREAM_MUSIC) {

        mVolumeCurves->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
    // initialize other private stream volumes which follow this one
    routing_strategy strategy = getStrategy(stream);
    for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
        routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
        if (!strategiesMatchForvolume(strategy, curStrategy)) {
            continue;
        }
        mVolumeCurves->initStreamVolume((audio_stream_type_t)curStream, indexMin, indexMax);
    }
    }
}
}


@@ -1823,38 +1830,43 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
    if (device == AUDIO_DEVICE_OUT_DEFAULT) {
    if (device == AUDIO_DEVICE_OUT_DEFAULT) {
        mVolumeCurves->clearCurrentVolumeIndex(stream);
        mVolumeCurves->clearCurrentVolumeIndex(stream);
    }
    }
    mVolumeCurves->addCurrentVolumeIndex(stream, device, index);

    // update volume on all outputs whose current device is also selected by the same
    // strategy as the device specified by the caller
    audio_devices_t selectedDevices = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
    // it is possible that the requested device is not selected by the strategy (e.g an explicit
    // audio patch is active causing getDevicesForStream() to return this device. We must make
    // sure that the device passed is part of the devices considered when applying volume below.
    selectedDevices |= device;


    //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
    // update other private stream volumes which follow this one
    audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
    routing_strategy strategy = getStrategy(stream);
    if (stream == AUDIO_STREAM_MUSIC) {
    for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
        mVolumeCurves->addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
        routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
        accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
        if (!strategiesMatchForvolume(strategy, curStrategy)) {
            continue;
        }
        mVolumeCurves->addCurrentVolumeIndex((audio_stream_type_t)curStream, device, index);
    }
    }


    // update volume on all outputs whose current device is also selected by the same
    // strategy as the device specified by the caller
    status_t status = NO_ERROR;
    status_t status = NO_ERROR;
    for (size_t i = 0; i < mOutputs.size(); i++) {
    for (size_t i = 0; i < mOutputs.size(); i++) {
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
        audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
        if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & selectedDevices) != 0)) {
        for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
            status_t volStatus = checkAndSetVolume(stream, index, desc, curDevice);
            routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
            if (!strategiesMatchForvolume(strategy, curStrategy)) {
                continue;
            }
            audio_devices_t curStreamDevice = getDeviceForStrategy(curStrategy, true /*fromCache*/);
            // it is possible that the requested device is not selected by the strategy
            // (e.g an explicit audio patch is active causing getDevicesForStream()
            // to return this device. We must make sure that the device passed is part of the
            // devices considered when applying volume below.
            curStreamDevice |= device;

            if (((device == AUDIO_DEVICE_OUT_DEFAULT) ||
                    ((curDevice & curStreamDevice) != 0))) {
                status_t volStatus =
                        checkAndSetVolume((audio_stream_type_t)curStream, index, desc, curDevice);
                if (volStatus != NO_ERROR) {
                if (volStatus != NO_ERROR) {
                    status = volStatus;
                    status = volStatus;
                }
                }
            }
            }
        if ((accessibilityDevice != AUDIO_DEVICE_NONE) &&
                ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)))
        {
            status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
                                                   index, desc, curDevice);
        }
        }
    }
    }
    return status;
    return status;
@@ -1957,7 +1969,17 @@ status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc,


bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
{
    return mOutputs.isStreamActive(stream, inPastMs);
    bool active = false;
    routing_strategy strategy = getStrategy(stream);
    for (int curStream = 0; curStream < AUDIO_STREAM_CNT && !active; curStream++) {
        routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
        if (!strategiesMatchForvolume(strategy, curStrategy)) {
            continue;
        }
        active = mOutputs.isStreamActive((audio_stream_type_t)curStream, inPastMs);
    }

    return active;
}
}


bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
@@ -2838,7 +2860,7 @@ status_t AudioPolicyManager::connectAudioSource(const sp<AudioSourceDescriptor>&
    disconnectAudioSource(sourceDesc);
    disconnectAudioSource(sourceDesc);


    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&sourceDesc->mAttributes);
    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&sourceDesc->mAttributes);
    audio_stream_type_t stream = audio_attributes_to_stream_type(&sourceDesc->mAttributes);
    audio_stream_type_t stream = streamTypefromAttributesInt(&sourceDesc->mAttributes);
    sp<DeviceDescriptor> srcDeviceDesc = sourceDesc->mDevice;
    sp<DeviceDescriptor> srcDeviceDesc = sourceDesc->mDevice;


    audio_devices_t sinkDevice = getDeviceForStrategy(strategy, true);
    audio_devices_t sinkDevice = getDeviceForStrategy(strategy, true);
@@ -2971,7 +2993,7 @@ status_t AudioPolicyManager::disconnectAudioSource(const sp<AudioSourceDescripto
    }
    }
    removeAudioPatch(sourceDesc->mPatchDesc->mHandle);
    removeAudioPatch(sourceDesc->mPatchDesc->mHandle);


    audio_stream_type_t stream = audio_attributes_to_stream_type(&sourceDesc->mAttributes);
    audio_stream_type_t stream = streamTypefromAttributesInt(&sourceDesc->mAttributes);
    sp<SwAudioOutputDescriptor> swOutputDesc = sourceDesc->mSwOutput.promote();
    sp<SwAudioOutputDescriptor> swOutputDesc = sourceDesc->mSwOutput.promote();
    if (swOutputDesc != 0) {
    if (swOutputDesc != 0) {
        stopSource(swOutputDesc, stream, false);
        stopSource(swOutputDesc, stream, false);
@@ -4170,10 +4192,10 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescr
    //      use device for strategy phone
    //      use device for strategy phone
    // 3: the strategy for enforced audible is active but not enforced on the output:
    // 3: the strategy for enforced audible is active but not enforced on the output:
    //      use the device for strategy enforced audible
    //      use the device for strategy enforced audible
    // 4: the strategy accessibility is active on the output:
    // 4: the strategy sonification is active on the output:
    //      use device for strategy accessibility
    // 5: the strategy sonification is active on the output:
    //      use device for strategy sonification
    //      use device for strategy sonification
    // 5: the strategy accessibility is active on the output:
    //      use device for strategy accessibility
    // 6: the strategy "respectful" sonification is active on the output:
    // 6: the strategy "respectful" sonification is active on the output:
    //      use device for strategy "respectful" sonification
    //      use device for strategy "respectful" sonification
    // 7: the strategy media is active on the output:
    // 7: the strategy media is active on the output:
@@ -4190,10 +4212,10 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescr
        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
    } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
        device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
        device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
        device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
        device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
    } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
        device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
        device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
    } else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
    } else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
@@ -4229,6 +4251,13 @@ audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input)
    return device;
    return device;
}
}


bool AudioPolicyManager::strategiesMatchForvolume(routing_strategy strategy1,
                                                  routing_strategy strategy2) {
    return ((strategy1 == strategy2) ||
            ((strategy1 == STRATEGY_ACCESSIBILITY) && (strategy2 == STRATEGY_MEDIA)) ||
            ((strategy1 == STRATEGY_MEDIA) && (strategy2 == STRATEGY_ACCESSIBILITY)));
}

uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) {
uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) {
    return (uint32_t)getStrategy(stream);
    return (uint32_t)getStrategy(stream);
}
}
@@ -4240,16 +4269,22 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
    if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
    if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
        return AUDIO_DEVICE_NONE;
        return AUDIO_DEVICE_NONE;
    }
    }
    audio_devices_t devices;
    audio_devices_t devices = AUDIO_DEVICE_NONE;
    routing_strategy strategy = getStrategy(stream);
    routing_strategy strategy = getStrategy(stream);
    devices = getDeviceForStrategy(strategy, true /*fromCache*/);
    for (int curStrategy = 0; curStrategy < NUM_STRATEGIES; curStrategy++) {
    SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs);
        if (!strategiesMatchForvolume(strategy, (routing_strategy)curStrategy)) {
            continue;
        }
        audio_devices_t curDevices =
                getDeviceForStrategy((routing_strategy)curStrategy, true /*fromCache*/);
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(curDevices, mOutputs);
        for (size_t i = 0; i < outputs.size(); i++) {
        for (size_t i = 0; i < outputs.size(); i++) {
            sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
            sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
        if (isStrategyActive(outputDesc, strategy)) {
            if (isStrategyActive(outputDesc, (routing_strategy)curStrategy)) {
            devices = outputDesc->device();
                curDevices |= outputDesc->device();
            break;
            }
        }
        }
        devices |= curDevices;
    }
    }


    /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
    /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
@@ -4361,15 +4396,8 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
    // the device = the device from the descriptor in the RouteMap, and exit.
    // the device = the device from the descriptor in the RouteMap, and exit.
    for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
    for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
        sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
        sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
        routing_strategy strat = getStrategy(route->mStreamType);
        routing_strategy routeStrategy = getStrategy(route->mStreamType);
        // Special case for accessibility strategy which must follow any strategy it is
        if ((routeStrategy == strategy) && route->isActive()) {
        // currently remapped to
        bool strategyMatch = (strat == strategy) ||
                             ((strategy == STRATEGY_ACCESSIBILITY) &&
                              ((mEngine->getStrategyForUsage(
                                      AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY) == strat) ||
                               (strat == STRATEGY_MEDIA)));
        if (strategyMatch && route->isActive()) {
            return route->mDeviceDescriptor->type();
            return route->mDeviceDescriptor->type();
        }
        }
    }
    }
@@ -5007,15 +5035,6 @@ audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
        return AUDIO_STREAM_MUSIC;
        return AUDIO_STREAM_MUSIC;
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        if (isStreamActive(AUDIO_STREAM_ALARM)) {
            return AUDIO_STREAM_ALARM;
        }
        if (isStreamActive(AUDIO_STREAM_RING)) {
            return AUDIO_STREAM_RING;
        }
        if (isInCall()) {
            return AUDIO_STREAM_VOICE_CALL;
        }
        return AUDIO_STREAM_ACCESSIBILITY;
        return AUDIO_STREAM_ACCESSIBILITY;
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
        return AUDIO_STREAM_SYSTEM;
        return AUDIO_STREAM_SYSTEM;
+3 −0
Original line number Original line Diff line number Diff line
@@ -506,6 +506,9 @@ protected:
        void clearAudioSources(uid_t uid);
        void clearAudioSources(uid_t uid);




        static bool strategiesMatchForvolume(routing_strategy strategy1,
                                             routing_strategy strategy2);

        uid_t mUidCached;
        uid_t mUidCached;
        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
        sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor
        sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor