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