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 Original line Diff line number Diff line
@@ -24,6 +24,7 @@
namespace android {
namespace android {


class DeviceDescriptor;
class DeviceDescriptor;
class DeviceVector;


class SessionRoute : public RefBase
class SessionRoute : public RefBase
{
{
@@ -98,7 +99,8 @@ public:
    int decRouteActivity(audio_session_t session);
    int decRouteActivity(audio_session_t session);
    bool getAndClearRouteChanged(audio_session_t session); // also clears the changed flag
    bool getAndClearRouteChanged(audio_session_t session); // also clears the changed flag
    void log(const char* caption);
    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
    // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the
    // source argument.
    // source argument.
    // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT
    // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT
+19 −1
Original line number Original line 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
} // namespace android
+28 −14
Original line number Original line Diff line number Diff line
@@ -1157,7 +1157,9 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
        }
        }
    } else if (mOutputRoutes.getAndClearRouteChanged(session)) {
    } else if (mOutputRoutes.getAndClearRouteChanged(session)) {
        newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
        newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
        if (newDevice != outputDesc->device()) {
            checkStrategyRoute(getStrategy(stream), output);
            checkStrategyRoute(getStrategy(stream), output);
        }
    } else {
    } else {
        newDevice = AUDIO_DEVICE_NONE;
        newDevice = AUDIO_DEVICE_NONE;
    }
    }
@@ -1408,6 +1410,7 @@ status_t AudioPolicyManager::stopSource(const sp<AudioOutputDescriptor>& outputD
                        (newDevice != desc->device())) {
                        (newDevice != desc->device())) {
                    audio_devices_t newDevice2 = getNewOutputDevice(desc, false /*fromCache*/);
                    audio_devices_t newDevice2 = getNewOutputDevice(desc, false /*fromCache*/);
                    bool force = desc->device() != newDevice2;
                    bool force = desc->device() != newDevice2;

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