• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "android.hardware.media.c2-service"
19 
20 #include <android-base/logging.h>
21 #include <minijail.h>
22 
23 #include <util/C2InterfaceHelper.h>
24 #include <C2Component.h>
25 #include <C2Config.h>
26 
27 // HIDL
28 #include <binder/ProcessState.h>
29 #include <codec2/hidl/1.2/ComponentStore.h>
30 #include <hidl/HidlTransportSupport.h>
31 
32 // AIDL
33 #include <android/binder_manager.h>
34 #include <android/binder_process.h>
35 #include <codec2/aidl/ComponentStore.h>
36 #include <codec2/aidl/ParamTypes.h>
37 
38 // This is the absolute on-device path of the prebuild_etc module
39 // "android.hardware.media.c2-default-seccomp_policy" in Android.bp.
40 static constexpr char kBaseSeccompPolicyPath[] =
41         "/vendor/etc/seccomp_policy/"
42         "android.hardware.media.c2-default-seccomp_policy";
43 
44 // Additional seccomp permissions can be added in this file.
45 // This file does not exist by default.
46 static constexpr char kExtSeccompPolicyPath[] =
47         "/vendor/etc/seccomp_policy/"
48         "android.hardware.media.c2-extended-seccomp_policy";
49 
50 // We want multiple threads to be running so that a blocking operation
51 // on one codec does not block the other codecs.
52 // For HIDL: Extra threads may be needed to handle a stacked IPC sequence that
53 // contains alternating binder and hwbinder calls. (See b/35283480.)
54 static constexpr int kThreadCount = 8;
55 
56 class StoreImpl : public C2ComponentStore {
57 public:
StoreImpl()58     StoreImpl()
59         : mReflectorHelper(std::make_shared<C2ReflectorHelper>()),
60           mInterface(mReflectorHelper) {
61     }
62 
63     virtual ~StoreImpl() override = default;
64 
getName() const65     virtual C2String getName() const override {
66         return "default";
67     }
68 
createComponent(C2String,std::shared_ptr<C2Component> * const)69     virtual c2_status_t createComponent(
70             C2String /*name*/,
71             std::shared_ptr<C2Component>* const /*component*/) override {
72         return C2_NOT_FOUND;
73     }
74 
createInterface(C2String,std::shared_ptr<C2ComponentInterface> * const)75     virtual c2_status_t createInterface(
76             C2String /* name */,
77             std::shared_ptr<C2ComponentInterface>* const /* interface */) override {
78         return C2_NOT_FOUND;
79     }
80 
81     virtual std::vector<std::shared_ptr<const C2Component::Traits>>
listComponents()82             listComponents() override {
83         return {};
84     }
85 
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)86     virtual c2_status_t copyBuffer(
87             std::shared_ptr<C2GraphicBuffer> /* src */,
88             std::shared_ptr<C2GraphicBuffer> /* dst */) override {
89         return C2_OMITTED;
90     }
91 
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const92     virtual c2_status_t query_sm(
93         const std::vector<C2Param*>& stackParams,
94         const std::vector<C2Param::Index>& heapParamIndices,
95         std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
96         return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
97     }
98 
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)99     virtual c2_status_t config_sm(
100             const std::vector<C2Param*>& params,
101             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
102         return mInterface.config(params, C2_MAY_BLOCK, failures);
103     }
104 
getParamReflector() const105     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override {
106         return mReflectorHelper;
107     }
108 
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const109     virtual c2_status_t querySupportedParams_nb(
110             std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
111         return mInterface.querySupportedParams(params);
112     }
113 
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const114     virtual c2_status_t querySupportedValues_sm(
115             std::vector<C2FieldSupportedValuesQuery>& fields) const override {
116         return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
117     }
118 
119 private:
120     class Interface : public C2InterfaceHelper {
121     public:
Interface(const std::shared_ptr<C2ReflectorHelper> & helper)122         Interface(const std::shared_ptr<C2ReflectorHelper> &helper)
123             : C2InterfaceHelper(helper) {
124             setDerivedInstance(this);
125 
126             addParameter(
127                 DefineParam(mIonUsageInfo, "ion-usage")
128                 .withDefault(new C2StoreIonUsageInfo())
129                 .withFields({
130                     C2F(mIonUsageInfo, usage).flags(
131                             {C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
132                     C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
133                     C2F(mIonUsageInfo, heapMask).any(),
134                     C2F(mIonUsageInfo, allocFlags).flags({}),
135                     C2F(mIonUsageInfo, minAlignment).equalTo(0)
136                 })
137                 .withSetter(SetIonUsage)
138                 .build());
139 
140             addParameter(
141                 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
142                 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(128))
143                 .withFields({
144                     C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
145                     C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
146                     C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
147                     C2F(mDmaBufUsageInfo, m.heapName).any(),
148                 })
149                 .withSetter(SetDmaBufUsage)
150                 .build());
151         }
152 
153         virtual ~Interface() = default;
154 
155     private:
SetIonUsage(bool,C2P<C2StoreIonUsageInfo> & me)156         static C2R SetIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
157             // Vendor's TODO: put appropriate mapping logic
158             me.set().heapMask = ~0;
159             me.set().allocFlags = 0;
160             me.set().minAlignment = 0;
161             return C2R::Ok();
162         }
163 
SetDmaBufUsage(bool,C2P<C2StoreDmaBufUsageInfo> & me)164         static C2R SetDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
165             // Vendor's TODO: put appropriate mapping logic
166             strncpy(me.set().m.heapName, "system", me.v.flexCount());
167             me.set().m.allocFlags = 0;
168             return C2R::Ok();
169         }
170 
171 
172         std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
173         std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
174     };
175     std::shared_ptr<C2ReflectorHelper> mReflectorHelper;
176     Interface mInterface;
177 };
178 
runAidlService()179 void runAidlService() {
180     ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
181     ABinderProcess_startThreadPool();
182 
183     // Create IComponentStore service.
184     using namespace ::aidl::android::hardware::media::c2;
185     std::shared_ptr<IComponentStore> store;
186 
187     // TODO: Replace this with
188     // store = new utils::ComponentStore(
189     //         /* implementation of C2ComponentStore */);
190     LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
191     store = ::ndk::SharedRefBase::make<utils::ComponentStore>(
192             std::make_shared<StoreImpl>());
193 
194     if (store == nullptr) {
195         LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
196     } else {
197         const std::string serviceName =
198             std::string(IComponentStore::descriptor) + "/default";
199         binder_exception_t ex = AServiceManager_addService(
200                 store->asBinder().get(), serviceName.c_str());
201         if (ex != EX_NONE) {
202             LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
203                           " with instance name << \""
204                        << serviceName << "\".";
205         } else {
206             LOG(DEBUG) << "Codec2's IComponentStore service registered. "
207                           "Instance name: \"" << serviceName << "\".";
208         }
209     }
210 
211     ABinderProcess_joinThreadPool();
212 }
213 
runHidlService()214 void runHidlService() {
215     using namespace ::android;
216 
217     // Enable vndbinder to allow vendor-to-vendor binder calls.
218     ProcessState::initWithDriver("/dev/vndbinder");
219 
220     ProcessState::self()->startThreadPool();
221     hardware::configureRpcThreadpool(kThreadCount, true /* callerWillJoin */);
222 
223     // Create IComponentStore service.
224     {
225         using namespace ::android::hardware::media::c2::V1_2;
226         sp<IComponentStore> store;
227 
228         // TODO: Replace this with
229         // store = new utils::ComponentStore(
230         //         /* implementation of C2ComponentStore */);
231         LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
232         store = new utils::ComponentStore(
233                 std::make_shared<StoreImpl>());
234 
235         if (store == nullptr) {
236             LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
237         } else {
238             constexpr char const* serviceName = "default";
239             if (store->registerAsService(serviceName) != OK) {
240                 LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
241                               " with instance name << \""
242                            << serviceName << "\".";
243             } else {
244                 LOG(DEBUG) << "Codec2's IComponentStore service registered. "
245                               "Instance name: \"" << serviceName << "\".";
246             }
247         }
248     }
249 
250     hardware::joinRpcThreadpool();
251 }
252 
main(int,char **)253 int main(int /* argc */, char** /* argv */) {
254     const bool aidlEnabled = ::aidl::android::hardware::media::c2::utils::IsEnabled();
255     LOG(DEBUG) << "android.hardware.media.c2" << (aidlEnabled ? "-V1" : "@1.2")
256                << "-service starting...";
257 
258     // Set up minijail to limit system calls.
259     signal(SIGPIPE, SIG_IGN);
260     android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
261     if (aidlEnabled) {
262         runAidlService();
263     } else {
264         runHidlService();
265     }
266     return 0;
267 }
268