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

Commit f3a5a601 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio polcy: fix explicit device routing in call

Make sure tracks with an explicit routing request are not systematically invalidated
when starting while another track on the same strategy is already active.

Also fix a problem where explicit routing is not taken into account by
getNewOutputDevice() when in call because the strategy with the
explicit routing is not evaluated.

Bug: 69680975
Bug: 79878501
Test: voice call regression, CTS for explicit audio routing, test case
for b/79878501

Change-Id: I99b83f8a3304549bf327c3c327f6671f777cfb4b
parent c2d0641b
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
namespace android {

class DeviceDescriptor;
class DeviceVector;

class SessionRoute : public RefBase
{
@@ -98,7 +99,8 @@ public:
    int decRouteActivity(audio_session_t session);
    bool getAndClearRouteChanged(audio_session_t session); // also clears the changed flag
    void log(const char* caption);

    audio_devices_t getActiveDeviceForStream(audio_stream_type_t streamType,
                                             const DeviceVector& availableDevices);
    // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the
    // source argument.
    // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT
+19 −1
Original line number Diff line number Diff line
@@ -119,4 +119,22 @@ void SessionRouteMap::addRoute(audio_session_t session,
    }
}

audio_devices_t SessionRouteMap::getActiveDeviceForStream(audio_stream_type_t streamType,
                                                          const DeviceVector& availableDevices)
{
    audio_devices_t device = AUDIO_DEVICE_NONE;

    for (size_t index = 0; index < size(); index++) {
        sp<SessionRoute> route = valueAt(index);
        if (streamType == route->mStreamType && route->isActiveOrChanged()
                && route->mDeviceDescriptor != 0) {
            device = route->mDeviceDescriptor->type();
            if (!availableDevices.getDevicesFromType(device).isEmpty()) {
                break;
            }
        }
    }
    return device;
}

} // namespace android
+28 −14
Original line number Diff line number Diff line
@@ -1157,7 +1157,9 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
        }
    } else if (mOutputRoutes.getAndClearRouteChanged(session)) {
        newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
        if (newDevice != outputDesc->device()) {
            checkStrategyRoute(getStrategy(stream), output);
        }
    } else {
        newDevice = AUDIO_DEVICE_NONE;
    }
@@ -1408,6 +1410,7 @@ status_t AudioPolicyManager::stopSource(const sp<AudioOutputDescriptor>& outputD
                        (newDevice != desc->device())) {
                    audio_devices_t newDevice2 = getNewOutputDevice(desc, false /*fromCache*/);
                    bool force = desc->device() != newDevice2;

                    setOutputDevice(desc,
                                    newDevice2,
                                    force,
@@ -4836,6 +4839,20 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescr
        }
    }

    // Check if an explicit routing request exists for an active stream on this output and
    // use it in priority before any other rule
    for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
        if (outputDesc->isStreamActive((audio_stream_type_t)stream)) {
            audio_devices_t forcedDevice =
                    mOutputRoutes.getActiveDeviceForStream(
                            (audio_stream_type_t)stream, mAvailableOutputDevices);

            if (forcedDevice != AUDIO_DEVICE_NONE) {
                return forcedDevice;
            }
        }
    }

    // check the following by order of priority to request a routing change if necessary:
    // 1: the strategy enforced audible is active and enforced on the output:
    //      use device for strategy enforced audible
@@ -5043,19 +5060,16 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) {
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
                                                         bool fromCache)
{
    // Routing
    // see if we have an explicit route
    // scan the whole RouteMap, for each entry, convert the stream type to a strategy
    // (getStrategy(stream)).
    // if the strategy from the stream type in the RouteMap is the same as the argument above,
    // and activity count is non-zero and the device in the route descriptor is available
    // then select this device.
    for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
        sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
        routing_strategy routeStrategy = getStrategy(route->mStreamType);
        if ((routeStrategy == strategy) && route->isActiveOrChanged() &&
                (mAvailableOutputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
            return route->mDeviceDescriptor->type();
    // Check if an explicit routing request exists for a stream type corresponding to the
    // specified strategy and use it in priority over default routing rules.
    for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
        if (getStrategy((audio_stream_type_t)stream) == strategy) {
            audio_devices_t forcedDevice =
                    mOutputRoutes.getActiveDeviceForStream(
                            (audio_stream_type_t)stream, mAvailableOutputDevices);
            if (forcedDevice != AUDIO_DEVICE_NONE) {
                return forcedDevice;
            }
        }
    }