• 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 "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 &params,
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, &params, 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(&paramPointers, 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