/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-Configurable"
#include <android-base/logging.h>
#include <codec2/hidl/1.0/Configurable.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/types.h>
#include <C2ParamInternal.h>
namespace android {
namespace hardware {
namespace media {
namespace c2 {
namespace V1_0 {
namespace utils {
using namespace ::android;
CachedConfigurable::CachedConfigurable(
std::unique_ptr<ConfigurableC2Intf>&& intf)
: mIntf{std::move(intf)} {
}
c2_status_t CachedConfigurable::init(ComponentStore* store) {
// Retrieve supported parameters from store
c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
c2_status_t validate = store->validateSupportedParams(mSupportedParams);
return init == C2_OK ? C2_OK : validate;
}
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
Return<uint32_t> CachedConfigurable::getId() {
return mIntf->getId();
}
Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
_hidl_cb(mIntf->getName());
return Void();
}
Return<void> CachedConfigurable::query(
const hidl_vec<uint32_t>& indices,
bool mayBlock,
query_cb _hidl_cb) {
typedef C2Param::Index Index;
std::vector<Index> c2heapParamIndices(
(Index*)indices.data(),
(Index*)indices.data() + indices.size());
std::vector<std::unique_ptr<C2Param>> c2heapParams;
c2_status_t c2res = mIntf->query(
c2heapParamIndices,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
&c2heapParams);
hidl_vec<uint8_t> params;
if (!createParamsBlob(¶ms, c2heapParams)) {
LOG(WARNING) << "query -- invalid output params.";
}
_hidl_cb(static_cast<Status>(c2res), params);
return Void();
}
Return<void> CachedConfigurable::config(
const hidl_vec<uint8_t>& inParams,
bool mayBlock,
config_cb _hidl_cb) {
// inParams is not writable, so create a copy as config modifies the parameters
hidl_vec<uint8_t> inParamsCopy = inParams;
std::vector<C2Param*> c2params;
if (!parseParamsBlob(&c2params, inParamsCopy)) {
LOG(WARNING) << "config -- invalid input params.";
_hidl_cb(Status::CORRUPTED,
hidl_vec<SettingResult>(),
hidl_vec<uint8_t>());
return Void();
}
// TODO: check if blob was invalid
std::vector<std::unique_ptr<C2SettingResult>> c2failures;
c2_status_t c2res = mIntf->config(
c2params,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
&c2failures);
hidl_vec<SettingResult> failures(c2failures.size());
{
size_t ix = 0;
for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
if (c2result) {
if (objcpy(&failures[ix], *c2result)) {
++ix;
} else {
LOG(DEBUG) << "config -- invalid setting results.";
break;
}
}
}
failures.resize(ix);
}
hidl_vec<uint8_t> outParams;
if (!createParamsBlob(&outParams, c2params)) {
LOG(DEBUG) << "config -- invalid output params.";
}
_hidl_cb((Status)c2res, failures, outParams);
return Void();
}
Return<void> CachedConfigurable::querySupportedParams(
uint32_t start,
uint32_t count,
querySupportedParams_cb _hidl_cb) {
C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
start, count);
hidl_vec<ParamDescriptor> params(request.size());
Status res = Status::OK;
size_t dstIx = 0;
for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
if (mSupportedParams[srcIx]) {
if (objcpy(¶ms[dstIx], *mSupportedParams[srcIx])) {
++dstIx;
} else {
res = Status::CORRUPTED;
LOG(WARNING) << "querySupportedParams -- invalid output params.";
break;
}
} else {
res = Status::BAD_INDEX;
}
}
params.resize(dstIx);
_hidl_cb(res, params);
return Void();
}
Return<void> CachedConfigurable::querySupportedValues(
const hidl_vec<FieldSupportedValuesQuery>& inFields,
bool mayBlock,
querySupportedValues_cb _hidl_cb) {
std::vector<C2FieldSupportedValuesQuery> c2fields;
{
// C2FieldSupportedValuesQuery objects are restricted in that some
// members are const.
// C2ParamField - required for its constructor - has no constructors
// from fields. Use C2ParamInspector.
for (const FieldSupportedValuesQuery &query : inFields) {
c2fields.emplace_back(_C2ParamInspector::CreateParamField(
query.field.index,
query.field.fieldId.offset,
query.field.fieldId.size),
query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
C2FieldSupportedValuesQuery::POSSIBLE :
C2FieldSupportedValuesQuery::CURRENT);
}
}
c2_status_t c2res = mIntf->querySupportedValues(
c2fields,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
hidl_vec<FieldSupportedValuesQueryResult> outFields(inFields.size());
size_t dstIx = 0;
for (const C2FieldSupportedValuesQuery &result : c2fields) {
if (objcpy(&outFields[dstIx], result)) {
++dstIx;
} else {
outFields.resize(dstIx);
c2res = C2_CORRUPTED;
LOG(WARNING) << "querySupportedValues -- invalid output params.";
break;
}
}
_hidl_cb((Status)c2res, outFields);
return Void();
}
} // namespace utils
} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android