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

Commit 4ff3cf8e authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audio: Facilitate extension of Module class by vendors

Make interface methods protected so that subclasses can
augment them.

Provide getters for private fields.

Bug: 282568751
Test: atest VtsHalAudioCoreTargetTest
Merged-In: I0e4810f8a4c816c4f673139816e9768f6dc8da7c
Change-Id: I0e4810f8a4c816c4f673139816e9768f6dc8da7c
(cherry picked from commit 57f0dcf7)
parent fc45cfd9
Loading
Loading
Loading
Loading
+68 −54
Original line number Diff line number Diff line
@@ -39,33 +39,9 @@ class Module : public BnModule {
    static StreamIn::CreateInstance getStreamInCreator(Type type);
    static StreamOut::CreateInstance getStreamOutCreator(Type type);

  private:
    struct VendorDebug {
        static const std::string kForceTransientBurstName;
        static const std::string kForceSynchronousDrainName;
        bool forceTransientBurst = false;
        bool forceSynchronousDrain = false;
    };
    // Helper used for interfaces that require a persistent instance. We hold them via a strong
    // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
    template <class C>
    struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
        ChildInterface() {}
        ChildInterface& operator=(const std::shared_ptr<C>& c) {
            return operator=(std::shared_ptr<C>(c));
        }
        ChildInterface& operator=(std::shared_ptr<C>&& c) {
            this->first = std::move(c);
            this->second = this->first->asBinder();
            AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
                                           ANDROID_PRIORITY_AUDIO);
            return *this;
        }
        explicit operator bool() const { return !!this->first; }
        C& operator*() const { return *(this->first); }
        C* operator->() const { return this->first; }
        std::shared_ptr<C> getPtr() const { return this->first; }
    };
  protected:
    // The vendor extension done via inheritance can override interface methods and augment
    // a call to the base implementation.

    ndk::ScopedAStatus setModuleDebug(
            const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
@@ -146,29 +122,46 @@ class Module : public BnModule {
    ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
    ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;

    void cleanUpPatch(int32_t patchId);
    ndk::ScopedAStatus createStreamContext(
            int32_t in_portConfigId, int64_t in_bufferSizeFrames,
            std::shared_ptr<IStreamCallback> asyncCallback,
            std::shared_ptr<IStreamOutEventCallback> outEventCallback,
            ::aidl::android::hardware::audio::core::StreamContext* out_context);
    std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
            int32_t portConfigId);
    std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
    ndk::ScopedAStatus findPortIdForNewStream(
            int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
    internal::Configuration& getConfig();
    template <typename C>
    std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
    void registerPatch(const AudioPatch& patch);
    void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
    bool isMmapSupported();

    // This value is used for all AudioPatches.
    static constexpr int32_t kMinimumStreamBufferSizeFrames = 256;
    // The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
    static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;

  private:
    struct VendorDebug {
        static const std::string kForceTransientBurstName;
        static const std::string kForceSynchronousDrainName;
        bool forceTransientBurst = false;
        bool forceSynchronousDrain = false;
    };
    // Helper used for interfaces that require a persistent instance. We hold them via a strong
    // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
    template <class C>
    struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
        ChildInterface() {}
        ChildInterface& operator=(const std::shared_ptr<C>& c) {
            return operator=(std::shared_ptr<C>(c));
        }
        ChildInterface& operator=(std::shared_ptr<C>&& c) {
            this->first = std::move(c);
            this->second = this->first->asBinder();
            AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
                                           ANDROID_PRIORITY_AUDIO);
            return *this;
        }
        explicit operator bool() const { return !!this->first; }
        C& operator*() const { return *(this->first); }
        C* operator->() const { return this->first; }
        std::shared_ptr<C> getPtr() const { return this->first; }
    };
    // ids of device ports created at runtime via 'connectExternalDevice'.
    // Also stores a list of ids of mix ports with dynamic profiles that were populated from
    // the connected port. This list can be empty, thus an int->int multimap can't be used.
    using ConnectedDevicePorts = std::map<int32_t, std::vector<int32_t>>;
    // Maps port ids and port config ids to patch ids.
    // Multimap because both ports and configs can be used by multiple patches.
    using Patches = std::multimap<int32_t, int32_t>;

    const Type mType;
    std::unique_ptr<internal::Configuration> mConfig;
    ModuleDebug mDebug;
@@ -177,19 +170,18 @@ class Module : public BnModule {
    ChildInterface<IBluetooth> mBluetooth;
    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
    ChildInterface<IBluetoothLe> mBluetoothLe;
    // ids of device ports created at runtime via 'connectExternalDevice'.
    // Also stores ids of mix ports with dynamic profiles which got populated from the connected
    // port.
    std::map<int32_t, std::vector<int32_t>> mConnectedDevicePorts;
    ConnectedDevicePorts mConnectedDevicePorts;
    Streams mStreams;
    // Maps port ids and port config ids to patch ids.
    // Multimap because both ports and configs can be used by multiple patches.
    std::multimap<int32_t, int32_t> mPatches;
    Patches mPatches;
    bool mMicMute = false;
    bool mMasterMute = false;
    float mMasterVolume = 1.0f;
    ChildInterface<sounddose::ISoundDose> mSoundDose;
    std::optional<bool> mIsMmapSupported;

  protected:
    // The following virtual functions are intended for vendor extension via inheritance.

    // If the module is unable to populate the connected device port correctly, the returned error
    // code must correspond to the errors of `IModule.connectedExternalDevice` method.
    virtual ndk::ScopedAStatus populateConnectedDevicePort(
@@ -204,8 +196,30 @@ class Module : public BnModule {
    virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
    virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);

    bool mMasterMute = false;
    float mMasterVolume = 1.0f;
    // Utility and helper functions accessible to subclasses.
    void cleanUpPatch(int32_t patchId);
    ndk::ScopedAStatus createStreamContext(
            int32_t in_portConfigId, int64_t in_bufferSizeFrames,
            std::shared_ptr<IStreamCallback> asyncCallback,
            std::shared_ptr<IStreamOutEventCallback> outEventCallback,
            ::aidl::android::hardware::audio::core::StreamContext* out_context);
    std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
            int32_t portConfigId);
    std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
    ndk::ScopedAStatus findPortIdForNewStream(
            int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
    internal::Configuration& getConfig();
    const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
    bool getMasterMute() const { return mMasterMute; }
    bool getMasterVolume() const { return mMasterVolume; }
    bool getMicMute() const { return mMicMute; }
    const Patches& getPatches() const { return mPatches; }
    const Streams& getStreams() const { return mStreams; }
    bool isMmapSupported();
    template <typename C>
    std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
    void registerPatch(const AudioPatch& patch);
    void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
};

}  // namespace aidl::android::hardware::audio::core
+2 −2
Original line number Diff line number Diff line
@@ -175,8 +175,8 @@ void ModuleUsb::onExternalDeviceConnectionChanged(
        return;
    }
    const int card = address.get<AudioDeviceAddress::alsa>()[0];
    usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, mMasterMute,
                                                                     mMasterVolume, connected);
    usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, getMasterMute(),
                                                                     getMasterVolume(), connected);
}

ndk::ScopedAStatus ModuleUsb::onMasterMuteChanged(bool mute) {