1 /*
2  * Copyright (C) 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 "Codec2-ComponentStore"
19 #include <log/log.h>
20 
21 #include <codec2/hidl/1.0/ComponentStore.h>
22 #include <codec2/hidl/1.0/InputSurface.h>
23 #include <codec2/hidl/1.0/Component.h>
24 #include <codec2/hidl/1.0/ConfigurableC2Intf.h>
25 #include <codec2/hidl/1.0/types.h>
26 
27 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
28 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
29 
30 #include <C2PlatformSupport.h>
31 
32 #include <utils/Errors.h>
33 
34 #include <android-base/file.h>
35 
36 #ifdef LOG
37 #undef LOG
38 #endif
39 
40 #ifdef PLOG
41 #undef PLOG
42 #endif
43 
44 #include <android-base/logging.h>
45 
46 #include <ostream>
47 #include <sstream>
48 #include <iomanip>
49 
50 namespace hardware {
51 namespace google {
52 namespace media {
53 namespace c2 {
54 namespace V1_0 {
55 namespace utils {
56 
57 using namespace ::android;
58 using ::android::GraphicBufferSource;
59 using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
60 
61 namespace /* unnamed */ {
62 
63 struct StoreIntf : public ConfigurableC2Intf {
StoreIntfhardware::google::media::c2::V1_0::utils::__anon66409a0c0111::StoreIntf64     StoreIntf(const std::shared_ptr<C2ComponentStore>& store) :
65         ConfigurableC2Intf(store ? store->getName() : ""),
66         mStore(store) {
67     }
68 
confighardware::google::media::c2::V1_0::utils::__anon66409a0c0111::StoreIntf69     c2_status_t config(
70             const std::vector<C2Param*> &params,
71             c2_blocking_t mayBlock,
72             std::vector<std::unique_ptr<C2SettingResult>> *const failures
73             ) override {
74         // Assume all params are blocking
75         // TODO: Filter for supported params
76         if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
77             return C2_BLOCKING;
78         }
79         return mStore->config_sm(params, failures);
80     }
81 
queryhardware::google::media::c2::V1_0::utils::__anon66409a0c0111::StoreIntf82     c2_status_t query(
83             const std::vector<C2Param::Index> &indices,
84             c2_blocking_t mayBlock,
85             std::vector<std::unique_ptr<C2Param>> *const params) const override {
86         // Assume all params are blocking
87         // TODO: Filter for supported params
88         if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
89             return C2_BLOCKING;
90         }
91         return mStore->query_sm({}, indices, params);
92     }
93 
querySupportedParamshardware::google::media::c2::V1_0::utils::__anon66409a0c0111::StoreIntf94     c2_status_t querySupportedParams(
95             std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
96             ) const override {
97         return mStore->querySupportedParams_nb(params);
98     }
99 
querySupportedValueshardware::google::media::c2::V1_0::utils::__anon66409a0c0111::StoreIntf100     c2_status_t querySupportedValues(
101             std::vector<C2FieldSupportedValuesQuery> &fields,
102             c2_blocking_t mayBlock) const override {
103         // Assume all params are blocking
104         // TODO: Filter for supported params
105         if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
106             return C2_BLOCKING;
107         }
108         return mStore->querySupportedValues_sm(fields);
109     }
110 
111 protected:
112     std::shared_ptr<C2ComponentStore> mStore;
113 };
114 
115 } // unnamed namespace
116 
ComponentStore(const std::shared_ptr<C2ComponentStore> & store)117 ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store) :
118     Configurable(new CachedConfigurable(std::make_unique<StoreIntf>(store))),
119     mStore(store) {
120 
121     std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
122     SetPreferredCodec2ComponentStore(store);
123 
124     // Retrieve struct descriptors
125     mParamReflector = mStore->getParamReflector();
126 
127     // Retrieve supported parameters from store
128     mInit = init(this);
129 }
130 
validateSupportedParams(const std::vector<std::shared_ptr<C2ParamDescriptor>> & params)131 c2_status_t ComponentStore::validateSupportedParams(
132         const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
133     c2_status_t res = C2_OK;
134 
135     for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
136         if (!desc) {
137             // All descriptors should be valid
138             res = res ? res : C2_BAD_VALUE;
139             continue;
140         }
141         C2Param::CoreIndex coreIndex = desc->index().coreIndex();
142         std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
143         auto it = mStructDescriptors.find(coreIndex);
144         if (it == mStructDescriptors.end()) {
145             std::shared_ptr<C2StructDescriptor> structDesc =
146                     mParamReflector->describe(coreIndex);
147             if (!structDesc) {
148                 // All supported params must be described
149                 res = C2_BAD_INDEX;
150             }
151             mStructDescriptors.insert({ coreIndex, structDesc });
152         }
153     }
154     return res;
155 }
156 
157 // Methods from ::android::hardware::media::c2::V1_0::IComponentStore
createComponent(const hidl_string & name,const sp<IComponentListener> & listener,const sp<IClientManager> & pool,createComponent_cb _hidl_cb)158 Return<void> ComponentStore::createComponent(
159         const hidl_string& name,
160         const sp<IComponentListener>& listener,
161         const sp<IClientManager>& pool,
162         createComponent_cb _hidl_cb) {
163 
164     sp<Component> component;
165     std::shared_ptr<C2Component> c2component;
166     Status status = static_cast<Status>(
167             mStore->createComponent(name, &c2component));
168 
169     if (status == Status::OK) {
170         onInterfaceLoaded(c2component->intf());
171         component = new Component(c2component, listener, this, pool);
172         if (!component) {
173             status = Status::CORRUPTED;
174         } else if (component->status() != C2_OK) {
175             status = static_cast<Status>(component->status());
176         } else {
177             component->initListener(component);
178             if (component->status() != C2_OK) {
179                 status = static_cast<Status>(component->status());
180             } else {
181                 std::lock_guard<std::mutex> lock(mComponentRosterMutex);
182                 component->setLocalId(
183                         mComponentRoster.emplace(
184                             Component::InterfaceKey(component),
185                             c2component)
186                         .first);
187             }
188         }
189     }
190     _hidl_cb(status, component);
191     return Void();
192 }
193 
createInterface(const hidl_string & name,createInterface_cb _hidl_cb)194 Return<void> ComponentStore::createInterface(
195         const hidl_string& name,
196         createInterface_cb _hidl_cb) {
197     std::shared_ptr<C2ComponentInterface> c2interface;
198     c2_status_t res = mStore->createInterface(name, &c2interface);
199     sp<IComponentInterface> interface;
200     if (res == C2_OK) {
201         onInterfaceLoaded(c2interface);
202         interface = new ComponentInterface(c2interface, this);
203     }
204     _hidl_cb((Status)res, interface);
205     return Void();
206 }
207 
listComponents(listComponents_cb _hidl_cb)208 Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
209     std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
210             mStore->listComponents();
211     hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
212     size_t ix = 0;
213     for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
214         if (c2trait) {
215             objcpy(&traits[ix++], *c2trait);
216         }
217     }
218     traits.resize(ix);
219     _hidl_cb(traits);
220     return Void();
221 }
222 
createInputSurface()223 Return<sp<IInputSurface>> ComponentStore::createInputSurface() {
224     sp<GraphicBufferSource> source = new GraphicBufferSource();
225     if (source->initCheck() != OK) {
226         return nullptr;
227     }
228     typedef ::android::hardware::graphics::bufferqueue::V1_0::
229             IGraphicBufferProducer HGBP;
230     typedef ::android::TWGraphicBufferProducer<HGBP> B2HGBP;
231     return new InputSurface(
232             this,
233             new B2HGBP(source->getIGraphicBufferProducer()),
234             source);
235 }
236 
onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> & intf)237 void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
238     // invalidate unsupported struct descriptors if a new interface is loaded as it may have
239     // exposed new descriptors
240     std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
241     if (!mLoadedInterfaces.count(intf->getName())) {
242         mUnsupportedStructDescriptors.clear();
243         mLoadedInterfaces.emplace(intf->getName());
244     }
245 }
246 
getStructDescriptors(const hidl_vec<uint32_t> & indices,getStructDescriptors_cb _hidl_cb)247 Return<void> ComponentStore::getStructDescriptors(
248         const hidl_vec<uint32_t>& indices,
249         getStructDescriptors_cb _hidl_cb) {
250     hidl_vec<StructDescriptor> descriptors(indices.size());
251     size_t dstIx = 0;
252     Status res = Status::OK;
253     for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
254         std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
255         const C2Param::CoreIndex coreIndex = C2Param::CoreIndex(indices[srcIx]).coreIndex();
256         const auto item = mStructDescriptors.find(coreIndex);
257         if (item == mStructDescriptors.end()) {
258             // not in the cache, and not known to be unsupported, query local reflector
259             if (!mUnsupportedStructDescriptors.count(coreIndex)) {
260                 std::shared_ptr<C2StructDescriptor> structDesc =
261                     mParamReflector->describe(coreIndex);
262                 if (!structDesc) {
263                     mUnsupportedStructDescriptors.emplace(coreIndex);
264                 } else {
265                     mStructDescriptors.insert({ coreIndex, structDesc });
266                     objcpy(&descriptors[dstIx++], *structDesc);
267                     continue;
268                 }
269             }
270             res = Status::NOT_FOUND;
271         } else if (item->second) {
272             objcpy(&descriptors[dstIx++], *item->second);
273         } else {
274             res = Status::NO_MEMORY;
275         }
276     }
277     descriptors.resize(dstIx);
278     _hidl_cb(res, descriptors);
279     return Void();
280 }
281 
getPoolClientManager()282 Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
283     return ClientManager::getInstance();
284 }
285 
copyBuffer(const Buffer & src,const Buffer & dst)286 Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
287     // TODO implement
288     (void)src;
289     (void)dst;
290     return Status::OMITTED;
291 }
292 
reportComponentDeath(const Component::LocalId & componentLocalId)293 void ComponentStore::reportComponentDeath(
294         const Component::LocalId& componentLocalId) {
295     std::lock_guard<std::mutex> lock(mComponentRosterMutex);
296     mComponentRoster.erase(componentLocalId);
297 }
298 
findC2Component(const sp<IComponent> & component) const299 std::shared_ptr<C2Component> ComponentStore::findC2Component(
300         const sp<IComponent>& component) const {
301     std::lock_guard<std::mutex> lock(mComponentRosterMutex);
302     Component::LocalId it = mComponentRoster.find(
303             Component::InterfaceKey(component));
304     if (it == mComponentRoster.end()) {
305         return std::shared_ptr<C2Component>();
306     }
307     return it->second.lock();
308 }
309 
310 // Debug dump
311 
312 namespace /* unnamed */ {
313 
314 // Dump component traits
dump(std::ostream & out,const std::shared_ptr<const C2Component::Traits> & comp)315 std::ostream& dump(
316         std::ostream& out,
317         const std::shared_ptr<const C2Component::Traits>& comp) {
318 
319     constexpr const char indent[] = "    ";
320 
321     out << indent << "name: " << comp->name << std::endl;
322     out << indent << "domain: " << comp->domain << std::endl;
323     out << indent << "kind: " << comp->kind << std::endl;
324     out << indent << "rank: " << comp->rank << std::endl;
325     out << indent << "mediaType: " << comp->mediaType << std::endl;
326     out << indent << "aliases:";
327     for (const auto& alias : comp->aliases) {
328         out << ' ' << alias;
329     }
330     out << std::endl;
331 
332     return out;
333 }
334 
335 // Dump component
dump(std::ostream & out,const std::shared_ptr<C2Component> & comp)336 std::ostream& dump(
337         std::ostream& out,
338         const std::shared_ptr<C2Component>& comp) {
339 
340     constexpr const char indent[] = "    ";
341 
342     std::shared_ptr<C2ComponentInterface> intf = comp->intf();
343     if (!intf) {
344         out << indent << "Unknown -- null interface" << std::endl;
345         return out;
346     }
347     out << indent << "name: " << intf->getName() << std::endl;
348     out << indent << "id: " << intf->getId() << std::endl;
349     return out;
350 }
351 
352 } // unnamed namespace
353 
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)354 Return<void> ComponentStore::debug(
355         const hidl_handle& handle,
356         const hidl_vec<hidl_string>& /* args */) {
357    LOG(INFO) << "debug -- dumping...";
358    const native_handle_t *h = handle.getNativeHandle();
359    if (!h || h->numFds != 1) {
360       LOG(ERROR) << "debug -- dumping failed -- "
361               "invalid file descriptor to dump to";
362       return Void();
363    }
364    std::ostringstream out;
365 
366    { // Populate "out".
367 
368         constexpr const char indent[] = "  ";
369 
370         // Show name.
371         out << "Beginning of dump -- C2ComponentStore: "
372                 << mStore->getName() << std::endl << std::endl;
373 
374         // Retrieve the list of supported components.
375         std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
376                 mStore->listComponents();
377 
378         // Dump the traits of supported components.
379         out << indent << "Supported components:" << std::endl << std::endl;
380         if (traitsList.size() == 0) {
381             out << indent << indent << "NONE" << std::endl << std::endl;
382         } else {
383             for (const auto& traits : traitsList) {
384                 dump(out, traits) << std::endl;
385             }
386         }
387 
388         // Retrieve the list of active components.
389         std::list<std::shared_ptr<C2Component>> activeComps;
390         {
391             std::lock_guard<std::mutex> lock(mComponentRosterMutex);
392             auto i = mComponentRoster.begin();
393             while (i != mComponentRoster.end()) {
394                 std::shared_ptr<C2Component> c2comp = i->second.lock();
395                 if (!c2comp) {
396                     auto j = i;
397                     ++i;
398                     mComponentRoster.erase(j);
399                 } else {
400                     ++i;
401                     activeComps.emplace_back(c2comp);
402                 }
403             }
404         }
405 
406         // Dump active components.
407         out << indent << "Active components:" << std::endl << std::endl;
408         if (activeComps.size() == 0) {
409             out << indent << indent << "NONE" << std::endl << std::endl;
410         } else {
411             for (const std::shared_ptr<C2Component>& c2comp : activeComps) {
412                 dump(out, c2comp) << std::endl;
413             }
414         }
415 
416         out << "End of dump -- C2ComponentStore: "
417                 << mStore->getName() << std::endl;
418    }
419 
420    if (!android::base::WriteStringToFd(out.str(), h->data[0])) {
421        PLOG(WARNING) << "debug -- dumping failed -- write()";
422    } else {
423        LOG(INFO) << "debug -- dumping succeeded";
424    }
425    return Void();
426 }
427 
428 
429 }  // namespace utils
430 }  // namespace V1_0
431 }  // namespace c2
432 }  // namespace media
433 }  // namespace google
434 }  // namespace hardware
435