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-Configurable"
19 #include <android-base/logging.h>
20 
21 #include <codec2/hidl/1.0/Configurable.h>
22 #include <codec2/hidl/1.0/ComponentStore.h>
23 #include <codec2/hidl/1.0/types.h>
24 
25 #include <C2ParamInternal.h>
26 
27 namespace android {
28 namespace hardware {
29 namespace media {
30 namespace c2 {
31 namespace V1_0 {
32 namespace utils {
33 
34 using namespace ::android;
35 
CachedConfigurable(std::unique_ptr<ConfigurableC2Intf> && intf)36 CachedConfigurable::CachedConfigurable(
37         std::unique_ptr<ConfigurableC2Intf>&& intf)
38       : mIntf{std::move(intf)} {
39 }
40 
init(const std::shared_ptr<ParameterCache> & cache)41 c2_status_t CachedConfigurable::init(
42         const std::shared_ptr<ParameterCache>& cache) {
43     // Retrieve supported parameters from store
44     c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
45     c2_status_t validate = cache->validate(mSupportedParams);
46     return init == C2_OK ? C2_OK : validate;
47 }
48 
49 // Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
getId()50 Return<uint32_t> CachedConfigurable::getId() {
51     return mIntf->getId();
52 }
53 
getName(getName_cb _hidl_cb)54 Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
55     _hidl_cb(mIntf->getName());
56     return Void();
57 }
58 
query(const hidl_vec<uint32_t> & indices,bool mayBlock,query_cb _hidl_cb)59 Return<void> CachedConfigurable::query(
60         const hidl_vec<uint32_t>& indices,
61         bool mayBlock,
62         query_cb _hidl_cb) {
63     typedef C2Param::Index Index;
64     std::vector<Index> c2heapParamIndices(
65             (Index*)indices.data(),
66             (Index*)indices.data() + indices.size());
67     std::vector<std::unique_ptr<C2Param>> c2heapParams;
68     c2_status_t c2res = mIntf->query(
69             c2heapParamIndices,
70             mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
71             &c2heapParams);
72 
73     hidl_vec<uint8_t> params;
74     if (!createParamsBlob(&params, c2heapParams)) {
75         LOG(WARNING) << "query -- invalid output params.";
76     }
77     _hidl_cb(static_cast<Status>(c2res), params);
78     return Void();
79 }
80 
config(const hidl_vec<uint8_t> & inParams,bool mayBlock,config_cb _hidl_cb)81 Return<void> CachedConfigurable::config(
82         const hidl_vec<uint8_t>& inParams,
83         bool mayBlock,
84         config_cb _hidl_cb) {
85     // inParams is not writable, so create a copy as config modifies the parameters
86     hidl_vec<uint8_t> inParamsCopy = inParams;
87     std::vector<C2Param*> c2params;
88     if (!parseParamsBlob(&c2params, inParamsCopy)) {
89         LOG(WARNING) << "config -- invalid input params.";
90         _hidl_cb(Status::CORRUPTED,
91                 hidl_vec<SettingResult>(),
92                 hidl_vec<uint8_t>());
93         return Void();
94     }
95     // TODO: check if blob was invalid
96     std::vector<std::unique_ptr<C2SettingResult>> c2failures;
97     c2_status_t c2res = mIntf->config(
98             c2params,
99             mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
100             &c2failures);
101     hidl_vec<SettingResult> failures(c2failures.size());
102     {
103         size_t ix = 0;
104         for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
105             if (c2result) {
106                 if (objcpy(&failures[ix], *c2result)) {
107                     ++ix;
108                 } else {
109                     LOG(DEBUG) << "config -- invalid setting results.";
110                     break;
111                 }
112             }
113         }
114         failures.resize(ix);
115     }
116     hidl_vec<uint8_t> outParams;
117     if (!createParamsBlob(&outParams, c2params)) {
118         LOG(DEBUG) << "config -- invalid output params.";
119     }
120     _hidl_cb((Status)c2res, failures, outParams);
121     return Void();
122 }
123 
querySupportedParams(uint32_t start,uint32_t count,querySupportedParams_cb _hidl_cb)124 Return<void> CachedConfigurable::querySupportedParams(
125         uint32_t start,
126         uint32_t count,
127         querySupportedParams_cb _hidl_cb) {
128     C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
129             start, count);
130     hidl_vec<ParamDescriptor> params(request.size());
131     Status res = Status::OK;
132     size_t dstIx = 0;
133     for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
134         if (mSupportedParams[srcIx]) {
135             if (objcpy(&params[dstIx], *mSupportedParams[srcIx])) {
136                 ++dstIx;
137             } else {
138                 res = Status::CORRUPTED;
139                 LOG(WARNING) << "querySupportedParams -- invalid output params.";
140                 break;
141             }
142         } else {
143             res = Status::BAD_INDEX;
144         }
145     }
146     params.resize(dstIx);
147     _hidl_cb(res, params);
148     return Void();
149 }
150 
querySupportedValues(const hidl_vec<FieldSupportedValuesQuery> & inFields,bool mayBlock,querySupportedValues_cb _hidl_cb)151 Return<void> CachedConfigurable::querySupportedValues(
152         const hidl_vec<FieldSupportedValuesQuery>& inFields,
153         bool mayBlock,
154         querySupportedValues_cb _hidl_cb) {
155     std::vector<C2FieldSupportedValuesQuery> c2fields;
156     {
157         // C2FieldSupportedValuesQuery objects are restricted in that some
158         // members are const.
159         // C2ParamField - required for its constructor - has no constructors
160         // from fields. Use C2ParamInspector.
161         for (const FieldSupportedValuesQuery &query : inFields) {
162             c2fields.emplace_back(_C2ParamInspector::CreateParamField(
163                     query.field.index,
164                     query.field.fieldId.offset,
165                     query.field.fieldId.size),
166                     query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
167                     C2FieldSupportedValuesQuery::POSSIBLE :
168                     C2FieldSupportedValuesQuery::CURRENT);
169         }
170     }
171     c2_status_t c2res = mIntf->querySupportedValues(
172             c2fields,
173             mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
174     hidl_vec<FieldSupportedValuesQueryResult> outFields(inFields.size());
175     size_t dstIx = 0;
176     for (const C2FieldSupportedValuesQuery &result : c2fields) {
177         if (objcpy(&outFields[dstIx], result)) {
178             ++dstIx;
179         } else {
180             outFields.resize(dstIx);
181             c2res = C2_CORRUPTED;
182             LOG(WARNING) << "querySupportedValues -- invalid output params.";
183             break;
184         }
185     }
186     _hidl_cb((Status)c2res, outFields);
187     return Void();
188 }
189 
190 }  // namespace utils
191 }  // namespace V1_0
192 }  // namespace c2
193 }  // namespace media
194 }  // namespace hardware
195 }  // namespace android
196 
197