blob: 59fc1cd74ba008689fdda2368856d4ab0e1d881f [file] [log] [blame]
/*
* Copyright (C) 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.
*/
#include <android/hardware/camera/device/3.2/types.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
#include <aidl/AidlUtils.h>
#include <hidl/AidlCameraDeviceCallbacks.h>
#include <hidl/HidlCameraDeviceUser.h>
#include <hidl/Utils.h>
#include <android/hardware/camera/device/3.2/types.h>
#include <android-base/properties.h>
namespace android {
namespace frameworks {
namespace cameraservice {
namespace device {
namespace V2_1 {
namespace implementation {
using hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
using hardware::cameraservice::utils::conversion::convertToHidl;
using hardware::cameraservice::utils::conversion::convertFromHidl;
using hardware::cameraservice::utils::conversion::B2HStatus;
using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
using hardware::hidl_vec;
using hardware::Return;
using hardware::Void;
using HSubmitInfo = device::V2_0::SubmitInfo;
using hardware::camera2::params::OutputConfiguration;
using hardware::camera2::params::SessionConfiguration;
static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
Return<void> HidlCameraDeviceUser::disconnect() {
mDeviceRemote->disconnect();
return Void();
}
HidlCameraDeviceUser::HidlCameraDeviceUser(
const sp<hardware::camera2::ICameraDeviceUser> &deviceRemote)
: mDeviceRemote(deviceRemote) {
mInitSuccess = initDevice();
mVndkVersion = base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
}
bool HidlCameraDeviceUser::initDevice() {
// TODO: Get request and result metadata queue size from a system property.
int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
mCaptureRequestMetadataQueue =
std::make_unique<CaptureRequestMetadataQueue>(static_cast<size_t>(reqFMQSize),
false /* non blocking */);
if (!mCaptureRequestMetadataQueue->isValid()) {
ALOGE("%s: invalid request fmq", __FUNCTION__);
return false;
}
int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
mCaptureResultMetadataQueue =
std::make_shared<CaptureResultMetadataQueue>(static_cast<size_t>(resFMQSize),
false /* non blocking */);
if (!mCaptureResultMetadataQueue->isValid()) {
ALOGE("%s: invalid result fmq", __FUNCTION__);
return false;
}
return true;
}
Return<void> HidlCameraDeviceUser::getCaptureRequestMetadataQueue(
getCaptureRequestMetadataQueue_cb _hidl_cb) {
if (mInitSuccess) {
_hidl_cb(*mCaptureRequestMetadataQueue->getDesc());
}
return Void();
}
Return<void> HidlCameraDeviceUser::getCaptureResultMetadataQueue(
getCaptureResultMetadataQueue_cb _hidl_cb) {
if (mInitSuccess) {
_hidl_cb(*mCaptureResultMetadataQueue->getDesc());
}
return Void();
}
/**
* To be used only by submitRequestList implementation, since it requires
* clients to call this method serially, incase fmq is used to send metadata.
*/
bool HidlCameraDeviceUser::copyPhysicalCameraSettings(
const hidl_vec<HPhysicalCameraSettings> &hPhysicalCameraSettings,
std::vector<CaptureRequest::PhysicalCameraSettings> *physicalCameraSettings) {
bool converted = false;
for (auto &e : hPhysicalCameraSettings) {
physicalCameraSettings->emplace_back();
CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
physicalCameraSettings->back();
physicalCameraSetting.id = e.id;
// Read the settings either from the fmq or straightaway from the
// request. We don't need any synchronization, since submitRequestList
// is guaranteed to be called serially by the client if it decides to
// use fmq.
if (e.settings.getDiscriminator() ==
V2_0::FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
/**
* Get settings from the fmq.
*/
HCameraMetadata settingsFmq;
settingsFmq.resize(e.settings.fmqMetadataSize());
bool read = mCaptureRequestMetadataQueue->read(settingsFmq.data(),
e.settings.fmqMetadataSize());
if (!read) {
ALOGE("%s capture request settings could't be read from fmq size",
__FUNCTION__);
converted = false;
} else {
converted = convertFromHidl(settingsFmq, &physicalCameraSetting.settings);
}
} else {
/**
* The settings metadata is contained in request settings field.
*/
converted =
convertFromHidl(e.settings.metadata(),
&physicalCameraSetting.settings);
}
if (!converted) {
ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__);
return false;
}
}
return true;
}
bool HidlCameraDeviceUser::convertRequestFromHidl(const HCaptureRequest &hRequest,
CaptureRequest *request) {
// No reprocessing support.
request->mIsReprocess = false;
for (const auto &streamAndWindowId : hRequest.streamAndWindowIds) {
request->mStreamIdxList.push_back(streamAndWindowId.streamId);
request->mSurfaceIdxList.push_back(streamAndWindowId.windowId);
}
return copyPhysicalCameraSettings(hRequest.physicalCameraSettings,
&(request->mPhysicalCameraSettings));
}
Return<void> HidlCameraDeviceUser::submitRequestList(const hidl_vec<HCaptureRequest>& hRequestList,
bool streaming,
submitRequestList_cb _hidl_cb) {
hardware::camera2::utils::SubmitInfo submitInfo;
HSubmitInfo hSubmitInfo;
/**
* Create AIDL CaptureRequest from requestList and graphicBufferProducers.
*/
std::vector<hardware::camera2::CaptureRequest> requests;
for (auto &hRequest : hRequestList) {
requests.emplace_back();
auto &request = requests.back();
if (!convertRequestFromHidl(hRequest, &request)) {
_hidl_cb(HStatus::ILLEGAL_ARGUMENT, hSubmitInfo);
return Void();
}
}
mDeviceRemote->submitRequestList(requests, streaming, &submitInfo);
mRequestId = submitInfo.mRequestId;
convertToHidl(submitInfo, &hSubmitInfo);
_hidl_cb(HStatus::NO_ERROR, hSubmitInfo);
return Void();
}
Return<void> HidlCameraDeviceUser::cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) {
int64_t lastFrameNumber = 0;
binder::Status ret = mDeviceRemote->cancelRequest(mRequestId, &lastFrameNumber);
_hidl_cb(B2HStatus(ret), lastFrameNumber);
return Void();
}
Return<HStatus> HidlCameraDeviceUser::beginConfigure() {
binder::Status ret = mDeviceRemote->beginConfigure();
return B2HStatus(ret);
}
Return<HStatus> HidlCameraDeviceUser::endConfigure(StreamConfigurationMode operatingMode,
const hidl_vec<uint8_t>& sessionParams) {
return endConfigure_2_1(operatingMode, sessionParams, systemTime());
}
Return<HStatus> HidlCameraDeviceUser::endConfigure_2_1(StreamConfigurationMode operatingMode,
const hidl_vec<uint8_t>& sessionParams,
nsecs_t startTimeNs) {
android::CameraMetadata cameraMetadata;
if (!convertFromHidl(sessionParams, &cameraMetadata)) {
return HStatus::ILLEGAL_ARGUMENT;
}
std::vector<int> offlineStreamIds;
binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode),
cameraMetadata, ns2ms(startTimeNs),
&offlineStreamIds);
return B2HStatus(ret);
}
Return<HStatus> HidlCameraDeviceUser::deleteStream(int32_t streamId) {
binder::Status ret = mDeviceRemote->deleteStream(streamId);
return B2HStatus(ret);
}
Return<void> HidlCameraDeviceUser::createStream(const HOutputConfiguration& hOutputConfiguration,
createStream_cb hidl_cb_) {
OutputConfiguration outputConfiguration =
convertFromHidl(hOutputConfiguration);
int32_t newStreamId = 0;
binder::Status ret = mDeviceRemote->createStream(outputConfiguration, &newStreamId);
HStatus status = B2HStatus(ret);
hidl_cb_(status, newStreamId);
return Void();
}
Return<void> HidlCameraDeviceUser::createDefaultRequest(TemplateId templateId,
createDefaultRequest_cb _hidl_cb) {
android::CameraMetadata cameraMetadata;
binder::Status ret = mDeviceRemote->createDefaultRequest(convertFromHidl(templateId),
&cameraMetadata);
HCameraMetadata hidlMetadata;
if (filterVndkKeys(mVndkVersion, cameraMetadata, /*isStatic*/false) != OK) {
ALOGE("%s: Unable to filter vndk metadata keys for version %d",
__FUNCTION__, mVndkVersion);
_hidl_cb(HStatus::UNKNOWN_ERROR, hidlMetadata);
return Void();
}
HStatus hStatus = B2HStatus(ret);
const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock();
convertToHidl(rawMetadata, &hidlMetadata);
_hidl_cb(hStatus, hidlMetadata);
cameraMetadata.unlock(rawMetadata);
return Void();
}
Return<HStatus> HidlCameraDeviceUser::waitUntilIdle() {
binder::Status ret = mDeviceRemote->waitUntilIdle();
return B2HStatus(ret);
}
Return<void> HidlCameraDeviceUser::flush(flush_cb _hidl_cb) {
int64_t lastFrameNumber = 0;
binder::Status ret = mDeviceRemote->flush(&lastFrameNumber);
_hidl_cb(B2HStatus(ret),lastFrameNumber);
return Void();
}
Return<HStatus> HidlCameraDeviceUser::updateOutputConfiguration(
int32_t streamId,
const HOutputConfiguration& hOutputConfiguration) {
OutputConfiguration outputConfiguration = convertFromHidl(hOutputConfiguration);
binder::Status ret = mDeviceRemote->updateOutputConfiguration(streamId, outputConfiguration);
return B2HStatus(ret);
}
Return<void> HidlCameraDeviceUser::isSessionConfigurationSupported(
const HSessionConfiguration& hSessionConfiguration,
isSessionConfigurationSupported_cb _hidl_cb) {
bool supported = false;
SessionConfiguration sessionConfiguration = convertFromHidl(hSessionConfiguration);
binder::Status ret = mDeviceRemote->isSessionConfigurationSupported(
sessionConfiguration, &supported);
HStatus status = B2HStatus(ret);
_hidl_cb(status, supported);
return Void();
}
} // implementation
} // V2_0
} // device
} // cameraservice
} // frameworks
} // android