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