blob: 5311bbda168704db612874987519de491fcb4708 [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#include "HidlCamera.h"
#include "AidlCameraStream.h"
#include "AidlDisplay.h"
#include "utils/include/Utils.h"
#include <android-base/logging.h>
namespace aidl::android::automotive::evs::implementation {
namespace hidlevs = ::android::hardware::automotive::evs;
using ::aidl::android::hardware::automotive::evs::BufferDesc;
using ::aidl::android::hardware::automotive::evs::CameraDesc;
using ::aidl::android::hardware::automotive::evs::CameraParam;
using ::aidl::android::hardware::automotive::evs::DisplayState;
using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
using ::aidl::android::hardware::automotive::evs::EvsEventType;
using ::aidl::android::hardware::automotive::evs::EvsResult;
using ::aidl::android::hardware::automotive::evs::IEvsCameraStream;
using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
using ::aidl::android::hardware::automotive::evs::ParameterRange;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::ndk::ScopedAStatus;
HidlCamera::~HidlCamera() {
mAidlCamera = nullptr;
mAidlStream = nullptr;
}
Return<void> HidlCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb({});
return {};
}
CameraDesc aidlDesc;
if (auto status = mAidlCamera->getCameraInfo(&aidlDesc); !status.isOk()) {
LOG(ERROR) << "Failed to get a camera information, status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
_hidl_cb({});
return {};
}
_hidl_cb(std::move(Utils::makeToHidlV1_0(aidlDesc)));
return {};
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::setMaxFramesInFlight(uint32_t bufferCount) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
auto status = mAidlCamera->setMaxFramesInFlight(static_cast<int32_t>(bufferCount));
if (!status.isOk()) {
return hidlevs::V1_0::EvsResult::BUFFER_NOT_AVAILABLE;
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::startVideoStream(
const ::android::sp<hidlevs::V1_0::IEvsCameraStream>& stream) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
} else if (!stream) {
LOG(ERROR) << "A given HIDL IEvsCameraStream object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
} else if (mAidlStream) {
LOG(WARNING) << "A video stream is already running.";
return hidlevs::V1_0::EvsResult::STREAM_ALREADY_RUNNING;
}
// Creates a wrapper object and requests a video stream
mAidlStream = ::ndk::SharedRefBase::make<AidlCameraStream>(stream);
if (auto status = mAidlCamera->startVideoStream(mAidlStream); !status.isOk()) {
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<void> HidlCamera::doneWithFrame(const hidlevs::V1_0::BufferDesc& buffer) {
if (!mAidlStream) {
LOG(ERROR) << "A reference to AIDL IEvsCameraStream object is invalid.";
return {};
}
BufferDesc aidlBuffer;
if (!mAidlStream->getBuffer(buffer.bufferId, &aidlBuffer)) {
LOG(ERROR) << "Ignores an unknown buffer " << buffer.bufferId;
return {};
}
std::vector<BufferDesc> buffersToReturn(1);
int bufferId = aidlBuffer.bufferId; // save pre move() for log message.
buffersToReturn[0] = std::move(aidlBuffer);
if (auto status = mAidlCamera->doneWithFrame(std::move(buffersToReturn)); !status.isOk()) {
LOG(WARNING) << "Failed to return a buffer " << bufferId << ", status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
return {};
}
return {};
}
Return<void> HidlCamera::stopVideoStream() {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return {};
}
mAidlCamera->stopVideoStream();
return {};
}
Return<int32_t> HidlCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return 0;
}
std::vector<uint8_t> value;
if (!mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value).isOk() ||
value.size() < sizeof(int32_t)) {
return 0;
}
return *reinterpret_cast<int32_t*>(value.data());
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo(uint32_t opaqueIdentifier,
int32_t opaqueValue) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
std::vector<uint8_t> value(sizeof(int32_t));
*reinterpret_cast<int32_t*>(value.data()) = opaqueValue;
auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
if (!status.isOk()) {
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
Return<void> HidlCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb({});
return {};
}
CameraDesc aidlDesc;
if (auto status = mAidlCamera->getCameraInfo(&aidlDesc); !status.isOk()) {
LOG(ERROR) << "Failed to get a camera information, status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
_hidl_cb({});
return {};
}
_hidl_cb(std::move(Utils::makeToHidlV1_1(aidlDesc)));
return {};
}
Return<void> HidlCamera::getPhysicalCameraInfo(const hidl_string& deviceId,
getPhysicalCameraInfo_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb({});
return {};
}
CameraDesc aidlDesc;
if (auto status = mAidlCamera->getPhysicalCameraInfo(deviceId, &aidlDesc); !status.isOk()) {
LOG(ERROR) << "Failed to read information of a camera " << deviceId << ", status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
_hidl_cb({});
return {};
}
_hidl_cb(Utils::makeToHidlV1_1(aidlDesc));
return {};
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::doneWithFrame_1_1(
const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers) {
if (!mAidlStream) {
LOG(WARNING) << "A reference to AIDL IEvsCameraStream object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
std::vector<BufferDesc> buffersToReturn(buffers.size());
for (auto i = 0; i < buffers.size(); ++i) {
BufferDesc aidlBuffer;
if (!mAidlStream->getBuffer(buffers[i].bufferId, &aidlBuffer)) {
LOG(WARNING) << "Ignores an unknown buffer " << buffers[i].bufferId;
continue;
}
buffersToReturn[i] = std::move(aidlBuffer);
}
if (auto status = mAidlCamera->doneWithFrame(std::move(buffersToReturn)); !status.isOk()) {
LOG(ERROR) << "Failed to return buffers, status = " << status.getServiceSpecificError();
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::setMaster() {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
if (auto status = mAidlCamera->setPrimaryClient(); !status.isOk()) {
EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
if (err == EvsResult::PERMISSION_DENIED) {
// HIDL EvsManager implementations return EvsResult::OWNERSHIP_LOST
// if the primary client exists already.
err = EvsResult::OWNERSHIP_LOST;
}
return Utils::makeToHidl(err);
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::forceMaster(
const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
auto status = mAidlCamera->forcePrimaryClient(::ndk::SharedRefBase::make<AidlDisplay>(display));
if (!status.isOk()) {
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::unsetMaster() {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
if (auto status = mAidlCamera->unsetPrimaryClient(); !status.isOk()) {
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<void> HidlCamera::getParameterList(getParameterList_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb({});
return {};
}
std::vector<CameraParam> aidlList;
if (auto status = mAidlCamera->getParameterList(&aidlList); !status.isOk()) {
LOG(ERROR) << "Failed to get a parameter list, status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
_hidl_cb({});
return {};
}
hidl_vec<hidlevs::V1_1::CameraParam> hidlList;
hidlList.resize(aidlList.size());
for (auto i = 0; i < aidlList.size(); ++i) {
hidlList[i] = Utils::makeToHidl(aidlList[i]);
}
_hidl_cb(hidlList);
return {};
}
Return<void> HidlCamera::getIntParameterRange(hidlevs::V1_1::CameraParam id,
getIntParameterRange_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb(0, 0, 0);
return {};
}
ParameterRange aidlRange;
if (auto status = mAidlCamera->getIntParameterRange(Utils::makeFromHidl(id), &aidlRange);
!status.isOk()) {
LOG(ERROR) << "Failed to get a parameter range, status = "
<< toString(static_cast<EvsResult>(status.getServiceSpecificError()));
_hidl_cb(0, 0, 0);
return {};
}
_hidl_cb(aidlRange.min, aidlRange.max, aidlRange.step);
return {};
}
Return<void> HidlCamera::setIntParameter(hidlevs::V1_1::CameraParam id, int32_t value,
setIntParameter_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
return {};
}
std::vector<int32_t> aidlValues;
auto status = mAidlCamera->setIntParameter(Utils::makeFromHidl(id), value, &aidlValues);
if (!status.isOk()) {
EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
if (err == EvsResult::PERMISSION_DENIED) {
// HIDL EvsManager implementations return EvsResult::INVALID_ARG if
// the client is not permitted to change parameters.
err = EvsResult::INVALID_ARG;
}
_hidl_cb(Utils::makeToHidl(err), {value});
return {};
}
_hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
return {};
}
Return<void> HidlCamera::getIntParameter(hidlevs::V1_1::CameraParam id,
getIntParameter_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
return {};
}
std::vector<int32_t> aidlValues;
auto status = mAidlCamera->getIntParameter(Utils::makeFromHidl(id), &aidlValues);
if (!status.isOk()) {
_hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
return {};
}
_hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
return {};
}
Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo_1_1(
uint32_t opaqueIdentifier, const hidl_vec<uint8_t>& opaqueValue) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
}
std::vector<uint8_t> value(opaqueValue);
auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
if (!status.isOk()) {
return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
}
return hidlevs::V1_0::EvsResult::OK;
}
Return<void> HidlCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
return {};
}
std::vector<uint8_t> value;
auto status = mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value);
if (!status.isOk()) {
_hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
return {};
}
_hidl_cb(hidlevs::V1_0::EvsResult::OK, value);
return {};
}
Return<void> HidlCamera::importExternalBuffers(const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers,
importExternalBuffers_cb _hidl_cb) {
if (!mAidlCamera) {
LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
_hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, 0);
return {};
}
std::vector<BufferDesc> aidlBuffers(buffers.size());
for (auto i = 0; i < buffers.size(); ++i) {
aidlBuffers[i] = std::move(Utils::makeFromHidl(buffers[i]));
}
int32_t delta = 0;
if (auto status = mAidlCamera->importExternalBuffers(aidlBuffers, &delta); !status.isOk()) {
_hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())),
delta);
return {};
}
_hidl_cb(hidlevs::V1_0::EvsResult::OK, delta);
return {};
}
} // namespace aidl::android::automotive::evs::implementation