• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <map>
20 #include <memory>
21 
22 #include <aidl/android/hardware/audio/effect/BnEffect.h>
23 #include <aidl/android/hardware/audio/effect/BnFactory.h>
24 #include <fmq/AidlMessageQueue.h>
25 #include <system/audio_effect.h>
26 
27 namespace android {
28 namespace effect {
29 
30 /**
31  * EffectProxy is the proxy for one or more effect AIDL implementations (sub effect) of same type.
32  * The audio framework use EffectProxy as a composite implementation of all sub effect
33  * implementations.
34  *
35  * At any given time, there is only one active effect which consuming and producing data for each
36  * proxy. All setter commands (except the legacy EFFECT_CMD_OFFLOAD, it will be handled by the audio
37  * framework directly) and parameters will be pass through to all sub effects, the getter commands
38  * and parameters will only passthrough to the active sub-effect.
39  *
40  */
41 class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEffect {
42   public:
43     EffectProxy(
44             const ::aidl::android::media::audio::common::AudioUuid& uuid,
45             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& descriptors,
46             const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory);
47 
48     /**
49      * Handle offload parameter setting from framework.
50      */
51     ndk::ScopedAStatus setOffloadParam(const effect_offload_param_t* offload);
52 
53     /**
54      * Destroy all sub-effects via AIDL IFactory.
55      */
56     ndk::ScopedAStatus destroy();
57 
58     // IEffect interfaces override
59     ndk::ScopedAStatus open(
60             const ::aidl::android::hardware::audio::effect::Parameter::Common& common,
61             const std::optional<::aidl::android::hardware::audio::effect::Parameter::Specific>&
62                     specific,
63             ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
64     ndk::ScopedAStatus close() override;
65     ndk::ScopedAStatus getDescriptor(
66             ::aidl::android::hardware::audio::effect::Descriptor* desc) override;
67     ndk::ScopedAStatus command(::aidl::android::hardware::audio::effect::CommandId id) override;
68     ndk::ScopedAStatus getState(::aidl::android::hardware::audio::effect::State* state) override;
69     ndk::ScopedAStatus setParameter(
70             const ::aidl::android::hardware::audio::effect::Parameter& param) override;
71     ndk::ScopedAStatus getParameter(
72             const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
73             ::aidl::android::hardware::audio::effect::Parameter* param) override;
74 
75     static ndk::ScopedAStatus buildDescriptor(
76             const ::aidl::android::media::audio::common::AudioUuid& uuid,
77             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& subEffectDescs,
78             ::aidl::android::hardware::audio::effect::Descriptor* desc);
79 
80     /**
81      * Get the const reference of the active sub-effect return parameters.
82      * Always use this interface to get the effect open return parameters (FMQs) after a success
83      * setOffloadParam() call.
84      */
85     using StatusMQ = ::android::AidlMessageQueue<
86             ::aidl::android::hardware::audio::effect::IEffect::Status,
87             ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
88     using DataMQ = ::android::AidlMessageQueue<
89             float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
getStatusMQ()90     const std::shared_ptr<StatusMQ>& getStatusMQ() const {
91         return mSubEffects[mActiveSubIdx].effectMq.statusQ;
92     }
getInputMQ()93     const std::shared_ptr<DataMQ>& getInputMQ() const {
94         return mSubEffects[mActiveSubIdx].effectMq.inputQ;
95     }
getOutputMQ()96     const std::shared_ptr<DataMQ>& getOutputMQ() const {
97         return mSubEffects[mActiveSubIdx].effectMq.outputQ;
98     }
99 
100     bool isBypassing() const;
101 
102     // call dump for all sub-effects
103     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
104 
105     std::string toString(size_t indent = 0) const;
106 
107   private:
108     // Proxy descriptor common part, copy from one sub-effect, and update the implementation UUID to
109     // proxy UUID, proxy descriptor capability part comes from the active sub-effect capability
110     const ::aidl::android::hardware::audio::effect::Descriptor::Common mDescriptorCommon;
111 
112     struct EffectMQ {
113         std::shared_ptr<StatusMQ> statusQ;
114         std::shared_ptr<DataMQ> inputQ, outputQ;
115     };
116     struct SubEffect {
117         const ::aidl::android::hardware::audio::effect::Descriptor descriptor;
118         std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> handle;
119         EffectMQ effectMq;
120     };
121     std::vector<SubEffect> mSubEffects;
122 
123     const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
124 
125     // index of the active sub-effects, by default use the first one (index 0)
126     // It's safe to assume there will always at least two SubEffects in mSubEffects
127     size_t mActiveSubIdx = 0;
128 
129     ndk::ScopedAStatus runWithActiveSubEffectThenOthers(
130             std::function<ndk::ScopedAStatus(
131                     const std::shared_ptr<
132                             ::aidl::android::hardware::audio::effect::IEffect>&)> const& func);
133 
134     ndk::ScopedAStatus runWithActiveSubEffect(
135             std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func);
136 
137     ndk::ScopedAStatus runWithAllSubEffects(
138             std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func);
139 
140     // build Descriptor.Common with all sub-effect descriptors
141     static ::aidl::android::hardware::audio::effect::Descriptor::Common buildDescriptorCommon(
142             const ::aidl::android::media::audio::common::AudioUuid& uuid,
143             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>&
144                     subEffectDescs);
145 
146     // close and release all sub-effects
147     ~EffectProxy();
148 };
149 
150 } // namespace effect
151 } // namespace android
152