• 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 reopen(
66             ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
67     ndk::ScopedAStatus getDescriptor(
68             ::aidl::android::hardware::audio::effect::Descriptor* desc) override;
69     ndk::ScopedAStatus command(::aidl::android::hardware::audio::effect::CommandId id) override;
70     ndk::ScopedAStatus getState(::aidl::android::hardware::audio::effect::State* state) override;
71     ndk::ScopedAStatus setParameter(
72             const ::aidl::android::hardware::audio::effect::Parameter& param) override;
73     ndk::ScopedAStatus getParameter(
74             const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
75             ::aidl::android::hardware::audio::effect::Parameter* param) override;
76 
77     static ndk::ScopedAStatus buildDescriptor(
78             const ::aidl::android::media::audio::common::AudioUuid& uuid,
79             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& subEffectDescs,
80             ::aidl::android::hardware::audio::effect::Descriptor* desc);
81 
82     /**
83      * Get the const reference of the active sub-effect return parameters.
84      * Always use this interface to get the effect open return parameters (FMQs) after a success
85      * setOffloadParam() call.
86      */
87     using StatusMQ = ::android::AidlMessageQueue<
88             ::aidl::android::hardware::audio::effect::IEffect::Status,
89             ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
90     using DataMQ = ::android::AidlMessageQueue<
91             float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
getStatusMQ()92     const std::shared_ptr<StatusMQ>& getStatusMQ() const {
93         return mSubEffects[mActiveSubIdx].effectMq.statusQ;
94     }
getInputMQ()95     const std::shared_ptr<DataMQ>& getInputMQ() const {
96         return mSubEffects[mActiveSubIdx].effectMq.inputQ;
97     }
getOutputMQ()98     const std::shared_ptr<DataMQ>& getOutputMQ() const {
99         return mSubEffects[mActiveSubIdx].effectMq.outputQ;
100     }
101 
102     bool isBypassing() const;
103     bool isTunnel() const;
104 
105     // call dump for all sub-effects
106     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
107 
108     std::string toString(size_t indent = 0) const;
109 
110   private:
111     // Proxy descriptor common part, copy from one sub-effect, and update the implementation UUID to
112     // proxy UUID, proxy descriptor capability part comes from the active sub-effect capability
113     const ::aidl::android::hardware::audio::effect::Descriptor::Common mDescriptorCommon;
114 
115     struct EffectMQ {
116         std::shared_ptr<StatusMQ> statusQ;
117         std::shared_ptr<DataMQ> inputQ, outputQ;
118     };
119     struct SubEffect {
120         const ::aidl::android::hardware::audio::effect::Descriptor descriptor;
121         std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> handle;
122         EffectMQ effectMq;
123     };
124     std::vector<SubEffect> mSubEffects;
125 
126     const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
127 
128     // index of the active sub-effects, by default use the first one (index 0)
129     // It's safe to assume there will always at least two SubEffects in mSubEffects
130     size_t mActiveSubIdx = 0;
131 
132     ndk::ScopedAStatus runWithActiveSubEffectThenOthers(
133             std::function<ndk::ScopedAStatus(
134                     const std::shared_ptr<
135                             ::aidl::android::hardware::audio::effect::IEffect>&)> const& func);
136 
137     ndk::ScopedAStatus runWithActiveSubEffect(
138             std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func);
139 
140     ndk::ScopedAStatus runWithAllSubEffects(
141             std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func);
142 
143     // build Descriptor.Common with all sub-effect descriptors
144     static ::aidl::android::hardware::audio::effect::Descriptor::Common buildDescriptorCommon(
145             const ::aidl::android::media::audio::common::AudioUuid& uuid,
146             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>&
147                     subEffectDescs);
148 
149     // close and release all sub-effects
150     ~EffectProxy();
151 };
152 
153 } // namespace effect
154 } // namespace android
155