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

Commit 4376579d authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Android (Google) Code Review
Browse files

Merge "Close input streams for external devices immediately after probing" into main

parents 71028c9a c66ffc15
Loading
Loading
Loading
Loading
+32 −25
Original line number Diff line number Diff line
@@ -396,8 +396,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
            // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
            // parameters on newly connected devices (instead of opening the inputs...)
            broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
            // Propagate device availability to Engine
            setEngineDeviceConnectionState(device, state);

            if (checkInputsForDevice(device, state) != NO_ERROR) {
                setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);

                mAvailableInputDevices.remove(device);

                broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
@@ -431,6 +435,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript

            // remove device from mReportedFormatsMap cache
            mReportedFormatsMap.erase(device);

            // Propagate device availability to Engine
            setEngineDeviceConnectionState(device, state);
        } break;

        default:
@@ -438,9 +445,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
            return BAD_VALUE;
        }

        // Propagate device availability to Engine
        setEngineDeviceConnectionState(device, state);

        checkCloseInputs();
        // As the input device list can impact the output device selection, update
        // getDeviceForStrategy() cache
@@ -3337,37 +3341,35 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId)
    releaseInput(portId);
}

void AudioPolicyManager::checkCloseInputs() {
    // After connecting or disconnecting an input device, close input if:
    // - it has no client (was just opened to check profile)  OR
    // - none of its supported devices are connected anymore OR
    // - one of its clients cannot be routed to one of its supported
    // devices anymore. Otherwise update device selection
    std::vector<audio_io_handle_t> inputsToClose;
    for (size_t i = 0; i < mInputs.size(); i++) {
        const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
bool AudioPolicyManager::checkCloseInput(const sp<AudioInputDescriptor>& input) {
    if (input->clientsList().size() == 0
            || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
            inputsToClose.push_back(mInputs.keyAt(i));
        } else {
            bool close = false;
        return true;
    }
    for (const auto& client : input->clientsList()) {
        sp<DeviceDescriptor> device =
            mEngine->getInputDeviceForAttributes(client->attributes(), client->uid(),
                                                 client->session());
        if (!input->supportedDevices().contains(device)) {
                    close = true;
                    break;
            return true;
        }
    }
            if (close) {
                inputsToClose.push_back(mInputs.keyAt(i));
            } else {
    setInputDevice(input->mIoHandle, getNewInputDevice(input));
    return false;
}

void AudioPolicyManager::checkCloseInputs() {
    // After connecting or disconnecting an input device, close input if:
    // - it has no client (was just opened to check profile)  OR
    // - none of its supported devices are connected anymore OR
    // - one of its clients cannot be routed to one of its supported
    // devices anymore. Otherwise update device selection
    std::vector<audio_io_handle_t> inputsToClose;
    for (size_t i = 0; i < mInputs.size(); i++) {
        if (checkCloseInput(mInputs.valueAt(i))) {
            inputsToClose.push_back(mInputs.keyAt(i));
        }
    }

    for (const audio_io_handle_t handle : inputsToClose) {
        ALOGV("%s closing input %d", __func__, handle);
        closeInput(handle);
@@ -6865,14 +6867,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device,
                                                  audio_policy_dev_state_t state)
{
    sp<AudioInputDescriptor> desc;

    if (audio_device_is_digital(device->type())) {
        // erase all current sample rates, formats and channel masks
        device->clearAudioProfiles();
    }

    if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
        sp<AudioInputDescriptor> desc;

        // first call getAudioPort to get the supported attributes from the HAL
        struct audio_port_v7 port = {};
        device->toAudioPort(&port);
@@ -6963,6 +6965,11 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
                    device->importAudioPortAndPickAudioProfile(profile);
                }
                ALOGV("checkInputsForDevice(): adding input %d", input);

                if (checkCloseInput(desc)) {
                    ALOGV("%s closing input %d", __func__, input);
                    closeInput(input);
                }
            }
        } // end scan profiles

+1 −0
Original line number Diff line number Diff line
@@ -533,6 +533,7 @@ protected:
        void addOutput(audio_io_handle_t output, const sp<SwAudioOutputDescriptor>& outputDesc);
        void removeOutput(audio_io_handle_t output);
        void addInput(audio_io_handle_t input, const sp<AudioInputDescriptor>& inputDesc);
        bool checkCloseInput(const sp<AudioInputDescriptor>& input);

        /**
         * @brief setOutputDevices change the route of the specified output.
+19 −0
Original line number Diff line number Diff line
@@ -70,6 +70,22 @@ public:
            return BAD_VALUE;
        }
        *input = mNextIoHandle++;
        mOpenedInputs.insert(*input);
        ALOGD("%s: opened input %d", __func__, *input);
        return NO_ERROR;
    }

    status_t closeInput(audio_io_handle_t input) override {
        if (mOpenedInputs.erase(input) != 1) {
            if (input >= mNextIoHandle) {
                ALOGE("%s: I/O handle %d has not been allocated yet (next is %d)",
                      __func__, input, mNextIoHandle);
            } else {
                ALOGE("%s: Attempt to close input %d twice", __func__, input);
            }
            return BAD_VALUE;
        }
        ALOGD("%s: closed input %d", __func__, input);
        return NO_ERROR;
    }

@@ -124,6 +140,8 @@ public:
        return &it->second;
    };

    size_t getOpenedInputsCount() const { return mOpenedInputs.size(); }

    audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }

    void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
@@ -256,6 +274,7 @@ private:
    std::set<audio_format_t> mSupportedFormats;
    std::set<audio_channel_mask_t> mSupportedChannelMasks;
    std::map<audio_port_handle_t, bool> mTracksInternalMute;
    std::set<audio_io_handle_t> mOpenedInputs;
};

} // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ class AudioPolicyTestManager : public AudioPolicyManager {
    using AudioPolicyManager::getInputs;
    using AudioPolicyManager::getAvailableOutputDevices;
    using AudioPolicyManager::getAvailableInputDevices;
    using AudioPolicyManager::checkInputsForDevice;
    using AudioPolicyManager::setSurroundFormatEnabled;
    using AudioPolicyManager::releaseMsdOutputPatches;
    using AudioPolicyManager::setMsdOutputPatches;
@@ -44,6 +45,7 @@ class AudioPolicyTestManager : public AudioPolicyManager {
    using AudioPolicyManager::deviceToAudioPort;
    using AudioPolicyManager::handleDeviceConfigChange;
    uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
    HwModuleCollection getHwModules() const { return mHwModules; }
};

}  // namespace android
+29 −0
Original line number Diff line number Diff line
@@ -1204,6 +1204,35 @@ TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferExactConfigForInput) {
                                                           "", "", AUDIO_FORMAT_DEFAULT));
}

TEST_F(AudioPolicyManagerTestWithConfigurationFile, CheckInputsForDeviceClosesStreams) {
    mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT);
    mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED);
    mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO);
    mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO);
    // Since 'checkInputsForDevice' is called as part of the 'setDeviceConnectionState',
    // call it directly here, as we need to ensure that it does not keep all intermediate
    // streams opened, as it may cause a rejection from the HAL based on the cap.
    const size_t streamCountBefore = mClient->getOpenedInputsCount();
    sp<DeviceDescriptor> device = mManager->getHwModules().getDeviceDescriptor(
            AUDIO_DEVICE_IN_USB_DEVICE, "", "", AUDIO_FORMAT_DEFAULT, true /*allowToCreate*/);
    ASSERT_NE(nullptr, device.get());
    EXPECT_EQ(NO_ERROR,
            mManager->checkInputsForDevice(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
    EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount());
}

TEST_F(AudioPolicyManagerTestWithConfigurationFile, SetDeviceConnectionStateClosesStreams) {
    mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT);
    mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED);
    mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO);
    mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO);
    const size_t streamCountBefore = mClient->getOpenedInputsCount();
    EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
                                                           AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
                                                           "", "", AUDIO_FORMAT_DEFAULT));
    EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount());
}

class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
    void TearDown() override;
Loading