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

Commit 0d3349c7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "AHAL: add API to notify the HAL module about disconnecting device." into main

parents fb29f53f dd23b0e5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ interface IModule {
  boolean supportsVariableLatency();
  int getAAudioMixerBurstCount();
  int getAAudioHardwareBurstMinUsec();
  void prepareToDisconnectExternalDevice(int portId);
  const int DEFAULT_AAUDIO_MIXER_BURST_COUNT = 2;
  const int DEFAULT_AAUDIO_HARDWARE_BURST_MIN_DURATION_US = 1000;
  @VintfStability
+29 −7
Original line number Diff line number Diff line
@@ -206,8 +206,10 @@ interface IModule {
     * after successful connection of an external device.
     *
     * Handling of a disconnect is done in a reverse order:
     *  1. Reset port configuration using the 'resetAudioPortConfig' method.
     *  2. Release the connected device port by calling the 'disconnectExternalDevice'
     *  1. Notify the HAL module to prepare for device disconnection using
     *     'prepareToDisconnectExternalDevice' method.
     *  2. Reset port configuration using the 'resetAudioPortConfig' method.
     *  3. Release the connected device port by calling the 'disconnectExternalDevice'
     *     method. This also removes the audio routes associated with this
     *     device port.
     *
@@ -234,11 +236,15 @@ interface IModule {
     * instance previously instantiated using the 'connectExternalDevice'
     * method.
     *
     * The framework will call this method before closing streams and resetting
     * patches. This call can be used by the HAL module to prepare itself to
     * device disconnection. If the HAL module indicates an error after the first
     * call, the framework will call this method once again after closing associated
     * streams and patches.
     * On AIDL HAL v1, the framework will call this method before closing streams
     * and resetting patches. This call can be used by the HAL module to prepare
     * itself to device disconnection. If the HAL module indicates an error after
     * the first call, the framework will call this method once again after closing
     * associated streams and patches.
     *
     * On AIDL HAL v2 and later, the framework will call 'prepareToDisconnectExternalDevice'
     * method to notify the HAL module to prepare itself for device disconnection. The
     * framework will only call this method after closing associated streams and patches.
     *
     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
     *                             - If the port can not be found by the ID.
@@ -912,4 +918,20 @@ interface IModule {
     * @throw EX_UNSUPPORTED_OPERATION If the module does not support aaudio MMAP.
     */
    int getAAudioHardwareBurstMinUsec();

    /**
     * Notify the HAL module to prepare for disconnecting an external device.
     *
     * This method is used to inform the HAL module that 'disconnectExternalDevice' will be
     * called soon. The HAL module can rely on this method to abort active data operations
     * early. The 'portId' must be of a connected device Port instance previously instantiated
     * using 'connectExternalDevice' method. 'disconnectExternalDevice' method will be called
     * soon after this method with the same 'portId'.
     *
     * @param portId The ID of the audio port that is about to disconnect
     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
     *                             - If the port can not be found by the ID.
     *                             - If this is not a connected device port.
     */
    void prepareToDisconnectExternalDevice(int portId);
}
+27 −0
Original line number Diff line number Diff line
@@ -758,6 +758,28 @@ ndk::ScopedAStatus Module::disconnectExternalDevice(int32_t in_portId) {
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Module::prepareToDisconnectExternalDevice(int32_t in_portId) {
    auto& ports = getConfig().ports;
    auto portIt = findById<AudioPort>(ports, in_portId);
    if (portIt == ports.end()) {
        LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    if (portIt->ext.getTag() != AudioPortExt::Tag::device) {
        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a device port";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    auto connectedPortsIt = mConnectedDevicePorts.find(in_portId);
    if (connectedPortsIt == mConnectedDevicePorts.end()) {
        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a connected device port";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }

    onPrepareToDisconnectExternalDevice(*portIt);

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Module::getAudioPatches(std::vector<AudioPatch>* _aidl_return) {
    *_aidl_return = getConfig().patches;
    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " patches";
@@ -1537,6 +1559,11 @@ void Module::onExternalDeviceConnectionChanged(
    LOG(DEBUG) << __func__ << ": do nothing and return";
}

void Module::onPrepareToDisconnectExternalDevice(
        const ::aidl::android::media::audio::common::AudioPort& audioPort __unused) {
    LOG(DEBUG) << __func__ << ": do nothing and return";
}

ndk::ScopedAStatus Module::onMasterMuteChanged(bool mute __unused) {
    LOG(VERBOSE) << __func__ << ": do nothing and return ok";
    return ndk::ScopedAStatus::ok();
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ class Module : public BnModule {
            const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
            ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
    ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
    ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t in_portId) override;
    ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
    ndk::ScopedAStatus getAudioPort(
            int32_t in_portId,
@@ -195,6 +196,8 @@ class Module : public BnModule {
            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
    virtual void onExternalDeviceConnectionChanged(
            const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
    virtual void onPrepareToDisconnectExternalDevice(
            const ::aidl::android::media::audio::common::AudioPort& audioPort);
    virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
    virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
    virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();
+29 −0
Original line number Diff line number Diff line
@@ -69,6 +69,23 @@ inline ::testing::AssertionResult assertResult(const char* exp_expr, const char*
                                         << "\n  but is has completed with: " << status;
}

inline ::testing::AssertionResult assertIsOkOrUnknownTransaction(
        const char* expr, const ::ndk::ScopedAStatus& status) {
    if (status.getStatus() == STATUS_UNKNOWN_TRANSACTION) {
        return ::testing::AssertionSuccess();
    }
    return assertIsOk(expr, status);
}

inline ::testing::AssertionResult assertResultOrUnknownTransaction(
        const char* exp_expr, const char* act_expr, int32_t expected,
        const ::ndk::ScopedAStatus& status) {
    if (status.getStatus() == STATUS_UNKNOWN_TRANSACTION) {
        return ::testing::AssertionSuccess();
    }
    return assertResult(exp_expr, act_expr, expected, status);
}

}  // namespace detail

}  // namespace android::hardware::audio::common::testing
@@ -93,3 +110,15 @@ inline ::testing::AssertionResult assertResult(const char* exp_expr, const char*
            GTEST_SKIP() << "Skip data path for offload";                                        \
        }                                                                                        \
    })

// Test that the transaction status 'isOk' if it is a known transaction
#define EXPECT_IS_OK_OR_UNKNOWN_TRANSACTION(ret)                                                 \
    EXPECT_PRED_FORMAT1(                                                                         \
            ::android::hardware::audio::common::testing::detail::assertIsOkOrUnknownTransaction, \
            ret)

// Test that the transaction status is as expected if it is a known transaction
#define EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(expected, ret)                                        \
    EXPECT_PRED_FORMAT2(                                                                           \
            ::android::hardware::audio::common::testing::detail::assertResultOrUnknownTransaction, \
            expected, ret)
Loading