diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp index a86cc87da9..38ff37f51a 100644 --- a/camera/VendorTagDescriptor.cpp +++ b/camera/VendorTagDescriptor.cpp @@ -315,6 +315,10 @@ status_t VendorTagDescriptor::lookupTag(const String8& name, const String8& sect return OK; } +ssize_t VendorTagDescriptor::getSectionIndex(uint32_t tag) const { + return mTagToSectionMap.valueFor(tag); +} + void VendorTagDescriptor::dump(int fd, int verbosity, int indentation) const { size_t size = mTagToNameMap.size(); diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp index feb04c24ed..321eb08bea 100644 --- a/camera/camera2/OutputConfiguration.cpp +++ b/camera/camera2/OutputConfiguration.cpp @@ -175,6 +175,12 @@ OutputConfiguration::OutputConfiguration(sp& gbp, int ro mIsShared = isShared; } +OutputConfiguration::OutputConfiguration( + const std::vector>& gbps, + int rotation, int surfaceSetID, int surfaceType, int width, int height, bool isShared) + : mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType), + mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared) { } + status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const { if (parcel == nullptr) return BAD_VALUE; diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp new file mode 100644 index 0000000000..ef6930ca0c --- /dev/null +++ b/camera/cameraserver/Android.bp @@ -0,0 +1,46 @@ +// 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. + +cc_binary { + name: "cameraserver", + + srcs: ["main_cameraserver.cpp"], + + shared_libs: [ + "libcameraservice", + "liblog", + "libutils", + "libui", + "libgui", + "libbinder", + "libhidltransport", + "android.hardware.camera.common@1.0", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + ], + compile_multilib: "32", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wno-unused-parameter", + ], + + init_rc: ["cameraserver.rc"], + + vintf_fragments: [ + "manifest_android.frameworks.cameraservice.service@2.0.xml", + ], +} diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk deleted file mode 100644 index b8c94e64e3..0000000000 --- a/camera/cameraserver/Android.mk +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2015 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. - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - main_cameraserver.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcameraservice \ - liblog \ - libutils \ - libui \ - libgui \ - libbinder \ - libhidltransport \ - android.hardware.camera.common@1.0 \ - android.hardware.camera.provider@2.4 \ - android.hardware.camera.device@1.0 \ - android.hardware.camera.device@3.2 - -LOCAL_MODULE:= cameraserver -LOCAL_32_BIT_ONLY := true - -LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter - -LOCAL_INIT_RC := cameraserver.rc - -include $(BUILD_EXECUTABLE) diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp index 3972436a76..53b3d84894 100644 --- a/camera/cameraserver/main_cameraserver.cpp +++ b/camera/cameraserver/main_cameraserver.cpp @@ -26,8 +26,9 @@ int main(int argc __unused, char** argv __unused) { signal(SIGPIPE, SIG_IGN); - // Set 3 threads for HIDL calls - hardware::configureRpcThreadpool(3, /*willjoin*/ false); + // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in + // addition to consuming them from the Camera HAL as well. + hardware::configureRpcThreadpool(5, /*willjoin*/ false); sp proc(ProcessState::self()); sp sm = defaultServiceManager(); diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml new file mode 100644 index 0000000000..601c7171b0 --- /dev/null +++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml @@ -0,0 +1,11 @@ + + + android.frameworks.cameraservice.service + hwbinder + 2.0 + + ICameraService + default + + + diff --git a/camera/include/camera/VendorTagDescriptor.h b/camera/include/camera/VendorTagDescriptor.h index 904fba2919..c718c93aba 100644 --- a/camera/include/camera/VendorTagDescriptor.h +++ b/camera/include/camera/VendorTagDescriptor.h @@ -98,6 +98,11 @@ class VendorTagDescriptor : public Parcelable { */ void dump(int fd, int verbosity, int indentation) const; + /** + * Get Section for corresponding tag. + */ + ssize_t getSectionIndex(uint32_t tag) const; + /** * Read values VendorTagDescriptor object from the given parcel. * diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h index a80f44b1f4..5b117fb14e 100644 --- a/camera/include/camera/camera2/OutputConfiguration.h +++ b/camera/include/camera/camera2/OutputConfiguration.h @@ -67,6 +67,11 @@ public: OutputConfiguration(sp& gbp, int rotation, int surfaceSetID = INVALID_SET_ID, bool isShared = false); + OutputConfiguration(const std::vector>& gbps, + int rotation, int surfaceSetID = INVALID_SET_ID, + int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0, + int height = 0, bool isShared = false); + bool operator == (const OutputConfiguration& other) const { return ( mRotation == other.mRotation && mSurfaceSetID == other.mSurfaceSetID && diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index a1163ed646..9f2515ebb0 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -53,6 +53,11 @@ cc_library_shared { "device3/DistortionMapper.cpp", "gui/RingBufferConsumer.cpp", "utils/CameraThreadState.cpp", + "hidl/AidlCameraDeviceCallbacks.cpp", + "hidl/AidlCameraServiceListener.cpp", + "hidl/Convert.cpp", + "hidl/HidlCameraDeviceUser.cpp", + "hidl/HidlCameraService.cpp", "utils/CameraTraces.cpp", "utils/AutoConditionLock.cpp", "utils/TagMonitor.cpp", @@ -67,6 +72,7 @@ cc_library_shared { "libbinder", "libcutils", "libmedia", + "libmediandk", "libmediautils", "libcamera_client", "libcamera_metadata", @@ -78,6 +84,10 @@ cc_library_shared { "libhidltransport", "libjpeg", "libmemunreachable", + "libstagefright_foundation", + "android.frameworks.cameraservice.common@2.0", + "android.frameworks.cameraservice.service@2.0", + "android.frameworks.cameraservice.device@2.0", "android.hardware.camera.common@1.0", "android.hardware.camera.provider@2.4", "android.hardware.camera.device@1.0", @@ -96,6 +106,7 @@ cc_library_shared { include_dirs: [ "system/media/private/camera/include", "frameworks/native/include/media/openmax", + "frameworks/av/media/ndk", ], export_include_dirs: ["."], diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index d45be62edf..4dacd0273e 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -47,6 +47,8 @@ #include #include #include +#include "hidl/HidlCameraService.h" +#include #include #include #include @@ -78,6 +80,7 @@ namespace { namespace android { using binder::Status; +using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService; using hardware::ICamera; using hardware::ICameraClient; using hardware::ICameraServiceProxy; @@ -142,6 +145,11 @@ void CameraService::onFirstRef() mUidPolicy = new UidPolicy(this); mUidPolicy->registerSelf(); + sp hcs = HidlCameraService::getInstance(this); + if (hcs->registerAsService() != android::OK) { + ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0", + __FUNCTION__); + } } status_t CameraService::enumerateProviders() { diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp new file mode 100644 index 0000000000..e5e5024204 --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp @@ -0,0 +1,205 @@ +/* + * 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 + +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using hardware::hidl_vec; +using HCaptureResultExtras = android::frameworks::cameraservice::device::V2_0::CaptureResultExtras; +using HPhysicalCaptureResultInfo = android::frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using HCameraMetadata = android::frameworks::cameraservice::device::V2_0::CameraMetadata; + +const char *H2BCameraDeviceCallbacks::kResultKey = "CaptureResult"; + +H2BCameraDeviceCallbacks::H2BCameraDeviceCallbacks(const sp& base) : CBase(base) { } + +bool H2BCameraDeviceCallbacks::initializeLooper() { + mCbLooper = new ALooper; + mCbLooper->setName("cs-looper"); + status_t err = mCbLooper->start(/*runOnCallingThread*/ false, /*canCallJava*/ false, + PRIORITY_DEFAULT); + if (err !=OK) { + ALOGE("Unable to start camera device callback looper"); + return false; + } + mHandler = new CallbackHandler(this); + mCbLooper->registerHandler(mHandler); + return true; +} + +H2BCameraDeviceCallbacks::~H2BCameraDeviceCallbacks() { + if (mCbLooper != nullptr) { + if (mHandler != nullptr) { + mCbLooper->unregisterHandler(mHandler->id()); + } + mCbLooper->stop(); + } + mCbLooper.clear(); + mHandler.clear(); +} + +binder::Status H2BCameraDeviceCallbacks::onDeviceError( + int32_t errorCode, const CaptureResultExtras& resultExtras) { + using hardware::cameraservice::utils::conversion::convertToHidl; + HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras); + auto ret = mBase->onDeviceError(convertToHidl(errorCode), hCaptureResultExtras); + if (!ret.isOk()) { + ALOGE("%s OnDeviceError callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onDeviceIdle() { + auto ret = mBase->onDeviceIdle(); + if (!ret.isOk()) { + ALOGE("%s OnDeviceIdle callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onCaptureStarted( + const CaptureResultExtras& resultExtras, int64_t timestamp) { + using hardware::cameraservice::utils::conversion::convertToHidl; + HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras); + auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp); + if (!ret.isOk()) { + ALOGE("%s OnCaptureCallback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +void H2BCameraDeviceCallbacks::convertResultMetadataToHidl(const camera_metadata_t *rawMetadata, + FmqSizeOrMetadata *hResultMetadata) { + // First try writing to fmq. + size_t metadata_size = get_camera_metadata_size(rawMetadata); + if ((metadata_size > 0) && + (mCaptureResultMetadataQueue->availableToWrite() > 0)) { + if (mCaptureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) { + hResultMetadata->fmqMetadataSize(metadata_size); + } else { + ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__); + HCameraMetadata metadata; + hardware::cameraservice::utils::conversion::convertToHidl(rawMetadata, &metadata); + hResultMetadata->metadata(std::move(metadata)); + } + } +} + +void H2BCameraDeviceCallbacks::CallbackHandler::onMessageReceived(const sp &msg) { + sp obj = nullptr; + sp resultWrapper = nullptr; + bool found = false; + switch (msg->what()) { + case kWhatResultReceived: + found = msg->findObject(kResultKey, &obj); + if (!found || obj == nullptr) { + ALOGE("Cannot find result object in callback message"); + return; + } + resultWrapper = static_cast(obj.get()); + processResultMessage(resultWrapper); + break; + default: + ALOGE("Unknown callback sent"); + break; + } + return; +} + +void H2BCameraDeviceCallbacks::CallbackHandler::processResultMessage( + sp &resultWrapper) { + sp converter = mConverter.promote(); + if (converter == nullptr) { + ALOGE("Callback wrapper has died, result callback cannot be made"); + return; + } + CameraMetadataNative &result = resultWrapper->mResult; + auto resultExtras = resultWrapper->mResultExtras; + auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos; + HCaptureResultExtras hResultExtras = + hardware::cameraservice::utils::conversion::convertToHidl(resultExtras); + hidl_vec hPhysicalCaptureResultInfos = + hardware::cameraservice::utils::conversion::convertToHidl( + physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue); + + // Convert Metadata into HCameraMetadata; + FmqSizeOrMetadata hResult; + const camera_metadata_t *rawMetadata = result.getAndLock(); + converter->convertResultMetadataToHidl(rawMetadata, &hResult); + result.unlock(rawMetadata); + auto ret = converter->mBase->onResultReceived(hResult, hResultExtras, + hPhysicalCaptureResultInfos); + if (!ret.isOk()) { + ALOGE("%s OnResultReceived callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } +} + +binder::Status H2BCameraDeviceCallbacks::onResultReceived( + const CameraMetadataNative& result, + const CaptureResultExtras& resultExtras, + const ::std::vector& physicalCaptureResultInfos) { + // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on + // sp-able structure and post it. + sp resultWrapper = new ResultWrapper(const_cast(result), + resultExtras, physicalCaptureResultInfos); + sp msg = new AMessage(kWhatResultReceived, mHandler); + msg->setObject(kResultKey, resultWrapper); + msg->post(); + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onPrepared(int32_t streamId) { + // not implemented + // To silence Wunused-parameter. + (void) streamId; + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onRepeatingRequestError( + int64_t lastFrameNumber, + int32_t repeatingRequestId) { + auto ret = + mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId); + if (!ret.isOk()) { + ALOGE("%s OnRepeatingRequestEror callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onRequestQueueEmpty() { + // not implemented + return binder::Status::ok(); +} + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h new file mode 100644 index 0000000000..dbf520a0eb --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#ifndef ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H +#define ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using camerahybrid::H2BConverter; +using HCameraDeviceCallback = cameraservice::device::V2_0::ICameraDeviceCallback; +using HPhysicalCaptureResultInfo = cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using android::frameworks::cameraservice::device::V2_0::FmqSizeOrMetadata; + +using hardware::camera2::BnCameraDeviceCallbacks; +using hardware::camera2::ICameraDeviceCallbacks; +using hardware::camera2::impl::CaptureResultExtras; +using hardware::camera2::impl::CameraMetadataNative; +using hardware::camera2::impl::PhysicalCaptureResultInfo; +using hardware::kSynchronizedReadWrite; +using hardware::MessageQueue; +using CaptureResultMetadataQueue = MessageQueue; + +struct H2BCameraDeviceCallbacks : + public H2BConverter { + H2BCameraDeviceCallbacks(const sp& base); + + ~H2BCameraDeviceCallbacks(); + + bool initializeLooper(); + + virtual binder::Status onDeviceError(int32_t errorCode, + const CaptureResultExtras& resultExtras) override; + + virtual binder::Status onDeviceIdle() override; + + virtual binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras, + int64_t timestamp) override; + + virtual binder::Status onResultReceived( + const CameraMetadataNative& result, const CaptureResultExtras& resultExtras, + const std::vector& physicalCaptureResultInfos) override; + + virtual binder::Status onPrepared(int32_t streamId) override; + + virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber, + int32_t repeatingRequestId) override; + + virtual binder::Status onRequestQueueEmpty() override; + + void setCaptureResultMetadataQueue(std::shared_ptr metadataQueue) { + mCaptureResultMetadataQueue = metadataQueue; + } + + private: + // Wrapper struct so that parameters to onResultReceived callback may be + // sent through an AMessage. + struct ResultWrapper : public RefBase { + CameraMetadataNative mResult; + CaptureResultExtras mResultExtras; + std::vector mPhysicalCaptureResultInfos; + ResultWrapper(CameraMetadataNative &result, + const CaptureResultExtras resultExtras, + const std::vector &physicalCaptureResultInfos) : + // TODO: make this std::movable + mResult(result), mResultExtras(resultExtras), mPhysicalCaptureResultInfos(physicalCaptureResultInfos) { } + }; + + struct CallbackHandler : public AHandler { + public: + void onMessageReceived(const sp &msg) override; + CallbackHandler(H2BCameraDeviceCallbacks *converter) : mConverter(converter) { } + private: + void processResultMessage(sp &resultWrapper); + wp mConverter = nullptr; + Mutex mMetadataQueueLock; + }; + + void convertResultMetadataToHidl(const camera_metadata *rawMetadata, + FmqSizeOrMetadata *resultMetadata); + enum { + kWhatResultReceived, + }; + + static const char *kResultKey; + + std::shared_ptr mCaptureResultMetadataQueue = nullptr; + sp mHandler = nullptr; + sp mCbLooper = nullptr; +}; + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android +#endif // ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp new file mode 100644 index 0000000000..110ef8ea49 --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp @@ -0,0 +1,54 @@ +/* + * 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 +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace service { +namespace V2_0 { +namespace implementation { + +using hardware::cameraservice::utils::conversion::convertToHidlCameraDeviceStatus; + +binder::Status H2BCameraServiceListener::onStatusChanged( + int32_t status, const ::android::String16& cameraId) { + HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status); + CameraStatusAndId cameraStatusAndId; + cameraStatusAndId.deviceStatus = hCameraDeviceStatus; + cameraStatusAndId.cameraId = String8(cameraId).string(); + auto ret = mBase->onStatusChanged(cameraStatusAndId); + if (!ret.isOk()) { + ALOGE("%s OnStatusChanged callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged( + int32_t, const ::android::String16&) { + // We don't implement onTorchStatusChanged + return binder::Status::ok(); +} + +} // implementation +} // V2_0 +} // common +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h new file mode 100644 index 0000000000..ca9143d12c --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h @@ -0,0 +1,60 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace service { +namespace V2_0 { +namespace implementation { + +using hardware::BnCameraServiceListener; +using hardware::BpCameraServiceListener; +using camerahybrid::H2BConverter; +using HCameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus; +typedef frameworks::cameraservice::service::V2_0::ICameraServiceListener HCameraServiceListener; + +struct H2BCameraServiceListener : + public H2BConverter { + H2BCameraServiceListener(const sp& base) : CBase(base) { } + + ~H2BCameraServiceListener() { } + + virtual ::android::binder::Status onStatusChanged(int32_t status, + const ::android::String16& cameraId) override; + + virtual ::android::binder::Status onTorchStatusChanged( + int32_t status, const ::android::String16& cameraId) override; +}; + +} // implementation +} // V2_0 +} // service +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/CameraHybridInterface.h b/services/camera/libcameraservice/hidl/CameraHybridInterface.h new file mode 100644 index 0000000000..baf01127bc --- /dev/null +++ b/services/camera/libcameraservice/hidl/CameraHybridInterface.h @@ -0,0 +1,138 @@ +/* + * 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. + */ + +#ifndef ANDROID_CAMERA_HYBRIDINTERFACE_H +#define ANDROID_CAMERA_HYBRIDINTERFACE_H + +#include +#include + +#include +#include + +namespace android { +namespace camerahybrid { +typedef ::android::hidl::base::V1_0::IBase HInterface; + +template < + typename HINTERFACE, + typename INTERFACE, + typename BNINTERFACE > +class H2BConverter : public BNINTERFACE { +public: + typedef H2BConverter CBase; // Converter Base + typedef INTERFACE BaseInterface; + typedef HINTERFACE HalInterface; + + H2BConverter(const sp& base) : mBase(base) {} + virtual sp getHalInterface() { return mBase; } + virtual status_t linkToDeath( + const sp& recipient, + void* cookie = nullptr, + uint32_t flags = 0); + virtual status_t unlinkToDeath( + const wp& recipient, + void* cookie = nullptr, + uint32_t flags = 0, + wp* outRecipient = nullptr); + +protected: + sp mBase; + struct Obituary : public hardware::hidl_death_recipient { + wp recipient; + void* cookie; + uint32_t flags; + wp who; + Obituary( + const wp& r, + void* c, uint32_t f, + const wp& w) : + recipient(r), cookie(c), flags(f), who(w) { + } + Obituary(const Obituary& o) : + recipient(o.recipient), + cookie(o.cookie), + flags(o.flags), + who(o.who) { + } + Obituary& operator=(const Obituary& o) { + recipient = o.recipient; + cookie = o.cookie; + flags = o.flags; + who = o.who; + return *this; + } + void serviceDied(uint64_t, const wp&) override { + sp dr = recipient.promote(); + if (dr != nullptr) { + dr->binderDied(who); + } + } + }; + std::mutex mObituariesLock; + std::vector > mObituaries; +}; + +template < + typename HINTERFACE, + typename INTERFACE, + typename BNINTERFACE> +status_t H2BConverter:: + linkToDeath( + const sp& recipient, + void* cookie, uint32_t flags) { + LOG_ALWAYS_FATAL_IF(recipient == nullptr, + "linkToDeath(): recipient must be non-nullptr"); + { + std::lock_guard lock(mObituariesLock); + mObituaries.push_back(new Obituary(recipient, cookie, flags, this)); + if (!mBase->linkToDeath(mObituaries.back(), 0)) { + return DEAD_OBJECT; + } + } + return NO_ERROR; +} + +template < + typename HINTERFACE, + typename INTERFACE, + typename BNINTERFACE> +status_t H2BConverter:: + unlinkToDeath( + const wp& recipient, + void* cookie, uint32_t flags, + wp* outRecipient) { + std::lock_guard lock(mObituariesLock); + for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) { + if ((flags = (*i)->flags) && ( + (recipient == (*i)->recipient) || + ((recipient == nullptr) && (cookie == (*i)->cookie)))) { + if (outRecipient != nullptr) { + *outRecipient = (*i)->recipient; + } + bool success = mBase->unlinkToDeath(*i); + mObituaries.erase(i); + return success ? NO_ERROR : DEAD_OBJECT; + } + } + return NAME_NOT_FOUND; +} + +} // namespace camerahybrid +} // namespace android + +#endif // ANDROID_CAMERA_HYBRIDINTERFACE_H + diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp new file mode 100644 index 0000000000..22e879e69a --- /dev/null +++ b/services/camera/libcameraservice/hidl/Convert.cpp @@ -0,0 +1,264 @@ +/* + * 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 +#include +#include + +namespace android { +namespace hardware { +namespace cameraservice { +namespace utils { +namespace conversion { + +using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer; + +// Note: existing data in dst will be gone. Caller still owns the memory of src +void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst) { + if (src == nullptr) { + ALOGW("%s:attempt to convert empty metadata to Hidl", __FUNCTION__); + return; + } + size_t size = get_camera_metadata_size(src); + dst->setToExternal((uint8_t *) src, size); + return; +} + +int32_t convertFromHidl(HStreamConfigurationMode streamConfigurationMode) { + switch (streamConfigurationMode) { + case HStreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE: + return camera2::ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE; + case HStreamConfigurationMode::NORMAL_MODE: + return camera2::ICameraDeviceUser::NORMAL_MODE; + default: + // TODO: Fix this + return camera2::ICameraDeviceUser::VENDOR_MODE_START; + } +} + +int32_t convertFromHidl(HTemplateId templateId) { + switch(templateId) { + case HTemplateId::PREVIEW: + return camera2::ICameraDeviceUser::TEMPLATE_PREVIEW; + case HTemplateId::STILL_CAPTURE: + return camera2::ICameraDeviceUser::TEMPLATE_STILL_CAPTURE; + case HTemplateId::RECORD: + return camera2::ICameraDeviceUser::TEMPLATE_RECORD; + case HTemplateId::VIDEO_SNAPSHOT: + return camera2::ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT; + case HTemplateId::ZERO_SHUTTER_LAG: + return camera2::ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG; + case HTemplateId::MANUAL: + return camera2::ICameraDeviceUser::TEMPLATE_MANUAL; + } +} + +int convertFromHidl(HOutputConfiguration::Rotation rotation) { + switch(rotation) { + case HOutputConfiguration::Rotation::R0: + return 0; + case HOutputConfiguration::Rotation::R90: + return 1; + case HOutputConfiguration::Rotation::R180: + return 2; + case HOutputConfiguration::Rotation::R270: + return 3; + } +} + +hardware::camera2::params::OutputConfiguration convertFromHidl( + const HOutputConfiguration &hOutputConfiguration) { + std::vector> iGBPs; + auto &windowHandles = hOutputConfiguration.windowHandles; + iGBPs.reserve(windowHandles.size()); + for (auto &handle : windowHandles) { + iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle))); + } + hardware::camera2::params::OutputConfiguration outputConfiguration( + iGBPs, convertFromHidl(hOutputConfiguration.rotation), + hOutputConfiguration.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0, + (windowHandles.size() > 1)); + return outputConfiguration; +} + +// The camera metadata here is cloned. Since we're reading metadata over +// hwbinder we would need to clone it in order to avoid aligment issues. +bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst) { + const camera_metadata_t *buffer = reinterpret_cast(src.data()); + size_t expectedSize = src.size(); + int res = validate_camera_metadata_structure(buffer, &expectedSize); + if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) { + *dst = buffer; + } else { + ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__); + return false; + } + return true; +} + +HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status) { + HCameraDeviceStatus deviceStatus = HCameraDeviceStatus::STATUS_UNKNOWN; + switch(status) { + case hardware::ICameraServiceListener::STATUS_NOT_PRESENT: + deviceStatus = HCameraDeviceStatus::STATUS_NOT_PRESENT; + break; + case hardware::ICameraServiceListener::STATUS_PRESENT: + deviceStatus = HCameraDeviceStatus::STATUS_PRESENT; + break; + case hardware::ICameraServiceListener::STATUS_ENUMERATING: + deviceStatus = HCameraDeviceStatus::STATUS_ENUMERATING; + break; + case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE: + deviceStatus = HCameraDeviceStatus::STATUS_NOT_AVAILABLE; + break; + default: + break; + } + return deviceStatus; +} + +HCaptureResultExtras convertToHidl(const CaptureResultExtras &captureResultExtras) { + HCaptureResultExtras hCaptureResultExtras; + hCaptureResultExtras.burstId = captureResultExtras.burstId; + hCaptureResultExtras.frameNumber = captureResultExtras.frameNumber; + hCaptureResultExtras.partialResultCount = captureResultExtras.partialResultCount; + hCaptureResultExtras.errorStreamId = captureResultExtras.errorStreamId; + return hCaptureResultExtras; +} + +HErrorCode convertToHidl(int32_t errorCode) { + switch(errorCode) { + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED: + return HErrorCode::CAMERA_DISCONNECTED; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE : + return HErrorCode::CAMERA_DEVICE; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE: + return HErrorCode::CAMERA_SERVICE; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST: + return HErrorCode::CAMERA_REQUEST; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT: + return HErrorCode::CAMERA_RESULT; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER: + return HErrorCode::CAMERA_BUFFER; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISABLED: + return HErrorCode::CAMERA_DISABLED; + case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR: + return HErrorCode::CAMERA_INVALID_ERROR; + default: + return HErrorCode::CAMERA_UNKNOWN_ERROR; + } +} + +void convertToHidl(const std::vector &src, + hidl_vec* dst) { + dst->resize(src.size()); + size_t i = 0; + for (auto &statusAndId : src) { + auto &a = (*dst)[i++]; + a.cameraId = statusAndId.cameraId.c_str(); + a.deviceStatus = convertToHidlCameraDeviceStatus(statusAndId.status); + } + return; +} + +void convertToHidl( + const hardware::camera2::utils::SubmitInfo &submitInfo, + frameworks::cameraservice::device::V2_0::SubmitInfo *hSubmitInfo) { + hSubmitInfo->requestId = submitInfo.mRequestId; + hSubmitInfo->lastFrameNumber = submitInfo.mLastFrameNumber; +} + +HStatus B2HStatus(const binder::Status &bStatus) { + HStatus status = HStatus::NO_ERROR; + if (bStatus.isOk()) { + // NO Error here + return status; + } + switch(bStatus.serviceSpecificErrorCode()) { + case hardware::ICameraService::ERROR_DISCONNECTED: + status = HStatus::DISCONNECTED; + break; + case hardware::ICameraService::ERROR_CAMERA_IN_USE: + status = HStatus::CAMERA_IN_USE; + break; + case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE: + status = HStatus::MAX_CAMERAS_IN_USE; + break; + case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT: + status = HStatus::ILLEGAL_ARGUMENT; + break; + case hardware::ICameraService::ERROR_DEPRECATED_HAL: + // Should not reach here since we filtered legacy HALs earlier + status = HStatus::DEPRECATED_HAL; + break; + case hardware::ICameraService::ERROR_DISABLED: + status = HStatus::DISABLED; + break; + case hardware::ICameraService::ERROR_PERMISSION_DENIED: + status = HStatus::PERMISSION_DENIED; + break; + case hardware::ICameraService::ERROR_INVALID_OPERATION: + status = HStatus::INVALID_OPERATION; + break; + default: + status = HStatus::UNKNOWN_ERROR; + break; + } + return status; +} + +HPhysicalCaptureResultInfo convertToHidl( + const PhysicalCaptureResultInfo &physicalCaptureResultInfo, + std::shared_ptr &captureResultMetadataQueue) { + HPhysicalCaptureResultInfo hPhysicalCaptureResultInfo; + hPhysicalCaptureResultInfo.physicalCameraId = + String8(physicalCaptureResultInfo.mPhysicalCameraId).string(); + const camera_metadata_t *rawMetadata = + physicalCaptureResultInfo.mPhysicalCameraMetadata.getAndLock(); + // Try using fmq at first. + size_t metadata_size = get_camera_metadata_size(rawMetadata); + if ((metadata_size > 0) && (captureResultMetadataQueue->availableToWrite() > 0)) { + if (captureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) { + hPhysicalCaptureResultInfo.physicalCameraMetadata.fmqMetadataSize(metadata_size); + } else { + ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__); + HCameraMetadata metadata; + convertToHidl(rawMetadata, &metadata); + hPhysicalCaptureResultInfo.physicalCameraMetadata.metadata(std::move(metadata)); + } + } + physicalCaptureResultInfo.mPhysicalCameraMetadata.unlock(rawMetadata); + return hPhysicalCaptureResultInfo; +} + +hidl_vec convertToHidl( + const std::vector &physicalCaptureResultInfos, + std::shared_ptr &captureResultMetadataQueue) { + hidl_vec hPhysicalCaptureResultInfos; + hPhysicalCaptureResultInfos.resize(physicalCaptureResultInfos.size()); + size_t i = 0; + for (auto &physicalCaptureResultInfo : physicalCaptureResultInfos) { + hPhysicalCaptureResultInfos[i++] = convertToHidl(physicalCaptureResultInfo, + captureResultMetadataQueue); + } + return hPhysicalCaptureResultInfos; +} + +} //conversion +} // utils +} //cameraservice +} // hardware +} // android diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h new file mode 100644 index 0000000000..82937a30d6 --- /dev/null +++ b/services/camera/libcameraservice/hidl/Convert.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#ifndef CAMERASERVER_CONVERT_HIDL +#define CAMERASERVER_CONVERT_HIDL + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace cameraservice { +namespace utils { +namespace conversion { + +using hardware::camera2::impl::CaptureResultExtras; +using hardware::camera2::impl::PhysicalCaptureResultInfo; + +using CaptureResultMetadataQueue = MessageQueue; +using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata; +using HCameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus; +using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; +using HCameraDeviceUser = frameworks::cameraservice::device::V2_0::ICameraDeviceUser; +using HCaptureResultExtras = frameworks::cameraservice::device::V2_0::CaptureResultExtras; +using HCaptureRequest = frameworks::cameraservice::device::V2_0::CaptureRequest; +using HErrorCode = frameworks::cameraservice::device::V2_0::ErrorCode; +using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer; +using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; +using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings; +using HPhysicalCaptureResultInfo = frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using HSubmitInfo = frameworks::cameraservice::device::V2_0::SubmitInfo; +using HStatus = frameworks::cameraservice::common::V2_0::Status; +using HStreamConfigurationMode = frameworks::cameraservice::device::V2_0::StreamConfigurationMode; +using HTemplateId = frameworks::cameraservice::device::V2_0::TemplateId; + +// Note: existing data in dst will be gone. Caller still owns the memory of src +void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst); + +int32_t convertFromHidl(HStreamConfigurationMode streamConfigurationMode); + +int32_t convertFromHidl(HTemplateId templateId); + +bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst); + +hardware::camera2::params::OutputConfiguration convertFromHidl( + const HOutputConfiguration &hOutputConfiguration); + +HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status); + +void convertToHidl(const std::vector &src, + hidl_vec* dst); + +void convertToHidl(const hardware::camera2::utils::SubmitInfo &submitInfo, + HSubmitInfo *hSubmitInfo); + +HErrorCode convertToHidl(int32_t errorCode); + +HCaptureResultExtras convertToHidl(const CaptureResultExtras &captureResultExtras); + +hidl_vec convertToHidl( + const std::vector &physicalCaptureResultInfos, + std::shared_ptr &captureResultMetadataQueue); + +HStatus B2HStatus(const binder::Status &bStatus); + +} // conversion +} // utils +} // cameraservice +} // hardware +} //android + +#endif //CAMERASERVER_CONVERT_TO_HIDL diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp new file mode 100644 index 0000000000..d22ba5aa61 --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp @@ -0,0 +1,263 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +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; + +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 HidlCameraDeviceUser::disconnect() { + mDeviceRemote->disconnect(); + return Void(); +} + +HidlCameraDeviceUser::HidlCameraDeviceUser( + const sp &deviceRemote) + : mDeviceRemote(deviceRemote) { + mInitSuccess = initDevice(); +} + +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(static_cast(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(static_cast(resFMQSize), + false /* non blocking */); + if (!mCaptureResultMetadataQueue->isValid()) { + ALOGE("%s: invalid result fmq", __FUNCTION__); + return false; + } + return true; +} + +Return HidlCameraDeviceUser::getCaptureRequestMetadataQueue( + getCaptureRequestMetadataQueue_cb _hidl_cb) { + if (mInitSuccess) { + _hidl_cb(*mCaptureRequestMetadataQueue->getDesc()); + } + return Void(); +} + +Return 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, + std::vector *physicalCameraSettings) { + bool converted = false; + for (auto &e : hPhysicalCameraSettings) { + physicalCameraSettings->emplace_back(); + CaptureRequest::PhysicalCameraSettings &physicalCameraSetting = + physicalCameraSettings->back(); + physicalCameraSetting.id = e.id.c_str(); + + // 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() == + 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 HidlCameraDeviceUser::submitRequestList(const hidl_vec& hRequestList, + bool streaming, + submitRequestList_cb _hidl_cb) { + hardware::camera2::utils::SubmitInfo submitInfo; + HSubmitInfo hSubmitInfo; + /** + * Create AIDL CaptureRequest from requestList and graphicBufferProducers. + */ + std::vector 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 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 HidlCameraDeviceUser::beginConfigure() { + binder::Status ret = mDeviceRemote->beginConfigure(); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::endConfigure(StreamConfigurationMode operatingMode, + const hidl_vec& sessionParams) { + android::CameraMetadata cameraMetadata; + if (!convertFromHidl(sessionParams, &cameraMetadata)) { + return HStatus::ILLEGAL_ARGUMENT; + } + + binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode), + cameraMetadata); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::deleteStream(int32_t streamId) { + binder::Status ret = mDeviceRemote->deleteStream(streamId); + return B2HStatus(ret); +} + +Return 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 HidlCameraDeviceUser::createDefaultRequest(TemplateId templateId, + createDefaultRequest_cb _hidl_cb) { + android::CameraMetadata cameraMetadata; + binder::Status ret = mDeviceRemote->createDefaultRequest(convertFromHidl(templateId), + &cameraMetadata); + HStatus hStatus = B2HStatus(ret); + HCameraMetadata hidlMetadata; + const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock(); + convertToHidl(rawMetadata, &hidlMetadata); + _hidl_cb(hStatus, hidlMetadata); + cameraMetadata.unlock(rawMetadata); + return Void(); +} + +Return HidlCameraDeviceUser::waitUntilIdle() { + binder::Status ret = mDeviceRemote->waitUntilIdle(); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::flush(flush_cb _hidl_cb) { + int64_t lastFrameNumber = 0; + binder::Status ret = mDeviceRemote->flush(&lastFrameNumber); + _hidl_cb(B2HStatus(ret),lastFrameNumber); + return Void(); +} + +Return HidlCameraDeviceUser::updateOutputConfiguration( + int32_t streamId, + const HOutputConfiguration& hOutputConfiguration) { + OutputConfiguration outputConfiguration = convertFromHidl(hOutputConfiguration); + binder::Status ret = mDeviceRemote->updateOutputConfiguration(streamId, outputConfiguration); + return B2HStatus(ret); +} + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h new file mode 100644 index 0000000000..be8f1d63c5 --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#ifndef ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H +#define ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using frameworks::cameraservice::device::V2_0::StreamConfigurationMode; +using hardware::camera2::CaptureRequest; +using hardware::hidl_vec; +using hardware::kSynchronizedReadWrite; +using hardware::MessageQueue; +using hardware::MQDescriptorSync; +using hardware::Return; +using CaptureResultMetadataQueue = MessageQueue; +using CaptureRequestMetadataQueue = MessageQueue; +using TemplateId = frameworks::cameraservice::device::V2_0::TemplateId; + +using HCameraDeviceUser = device::V2_0::ICameraDeviceUser; +using HCameraMetadata = cameraservice::service::V2_0::CameraMetadata; +using HCaptureRequest = device::V2_0::CaptureRequest; +using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; +using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings; +using HStatus = frameworks::cameraservice::common::V2_0::Status; + +static constexpr int32_t REQUEST_ID_NONE = -1; + +struct HidlCameraDeviceUser final : public HCameraDeviceUser { + HidlCameraDeviceUser(const sp &deviceRemote); + + ~HidlCameraDeviceUser() { } + + virtual Return disconnect() override; + + virtual Return getCaptureRequestMetadataQueue( + getCaptureRequestMetadataQueue_cb _hidl_cb) override; + + virtual Return getCaptureResultMetadataQueue( + getCaptureResultMetadataQueue_cb _hidl_cb) override; + + virtual Return submitRequestList(const hidl_vec& requestList, + bool streaming, submitRequestList_cb _hidl_cb) override; + + virtual Return cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) override; + + virtual Return beginConfigure() override; + + virtual Return endConfigure(StreamConfigurationMode operatingMode, + const hidl_vec& sessionParams); + + virtual Return deleteStream(int32_t streamId) override; + + virtual Return createStream(const HOutputConfiguration& outputConfiguration, + createStream_cb _hidl_cb) override; + + Return createDefaultRequest(TemplateId templateId, + createDefaultRequest_cb _hidl_cb) override; + + virtual Return waitUntilIdle() override; + + virtual Return flush(flush_cb _hidl_cb) override; + + virtual Return updateOutputConfiguration( + int32_t streamId, const HOutputConfiguration& outputConfiguration) override; + + bool initStatus() { return mInitSuccess; } + + std::shared_ptr getCaptureResultMetadataQueue() { + return mCaptureResultMetadataQueue; + } + + private: + bool initDevice(); + + bool convertRequestFromHidl(const HCaptureRequest &hRequest, CaptureRequest *request); + + bool copyPhysicalCameraSettings( + const hidl_vec &hPhysicalCameraSettings, + std::vector *physicalCameraSettings); + + const sp mDeviceRemote; + std::unique_ptr mCaptureRequestMetadataQueue = nullptr; + std::shared_ptr mCaptureResultMetadataQueue = nullptr; + bool mInitSuccess = false; + int32_t mRequestId = REQUEST_ID_NONE; +}; + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android +#endif // ANDROID_FRAMEOWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp new file mode 100644 index 0000000000..31bdf6de20 --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp @@ -0,0 +1,260 @@ +/* + * 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 + +#include + +#include +#include +#include + +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace service { +namespace V2_0 { +namespace implementation { + +using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService; +using hardware::hidl_vec; +using hardware::cameraservice::utils::conversion::convertToHidl; +using hardware::cameraservice::utils::conversion::B2HStatus; +using hardware::Void; + +using device::V2_0::implementation::H2BCameraDeviceCallbacks; +using device::V2_0::implementation::HidlCameraDeviceUser; +using service::V2_0::implementation::H2BCameraServiceListener; +using HCameraMetadataType = android::frameworks::cameraservice::common::V2_0::CameraMetadataType; +using HVendorTag = android::frameworks::cameraservice::common::V2_0::VendorTag; +using HVendorTagSection = android::frameworks::cameraservice::common::V2_0::VendorTagSection; + +sp gHidlCameraService; + +sp HidlCameraService::getInstance(android::CameraService *cs) { + gHidlCameraService = new HidlCameraService(cs); + return gHidlCameraService; +} + +Return +HidlCameraService::getCameraCharacteristics(const hidl_string& cameraId, + getCameraCharacteristics_cb _hidl_cb) { + android::CameraMetadata cameraMetadata; + HStatus status = HStatus::NO_ERROR; + binder::Status serviceRet = + mAidlICameraService->getCameraCharacteristics(String16(cameraId.c_str()), &cameraMetadata); + HCameraMetadata hidlMetadata; + if (!serviceRet.isOk()) { + switch(serviceRet.serviceSpecificErrorCode()) { + // No ERROR_CAMERA_DISCONNECTED since we're in the same process. + case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT: + ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraId.c_str()); + status = HStatus::ILLEGAL_ARGUMENT; + break; + default: + ALOGE("Get camera characteristics from camera service failed: %s", + serviceRet.toString8().string()); + status = B2HStatus(serviceRet); + } + _hidl_cb(status, hidlMetadata); + return Void(); + } + const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock(); + convertToHidl(rawMetadata, &hidlMetadata); + _hidl_cb(status, hidlMetadata); + cameraMetadata.unlock(rawMetadata); + return Void(); +} + +Return HidlCameraService::connectDevice(const sp& hCallback, + const hidl_string& cameraId, + connectDevice_cb _hidl_cb) { + // Here, we first get ICameraDeviceUser from mAidlICameraService, then save + // that interface in the newly created HidlCameraDeviceUser impl class. + if (mAidlICameraService == nullptr) { + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + sp deviceRemote = nullptr; + // Create a hardware::camera2::ICameraDeviceCallback object which internally + // calls callback functions passed through hCallback. + sp hybridCallbacks = new H2BCameraDeviceCallbacks(hCallback); + if (!hybridCallbacks->initializeLooper()) { + ALOGE("Unable to handle callbacks on device, cannot connect"); + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + sp callbacks = hybridCallbacks; + binder::Status serviceRet = mAidlICameraService->connectDevice( + callbacks, String16(cameraId.c_str()), String16(""), + hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote); + HStatus status = HStatus::NO_ERROR; + if (!serviceRet.isOk()) { + ALOGE("%s: Unable to connect to camera device", __FUNCTION__); + status = B2HStatus(serviceRet); + _hidl_cb(status, nullptr); + return Void(); + } + // Now we create a HidlCameraDeviceUser class, store the deviceRemote in it, + // and return that back. All calls on that interface will be forwarded to + // the AIDL interface. + sp hDeviceRemote = new HidlCameraDeviceUser(deviceRemote); + if (!hDeviceRemote->initStatus()) { + ALOGE("%s: Unable to initialize camera device HIDL wrapper", __FUNCTION__); + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + hybridCallbacks->setCaptureResultMetadataQueue(hDeviceRemote->getCaptureResultMetadataQueue()); + _hidl_cb(status, hDeviceRemote); + return Void(); +} + +void HidlCameraService::addToListenerCacheLocked(sp hListener, + sp csListener) { + mListeners.emplace_back(std::make_pair(hListener, csListener)); +} + +sp +HidlCameraService::searchListenerCacheLocked(sp hListener, + bool shouldRemove) { + // Go through the mListeners list and compare the listener with the HIDL + // listener registered. + auto it = mListeners.begin(); + sp csListener = nullptr; + for (;it != mListeners.end(); it++) { + if (hardware::interfacesEqual(it->first, hListener)) { + break; + } + } + if (it != mListeners.end()) { + csListener = it->second; + if (shouldRemove) { + mListeners.erase(it); + } + } + return csListener; +} + +Return HidlCameraService::addListener(const sp& hCsListener, + addListener_cb _hidl_cb) { + if (mAidlICameraService == nullptr) { + _hidl_cb(HStatus::UNKNOWN_ERROR, {}); + return Void(); + } + if (hCsListener == nullptr) { + ALOGE("%s listener must not be NULL", __FUNCTION__); + _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {}); + return Void(); + } + sp csListener = nullptr; + // Check the cache for previously registered callbacks + { + Mutex::Autolock l(mListenerListLock); + csListener = searchListenerCacheLocked(hCsListener); + if (csListener == nullptr) { + // Wrap an hCsListener with AidlCameraServiceListener and pass it to + // CameraService. + csListener = new H2BCameraServiceListener(hCsListener); + // Add to cache + addToListenerCacheLocked(hCsListener, csListener); + } else { + ALOGE("%s: Trying to add a listener %p already registered", + __FUNCTION__, hCsListener.get()); + _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {}); + return Void(); + } + } + std::vector cameraStatusAndIds{}; + binder::Status serviceRet = mAidlICameraService->addListener(csListener, &cameraStatusAndIds); + HStatus status = HStatus::NO_ERROR; + if (!serviceRet.isOk()) { + ALOGE("%s: Unable to add camera device status listener", __FUNCTION__); + status = B2HStatus(serviceRet); + _hidl_cb(status, {}); + return Void(); + } + hidl_vec hCameraStatusAndIds; + //Convert cameraStatusAndIds to HIDL and call callback + convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds); + _hidl_cb(status, hCameraStatusAndIds); + return Void(); +} + +Return HidlCameraService::removeListener(const sp& hCsListener) { + if (hCsListener == nullptr) { + ALOGE("%s listener must not be NULL", __FUNCTION__); + return HStatus::ILLEGAL_ARGUMENT; + } + sp csListener = nullptr; + { + Mutex::Autolock l(mListenerListLock); + csListener = searchListenerCacheLocked(hCsListener, /*removeIfFound*/true); + } + if (csListener != nullptr) { + mAidlICameraService->removeListener(csListener); + } else { + ALOGE("%s Removing unregistered listener %p", __FUNCTION__, hCsListener.get()); + return HStatus::ILLEGAL_ARGUMENT; + } + return HStatus::NO_ERROR; +} + +Return HidlCameraService::getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) { + hidl_vec hVendorTagSections; + // TODO: Could this be just created on the stack since we don't set it to + // global cache or anything ? + HStatus hStatus = HStatus::NO_ERROR; + sp desc = new VendorTagDescriptor(); + binder::Status serviceRet = mAidlICameraService->getCameraVendorTagDescriptor(desc.get()); + + if (!serviceRet.isOk()) { + ALOGE("%s: Failed to get VendorTagDescriptor", __FUNCTION__); + _hidl_cb(B2HStatus(serviceRet), hVendorTagSections); + return Void(); + } + + const SortedVector* sectionNames = desc->getAllSectionNames(); + size_t numSections = sectionNames->size(); + std::vector> tagsBySection(numSections); + int tagCount = desc->getTagCount(); + std::vector tags(tagCount); + desc->getTagArray(tags.data()); + for (int i = 0; i < tagCount; i++) { + HVendorTag vt; + vt.tagId = tags[i]; + vt.tagName = desc->getTagName(tags[i]); + vt.tagType = (HCameraMetadataType) desc->getTagType(tags[i]); + ssize_t sectionIdx = desc->getSectionIndex(tags[i]); + tagsBySection[sectionIdx].push_back(vt); + } + hVendorTagSections.resize(numSections); + for (size_t s = 0; s < numSections; s++) { + hVendorTagSections[s].sectionName = (*sectionNames)[s].string(); + hVendorTagSections[s].tags = tagsBySection[s]; + } + _hidl_cb(hStatus, hVendorTagSections); + return Void(); +} + +} // implementation +} // V2_0 +} // service +} // cameraservice +} // frameworks +} // android + diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.h b/services/camera/libcameraservice/hidl/HidlCameraService.h new file mode 100644 index 0000000000..eead0bc07b --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraService.h @@ -0,0 +1,98 @@ +/* + * 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. + */ + +#ifndef ANDROID_FRAMEWORKS_CAMERASERVICE_V2_0_CAMERASERVICE_H +#define ANDROID_FRAMEWORKS_CAMERASERVICE_V2_0_CAMERASERVICE_H + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace service { +namespace V2_0 { +namespace implementation { + +using hardware::hidl_string; +using hardware::ICameraServiceListener; +using hardware::Return; + +using HCameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback; +using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata; +using HCameraService = frameworks::cameraservice::service::V2_0::ICameraService; +using HCameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener; +using HStatus = frameworks::cameraservice::common::V2_0::Status; +using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; + +struct HidlCameraService final : public HCameraService { + + ~HidlCameraService() { }; + + // Methods from ::android::frameworks::cameraservice::service::V2.0::ICameraService follow. + + Return connectDevice(const sp& callback, + const hidl_string& cameraId, connectDevice_cb _hidl_cb) override; + + Return addListener(const sp& listener, + addListener_cb _hidl_cb) override; + + Return removeListener(const sp& listener) override; + + Return getCameraCharacteristics(const hidl_string& cameraId, + getCameraCharacteristics_cb _hidl_cb) override; + + Return getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) override; + + // This method should only be called by the cameraservers main thread to + // instantiate the hidl cameraserver. + static sp getInstance(android::CameraService *cs); + +private: + HidlCameraService(android::CameraService *cs) : mAidlICameraService(cs) { }; + + sp searchListenerCacheLocked( + sp listener, /*removeIfFound*/ bool shouldRemove = false); + + void addToListenerCacheLocked(sp hListener, + sp csListener); + + android::CameraService *const mAidlICameraService = nullptr; + + Mutex mListenerListLock; + + using HIListeners = + std::pair, sp>; + std::list mListeners; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace service +} // namespace cameraservice +} // namespace frameworks +} // namespace android + +#endif // ANDROID_FRAMEWORKS_CAMERASERVICE_V2_0_CAMERASERVICE_H