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

Commit 61cc5c2a authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

Merge "audio policy: phone strategy routing based on preferred device API" am: af5c2201

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/1534354

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Icc79bd0ef512af8ba26bbd0a9309221a7102ce97
parents 49bc142e af5c2201
Loading
Loading
Loading
Loading
+81 −109
Original line number Diff line number Diff line
@@ -184,16 +184,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
        break;

    case STRATEGY_DTMF:
        if (!isInCall()) {
            // when off call, DTMF strategy follows the same rules as MEDIA strategy
            devices = getDevicesForStrategyInt(
                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
            break;
        }
        // when in call, DTMF and PHONE strategies follow the same rules
        FALLTHROUGH_INTENDED;

    case STRATEGY_PHONE:
    case STRATEGY_PHONE: {
        // Force use of only devices on primary output if:
        // - in call AND
        //   - cannot route from voice call RX OR
@@ -223,77 +214,17 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
                availableOutputDevices = availPrimaryOutputDevices;
            }
        }
        // for phone strategy, we first consider the forced use and then the available devices by
        // order of priority
        switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
        case AUDIO_POLICY_FORCE_BT_SCO:
            if (!isInCall() || strategy != STRATEGY_DTMF) {
                devices = availableOutputDevices.getDevicesFromType(
                        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
                if (!devices.isEmpty()) 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
        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
        if (!devices.isEmpty()) break;

            // TODO (b/161358428): remove when preferred device
            //  for strategy phone will be used instead of AUDIO_POLICY_FORCE_FOR_COMMUNICATION
            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_BLE_HEADSET);
            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)) {
                devices = availableOutputDevices.getFirstDevicesFromTypes({
                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
                if (!devices.isEmpty()) 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_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()) {
                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;
            }
        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
            break;

        case AUDIO_POLICY_FORCE_SPEAKER:
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
            // A2DP speaker when forcing to speaker output
            if (!isInCall()) {
                devices = availableOutputDevices.getDevicesFromType(
                        AUDIO_DEVICE_OUT_BLE_SPEAKER);
                if (!devices.isEmpty()) break;

                if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
                    devices = availableOutputDevices.getDevicesFromType(
                            AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
                    if (!devices.isEmpty()) break;
                }
            }
            if (!isInCall()) {
                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;
            }
            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
            break;
        }
    break;
    } break;

    case STRATEGY_SONIFICATION:

@@ -336,7 +267,8 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
                }
            }
            // 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 (audio_is_bluetooth_out_sco_device(getPreferredDeviceTypeForLegacyStrategy(
                    availableOutputDevices, STRATEGY_PHONE))) {
                if (strategy == STRATEGY_SONIFICATION) {
                    devices.replaceDevicesByType(
                            AUDIO_DEVICE_OUT_SPEAKER,
@@ -506,13 +438,16 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
        }
    }

    audio_devices_t commDeviceType =
        getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);

    switch (inputSource) {
    case AUDIO_SOURCE_DEFAULT:
    case AUDIO_SOURCE_MIC:
        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) {
        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            if (device != nullptr) break;
@@ -533,30 +468,29 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
            availableDevices = availablePrimaryDevices;
        }

        switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
        case AUDIO_POLICY_FORCE_BT_SCO:
        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
            // if SCO device is requested but no SCO device is available, fall back to default case
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            if (device != nullptr) {
                break;
            }
            FALLTHROUGH_INTENDED;

        default:    // FORCE_NONE
            // TODO (b/161358428): remove AUDIO_DEVICE_IN_BLE_HEADSET from the list
            //  when preferred device for strategy phone will be used instead of
            //  AUDIO_POLICY_FORCE_FOR_COMMUNICATION.
            device = availableDevices.getFirstExistingDevice({
                    AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
                    AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
                    AUDIO_DEVICE_IN_BUILTIN_MIC});
        }
        switch (commDeviceType) {
        case AUDIO_DEVICE_OUT_BLE_HEADSET:
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            break;

        case AUDIO_POLICY_FORCE_SPEAKER:
        case AUDIO_DEVICE_OUT_SPEAKER:
            device = availableDevices.getFirstExistingDevice({
                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
            break;
        default:    // FORCE_NONE
            device = availableDevices.getFirstExistingDevice({
                    AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
            break;

        }
        break;

@@ -569,7 +503,7 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
            LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
            availableDevices = availablePrimaryDevices;
        }
        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            if (device != nullptr) break;
@@ -619,6 +553,7 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
        ALOGE_IF(device == nullptr,
                 "getDeviceForInputSource() no default device defined");
    }

    ALOGV_IF(device != nullptr,
             "getDeviceForInputSource()input source %d, device %08x",
             inputSource, device->type());
@@ -636,17 +571,35 @@ void Engine::updateDeviceSelectionCache()
    }
}

DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
    for (const auto& strategyMap : mLegacyStrategyMap) {
        if (strategyMap.second == legacyStrategy) {
            return strategyMap.first;
        }
    }
    return PRODUCT_STRATEGY_NONE;
}

    // check if this strategy has a preferred device that is available,
    // if yes, give priority to it
audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
        const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const {
    product_strategy_t strategy = getProductStrategyFromLegacy(legacyStrategy);
    DeviceVector devices = getPreferredAvailableDevicesForProductStrategy(
            availableOutputDevices, strategy);
    if (devices.size() > 0) {
        return devices[0]->type();
    }
    return AUDIO_DEVICE_NONE;
}

DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
    DeviceVector preferredAvailableDevVec = {};
    AudioDeviceTypeAddrVector preferredStrategyDevices;
    const status_t status = getDevicesForRoleAndStrategy(
            strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
    if (status == NO_ERROR) {
        // there is a preferred device, is it available?
        DeviceVector preferredAvailableDevVec =
        preferredAvailableDevVec =
                availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
        if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
            ALOGVV("%s using pref device %s for strategy %u",
@@ -654,11 +607,30 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) c
            return preferredAvailableDevVec;
        }
    }
    return preferredAvailableDevVec;
}

    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
    const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
    auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
                          mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;

    // When not in call, STRATEGY_PHONE and STRATEGY_DTMF follow STRATEGY_MEDIA
    if (!isInCall() && (legacyStrategy == STRATEGY_PHONE || legacyStrategy == STRATEGY_DTMF)) {
        legacyStrategy = STRATEGY_MEDIA;
        strategy = getProductStrategyFromLegacy(STRATEGY_MEDIA);
    }
    // check if this strategy has a preferred device that is available,
    // if yes, give priority to it.
    DeviceVector preferredAvailableDevVec =
            getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, strategy);
    if (!preferredAvailableDevVec.isEmpty()) {
        return preferredAvailableDevVec;
    }

    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
    const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();

    return getDevicesForStrategyInt(legacyStrategy,
                                    availableOutputDevices,
                                    availableInputDevices, outputs);
+6 −0
Original line number Diff line number Diff line
@@ -83,6 +83,12 @@ private:

    sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;

    product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
    audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
        const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
    DeviceVector getPreferredAvailableDevicesForProductStrategy(
        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;

    DeviceStrategyMap mDevicesForStrategies;

    std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
+70 −30
Original line number Diff line number Diff line
@@ -790,16 +790,7 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
    }

    updateCallAndOutputRouting(forceVolumeReeval, delayMs);

    for (const auto& activeDesc : mInputs.getActiveInputs()) {
        auto newDevice = getNewInputDevice(activeDesc);
        // Force new input selection if the new device can not be reached via current input
        if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
            setInputDevice(activeDesc->mIoHandle, newDevice);
        } else {
            closeInput(activeDesc->mIoHandle);
        }
    }
    updateInputRouting();
}

void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
@@ -3145,6 +3136,7 @@ status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
    return res;
}


status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strategy,
                                                       device_role_t role,
                                                       const AudioDeviceTypeAddrVector &devices) {
@@ -3162,7 +3154,17 @@ status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strate
    }

    checkForDeviceAndOutputChanges();
    updateCallAndOutputRouting();

    bool forceVolumeReeval = false;
    // FIXME: workaround for truncated touch sounds
    // to be removed when the problem is handled by system UI
    uint32_t delayMs = 0;
    if (strategy == mCommunnicationStrategy) {
        forceVolumeReeval = true;
        delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
        updateInputRouting();
    }
    updateCallAndOutputRouting(forceVolumeReeval, delayMs);

    return NO_ERROR;
}
@@ -3193,6 +3195,18 @@ void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint
    }
}

void AudioPolicyManager::updateInputRouting() {
    for (const auto& activeDesc : mInputs.getActiveInputs()) {
        auto newDevice = getNewInputDevice(activeDesc);
        // Force new input selection if the new device can not be reached via current input
        if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
            setInputDevice(activeDesc->mIoHandle, newDevice);
        } else {
            closeInput(activeDesc->mIoHandle);
        }
    }
}

status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t strategy,
                                                          device_role_t role)
{
@@ -3200,12 +3214,23 @@ status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t str

    status_t status = mEngine->removeDevicesRoleForStrategy(strategy, role);
    if (status != NO_ERROR) {
        ALOGW("Engine could not remove preferred device for strategy %d", strategy);
        ALOGV("Engine could not remove preferred device for strategy %d status %d",
                strategy, status);
        return status;
    }

    checkForDeviceAndOutputChanges();
    updateCallAndOutputRouting();

    bool forceVolumeReeval = false;
    // FIXME: workaround for truncated touch sounds
    // to be removed when the problem is handled by system UI
    uint32_t delayMs = 0;
    if (strategy == mCommunnicationStrategy) {
        forceVolumeReeval = true;
        delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
        updateInputRouting();
    }
    updateCallAndOutputRouting(forceVolumeReeval, delayMs);

    return NO_ERROR;
}
@@ -3245,6 +3270,7 @@ status_t AudioPolicyManager::addDevicesRoleForCapturePreset(
            "Engine could not add preferred devices %s for audio source %d role %d",
            dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);

    updateInputRouting();
    return status;
}

@@ -3263,6 +3289,7 @@ status_t AudioPolicyManager::removeDevicesRoleForCapturePreset(
    ALOGW_IF(status != NO_ERROR,
            "Engine could not remove devices role (%d) for capture preset %d", role, audioSource);

    updateInputRouting();
    return status;
}

@@ -3274,6 +3301,7 @@ status_t AudioPolicyManager::clearDevicesRoleForCapturePreset(audio_source_t aud
    ALOGW_IF(status != NO_ERROR,
            "Engine could not clear devices role (%d) for capture preset %d", role, audioSource);

    updateInputRouting();
    return status;
}

@@ -3343,7 +3371,9 @@ void AudioPolicyManager::dump(String8 *dst) const
    }
    dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
    dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
    dst->appendFormat(" Communnication Strategy: %d\n", mCommunnicationStrategy);
    dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const

    mAvailableOutputDevices.dump(dst, String8("Available output"));
    mAvailableInputDevices.dump(dst, String8("Available input"));
    mHwModulesAll.dump(dst);
@@ -4639,6 +4669,9 @@ status_t AudioPolicyManager::initialize() {
    // Silence ALOGV statements
    property_set("log.tag." LOG_TAG, "D");

    mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
            mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));

    updateDevicesAndOutputs();
    return status;
}
@@ -5466,6 +5499,17 @@ void AudioPolicyManager::checkSecondaryOutputs() {
    }
}

bool AudioPolicyManager::isScoRequestedForComm() const {
    AudioDeviceTypeAddrVector devices;
    mEngine->getDevicesForRoleAndStrategy(mCommunnicationStrategy, DEVICE_ROLE_PREFERRED, devices);
    for (const auto &device : devices) {
        if (audio_is_bluetooth_out_sco_device(device.mType)) {
            return true;
        }
    }
    return false;
}

void AudioPolicyManager::checkA2dpSuspend()
{
    audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
@@ -5477,23 +5521,21 @@ void AudioPolicyManager::checkA2dpSuspend()
    bool isScoConnected =
            (mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
             !Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
    bool isScoRequested = isScoRequestedForComm();

    // if suspended, restore A2DP output if:
    //      ((SCO device is NOT connected) ||
    //       ((forced usage communication is NOT SCO) && (forced usage for record is NOT SCO) &&
    //       ((SCO is not requested) &&
    //        (phone state is NOT in call) && (phone state is NOT ringing)))
    //
    // if not suspended, suspend A2DP output if:
    //      (SCO device is connected) &&
    //       ((forced usage for communication is SCO) || (forced usage for record is SCO) ||
    //       ((SCO is requested) ||
    //       ((phone state is in call) || (phone state is ringing)))
    //
    if (mA2dpSuspended) {
        if (!isScoConnected ||
             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) !=
                     AUDIO_POLICY_FORCE_BT_SCO) &&
              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) !=
                      AUDIO_POLICY_FORCE_BT_SCO) &&
             (!isScoRequested &&
              (mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
              (mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {

@@ -5502,10 +5544,7 @@ void AudioPolicyManager::checkA2dpSuspend()
        }
    } else {
        if (isScoConnected &&
             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ==
                     AUDIO_POLICY_FORCE_BT_SCO) ||
              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) ==
                      AUDIO_POLICY_FORCE_BT_SCO) ||
             (isScoRequested ||
              (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
              (mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {

@@ -6217,16 +6256,17 @@ status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves,
    bool isVoiceVolSrc = callVolSrc == volumeSource;
    bool isBtScoVolSrc = btScoVolSrc == volumeSource;

    audio_policy_forced_cfg_t forceUseForComm =
            mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
    bool isScoRequested = isScoRequestedForComm();
    // do not change in call volume if bluetooth is connected and vice versa
    // if sco and call follow same curves, bypass forceUseForComm
    if ((callVolSrc != btScoVolSrc) &&
            ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
             (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
        ALOGV("%s cannot set volume group %d volume with force use = %d for comm", __func__,
             volumeSource, forceUseForComm);
        return INVALID_OPERATION;
            ((isVoiceVolSrc && isScoRequested) ||
             (isBtScoVolSrc && !isScoRequested))) {
        ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
             volumeSource, isScoRequested ? " " : "n ot ");
        // Do not return an error here as AudioService will always set both voice call
        // and bluetooth SCO volumes due to stream aliasing.
        return NO_ERROR;
    }
    if (deviceTypes.empty()) {
        deviceTypes = outputDesc->devices().types();
+10 −0
Original line number Diff line number Diff line
@@ -556,6 +556,11 @@ protected:
         */
        void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);

        /**
         * @brief updates routing for all inputs.
         */
        void updateInputRouting();

        /**
         * @brief checkOutputForAttributes checks and if necessary changes outputs used for the
         * given audio attributes.
@@ -812,6 +817,10 @@ protected:
        std::unordered_set<audio_format_t> mManualSurroundFormats;

        std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;

        // Cached product strategy ID corresponding to legacy strategy STRATEGY_PHONE
        product_strategy_t mCommunnicationStrategy;

private:
        void onNewAudioModulesAvailableInt(DeviceVector *newDevices);

@@ -967,6 +976,7 @@ private:
                std::function<bool(audio_devices_t)> predicate,
                const char* context);

        bool isScoRequestedForComm() const;
};

};