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 "CodecServiceRegistrant"
19
20 #include <android-base/properties.h>
21 #include <android-base/logging.h>
22 #include <android-base/properties.h>
23
24 #include <C2Component.h>
25 #include <C2PlatformSupport.h>
26 #include <codec2/hidl/1.0/ComponentStore.h>
27 #include <codec2/hidl/1.1/ComponentStore.h>
28 #include <codec2/hidl/1.2/ComponentStore.h>
29 #include <codec2/hidl/1.2/Configurable.h>
30 #include <codec2/hidl/1.2/types.h>
31 #include <hidl/HidlSupport.h>
32 #include <media/CodecServiceRegistrant.h>
33
34 namespace /* unnamed */ {
35
36 using ::android::hardware::hidl_vec;
37 using ::android::hardware::hidl_string;
38 using ::android::hardware::Return;
39 using ::android::hardware::Void;
40 using ::android::sp;
41 using namespace ::android::hardware::media::c2::V1_2;
42 using namespace ::android::hardware::media::c2::V1_2::utils;
43
44 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
45
46 // Converter from IComponentStore to C2ComponentStore.
47 class H2C2ComponentStore : public C2ComponentStore {
48 protected:
49 using IComponentStore =
50 ::android::hardware::media::c2::V1_0::IComponentStore;
51 using IConfigurable =
52 ::android::hardware::media::c2::V1_0::IConfigurable;
53 sp<IComponentStore> mStore;
54 sp<IConfigurable> mConfigurable;
55 public:
H2C2ComponentStore(sp<IComponentStore> const & store)56 explicit H2C2ComponentStore(sp<IComponentStore> const& store)
57 : mStore{store},
__anone6d7a5110202() 58 mConfigurable{[store]() -> sp<IConfigurable>{
59 if (!store) {
60 return nullptr;
61 }
62 Return<sp<IConfigurable>> transResult =
63 store->getConfigurable();
64 return transResult.isOk() ?
65 static_cast<sp<IConfigurable>>(transResult) :
66 nullptr;
67 }()} {
68 if (!mConfigurable) {
69 LOG(ERROR) << "Preferred store is corrupted.";
70 }
71 }
72
73 virtual ~H2C2ComponentStore() override = default;
74
config_sm(std::vector<C2Param * > const & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)75 virtual c2_status_t config_sm(
76 std::vector<C2Param*> const ¶ms,
77 std::vector<std::unique_ptr<C2SettingResult>>* const failures
78 ) override {
79 Params hidlParams;
80 if (!createParamsBlob(&hidlParams, params)) {
81 LOG(ERROR) << "config -- bad input.";
82 return C2_TRANSACTION_FAILED;
83 }
84 c2_status_t status{};
85 Return<void> transResult = mConfigurable->config(
86 hidlParams,
87 true,
88 [&status, ¶ms, failures](
89 Status s,
90 const hidl_vec<SettingResult> f,
91 const Params& o) {
92 status = static_cast<c2_status_t>(s);
93 if (status != C2_OK && status != C2_BAD_INDEX) {
94 LOG(DEBUG) << "config -- call failed: "
95 << status << ".";
96 }
97 size_t i = failures->size();
98 failures->resize(i + f.size());
99 for (const SettingResult& sf : f) {
100 if (!objcpy(&(*failures)[i++], sf)) {
101 LOG(ERROR) << "config -- "
102 << "invalid SettingResult returned.";
103 return;
104 }
105 }
106 if (!updateParamsFromBlob(params, o)) {
107 LOG(ERROR) << "config -- "
108 << "failed to parse returned params.";
109 status = C2_CORRUPTED;
110 }
111 });
112 if (!transResult.isOk()) {
113 LOG(ERROR) << "config -- transaction failed.";
114 return C2_TRANSACTION_FAILED;
115 }
116 return status;
117 };
118
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)119 virtual c2_status_t copyBuffer(
120 std::shared_ptr<C2GraphicBuffer>,
121 std::shared_ptr<C2GraphicBuffer>) override {
122 LOG(ERROR) << "copyBuffer -- not supported.";
123 return C2_OMITTED;
124 }
125
createComponent(C2String,std::shared_ptr<C2Component> * const component)126 virtual c2_status_t createComponent(
127 C2String, std::shared_ptr<C2Component> *const component) override {
128 component->reset();
129 LOG(ERROR) << "createComponent -- not supported.";
130 return C2_OMITTED;
131 }
132
createInterface(C2String,std::shared_ptr<C2ComponentInterface> * const interface)133 virtual c2_status_t createInterface(
134 C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
135 interface->reset();
136 LOG(ERROR) << "createInterface -- not supported.";
137 return C2_OMITTED;
138 }
139
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const140 virtual c2_status_t query_sm(
141 const std::vector<C2Param *> &stackParams,
142 const std::vector<C2Param::Index> &heapParamIndices,
143 std::vector<std::unique_ptr<C2Param>> *const heapParams) const
144 override {
145 hidl_vec<ParamIndex> indices(
146 stackParams.size() + heapParamIndices.size());
147 size_t numIndices = 0;
148 for (C2Param* const& stackParam : stackParams) {
149 if (!stackParam) {
150 LOG(WARNING) << "query -- null stack param encountered.";
151 continue;
152 }
153 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
154 }
155 size_t numStackIndices = numIndices;
156 for (const C2Param::Index& index : heapParamIndices) {
157 indices[numIndices++] =
158 static_cast<ParamIndex>(static_cast<uint32_t>(index));
159 }
160 indices.resize(numIndices);
161 if (heapParams) {
162 heapParams->reserve(heapParams->size() + numIndices);
163 }
164 c2_status_t status;
165 Return<void> transResult = mConfigurable->query(
166 indices,
167 true,
168 [&status, &numStackIndices, &stackParams, heapParams](
169 Status s, const Params& p) {
170 status = static_cast<c2_status_t>(s);
171 if (status != C2_OK && status != C2_BAD_INDEX) {
172 LOG(DEBUG) << "query -- call failed: "
173 << status << ".";
174 return;
175 }
176 std::vector<C2Param*> paramPointers;
177 if (!parseParamsBlob(¶mPointers, p)) {
178 LOG(ERROR) << "query -- error while parsing params.";
179 status = C2_CORRUPTED;
180 return;
181 }
182 size_t i = 0;
183 for (auto it = paramPointers.begin();
184 it != paramPointers.end(); ) {
185 C2Param* paramPointer = *it;
186 if (numStackIndices > 0) {
187 --numStackIndices;
188 if (!paramPointer) {
189 LOG(WARNING) << "query -- null stack param.";
190 ++it;
191 continue;
192 }
193 for (; i < stackParams.size() && !stackParams[i]; ) {
194 ++i;
195 }
196 if (i >= stackParams.size()) {
197 LOG(ERROR) << "query -- unexpected error.";
198 status = C2_CORRUPTED;
199 return;
200 }
201 if (stackParams[i]->index() != paramPointer->index()) {
202 LOG(WARNING) << "query -- param skipped: "
203 "index = "
204 << stackParams[i]->index() << ".";
205 stackParams[i++]->invalidate();
206 continue;
207 }
208 if (!stackParams[i++]->updateFrom(*paramPointer)) {
209 LOG(WARNING) << "query -- param update failed: "
210 "index = "
211 << paramPointer->index() << ".";
212 }
213 } else {
214 if (!paramPointer) {
215 LOG(WARNING) << "query -- null heap param.";
216 ++it;
217 continue;
218 }
219 if (!heapParams) {
220 LOG(WARNING) << "query -- "
221 "unexpected extra stack param.";
222 } else {
223 heapParams->emplace_back(
224 C2Param::Copy(*paramPointer));
225 }
226 }
227 ++it;
228 }
229 });
230 if (!transResult.isOk()) {
231 LOG(ERROR) << "query -- transaction failed.";
232 return C2_TRANSACTION_FAILED;
233 }
234 return status;
235 }
236
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const237 virtual c2_status_t querySupportedParams_nb(
238 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
239 c2_status_t status;
240 Return<void> transResult = mConfigurable->querySupportedParams(
241 std::numeric_limits<uint32_t>::min(),
242 std::numeric_limits<uint32_t>::max(),
243 [&status, params](
244 Status s,
245 const hidl_vec<ParamDescriptor>& p) {
246 status = static_cast<c2_status_t>(s);
247 if (status != C2_OK) {
248 LOG(DEBUG) << "querySupportedParams -- call failed: "
249 << status << ".";
250 return;
251 }
252 size_t i = params->size();
253 params->resize(i + p.size());
254 for (const ParamDescriptor& sp : p) {
255 if (!objcpy(&(*params)[i++], sp)) {
256 LOG(ERROR) << "querySupportedParams -- "
257 << "invalid returned ParamDescriptor.";
258 return;
259 }
260 }
261 });
262 if (!transResult.isOk()) {
263 LOG(ERROR) << "querySupportedParams -- transaction failed.";
264 return C2_TRANSACTION_FAILED;
265 }
266 return status;
267 }
268
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const269 virtual c2_status_t querySupportedValues_sm(
270 std::vector<C2FieldSupportedValuesQuery> &fields) const {
271 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
272 for (size_t i = 0; i < fields.size(); ++i) {
273 if (!objcpy(&inFields[i], fields[i])) {
274 LOG(ERROR) << "querySupportedValues -- bad input";
275 return C2_TRANSACTION_FAILED;
276 }
277 }
278
279 c2_status_t status;
280 Return<void> transResult = mConfigurable->querySupportedValues(
281 inFields,
282 true,
283 [&status, &inFields, &fields](
284 Status s,
285 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
286 status = static_cast<c2_status_t>(s);
287 if (status != C2_OK) {
288 LOG(DEBUG) << "querySupportedValues -- call failed: "
289 << status << ".";
290 return;
291 }
292 if (r.size() != fields.size()) {
293 LOG(ERROR) << "querySupportedValues -- "
294 "input and output lists "
295 "have different sizes.";
296 status = C2_CORRUPTED;
297 return;
298 }
299 for (size_t i = 0; i < fields.size(); ++i) {
300 if (!objcpy(&fields[i], inFields[i], r[i])) {
301 LOG(ERROR) << "querySupportedValues -- "
302 "invalid returned value.";
303 status = C2_CORRUPTED;
304 return;
305 }
306 }
307 });
308 if (!transResult.isOk()) {
309 LOG(ERROR) << "querySupportedValues -- transaction failed.";
310 return C2_TRANSACTION_FAILED;
311 }
312 return status;
313 }
314
getName() const315 virtual C2String getName() const {
316 C2String outName;
317 Return<void> transResult = mConfigurable->getName(
318 [&outName](const hidl_string& name) {
319 outName = name.c_str();
320 });
321 if (!transResult.isOk()) {
322 LOG(ERROR) << "getName -- transaction failed.";
323 }
324 return outName;
325 }
326
getParamReflector() const327 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
328 override {
329 struct SimpleParamReflector : public C2ParamReflector {
330 virtual std::unique_ptr<C2StructDescriptor> describe(
331 C2Param::CoreIndex coreIndex) const {
332 hidl_vec<ParamIndex> indices(1);
333 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
334 std::unique_ptr<C2StructDescriptor> descriptor;
335 Return<void> transResult = mBase->getStructDescriptors(
336 indices,
337 [&descriptor](
338 Status s,
339 const hidl_vec<StructDescriptor>& sd) {
340 c2_status_t status = static_cast<c2_status_t>(s);
341 if (status != C2_OK) {
342 LOG(DEBUG) << "SimpleParamReflector -- "
343 "getStructDescriptors() failed: "
344 << status << ".";
345 descriptor.reset();
346 return;
347 }
348 if (sd.size() != 1) {
349 LOG(DEBUG) << "SimpleParamReflector -- "
350 "getStructDescriptors() "
351 "returned vector of size "
352 << sd.size() << ". "
353 "It should be 1.";
354 descriptor.reset();
355 return;
356 }
357 if (!objcpy(&descriptor, sd[0])) {
358 LOG(DEBUG) << "SimpleParamReflector -- "
359 "getStructDescriptors() returned "
360 "corrupted data.";
361 descriptor.reset();
362 return;
363 }
364 });
365 return descriptor;
366 }
367
368 explicit SimpleParamReflector(sp<IComponentStore> base)
369 : mBase(base) { }
370
371 sp<IComponentStore> mBase;
372 };
373
374 return std::make_shared<SimpleParamReflector>(mStore);
375 }
376
377 virtual std::vector<std::shared_ptr<const C2Component::Traits>>
listComponents()378 listComponents() override {
379 LOG(ERROR) << "listComponents -- not supported.";
380 return {};
381 }
382 };
383
ionPropertiesDefined()384 bool ionPropertiesDefined() {
385 using namespace ::android::base;
386 std::string heapMask =
387 GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
388 std::string flags =
389 GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
390 std::string align =
391 GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
392 if (heapMask != "undefined" ||
393 flags != "undefined" ||
394 align != "undefined") {
395 LOG(INFO)
396 << "Some system properties for mediaswcodec ION usage are set: "
397 << "heapmask = " << heapMask << ", "
398 << "flags = " << flags << ", "
399 << "align = " << align << ". "
400 << "Preferred Codec2 store is defaulted to \"software\".";
401 return true;
402 }
403 return false;
404 }
405
406 } // unnamed namespace
407
RegisterCodecServices()408 extern "C" void RegisterCodecServices() {
409 LOG(INFO) << "Creating software Codec2 service...";
410 std::shared_ptr<C2ComponentStore> store =
411 android::GetCodec2PlatformComponentStore();
412 if (!store) {
413 LOG(ERROR) << "Failed to create Codec2 service.";
414 return;
415 }
416
417 using namespace ::android::hardware::media::c2;
418
419 int platformVersion =
420 android::base::GetIntProperty("ro.build.version.sdk", int32_t(29));
421 // STOPSHIP: Remove code name checking once platform version bumps up to 30.
422 std::string codeName =
423 android::base::GetProperty("ro.build.version.codename", "");
424 if (codeName == "S") {
425 platformVersion = 31;
426 }
427
428 switch (platformVersion) {
429 case 31: {
430 android::sp<V1_2::IComponentStore> storeV1_2 =
431 new V1_2::utils::ComponentStore(store);
432 if (storeV1_2->registerAsService("software") != android::OK) {
433 LOG(ERROR) << "Cannot register software Codec2 v1.2 service.";
434 return;
435 }
436 break;
437 }
438 case 30: {
439 android::sp<V1_1::IComponentStore> storeV1_1 =
440 new V1_1::utils::ComponentStore(store);
441 if (storeV1_1->registerAsService("software") != android::OK) {
442 LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
443 return;
444 }
445 break;
446 }
447 case 29: {
448 android::sp<V1_0::IComponentStore> storeV1_0 =
449 new V1_0::utils::ComponentStore(store);
450 if (storeV1_0->registerAsService("software") != android::OK) {
451 LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
452 return;
453 }
454 break;
455 }
456 default: {
457 LOG(ERROR) << "The platform version " << platformVersion <<
458 " is not supported.";
459 return;
460 }
461 }
462 if (!ionPropertiesDefined()) {
463 using IComponentStore =
464 ::android::hardware::media::c2::V1_0::IComponentStore;
465 std::string const preferredStoreName = "default";
466 sp<IComponentStore> preferredStore =
467 IComponentStore::getService(preferredStoreName.c_str());
468 if (preferredStore) {
469 ::android::SetPreferredCodec2ComponentStore(
470 std::make_shared<H2C2ComponentStore>(preferredStore));
471 LOG(INFO) <<
472 "Preferred Codec2 store is set to \"" <<
473 preferredStoreName << "\".";
474 } else {
475 LOG(INFO) <<
476 "Preferred Codec2 store is defaulted to \"software\".";
477 }
478 }
479 LOG(INFO) << "Software Codec2 service created and registered.";
480 }
481
482