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