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