From 9ed325bfffbac128073c3e265ab79ff084ae15f8 Mon Sep 17 00:00:00 2001 From: Kevin Han Date: Mon, 13 Mar 2023 21:18:28 +0000 Subject: [PATCH 1/2] Revert "Remove automotive.evs HIDL entry in compat matrix." Revert submission 21585493-b218588089 Reason for revert: b/273324345 Reverted changes: /q/submissionid:21585493-b218588089 Change-Id: I2173c457c47ae4603908f3192e0d4878d60d9159 --- compatibility_matrices/compatibility_matrix.8.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml index 8f16e06a84..d4fca6a85e 100644 --- a/compatibility_matrices/compatibility_matrix.8.xml +++ b/compatibility_matrices/compatibility_matrix.8.xml @@ -84,6 +84,15 @@ [a-z]+/[0-9]+ + + android.hardware.automotive.evs + 1.0-1 + + IEvsEnumerator + default + [a-z]+/[0-9]+ + + android.hardware.automotive.occupant_awareness 1 From d12e05929a18baf5f89b7d85e5c59483d1a793d0 Mon Sep 17 00:00:00 2001 From: Kevin Han Date: Mon, 13 Mar 2023 21:18:28 +0000 Subject: [PATCH 2/2] Revert "Add default implementation of AIDL EVS interface" Revert submission 21585493-b218588089 Reason for revert: b/273324345 Reverted changes: /q/submissionid:21585493-b218588089 Change-Id: I2826a16105f8e7b03f852f9babffb03d78d53fd0 --- automotive/evs/aidl/impl/default/Android.bp | 49 +- .../aidl/impl/default/evs-default-service.rc | 7 +- .../aidl/impl/default/evs-default-service.xml | 11 + .../aidl/impl/default/include/ConfigManager.h | 384 ------- .../impl/default/include/ConfigManagerUtil.h | 62 -- .../default/include/DefaultEvsEnumerator.h | 66 ++ .../aidl/impl/default/include/EvsEnumerator.h | 134 --- .../aidl/impl/default/include/EvsGlDisplay.h | 89 -- .../aidl/impl/default/include/EvsMockCamera.h | 152 --- .../evs/aidl/impl/default/include/GlWrapper.h | 79 -- .../default/manifest_evs-default-service.xml | 6 - .../resources/evs_mock_configuration.xml | 68 -- .../aidl/impl/default/src/ConfigManager.cpp | 992 ------------------ .../impl/default/src/ConfigManagerUtil.cpp | 155 --- .../impl/default/src/DefaultEvsEnumerator.cpp | 93 ++ .../aidl/impl/default/src/EvsEnumerator.cpp | 552 ---------- .../aidl/impl/default/src/EvsGlDisplay.cpp | 417 -------- .../aidl/impl/default/src/EvsMockCamera.cpp | 642 ------------ .../evs/aidl/impl/default/src/GlWrapper.cpp | 465 -------- .../evs/aidl/impl/default/src/service.cpp | 77 +- 20 files changed, 195 insertions(+), 4305 deletions(-) create mode 100644 automotive/evs/aidl/impl/default/evs-default-service.xml delete mode 100644 automotive/evs/aidl/impl/default/include/ConfigManager.h delete mode 100644 automotive/evs/aidl/impl/default/include/ConfigManagerUtil.h create mode 100644 automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h delete mode 100644 automotive/evs/aidl/impl/default/include/EvsEnumerator.h delete mode 100644 automotive/evs/aidl/impl/default/include/EvsGlDisplay.h delete mode 100644 automotive/evs/aidl/impl/default/include/EvsMockCamera.h delete mode 100644 automotive/evs/aidl/impl/default/include/GlWrapper.h delete mode 100644 automotive/evs/aidl/impl/default/manifest_evs-default-service.xml delete mode 100644 automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml delete mode 100644 automotive/evs/aidl/impl/default/src/ConfigManager.cpp delete mode 100644 automotive/evs/aidl/impl/default/src/ConfigManagerUtil.cpp create mode 100644 automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp delete mode 100644 automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp delete mode 100644 automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp delete mode 100644 automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp delete mode 100644 automotive/evs/aidl/impl/default/src/GlWrapper.cpp diff --git a/automotive/evs/aidl/impl/default/Android.bp b/automotive/evs/aidl/impl/default/Android.bp index bf6c0be236..dbe0314118 100644 --- a/automotive/evs/aidl/impl/default/Android.bp +++ b/automotive/evs/aidl/impl/default/Android.bp @@ -24,56 +24,13 @@ package { cc_binary { name: "android.hardware.automotive.evs-aidl-default-service", defaults: ["EvsHalDefaults"], - vintf_fragments: ["manifest_evs-default-service.xml"], + local_include_dirs: ["include"], + vintf_fragments: ["evs-default-service.xml"], init_rc: ["evs-default-service.rc"], vendor: true, relative_install_path: "hw", - cflags: [ - "-DGL_GLEXT_PROTOTYPES", - "-DEGL_EGLEXT_PROTOTYPES", - "-Wall", - "-Wextra", - "-Werror", - "-Wthread-safety", - ], - srcs: [ - ":libgui_frame_event_aidl", - "src/*.cpp" - ], + srcs: ["src/*.cpp"], shared_libs: [ - "android.hardware.graphics.bufferqueue@1.0", - "android.hardware.graphics.bufferqueue@2.0", - "android.hidl.token@1.0-utils", - "libEGL", - "libGLESv2", - "libbase", "libbinder_ndk", - "libbufferqueueconverter", - "libcamera_metadata", - "libhardware_legacy", - "libhidlbase", - "liblog", - "libnativewindow", - "libtinyxml2", - "libui", - "libutils", - "libyuv", ], - static_libs: [ - "android.frameworks.automotive.display-V1-ndk", - "android.hardware.automotive.evs-V1-ndk", - "android.hardware.common-V2-ndk", - "libaidlcommonsupport", - "libcutils", - ], - local_include_dirs: ["include"], - include_dirs: ["frameworks/native/include/"], - required: ["evs_mock_hal_configuration.xml"], -} - -prebuilt_etc { - name: "evs_mock_hal_configuration.xml", - soc_specific: true, - src: "resources/evs_mock_configuration.xml", - sub_dir: "automotive/evs", } diff --git a/automotive/evs/aidl/impl/default/evs-default-service.rc b/automotive/evs/aidl/impl/default/evs-default-service.rc index 3da41ff787..ea8e6892dc 100644 --- a/automotive/evs/aidl/impl/default/evs-default-service.rc +++ b/automotive/evs/aidl/impl/default/evs-default-service.rc @@ -1,8 +1,5 @@ service vendor.evs-hal-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-default-service class early_hal - priority -20 - user graphics - group automotive_evs camera - onrestart restart cardisplayproxyd - onrestart restart evsmanagerd + user automotive_evs + group automotive_evs disabled diff --git a/automotive/evs/aidl/impl/default/evs-default-service.xml b/automotive/evs/aidl/impl/default/evs-default-service.xml new file mode 100644 index 0000000000..96ff9f6576 --- /dev/null +++ b/automotive/evs/aidl/impl/default/evs-default-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.automotive.evs + hwbinder + 1 + + IEvsEnumerator + hw/0 + + + diff --git a/automotive/evs/aidl/impl/default/include/ConfigManager.h b/automotive/evs/aidl/impl/default/include/ConfigManager.h deleted file mode 100644 index 1d5fe772b2..0000000000 --- a/automotive/evs/aidl/impl/default/include/ConfigManager.h +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include "ConfigManagerUtil.h" - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -/* - * Please note that this is different from what is defined in - * libhardware/modules/camera/3_4/metadata/types.h; this has one additional - * field to store a framerate. - */ -typedef struct { - int id; - int width; - int height; - ::aidl::android::hardware::graphics::common::PixelFormat format; - int type; - int framerate; -} StreamConfiguration; - -class ConfigManager final { - public: - static std::unique_ptr Create(); - ConfigManager(const ConfigManager&) = delete; - ConfigManager& operator=(const ConfigManager&) = delete; - - /* Camera device's capabilities and metadata */ - class CameraInfo { - public: - CameraInfo() : characteristics(nullptr) {} - - virtual ~CameraInfo(); - - /* Allocate memory for camera_metadata_t */ - bool allocate(size_t entry_cap, size_t data_cap) { - if (characteristics != nullptr) { - LOG(ERROR) << "Camera metadata is already allocated"; - return false; - } - - characteristics = allocate_camera_metadata(entry_cap, data_cap); - return characteristics != nullptr; - } - - /* - * List of supported controls that the primary client can program. - * Paraemters are stored with its valid range - */ - std::unordered_map<::aidl::android::hardware::automotive::evs::CameraParam, - std::tuple> - controls; - - /* - * List of supported output stream configurations. - */ - std::unordered_map streamConfigurations; - - /* - * Internal storage for camera metadata. Each entry holds a pointer to - * data and number of elements - */ - std::unordered_map> cameraMetadata; - - /* Camera module characteristics */ - camera_metadata_t* characteristics; - }; - - class CameraGroupInfo : public CameraInfo { - public: - CameraGroupInfo() {} - - /* ID of member camera devices */ - std::unordered_set devices; - - /* The capture operation of member camera devices are synchronized */ - int32_t synchronized = 0; - }; - - class SystemInfo { - public: - /* number of available cameras */ - int32_t numCameras = 0; - }; - - class DisplayInfo { - public: - /* - * List of supported input stream configurations. - */ - std::unordered_map streamConfigurations; - }; - - /* - * Return system information - * - * @return SystemInfo - * Constant reference of SystemInfo. - */ - const SystemInfo& getSystemInfo() { - std::unique_lock lock(mConfigLock); - mConfigCond.wait(lock, [this] { return mIsReady; }); - return mSystemInfo; - } - - /* - * Return a list of camera identifiers - * - * This function assumes that it is not being called frequently. - * - * @return std::vector - * A vector that contains unique camera device identifiers. - */ - std::vector getCameraIdList() { - std::unique_lock lock(mConfigLock); - mConfigCond.wait(lock, [this] { return mIsReady; }); - - std::vector aList; - aList.reserve(mCameraInfo.size()); - for (auto&& v : mCameraInfo) { - aList.push_back(v.first); - } - - return aList; - } - - /* - * Return a list of camera group identifiers - * - * This function assumes that it is not being called frequently. - * - * @return std::vector - * A vector that contains unique camera device identifiers. - */ - std::vector getCameraGroupIdList() { - std::unique_lock lock(mConfigLock); - mConfigCond.wait(lock, [this] { return mIsReady; }); - - std::vector aList; - aList.reserve(mCameraGroups.size()); - for (auto&& v : mCameraGroups) { - aList.push_back(v.first); - } - - return aList; - } - - /* - * Return a pointer to the camera group - * - * @return CameraGroup - * A pointer to a camera group identified by a given id. - */ - std::unique_ptr& getCameraGroupInfo(const std::string& gid) { - std::unique_lock lock(mConfigLock); - mConfigCond.wait(lock, [this] { return mIsReady; }); - - return mCameraGroups[gid]; - } - - /* - * Return a camera metadata - * - * @param cameraId - * Unique camera node identifier in string - * - * @return unique_ptr - * A pointer to CameraInfo that is associated with a given camera - * ID. This returns a null pointer if this does not recognize a - * given camera identifier. - */ - std::unique_ptr& getCameraInfo(const std::string& cameraId) noexcept { - std::unique_lock lock(mConfigLock); - mConfigCond.wait(lock, [this] { return mIsReady; }); - - return mCameraInfo[cameraId]; - } - - /* - * Tell whether the configuration data is ready to be used - * - * @return bool - * True if configuration data is ready to be consumed. - */ - bool isReady() const { return mIsReady; } - - private: - /* Constructors */ - ConfigManager() : mBinaryFilePath("") {} - - static std::string_view sConfigDefaultPath; - static std::string_view sConfigOverridePath; - - /* System configuration */ - SystemInfo mSystemInfo; - - /* Internal data structure for camera device information */ - std::unordered_map> mCameraInfo; - - /* Internal data structure for camera device information */ - std::unordered_map> mDisplayInfo; - - /* Camera groups are stored in hash map */ - std::unordered_map> mCameraGroups; - - /* - * Camera positions are stored in hash map. - * The position must be one of front, rear, left, and right. - */ - std::unordered_map> mCameraPosition; - - /* Configuration data lock */ - mutable std::mutex mConfigLock; - - /* - * This condition is signalled when it completes a configuration data - * preparation. - */ - std::condition_variable mConfigCond; - - /* A path to a binary configuration file */ - const char* mBinaryFilePath; - - /* Configuration data readiness */ - bool mIsReady = false; - - /* - * Parse a given EVS configuration file and store the information - * internally. - * - * @return bool - * True if it completes parsing a file successfully. - */ - bool readConfigDataFromXML() noexcept; - - /* - * read the information of the vehicle - * - * @param aSysElem - * A pointer to "system" XML element. - */ - void readSystemInfo(const tinyxml2::XMLElement* const aSysElem); - - /* - * read the information of camera devices - * - * @param aCameraElem - * A pointer to "camera" XML element that may contain multiple - * "device" elements. - */ - void readCameraInfo(const tinyxml2::XMLElement* const aCameraElem); - - /* - * read display device information - * - * @param aDisplayElem - * A pointer to "display" XML element that may contain multiple - * "device" elements. - */ - void readDisplayInfo(const tinyxml2::XMLElement* const aDisplayElem); - - /* - * read camera device information - * - * @param aCamera - * A pointer to CameraInfo that will be completed by this - * method. - * aDeviceElem - * A pointer to "device" XML element that contains camera module - * capability info and its characteristics. - * - * @return bool - * Return false upon any failure in reading and processing camera - * device information. - */ - bool readCameraDeviceInfo(CameraInfo* aCamera, const tinyxml2::XMLElement* aDeviceElem); - - /* - * read camera metadata - * - * @param aCapElem - * A pointer to "cap" XML element. - * @param aCamera - * A pointer to CameraInfo that is being filled by this method. - * @param dataSize - * Required size of memory to store camera metadata found in this - * method. This is calculated in this method and returned to the - * caller for camera_metadata allocation. - * - * @return size_t - * Number of camera metadata entries - */ - size_t readCameraCapabilities(const tinyxml2::XMLElement* const aCapElem, CameraInfo* aCamera, - size_t& dataSize); - - /* - * read camera metadata - * - * @param aParamElem - * A pointer to "characteristics" XML element. - * @param aCamera - * A pointer to CameraInfo that is being filled by this method. - * @param dataSize - * Required size of memory to store camera metadata found in this - * method. - * - * @return size_t - * Number of camera metadata entries - */ - size_t readCameraMetadata(const tinyxml2::XMLElement* const aParamElem, CameraInfo* aCamera, - size_t& dataSize); - - /* - * construct camera_metadata_t from camera capabilities and metadata - * - * @param aCamera - * A pointer to CameraInfo that is being filled by this method. - * @param totalEntries - * Number of camera metadata entries to be added. - * @param totalDataSize - * Sum of sizes of camera metadata entries to be added. - * - * @return bool - * False if either it fails to allocate memory for camera metadata - * or its size is not large enough to add all found camera metadata - * entries. - */ - bool constructCameraMetadata(CameraInfo* aCamera, const size_t totalEntries, - const size_t totalDataSize); - - /* - * Read configuration data from the binary file - * - * @return bool - * True if it succeeds to read configuration data from a binary - * file. - */ - bool readConfigDataFromBinary(); - - /* - * Store configuration data to the file - * - * @return bool - * True if it succeeds to serialize mCameraInfo to the file. - */ - bool writeConfigDataToBinary(); - - /* - * debugging method to print out all XML elements and their attributes in - * logcat message. - * - * @param aNode - * A pointer to the root XML element to navigate. - * @param prefix - * A prefix to XML string. - */ - void printElementNames(const tinyxml2::XMLElement* aNode, const std::string& prefix = "") const; -}; diff --git a/automotive/evs/aidl/impl/default/include/ConfigManagerUtil.h b/automotive/evs/aidl/impl/default/include/ConfigManagerUtil.h deleted file mode 100644 index 32b50d3332..0000000000 --- a/automotive/evs/aidl/impl/default/include/ConfigManagerUtil.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include - -class ConfigManagerUtil final { - public: - /** - * Convert a given string into V4L2_CID_* - */ - static bool convertToEvsCameraParam( - const std::string& id, - ::aidl::android::hardware::automotive::evs::CameraParam& camParam); - /** - * Convert a given string into android.hardware.graphics.common.PixelFormat - */ - static bool convertToPixelFormat(const std::string& in, - ::aidl::android::hardware::graphics::common::PixelFormat& out); - /** - * Convert a given string into corresponding camera metadata data tag defined in - * system/media/camera/include/system/camera_metadata_tags.h - */ - static bool convertToMetadataTag(const char* name, camera_metadata_tag& aTag); - /** - * Convert a given string into a floating value array - */ - static float* convertFloatArray(const char* sz, const char* vals, size_t& count, - const char delimiter = ','); - /** - * Trim a string - */ - static std::string trimString(const std::string& src, const std::string& ws = " \n\r\t\f\v"); - - /** - * Convert a given string to corresponding camera capabilities - */ - static bool convertToCameraCapability( - const char* name, camera_metadata_enum_android_request_available_capabilities_t& cap); - - DISALLOW_IMPLICIT_CONSTRUCTORS(ConfigManagerUtil); -}; diff --git a/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h new file mode 100644 index 0000000000..03a578d954 --- /dev/null +++ b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_ +#define android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_ + +#include + +namespace aidl::android::hardware::automotive::evs::implementation { + +class DefaultEvsEnumerator final + : public ::aidl::android::hardware::automotive::evs::BnEvsEnumerator { + ::ndk::ScopedAStatus isHardware(bool* flag) override; + ::ndk::ScopedAStatus openCamera( + const std::string& cameraId, + const ::aidl::android::hardware::automotive::evs::Stream& streamConfig, + std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>* obj) override; + ::ndk::ScopedAStatus closeCamera( + const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>& obj) + override; + ::ndk::ScopedAStatus getCameraList( + std::vector<::aidl::android::hardware::automotive::evs::CameraDesc>* list) override; + ::ndk::ScopedAStatus getStreamList( + const ::aidl::android::hardware::automotive::evs::CameraDesc& desc, + std::vector<::aidl::android::hardware::automotive::evs::Stream>* _aidl_return) override; + ::ndk::ScopedAStatus openDisplay( + int32_t displayId, + std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>* obj) override; + ::ndk::ScopedAStatus closeDisplay( + const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& obj) + override; + ::ndk::ScopedAStatus getDisplayIdList(std::vector* list) override; + ::ndk::ScopedAStatus getDisplayState( + ::aidl::android::hardware::automotive::evs::DisplayState* state) override; + ::ndk::ScopedAStatus registerStatusCallback( + const std::shared_ptr< + ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback>& + callback) override; + ::ndk::ScopedAStatus openUltrasonicsArray( + const std::string& id, + std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>* obj) + override; + ::ndk::ScopedAStatus closeUltrasonicsArray( + const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>& + arr) override; + ::ndk::ScopedAStatus getUltrasonicsArrayList( + std::vector<::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc>* list) + override; +}; + +} // namespace aidl::android::hardware::automotive::evs::implementation + +#endif // android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_ diff --git a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h b/automotive/evs/aidl/impl/default/include/EvsEnumerator.h deleted file mode 100644 index b11dd3ee80..0000000000 --- a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include "ConfigManager.h" -#include "EvsGlDisplay.h" -#include "EvsMockCamera.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace aidl::android::hardware::automotive::evs::implementation { - -class EvsEnumerator final : public ::aidl::android::hardware::automotive::evs::BnEvsEnumerator { - public: - // Methods from ::aidl::android::hardware::automotive::evs::IEvsEnumerator - ndk::ScopedAStatus isHardware(bool* flag) override; - ndk::ScopedAStatus openCamera(const std::string& cameraId, const evs::Stream& streamConfig, - std::shared_ptr* obj) override; - ndk::ScopedAStatus closeCamera(const std::shared_ptr& obj) override; - ndk::ScopedAStatus getCameraList(std::vector* _aidl_return) override; - ndk::ScopedAStatus getStreamList(const evs::CameraDesc& desc, - std::vector* _aidl_return) override; - ndk::ScopedAStatus openDisplay(int32_t displayId, - std::shared_ptr* obj) override; - ndk::ScopedAStatus closeDisplay(const std::shared_ptr& obj) override; - ndk::ScopedAStatus getDisplayIdList(std::vector* list) override; - ndk::ScopedAStatus getDisplayState(evs::DisplayState* state) override; - ndk::ScopedAStatus registerStatusCallback( - const std::shared_ptr& callback) override; - ndk::ScopedAStatus openUltrasonicsArray( - const std::string& id, std::shared_ptr* obj) override; - ndk::ScopedAStatus closeUltrasonicsArray( - const std::shared_ptr& obj) override; - ndk::ScopedAStatus getUltrasonicsArrayList( - std::vector* list) override; - - // Implementation details - EvsEnumerator(const std::shared_ptr< - ::aidl::android::frameworks::automotive::display::ICarDisplayProxy>& - proxyService); - - void notifyDeviceStatusChange(const std::string_view& deviceName, evs::DeviceStatusType type); - - private: - struct CameraRecord { - evs::CameraDesc desc; - std::weak_ptr activeInstance; - - CameraRecord(const char* cameraId) : desc() { desc.id = cameraId; } - }; - - class ActiveDisplays { - public: - struct DisplayInfo { - int32_t id{-1}; - std::weak_ptr displayWeak; - uintptr_t internalDisplayRawAddr; - }; - - std::optional popDisplay(int32_t id); - - std::optional popDisplay(const std::shared_ptr& display); - - std::unordered_map getAllDisplays(); - - bool tryInsert(int32_t id, const std::shared_ptr& display); - - private: - std::mutex mMutex; - std::unordered_map mIdToDisplay GUARDED_BY(mMutex); - std::unordered_map mDisplayToId GUARDED_BY(mMutex); - }; - - bool checkPermission(); - void closeCamera_impl(const std::shared_ptr& pCamera, - const std::string& cameraId); - - static bool qualifyCaptureDevice(const char* deviceName); - static CameraRecord* findCameraById(const std::string& cameraId); - static void enumerateCameras(); - static bool addCaptureDevice(const std::string& deviceName); - static bool removeCaptureDevice(const std::string& deviceName); - // Enumerate available displays and return an id of the internal display - static uint64_t enumerateDisplays(); - - static ActiveDisplays& mutableActiveDisplays(); - - // NOTE: All members values are static so that all clients operate on the same state - // That is to say, this is effectively a singleton despite the fact that HIDL - // constructs a new instance for each client. - // Because our server has a single thread in the thread pool, these values are - // never accessed concurrently despite potentially having multiple instance objects - // using them. - static std::unordered_map sCameraList; - // Object destructs if client dies. - static std::mutex sLock; // Mutex on shared camera device list. - static std::condition_variable sCameraSignal; // Signal on camera device addition. - static std::unique_ptr sConfigManager; // ConfigManager - static std::shared_ptr<::aidl::android::frameworks::automotive::display::ICarDisplayProxy> - sDisplayProxy; - static std::unordered_map sDisplayPortList; - - uint64_t mInternalDisplayId; - std::shared_ptr mCallback; -}; - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h b/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h deleted file mode 100644 index ceabd9e863..0000000000 --- a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include "GlWrapper.h" - -#include -#include -#include -#include -#include - -#include - -namespace aidl::android::hardware::automotive::evs::implementation { - -class EvsGlDisplay final : public BnEvsDisplay { - public: - // Methods from ::aidl::android::hardware::automotive::evs::IEvsDisplay - // follow. - ndk::ScopedAStatus getDisplayInfo(evs::DisplayDesc* _aidl_return) override; - ndk::ScopedAStatus getDisplayState(evs::DisplayState* _aidl_return) override; - ndk::ScopedAStatus getTargetBuffer(evs::BufferDesc* _aidl_return) override; - ndk::ScopedAStatus returnTargetBufferForDisplay(const evs::BufferDesc& buffer) override; - ndk::ScopedAStatus setDisplayState(evs::DisplayState state) override; - - // Implementation details - EvsGlDisplay(const std::shared_ptr& service, - uint64_t displayId); - virtual ~EvsGlDisplay() override; - - // This gets called if another caller "steals" ownership of the display - void forceShutdown(); - - private: - // A graphics buffer into which we'll store images. This member variable - // will be protected by semaphores. - struct BufferRecord { - ::aidl::android::hardware::graphics::common::HardwareBufferDescription description; - buffer_handle_t handle; - int fingerprint; - } mBuffer; - - // State of a rendering thread - enum RenderThreadStates { - STOPPED = 0, - STOPPING = 1, - RUN = 2, - }; - - uint64_t mDisplayId; - evs::DisplayDesc mInfo; - evs::DisplayState mRequestedState GUARDED_BY(mLock) = evs::DisplayState::NOT_VISIBLE; - std::shared_ptr mDisplayProxy; - - GlWrapper mGlWrapper; - mutable std::mutex mLock; - - // This tells us whether or not our buffer is in use. Protected by - // semaphores. - bool mBufferBusy = false; - - // Variables to synchronize a rendering thread w/ main and binder threads - std::thread mRenderThread; - RenderThreadStates mState GUARDED_BY(mLock) = STOPPED; - bool mBufferReady = false; - void renderFrames(); - bool initializeGlContextLocked() REQUIRES(mLock); - - std::condition_variable mBufferReadyToUse; - std::condition_variable mBufferReadyToRender; - std::condition_variable mBufferDone; -}; - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h deleted file mode 100644 index 46d47e77a2..0000000000 --- a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include "ConfigManager.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include -#include -#include - -#include -#include - -namespace aidl::android::hardware::automotive::evs::implementation { - -class EvsMockCamera : public evs::BnEvsCamera { - // This prevents constructors from direct access while it allows this class to - // be instantiated via ndk::SharedRefBase::make<>. - private: - struct Sigil { - explicit Sigil() = default; - }; - - public: - // Methods from ::android::hardware::automotive::evs::IEvsCamera follow. - ndk::ScopedAStatus doneWithFrame(const std::vector& buffers) override; - ndk::ScopedAStatus forcePrimaryClient( - const std::shared_ptr& display) override; - ndk::ScopedAStatus getCameraInfo(evs::CameraDesc* _aidl_return) override; - ndk::ScopedAStatus getExtendedInfo(int32_t opaqueIdentifier, - std::vector* value) override; - ndk::ScopedAStatus getIntParameter(evs::CameraParam id, std::vector* value) override; - ndk::ScopedAStatus getIntParameterRange(evs::CameraParam id, - evs::ParameterRange* _aidl_return) override; - ndk::ScopedAStatus getParameterList(std::vector* _aidl_return) override; - ndk::ScopedAStatus getPhysicalCameraInfo(const std::string& deviceId, - evs::CameraDesc* _aidl_return) override; - ndk::ScopedAStatus importExternalBuffers(const std::vector& buffers, - int32_t* _aidl_return) override; - ndk::ScopedAStatus pauseVideoStream() override; - ndk::ScopedAStatus resumeVideoStream() override; - ndk::ScopedAStatus setExtendedInfo(int32_t opaqueIdentifier, - const std::vector& opaqueValue) override; - ndk::ScopedAStatus setIntParameter(evs::CameraParam id, int32_t value, - std::vector* effectiveValue) override; - ndk::ScopedAStatus setPrimaryClient() override; - ndk::ScopedAStatus setMaxFramesInFlight(int32_t bufferCount) override; - ndk::ScopedAStatus startVideoStream( - const std::shared_ptr& receiver) override; - ndk::ScopedAStatus stopVideoStream() override; - ndk::ScopedAStatus unsetPrimaryClient() override; - - static std::shared_ptr Create(const char* deviceName); - static std::shared_ptr Create( - const char* deviceName, std::unique_ptr& camInfo, - const evs::Stream* streamCfg = nullptr); - EvsMockCamera(const EvsMockCamera&) = delete; - EvsMockCamera& operator=(const EvsMockCamera&) = delete; - - virtual ~EvsMockCamera() override; - void shutdown(); - - const evs::CameraDesc& getDesc() { return mDescription; } - - // Constructors - EvsMockCamera(Sigil sigil, const char* deviceName, - std::unique_ptr& camInfo); - - private: - // These three functions are expected to be called while mAccessLock is held - bool setAvailableFrames_Locked(unsigned bufferCount); - unsigned increaseAvailableFrames_Locked(unsigned numToAdd); - unsigned decreaseAvailableFrames_Locked(unsigned numToRemove); - - void generateFrames(); - void fillMockFrame(buffer_handle_t handle, const AHardwareBuffer_Desc* pDesc); - void returnBufferLocked(const uint32_t bufferId); - ndk::ScopedAStatus stopVideoStream_impl(); - - CameraDesc mDescription = {}; // The properties of this camera - - std::thread mCaptureThread; // The thread we'll use to synthesize frames - - // The callback used to deliver each frame - std::shared_ptr mStream; - - // Horizontal pixel count in the buffers - uint32_t mWidth = 0; - // Vertical pixel count in the buffers - uint32_t mHeight = 0; - // Values from android_pixel_format_t - uint32_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888; - // Values from from Gralloc.h - uint64_t mUsage = - GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; - // Bytes per line in the buffers - uint32_t mStride = 0; - - struct BufferRecord { - buffer_handle_t handle; - bool inUse; - - explicit BufferRecord(buffer_handle_t h) : handle(h), inUse(false){}; - }; - - std::vector mBuffers; // Graphics buffers to transfer images - unsigned mFramesAllowed; // How many buffers are we currently using - unsigned mFramesInUse; // How many buffers are currently outstanding - - enum StreamStateValues { - STOPPED, - RUNNING, - STOPPING, - DEAD, - }; - StreamStateValues mStreamState; - - // Synchronization necessary to deconflict mCaptureThread from the main service thread - std::mutex mAccessLock; - - // Static camera module information - std::unique_ptr& mCameraInfo; - - // For the extended info - std::unordered_map> mExtInfo; - std::unordered_map mParams; -}; - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/include/GlWrapper.h b/automotive/evs/aidl/impl/default/include/GlWrapper.h deleted file mode 100644 index adb250c8e1..0000000000 --- a/automotive/evs/aidl/impl/default/include/GlWrapper.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace aidl::android::hardware::automotive::evs::implementation { - -namespace automotivedisplay = ::aidl::android::frameworks::automotive::display; - -class GlWrapper { - public: - GlWrapper() : mSurfaceHolder(::android::SurfaceHolderUniquePtr(nullptr, nullptr)) {} - bool initialize(const std::shared_ptr& svc, - uint64_t displayId); - void shutdown(); - - bool updateImageTexture( - buffer_handle_t handle, - const ::aidl::android::hardware::graphics::common::HardwareBufferDescription& - description); - void renderImageToScreen(); - - void showWindow(const std::shared_ptr& svc, - uint64_t displayId); - void hideWindow(const std::shared_ptr& svc, - uint64_t displayId); - - unsigned getWidth() { return mWidth; }; - unsigned getHeight() { return mHeight; }; - - private: - ::android::sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer> - mGfxBufferProducer; - - EGLDisplay mDisplay; - EGLSurface mSurface; - EGLContext mContext; - - unsigned mWidth = 0; - unsigned mHeight = 0; - - EGLImageKHR mKHRimage = EGL_NO_IMAGE_KHR; - - GLuint mTextureMap = 0; - GLuint mShaderProgram = 0; - - // Opaque handle for a native hardware buffer defined in - // frameworks/native/opengl/include/EGL/eglplatform.h - ANativeWindow* mWindow; - - // Pointer to a Surface wrapper. - ::android::SurfaceHolderUniquePtr mSurfaceHolder; -}; - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml b/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml deleted file mode 100644 index 8480651e77..0000000000 --- a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - android.hardware.automotive.evs - IEvsEnumerator/hw/0 - - diff --git a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml deleted file mode 100644 index 6cbc18eacf..0000000000 --- a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp deleted file mode 100644 index da791ed0b9..0000000000 --- a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp +++ /dev/null @@ -1,992 +0,0 @@ -/* - * Copyright (C) 2023 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 "ConfigManager.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace { - -using ::aidl::android::hardware::automotive::evs::CameraParam; -using ::aidl::android::hardware::graphics::common::PixelFormat; -using ::tinyxml2::XMLAttribute; -using ::tinyxml2::XMLDocument; -using ::tinyxml2::XMLElement; - -} // namespace - -std::string_view ConfigManager::sConfigDefaultPath = - "/vendor/etc/automotive/evs/evs_mock_hal_configuration.xml"; -std::string_view ConfigManager::sConfigOverridePath = - "/vendor/etc/automotive/evs/evs_configuration_override.xml"; - -void ConfigManager::printElementNames(const XMLElement* rootElem, const std::string& prefix) const { - const XMLElement* curElem = rootElem; - - while (curElem != nullptr) { - LOG(VERBOSE) << "[ELEM] " << prefix << curElem->Name(); - const XMLAttribute* curAttr = curElem->FirstAttribute(); - while (curAttr) { - LOG(VERBOSE) << "[ATTR] " << prefix << curAttr->Name() << ": " << curAttr->Value(); - curAttr = curAttr->Next(); - } - - /* recursively go down to descendants */ - printElementNames(curElem->FirstChildElement(), prefix + "\t"); - - curElem = curElem->NextSiblingElement(); - } -} - -void ConfigManager::readCameraInfo(const XMLElement* const aCameraElem) { - if (aCameraElem == nullptr) { - LOG(WARNING) << "XML file does not have required camera element"; - return; - } - - const XMLElement* curElem = aCameraElem->FirstChildElement(); - while (curElem != nullptr) { - if (!strcmp(curElem->Name(), "group")) { - /* camera group identifier */ - const char* id = curElem->FindAttribute("id")->Value(); - - /* create a camera group to be filled */ - CameraGroupInfo* aCamera = new CameraGroupInfo(); - - /* read camera device information */ - if (!readCameraDeviceInfo(aCamera, curElem)) { - LOG(WARNING) << "Failed to read a camera information of " << id; - delete aCamera; - continue; - } - - /* camera group synchronization */ - const char* sync = curElem->FindAttribute("synchronized")->Value(); - if (!strcmp(sync, "CALIBRATED")) { - aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED; - } else if (!strcmp(sync, "APPROXIMATE")) { - aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE; - } else { - aCamera->synchronized = 0; // Not synchronized - } - - /* add a group to hash map */ - mCameraGroups.insert_or_assign(id, std::unique_ptr(aCamera)); - } else if (!std::strcmp(curElem->Name(), "device")) { - /* camera unique identifier */ - const char* id = curElem->FindAttribute("id")->Value(); - - /* camera mount location */ - const char* pos = curElem->FindAttribute("position")->Value(); - - /* create a camera device to be filled */ - CameraInfo* aCamera = new CameraInfo(); - - /* read camera device information */ - if (!readCameraDeviceInfo(aCamera, curElem)) { - LOG(WARNING) << "Failed to read a camera information of " << id; - delete aCamera; - continue; - } - - /* store read camera module information */ - mCameraInfo.insert_or_assign(id, std::unique_ptr(aCamera)); - - /* assign a camera device to a position group */ - mCameraPosition[pos].insert(id); - } else { - /* ignore other device types */ - LOG(DEBUG) << "Unknown element " << curElem->Name() << " is ignored"; - } - - curElem = curElem->NextSiblingElement(); - } -} - -bool ConfigManager::readCameraDeviceInfo(CameraInfo* aCamera, const XMLElement* aDeviceElem) { - if (aCamera == nullptr || aDeviceElem == nullptr) { - return false; - } - - /* size information to allocate camera_metadata_t */ - size_t totalEntries = 0; - size_t totalDataSize = 0; - - /* read device capabilities */ - totalEntries += - readCameraCapabilities(aDeviceElem->FirstChildElement("caps"), aCamera, totalDataSize); - - /* read camera metadata */ - totalEntries += readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"), aCamera, - totalDataSize); - - /* construct camera_metadata_t */ - if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) { - LOG(WARNING) << "Either failed to allocate memory or " - << "allocated memory was not large enough"; - } - - return true; -} - -size_t ConfigManager::readCameraCapabilities(const XMLElement* const aCapElem, CameraInfo* aCamera, - size_t& dataSize) { - if (aCapElem == nullptr || aCamera == nullptr) { - return 0; - } - - std::string token; - const XMLElement* curElem = nullptr; - - /* a list of supported camera parameters/controls */ - curElem = aCapElem->FirstChildElement("supported_controls"); - if (curElem != nullptr) { - const XMLElement* ctrlElem = curElem->FirstChildElement("control"); - while (ctrlElem != nullptr) { - const char* nameAttr = ctrlElem->FindAttribute("name")->Value(); - int32_t minVal = INT32_MIN, maxVal = INT32_MAX; - if (!android::base::ParseInt(ctrlElem->FindAttribute("min")->Value(), &minVal)) { - LOG(WARNING) << "Failed to parse " << ctrlElem->FindAttribute("min")->Value(); - } - - if (!android::base::ParseInt(ctrlElem->FindAttribute("max")->Value(), &maxVal)) { - LOG(WARNING) << "Failed to parse " << ctrlElem->FindAttribute("max")->Value(); - } - - int32_t stepVal = 1; - const XMLAttribute* stepAttr = ctrlElem->FindAttribute("step"); - if (stepAttr != nullptr) { - if (!android::base::ParseInt(stepAttr->Value(), &stepVal)) { - LOG(WARNING) << "Failed to parse " << stepAttr->Value(); - } - } - - CameraParam aParam; - if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) { - aCamera->controls.insert_or_assign( - aParam, std::move(std::make_tuple(minVal, maxVal, stepVal))); - } - - ctrlElem = ctrlElem->NextSiblingElement("control"); - } - } - - /* a list of camera stream configurations */ - curElem = aCapElem->FirstChildElement("stream"); - while (curElem != nullptr) { - /* read 5 attributes */ - const XMLAttribute* idAttr = curElem->FindAttribute("id"); - const XMLAttribute* widthAttr = curElem->FindAttribute("width"); - const XMLAttribute* heightAttr = curElem->FindAttribute("height"); - const XMLAttribute* fmtAttr = curElem->FindAttribute("format"); - const XMLAttribute* fpsAttr = curElem->FindAttribute("framerate"); - - int32_t id = -1; - int32_t framerate = 0; - if (!android::base::ParseInt(idAttr->Value(), &id)) { - LOG(WARNING) << "Failed to parse " << idAttr->Value(); - } - if (fpsAttr != nullptr) { - if (!android::base::ParseInt(fpsAttr->Value(), &framerate)) { - LOG(WARNING) << "Failed to parse " << fpsAttr->Value(); - } - } - - PixelFormat format = PixelFormat::UNSPECIFIED; - if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) { - StreamConfiguration cfg = { - .id = id, - .format = format, - .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, - .framerate = framerate, - }; - - if (!android::base::ParseInt(widthAttr->Value(), &cfg.width) || - !android::base::ParseInt(heightAttr->Value(), &cfg.height)) { - LOG(WARNING) << "Failed to parse " << widthAttr->Value() << " and " - << heightAttr->Value(); - } - aCamera->streamConfigurations.insert_or_assign(id, cfg); - } - - curElem = curElem->NextSiblingElement("stream"); - } - - dataSize = calculate_camera_metadata_entry_data_size( - get_camera_metadata_tag_type(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS), - aCamera->streamConfigurations.size() * sizeof(StreamConfiguration)); - - /* a single camera metadata entry contains multiple stream configurations */ - return dataSize > 0 ? 1 : 0; -} - -size_t ConfigManager::readCameraMetadata(const XMLElement* const aParamElem, CameraInfo* aCamera, - size_t& dataSize) { - if (aParamElem == nullptr || aCamera == nullptr) { - return 0; - } - - const XMLElement* curElem = aParamElem->FirstChildElement("parameter"); - size_t numEntries = 0; - camera_metadata_tag_t tag; - while (curElem != nullptr) { - if (ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(), tag)) { - switch (tag) { - case ANDROID_LENS_DISTORTION: - case ANDROID_LENS_POSE_ROTATION: - case ANDROID_LENS_POSE_TRANSLATION: - case ANDROID_LENS_INTRINSIC_CALIBRATION: { - /* float[] */ - size_t count = 0; - void* data = ConfigManagerUtil::convertFloatArray( - curElem->FindAttribute("size")->Value(), - curElem->FindAttribute("value")->Value(), count); - - aCamera->cameraMetadata.insert_or_assign(tag, std::make_pair(data, count)); - - ++numEntries; - dataSize += calculate_camera_metadata_entry_data_size( - get_camera_metadata_tag_type(tag), count); - - break; - } - - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: { - camera_metadata_enum_android_request_available_capabilities_t* data = - new camera_metadata_enum_android_request_available_capabilities_t[1]; - if (ConfigManagerUtil::convertToCameraCapability( - curElem->FindAttribute("value")->Value(), *data)) { - aCamera->cameraMetadata.insert_or_assign(tag, - std::make_pair((void*)data, 1)); - - ++numEntries; - dataSize += calculate_camera_metadata_entry_data_size( - get_camera_metadata_tag_type(tag), 1); - } - break; - } - - case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: { - /* a comma-separated list of physical camera devices */ - size_t len = strlen(curElem->FindAttribute("value")->Value()); - char* data = new char[len + 1]; - memcpy(data, curElem->FindAttribute("value")->Value(), len * sizeof(char)); - - /* replace commas with null char */ - char* p = data; - while (*p != '\0') { - if (*p == ',') { - *p = '\0'; - } - ++p; - } - - aCamera->cameraMetadata.insert_or_assign(tag, - std::make_pair((void*)data, len + 1)); - - ++numEntries; - dataSize += calculate_camera_metadata_entry_data_size( - get_camera_metadata_tag_type(tag), len); - break; - } - - /* TODO(b/140416878): add vendor-defined/custom tag support */ - default: - LOG(WARNING) << "Parameter " << curElem->FindAttribute("name")->Value() - << " is not supported"; - break; - } - } else { - LOG(WARNING) << "Unsupported metadata tag " << curElem->FindAttribute("name")->Value() - << " is found."; - } - - curElem = curElem->NextSiblingElement("parameter"); - } - - return numEntries; -} - -bool ConfigManager::constructCameraMetadata(CameraInfo* aCamera, size_t totalEntries, - size_t totalDataSize) { - if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) { - LOG(ERROR) << "Failed to allocate memory for camera metadata"; - return false; - } - - const size_t numStreamConfigs = aCamera->streamConfigurations.size(); - std::unique_ptr data(new int32_t[sizeof(StreamConfiguration) * numStreamConfigs]); - int32_t* ptr = data.get(); - for (auto& cfg : aCamera->streamConfigurations) { - memcpy(ptr, &cfg.second, sizeof(StreamConfiguration)); - ptr += sizeof(StreamConfiguration); - } - int32_t err = add_camera_metadata_entry( - aCamera->characteristics, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, data.get(), - numStreamConfigs * sizeof(StreamConfiguration)); - - if (err) { - LOG(ERROR) << "Failed to add stream configurations to metadata, ignored"; - return false; - } - - bool success = true; - for (auto& [tag, entry] : aCamera->cameraMetadata) { - /* try to add new camera metadata entry */ - int32_t err = - add_camera_metadata_entry(aCamera->characteristics, tag, entry.first, entry.second); - if (err) { - LOG(ERROR) << "Failed to add an entry with a tag, " << std::hex << tag; - - /* may exceed preallocated capacity */ - LOG(ERROR) << "Camera metadata has " - << get_camera_metadata_entry_count(aCamera->characteristics) << " / " - << get_camera_metadata_entry_capacity(aCamera->characteristics) - << " entries and " - << get_camera_metadata_data_count(aCamera->characteristics) << " / " - << get_camera_metadata_data_capacity(aCamera->characteristics) - << " bytes are filled."; - LOG(ERROR) << "\tCurrent metadata entry requires " - << calculate_camera_metadata_entry_data_size(tag, entry.second) << " bytes."; - - success = false; - } - } - - LOG(VERBOSE) << "Camera metadata has " - << get_camera_metadata_entry_count(aCamera->characteristics) << " / " - << get_camera_metadata_entry_capacity(aCamera->characteristics) << " entries and " - << get_camera_metadata_data_count(aCamera->characteristics) << " / " - << get_camera_metadata_data_capacity(aCamera->characteristics) - << " bytes are filled."; - return success; -} - -void ConfigManager::readSystemInfo(const XMLElement* const aSysElem) { - if (aSysElem == nullptr) { - return; - } - - /* - * Please note that this function assumes that a given system XML element - * and its child elements follow DTD. If it does not, it will cause a - * segmentation fault due to the failure of finding expected attributes. - */ - - /* read number of cameras available in the system */ - const XMLElement* xmlElem = aSysElem->FirstChildElement("num_cameras"); - if (xmlElem != nullptr) { - if (!android::base::ParseInt(xmlElem->FindAttribute("value")->Value(), - &mSystemInfo.numCameras)) { - LOG(WARNING) << "Failed to parse " << xmlElem->FindAttribute("value")->Value(); - } - } -} - -void ConfigManager::readDisplayInfo(const XMLElement* const aDisplayElem) { - if (aDisplayElem == nullptr) { - LOG(WARNING) << "XML file does not have required camera element"; - return; - } - - const XMLElement* curDev = aDisplayElem->FirstChildElement("device"); - while (curDev != nullptr) { - const char* id = curDev->FindAttribute("id")->Value(); - std::unique_ptr dpy(new DisplayInfo()); - if (dpy == nullptr) { - LOG(ERROR) << "Failed to allocate memory for DisplayInfo"; - return; - } - - const XMLElement* cap = curDev->FirstChildElement("caps"); - if (cap != nullptr) { - const XMLElement* curStream = cap->FirstChildElement("stream"); - while (curStream != nullptr) { - /* read 4 attributes */ - const XMLAttribute* idAttr = curStream->FindAttribute("id"); - const XMLAttribute* widthAttr = curStream->FindAttribute("width"); - const XMLAttribute* heightAttr = curStream->FindAttribute("height"); - const XMLAttribute* fmtAttr = curStream->FindAttribute("format"); - - int32_t id = -1; - if (!android::base::ParseInt(idAttr->Value(), &id)) { - LOG(WARNING) << "Failed to parse " << idAttr->Value(); - } - PixelFormat format = PixelFormat::UNSPECIFIED; - if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) { - StreamConfiguration cfg = { - .id = id, - .format = format, - .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT, - }; - if (!android::base::ParseInt(widthAttr->Value(), &cfg.width) || - !android::base::ParseInt(heightAttr->Value(), &cfg.height)) { - LOG(WARNING) << "Failed to parse " << widthAttr->Value() << " and " - << heightAttr->Value(); - } - dpy->streamConfigurations.insert_or_assign(id, cfg); - } - - curStream = curStream->NextSiblingElement("stream"); - } - } - - mDisplayInfo.insert_or_assign(id, std::move(dpy)); - curDev = curDev->NextSiblingElement("device"); - } - - return; -} - -bool ConfigManager::readConfigDataFromXML() noexcept { - XMLDocument xmlDoc; - - const int64_t parsingStart = android::elapsedRealtimeNano(); - - /* load and parse a configuration file */ - xmlDoc.LoadFile(sConfigOverridePath.data()); - if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) { - xmlDoc.LoadFile(sConfigDefaultPath.data()); - if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) { - LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr(); - return false; - } - } - - /* retrieve the root element */ - const XMLElement* rootElem = xmlDoc.RootElement(); - if (std::strcmp(rootElem->Name(), "configuration") != 0) { - LOG(ERROR) << "A configuration file is not in the required format. " - << "See /etc/automotive/evs/evs_configuration.dtd"; - return false; - } - - std::unique_lock lock(mConfigLock); - - /* - * parse camera information; this needs to be done before reading system - * information - */ - readCameraInfo(rootElem->FirstChildElement("camera")); - - /* parse system information */ - readSystemInfo(rootElem->FirstChildElement("system")); - - /* parse display information */ - readDisplayInfo(rootElem->FirstChildElement("display")); - - /* configuration data is ready to be consumed */ - mIsReady = true; - - /* notify that configuration data is ready */ - lock.unlock(); - mConfigCond.notify_all(); - - const int64_t parsingEnd = android::elapsedRealtimeNano(); - LOG(INFO) << "Parsing configuration file takes " << std::scientific - << (double)(parsingEnd - parsingStart) / 1000000.0 << " ms."; - - return true; -} - -bool ConfigManager::readConfigDataFromBinary() { - /* Temporary buffer to hold configuration data read from a binary file */ - char mBuffer[1024]; - - std::fstream srcFile; - const int64_t readStart = android::elapsedRealtimeNano(); - - srcFile.open(mBinaryFilePath, std::fstream::in | std::fstream::binary); - if (!srcFile) { - LOG(ERROR) << "Failed to open a source binary file, " << mBinaryFilePath; - return false; - } - - std::unique_lock lock(mConfigLock); - mIsReady = false; - - /* read configuration data into the internal buffer */ - srcFile.read(mBuffer, sizeof(mBuffer)); - LOG(VERBOSE) << __FUNCTION__ << ": " << srcFile.gcount() << " bytes are read."; - char* p = mBuffer; - size_t sz = 0; - - /* read number of camera group information entries */ - const size_t ngrps = *(reinterpret_cast(p)); - p += sizeof(size_t); - - /* read each camera information entry */ - for (size_t cidx = 0; cidx < ngrps; ++cidx) { - /* read camera identifier */ - std::string cameraId = *(reinterpret_cast(p)); - p += sizeof(std::string); - - /* size of camera_metadata_t */ - const size_t num_entry = *(reinterpret_cast(p)); - p += sizeof(size_t); - const size_t num_data = *(reinterpret_cast(p)); - p += sizeof(size_t); - - /* create CameraInfo and add it to hash map */ - std::unique_ptr aCamera; - if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) { - LOG(ERROR) << "Failed to create new CameraInfo object"; - mCameraInfo.clear(); - return false; - } - - /* controls */ - typedef struct { - CameraParam cid; - int32_t min; - int32_t max; - int32_t step; - } CameraCtrl; - sz = *(reinterpret_cast(p)); - p += sizeof(size_t); - CameraCtrl* ptr = reinterpret_cast(p); - for (size_t idx = 0; idx < sz; ++idx) { - CameraCtrl temp = *ptr++; - aCamera->controls.insert_or_assign( - temp.cid, std::move(std::make_tuple(temp.min, temp.max, temp.step))); - } - p = reinterpret_cast(ptr); - - /* stream configurations */ - sz = *(reinterpret_cast(p)); - p += sizeof(size_t); - int32_t* i32_ptr = reinterpret_cast(p); - for (size_t idx = 0; idx < sz; ++idx) { - const int32_t id = *i32_ptr++; - - StreamConfiguration temp; - memcpy(&temp, i32_ptr, sizeof(StreamConfiguration)); - i32_ptr += sizeof(StreamConfiguration); - aCamera->streamConfigurations.insert_or_assign(id, temp); - } - p = reinterpret_cast(i32_ptr); - - /* synchronization */ - aCamera->synchronized = *(reinterpret_cast(p)); - p += sizeof(int32_t); - - for (size_t idx = 0; idx < num_entry; ++idx) { - /* Read camera metadata entries */ - camera_metadata_tag_t tag = *reinterpret_cast(p); - p += sizeof(camera_metadata_tag_t); - const size_t count = *reinterpret_cast(p); - p += sizeof(size_t); - - const int32_t type = get_camera_metadata_tag_type(tag); - switch (type) { - case TYPE_BYTE: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(uint8_t); - break; - } - case TYPE_INT32: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(int32_t); - break; - } - case TYPE_FLOAT: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(float); - break; - } - case TYPE_INT64: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(int64_t); - break; - } - case TYPE_DOUBLE: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(double); - break; - } - case TYPE_RATIONAL: - p += count * sizeof(camera_metadata_rational_t); - break; - default: - LOG(WARNING) << "Type " << type << " is unknown; " - << "data may be corrupted."; - break; - } - } - - mCameraInfo.insert_or_assign(cameraId, std::move(aCamera)); - } - - /* read number of camera information entries */ - const size_t ncams = *(reinterpret_cast(p)); - p += sizeof(size_t); - - /* read each camera information entry */ - for (size_t cidx = 0; cidx < ncams; ++cidx) { - /* read camera identifier */ - std::string cameraId = *(reinterpret_cast(p)); - p += sizeof(std::string); - - /* size of camera_metadata_t */ - const size_t num_entry = *(reinterpret_cast(p)); - p += sizeof(size_t); - const size_t num_data = *(reinterpret_cast(p)); - p += sizeof(size_t); - - /* create CameraInfo and add it to hash map */ - std::unique_ptr aCamera; - if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) { - LOG(ERROR) << "Failed to create new CameraInfo object"; - mCameraInfo.clear(); - return false; - } - - /* controls */ - typedef struct { - CameraParam cid; - int32_t min; - int32_t max; - int32_t step; - } CameraCtrl; - sz = *(reinterpret_cast(p)); - p += sizeof(size_t); - CameraCtrl* ptr = reinterpret_cast(p); - for (size_t idx = 0; idx < sz; ++idx) { - CameraCtrl temp = *ptr++; - aCamera->controls.insert_or_assign( - temp.cid, std::move(std::make_tuple(temp.min, temp.max, temp.step))); - } - p = reinterpret_cast(ptr); - - /* stream configurations */ - sz = *(reinterpret_cast(p)); - p += sizeof(size_t); - int32_t* i32_ptr = reinterpret_cast(p); - for (size_t idx = 0; idx < sz; ++idx) { - const int32_t id = *i32_ptr++; - - StreamConfiguration temp; - memcpy(&temp, i32_ptr, sizeof(StreamConfiguration)); - i32_ptr += sizeof(StreamConfiguration); - aCamera->streamConfigurations.insert_or_assign(id, temp); - } - p = reinterpret_cast(i32_ptr); - - for (size_t idx = 0; idx < num_entry; ++idx) { - /* Read camera metadata entries */ - camera_metadata_tag_t tag = *reinterpret_cast(p); - p += sizeof(camera_metadata_tag_t); - const size_t count = *reinterpret_cast(p); - p += sizeof(size_t); - - const int32_t type = get_camera_metadata_tag_type(tag); - switch (type) { - case TYPE_BYTE: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(uint8_t); - break; - } - case TYPE_INT32: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(int32_t); - break; - } - case TYPE_FLOAT: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(float); - break; - } - case TYPE_INT64: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(int64_t); - break; - } - case TYPE_DOUBLE: { - add_camera_metadata_entry(aCamera->characteristics, tag, p, count); - p += count * sizeof(double); - break; - } - case TYPE_RATIONAL: - p += count * sizeof(camera_metadata_rational_t); - break; - default: - LOG(WARNING) << "Type " << type << " is unknown; " - << "data may be corrupted."; - break; - } - } - - mCameraInfo.insert_or_assign(cameraId, std::move(aCamera)); - } - - mIsReady = true; - - /* notify that configuration data is ready */ - lock.unlock(); - mConfigCond.notify_all(); - - int64_t readEnd = android::elapsedRealtimeNano(); - LOG(INFO) << __FUNCTION__ << " takes " << std::scientific - << (double)(readEnd - readStart) / 1000000.0 << " ms."; - - return true; -} - -bool ConfigManager::writeConfigDataToBinary() { - std::fstream outFile; - - const int64_t writeStart = android::elapsedRealtimeNano(); - - outFile.open(mBinaryFilePath, std::fstream::out | std::fstream::binary); - if (!outFile) { - LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath; - return false; - } - - /* lock a configuration data while it's being written to the filesystem */ - std::lock_guard lock(mConfigLock); - - /* write camera group information */ - size_t sz = mCameraGroups.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto&& [camId, camInfo] : mCameraGroups) { - LOG(INFO) << "Storing camera group " << camId; - - /* write a camera identifier string */ - outFile.write(reinterpret_cast(&camId), sizeof(std::string)); - - /* controls */ - sz = camInfo->controls.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto&& [ctrl, range] : camInfo->controls) { - outFile.write(reinterpret_cast(&ctrl), sizeof(CameraParam)); - outFile.write(reinterpret_cast(&std::get<0>(range)), sizeof(int32_t)); - outFile.write(reinterpret_cast(&std::get<1>(range)), sizeof(int32_t)); - outFile.write(reinterpret_cast(&std::get<2>(range)), sizeof(int32_t)); - } - - /* stream configurations */ - sz = camInfo->streamConfigurations.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto&& [sid, cfg] : camInfo->streamConfigurations) { - outFile.write(reinterpret_cast(sid), sizeof(int32_t)); - outFile.write(reinterpret_cast(&cfg), sizeof(cfg)); - } - - /* synchronization */ - outFile.write(reinterpret_cast(&camInfo->synchronized), sizeof(int32_t)); - - /* size of camera_metadata_t */ - size_t num_entry = 0; - size_t num_data = 0; - if (camInfo->characteristics != nullptr) { - num_entry = get_camera_metadata_entry_count(camInfo->characteristics); - num_data = get_camera_metadata_data_count(camInfo->characteristics); - } - outFile.write(reinterpret_cast(&num_entry), sizeof(size_t)); - outFile.write(reinterpret_cast(&num_data), sizeof(size_t)); - - /* write each camera metadata entry */ - if (num_entry > 0) { - camera_metadata_entry_t entry; - for (size_t idx = 0; idx < num_entry; ++idx) { - if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) { - LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx; - outFile.close(); - return false; - } - - outFile.write(reinterpret_cast(&entry.tag), sizeof(entry.tag)); - outFile.write(reinterpret_cast(&entry.count), sizeof(entry.count)); - - int32_t type = get_camera_metadata_tag_type(entry.tag); - switch (type) { - case TYPE_BYTE: - outFile.write(reinterpret_cast(entry.data.u8), - sizeof(uint8_t) * entry.count); - break; - case TYPE_INT32: - outFile.write(reinterpret_cast(entry.data.i32), - sizeof(int32_t) * entry.count); - break; - case TYPE_FLOAT: - outFile.write(reinterpret_cast(entry.data.f), - sizeof(float) * entry.count); - break; - case TYPE_INT64: - outFile.write(reinterpret_cast(entry.data.i64), - sizeof(int64_t) * entry.count); - break; - case TYPE_DOUBLE: - outFile.write(reinterpret_cast(entry.data.d), - sizeof(double) * entry.count); - break; - case TYPE_RATIONAL: - [[fallthrough]]; - default: - LOG(WARNING) << "Type " << type << " is not supported."; - break; - } - } - } - } - - /* write camera device information */ - sz = mCameraInfo.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto&& [camId, camInfo] : mCameraInfo) { - LOG(INFO) << "Storing camera " << camId; - - /* write a camera identifier string */ - outFile.write(reinterpret_cast(&camId), sizeof(std::string)); - - /* controls */ - sz = camInfo->controls.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto& [ctrl, range] : camInfo->controls) { - outFile.write(reinterpret_cast(&ctrl), sizeof(CameraParam)); - outFile.write(reinterpret_cast(&std::get<0>(range)), sizeof(int32_t)); - outFile.write(reinterpret_cast(&std::get<1>(range)), sizeof(int32_t)); - outFile.write(reinterpret_cast(&std::get<2>(range)), sizeof(int32_t)); - } - - /* stream configurations */ - sz = camInfo->streamConfigurations.size(); - outFile.write(reinterpret_cast(&sz), sizeof(size_t)); - for (auto&& [sid, cfg] : camInfo->streamConfigurations) { - outFile.write(reinterpret_cast(sid), sizeof(int32_t)); - outFile.write(reinterpret_cast(&cfg), sizeof(cfg)); - } - - /* size of camera_metadata_t */ - size_t num_entry = 0; - size_t num_data = 0; - if (camInfo->characteristics != nullptr) { - num_entry = get_camera_metadata_entry_count(camInfo->characteristics); - num_data = get_camera_metadata_data_count(camInfo->characteristics); - } - outFile.write(reinterpret_cast(&num_entry), sizeof(size_t)); - outFile.write(reinterpret_cast(&num_data), sizeof(size_t)); - - /* write each camera metadata entry */ - if (num_entry > 0) { - camera_metadata_entry_t entry; - for (size_t idx = 0; idx < num_entry; ++idx) { - if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) { - LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx; - outFile.close(); - return false; - } - - outFile.write(reinterpret_cast(&entry.tag), sizeof(entry.tag)); - outFile.write(reinterpret_cast(&entry.count), sizeof(entry.count)); - - int32_t type = get_camera_metadata_tag_type(entry.tag); - switch (type) { - case TYPE_BYTE: - outFile.write(reinterpret_cast(entry.data.u8), - sizeof(uint8_t) * entry.count); - break; - case TYPE_INT32: - outFile.write(reinterpret_cast(entry.data.i32), - sizeof(int32_t) * entry.count); - break; - case TYPE_FLOAT: - outFile.write(reinterpret_cast(entry.data.f), - sizeof(float) * entry.count); - break; - case TYPE_INT64: - outFile.write(reinterpret_cast(entry.data.i64), - sizeof(int64_t) * entry.count); - break; - case TYPE_DOUBLE: - outFile.write(reinterpret_cast(entry.data.d), - sizeof(double) * entry.count); - break; - case TYPE_RATIONAL: - [[fallthrough]]; - default: - LOG(WARNING) << "Type " << type << " is not supported."; - break; - } - } - } - } - - outFile.close(); - int64_t writeEnd = android::elapsedRealtimeNano(); - LOG(INFO) << __FUNCTION__ << " takes " << std::scientific - << (double)(writeEnd - writeStart) / 1000000.0 << " ms."; - - return true; -} - -std::unique_ptr ConfigManager::Create() { - std::unique_ptr cfgMgr(new ConfigManager()); - - /* - * Read a configuration from XML file - * - * If this is too slow, ConfigManager::readConfigDataFromBinary() and - * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object - * to the filesystem and construct CameraInfo instead; this was - * evaluated as 10x faster. - */ - if (!cfgMgr->readConfigDataFromXML()) { - return nullptr; - } else { - return cfgMgr; - } -} - -ConfigManager::CameraInfo::~CameraInfo() { - free_camera_metadata(characteristics); - - for (auto&& [tag, val] : cameraMetadata) { - switch (tag) { - case ANDROID_LENS_DISTORTION: - case ANDROID_LENS_POSE_ROTATION: - case ANDROID_LENS_POSE_TRANSLATION: - case ANDROID_LENS_INTRINSIC_CALIBRATION: { - delete[] reinterpret_cast(val.first); - break; - } - - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: { - delete[] reinterpret_cast< - camera_metadata_enum_android_request_available_capabilities_t*>(val.first); - break; - } - - case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: { - delete[] reinterpret_cast(val.first); - break; - } - - default: - LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. " - << "Data may be corrupted?"; - break; - } - } -} diff --git a/automotive/evs/aidl/impl/default/src/ConfigManagerUtil.cpp b/automotive/evs/aidl/impl/default/src/ConfigManagerUtil.cpp deleted file mode 100644 index e5fe6efa57..0000000000 --- a/automotive/evs/aidl/impl/default/src/ConfigManagerUtil.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2023 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 "ConfigManagerUtil.h" - -#include -#include -#include -#include - -#include -#include - -#include - -using ::aidl::android::hardware::automotive::evs::CameraParam; -using ::aidl::android::hardware::graphics::common::PixelFormat; - -bool ConfigManagerUtil::convertToEvsCameraParam(const std::string& id, CameraParam& camParam) { - std::string trimmed = ConfigManagerUtil::trimString(id); - bool success = true; - - if (!trimmed.compare("BRIGHTNESS")) { - camParam = CameraParam::BRIGHTNESS; - } else if (!trimmed.compare("CONTRAST")) { - camParam = CameraParam::CONTRAST; - } else if (!trimmed.compare("AUTOGAIN")) { - camParam = CameraParam::AUTOGAIN; - } else if (!trimmed.compare("GAIN")) { - camParam = CameraParam::GAIN; - } else if (!trimmed.compare("AUTO_WHITE_BALANCE")) { - camParam = CameraParam::AUTO_WHITE_BALANCE; - } else if (!trimmed.compare("WHITE_BALANCE_TEMPERATURE")) { - camParam = CameraParam::WHITE_BALANCE_TEMPERATURE; - } else if (!trimmed.compare("SHARPNESS")) { - camParam = CameraParam::SHARPNESS; - } else if (!trimmed.compare("AUTO_EXPOSURE")) { - camParam = CameraParam::AUTO_EXPOSURE; - } else if (!trimmed.compare("ABSOLUTE_EXPOSURE")) { - camParam = CameraParam::ABSOLUTE_EXPOSURE; - } else if (!trimmed.compare("ABSOLUTE_FOCUS")) { - camParam = CameraParam::ABSOLUTE_FOCUS; - } else if (!trimmed.compare("AUTO_FOCUS")) { - camParam = CameraParam::AUTO_FOCUS; - } else if (!trimmed.compare("ABSOLUTE_ZOOM")) { - camParam = CameraParam::ABSOLUTE_ZOOM; - } else { - success = false; - } - - return success; -} - -bool ConfigManagerUtil::convertToPixelFormat(const std::string& in, PixelFormat& out) { - std::string trimmed = ConfigManagerUtil::trimString(in); - bool success = true; - - if (!trimmed.compare("RGBA_8888")) { - out = PixelFormat::RGBA_8888; - } else if (!trimmed.compare("YCRCB_420_SP")) { - out = PixelFormat::YCRCB_420_SP; - } else if (!trimmed.compare("YCBCR_422_I")) { - out = PixelFormat::YCBCR_422_I; - } else { - out = PixelFormat::UNSPECIFIED; - success = false; - } - - return success; -} - -bool ConfigManagerUtil::convertToMetadataTag(const char* name, camera_metadata_tag& aTag) { - if (!std::strcmp(name, "LENS_DISTORTION")) { - aTag = ANDROID_LENS_DISTORTION; - } else if (!std::strcmp(name, "LENS_INTRINSIC_CALIBRATION")) { - aTag = ANDROID_LENS_INTRINSIC_CALIBRATION; - } else if (!std::strcmp(name, "LENS_POSE_ROTATION")) { - aTag = ANDROID_LENS_POSE_ROTATION; - } else if (!std::strcmp(name, "LENS_POSE_TRANSLATION")) { - aTag = ANDROID_LENS_POSE_TRANSLATION; - } else if (!std::strcmp(name, "REQUEST_AVAILABLE_CAPABILITIES")) { - aTag = ANDROID_REQUEST_AVAILABLE_CAPABILITIES; - } else if (!std::strcmp(name, "LOGICAL_MULTI_CAMERA_PHYSICAL_IDS")) { - aTag = ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS; - } else { - return false; - } - - return true; -} - -bool ConfigManagerUtil::convertToCameraCapability( - const char* name, camera_metadata_enum_android_request_available_capabilities_t& cap) { - if (!std::strcmp(name, "DEPTH_OUTPUT")) { - cap = ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT; - } else if (!std::strcmp(name, "LOGICAL_MULTI_CAMERA")) { - cap = ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA; - } else if (!std::strcmp(name, "MONOCHROME")) { - cap = ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME; - } else if (!std::strcmp(name, "SECURE_IMAGE_DATA")) { - cap = ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA; - } else { - return false; - } - - return true; -} - -float* ConfigManagerUtil::convertFloatArray(const char* sz, const char* vals, size_t& count, - const char delimiter) { - std::string size_string(sz); - std::string value_string(vals); - - if (!android::base::ParseUint(size_string, &count)) { - LOG(ERROR) << "Failed to parse " << size_string; - return nullptr; - } - float* result = new float[count]; - std::stringstream values(value_string); - - int32_t idx = 0; - std::string token; - while (getline(values, token, delimiter)) { - if (!android::base::ParseFloat(token, &result[idx++])) { - LOG(WARNING) << "Failed to parse " << token; - } - } - - return result; -} - -std::string ConfigManagerUtil::trimString(const std::string& src, const std::string& ws) { - const auto s = src.find_first_not_of(ws); - if (s == std::string::npos) { - return ""; - } - - const auto e = src.find_last_not_of(ws); - const auto r = e - s + 1; - - return src.substr(s, r); -} diff --git a/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp new file mode 100644 index 0000000000..5a81d05850 --- /dev/null +++ b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp @@ -0,0 +1,93 @@ +/* + * 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. + */ + +// TODO(b/203661081): Remove below lines to disable compiler warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" + +#define LOG_TAG "DefaultEvsEnumerator" + +#include + +namespace aidl::android::hardware::automotive::evs::implementation { + +using ::ndk::ScopedAStatus; + +ScopedAStatus DefaultEvsEnumerator::isHardware(bool* flag) { + // This returns true always. + *flag = true; + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::openCamera(const std::string& cameraId, + const Stream& streamConfig, + std::shared_ptr* obj) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::closeCamera(const std::shared_ptr& obj) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::getCameraList(std::vector* list) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::getStreamList(const CameraDesc& desc, + std::vector* _aidl_return) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::openDisplay(int32_t displayId, + std::shared_ptr* obj) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::closeDisplay(const std::shared_ptr& state) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::getDisplayIdList(std::vector* list) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::getDisplayState(DisplayState* state) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::registerStatusCallback( + const std::shared_ptr& callback) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::openUltrasonicsArray( + const std::string& id, std::shared_ptr* obj) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::closeUltrasonicsArray( + const std::shared_ptr& obj) { + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultEvsEnumerator::getUltrasonicsArrayList( + std::vector* list) { + return ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::automotive::evs::implementation + +#pragma clang diagnostic pop diff --git a/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp b/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp deleted file mode 100644 index 6e2405deb5..0000000000 --- a/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2023 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 "EvsEnumerator.h" - -#include "ConfigManager.h" -#include "EvsGlDisplay.h" -#include "EvsMockCamera.h" - -#include -#include -#include -#include - -#include -#include - -namespace { - -using ::aidl::android::frameworks::automotive::display::ICarDisplayProxy; -using ::aidl::android::hardware::graphics::common::BufferUsage; -using ::ndk::ScopedAStatus; -using std::chrono_literals::operator""s; - -// Constants -constexpr std::chrono::seconds kEnumerationTimeout = 10s; -constexpr uint64_t kInvalidDisplayId = std::numeric_limits::max(); -const std::set kAllowedUids = {AID_AUTOMOTIVE_EVS, AID_SYSTEM, AID_ROOT}; - -} // namespace - -namespace aidl::android::hardware::automotive::evs::implementation { - -// NOTE: All members values are static so that all clients operate on the same state -// That is to say, this is effectively a singleton despite the fact that HIDL -// constructs a new instance for each client. -std::unordered_map EvsEnumerator::sCameraList; -std::mutex EvsEnumerator::sLock; -std::condition_variable EvsEnumerator::sCameraSignal; -std::unique_ptr EvsEnumerator::sConfigManager; -std::shared_ptr EvsEnumerator::sDisplayProxy; -std::unordered_map EvsEnumerator::sDisplayPortList; - -EvsEnumerator::ActiveDisplays& EvsEnumerator::mutableActiveDisplays() { - static ActiveDisplays active_displays; - return active_displays; -} - -EvsEnumerator::EvsEnumerator(const std::shared_ptr& proxyService) { - LOG(DEBUG) << "EvsEnumerator is created."; - - if (!sConfigManager) { - /* loads and initializes ConfigManager in a separate thread */ - sConfigManager = ConfigManager::Create(); - } - - if (!sDisplayProxy) { - /* sets a car-window service handle */ - sDisplayProxy = proxyService; - } - - // Enumerate existing devices - enumerateCameras(); - mInternalDisplayId = enumerateDisplays(); -} - -bool EvsEnumerator::checkPermission() { - const auto uid = AIBinder_getCallingUid(); - if (kAllowedUids.find(uid) == kAllowedUids.end()) { - LOG(ERROR) << "EVS access denied: " - << "pid = " << AIBinder_getCallingPid() << ", uid = " << uid; - return false; - } - - return true; -} - -void EvsEnumerator::enumerateCameras() { - if (!sConfigManager) { - return; - } - - for (auto id : sConfigManager->getCameraIdList()) { - CameraRecord rec(id.data()); - std::unique_ptr& pInfo = sConfigManager->getCameraInfo(id); - if (pInfo) { - uint8_t* ptr = reinterpret_cast(pInfo->characteristics); - const size_t len = get_camera_metadata_size(pInfo->characteristics); - rec.desc.metadata.insert(rec.desc.metadata.end(), ptr, ptr + len); - } - sCameraList.insert_or_assign(id, std::move(rec)); - } -} - -uint64_t EvsEnumerator::enumerateDisplays() { - LOG(INFO) << __FUNCTION__ << ": Starting display enumeration"; - uint64_t internalDisplayId = kInvalidDisplayId; - if (!sDisplayProxy) { - LOG(ERROR) << "ICarDisplayProxy is not available!"; - return internalDisplayId; - } - - std::vector displayIds; - if (auto status = sDisplayProxy->getDisplayIdList(&displayIds); !status.isOk()) { - LOG(ERROR) << "Failed to retrieve a display id list" - << ::android::statusToString(status.getStatus()); - return internalDisplayId; - } - - if (displayIds.size() > 0) { - // The first entry of the list is the internal display. See - // SurfaceFlinger::getPhysicalDisplayIds() implementation. - internalDisplayId = displayIds[0]; - for (const auto& id : displayIds) { - const auto port = id & 0xFF; - LOG(INFO) << "Display " << std::hex << id << " is detected on the port, " << port; - sDisplayPortList.insert_or_assign(port, id); - } - } - - LOG(INFO) << "Found " << sDisplayPortList.size() << " displays"; - return internalDisplayId; -} - -// Methods from ::android::hardware::automotive::evs::IEvsEnumerator follow. -ScopedAStatus EvsEnumerator::getCameraList(std::vector* _aidl_return) { - LOG(DEBUG) << __FUNCTION__; - if (!checkPermission()) { - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::PERMISSION_DENIED)); - } - - { - std::unique_lock lock(sLock); - if (sCameraList.size() < 1) { - // No qualified device has been found. Wait until new device is ready, - // for 10 seconds. - if (!sCameraSignal.wait_for(lock, kEnumerationTimeout, - [] { return sCameraList.size() > 0; })) { - LOG(DEBUG) << "Timer expired. No new device has been added."; - } - } - } - - // Build up a packed array of CameraDesc for return - _aidl_return->resize(sCameraList.size()); - unsigned i = 0; - for (const auto& [key, cam] : sCameraList) { - (*_aidl_return)[i++] = cam.desc; - } - - if (sConfigManager) { - // Adding camera groups that represent logical camera devices - auto camGroups = sConfigManager->getCameraGroupIdList(); - for (auto&& id : camGroups) { - if (sCameraList.find(id) != sCameraList.end()) { - // Already exists in the _aidl_return - continue; - } - - std::unique_ptr& tempInfo = - sConfigManager->getCameraGroupInfo(id); - CameraRecord cam(id.data()); - if (tempInfo) { - uint8_t* ptr = reinterpret_cast(tempInfo->characteristics); - const size_t len = get_camera_metadata_size(tempInfo->characteristics); - cam.desc.metadata.insert(cam.desc.metadata.end(), ptr, ptr + len); - } - - sCameraList.insert_or_assign(id, cam); - _aidl_return->push_back(cam.desc); - } - } - - // Send back the results - LOG(DEBUG) << "Reporting " << sCameraList.size() << " cameras available"; - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::getStreamList(const CameraDesc& desc, - std::vector* _aidl_return) { - using AidlPixelFormat = ::aidl::android::hardware::graphics::common::PixelFormat; - - camera_metadata_t* pMetadata = const_cast( - reinterpret_cast(desc.metadata.data())); - camera_metadata_entry_t streamConfig; - if (!find_camera_metadata_entry(pMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, - &streamConfig)) { - const unsigned numStreamConfigs = streamConfig.count / sizeof(StreamConfiguration); - _aidl_return->resize(numStreamConfigs); - const StreamConfiguration* pCurrentConfig = - reinterpret_cast(streamConfig.data.i32); - for (unsigned i = 0; i < numStreamConfigs; ++i, ++pCurrentConfig) { - // Build ::aidl::android::hardware::automotive::evs::Stream from - // StreamConfiguration. - Stream current = { - .id = pCurrentConfig->id, - .streamType = - pCurrentConfig->type == - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT - ? StreamType::INPUT - : StreamType::OUTPUT, - .width = pCurrentConfig->width, - .height = pCurrentConfig->height, - .format = static_cast(pCurrentConfig->format), - .usage = BufferUsage::CAMERA_INPUT, - .rotation = Rotation::ROTATION_0, - }; - - (*_aidl_return)[i] = current; - } - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::openCamera(const std::string& id, const Stream& cfg, - std::shared_ptr* obj) { - LOG(DEBUG) << __FUNCTION__; - if (!checkPermission()) { - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::PERMISSION_DENIED)); - } - - // Is this a recognized camera id? - CameraRecord* pRecord = findCameraById(id); - if (!pRecord) { - LOG(ERROR) << id << " does not exist!"; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - // Has this camera already been instantiated by another caller? - std::shared_ptr pActiveCamera = pRecord->activeInstance.lock(); - if (pActiveCamera) { - LOG(WARNING) << "Killing previous camera because of new caller"; - closeCamera(pActiveCamera); - } - - // Construct a camera instance for the caller - if (!sConfigManager) { - pActiveCamera = EvsMockCamera::Create(id.data()); - } else { - pActiveCamera = EvsMockCamera::Create(id.data(), sConfigManager->getCameraInfo(id), &cfg); - } - - pRecord->activeInstance = pActiveCamera; - if (!pActiveCamera) { - LOG(ERROR) << "Failed to create new EvsMockCamera object for " << id; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::UNDERLYING_SERVICE_ERROR)); - } - - *obj = pActiveCamera; - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::closeCamera(const std::shared_ptr& cameraObj) { - LOG(DEBUG) << __FUNCTION__; - - if (!cameraObj) { - LOG(ERROR) << "Ignoring call to closeCamera with null camera ptr"; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - // Get the camera id so we can find it in our list - CameraDesc desc; - auto status = cameraObj->getCameraInfo(&desc); - if (!status.isOk()) { - LOG(ERROR) << "Failed to read a camera descriptor"; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::UNDERLYING_SERVICE_ERROR)); - } - auto cameraId = desc.id; - closeCamera_impl(cameraObj, cameraId); - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::openDisplay(int32_t id, std::shared_ptr* displayObj) { - LOG(DEBUG) << __FUNCTION__; - if (!checkPermission()) { - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::PERMISSION_DENIED)); - } - - auto& displays = mutableActiveDisplays(); - - if (auto existing_display_search = displays.popDisplay(id)) { - // If we already have a display active, then we need to shut it down so we can - // give exclusive access to the new caller. - std::shared_ptr pActiveDisplay = existing_display_search->displayWeak.lock(); - if (pActiveDisplay) { - LOG(WARNING) << "Killing previous display because of new caller"; - pActiveDisplay->forceShutdown(); - } - } - - // Create a new display interface and return it - uint64_t targetDisplayId = mInternalDisplayId; - auto it = sDisplayPortList.find(id); - if (it != sDisplayPortList.end()) { - targetDisplayId = it->second; - } else { - LOG(WARNING) << "No display is available on the port " << static_cast(id) - << ". The main display " << mInternalDisplayId << " will be used instead"; - } - - // Create a new display interface and return it. - std::shared_ptr pActiveDisplay = - ndk::SharedRefBase::make(sDisplayProxy, targetDisplayId); - - if (auto insert_result = displays.tryInsert(id, pActiveDisplay); !insert_result) { - LOG(ERROR) << "Display ID " << id << " has been used by another caller."; - pActiveDisplay->forceShutdown(); - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::RESOURCE_BUSY)); - } - - LOG(DEBUG) << "Returning new EvsGlDisplay object " << pActiveDisplay.get(); - *displayObj = pActiveDisplay; - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::closeDisplay(const std::shared_ptr& obj) { - LOG(DEBUG) << __FUNCTION__; - - auto& displays = mutableActiveDisplays(); - const auto display_search = displays.popDisplay(obj); - - if (!display_search) { - LOG(WARNING) << "Ignoring close of previously orphaned display - why did a client steal?"; - return ScopedAStatus::ok(); - } - - auto pActiveDisplay = display_search->displayWeak.lock(); - - if (!pActiveDisplay) { - LOG(ERROR) << "Somehow a display is being destroyed " - << "when the enumerator didn't know one existed"; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - pActiveDisplay->forceShutdown(); - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::getDisplayState(DisplayState* state) { - LOG(DEBUG) << __FUNCTION__; - if (!checkPermission()) { - *state = DisplayState::DEAD; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::PERMISSION_DENIED)); - } - - // TODO(b/262779341): For now we can just return the state of the 1st display. Need to update - // the API later. - - const auto& all_displays = mutableActiveDisplays().getAllDisplays(); - - // Do we still have a display object we think should be active? - if (all_displays.empty()) { - *state = DisplayState::NOT_OPEN; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - std::shared_ptr pActiveDisplay = all_displays.begin()->second.displayWeak.lock(); - if (pActiveDisplay) { - return pActiveDisplay->getDisplayState(state); - } else { - *state = DisplayState::NOT_OPEN; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } -} - -ScopedAStatus EvsEnumerator::getDisplayIdList(std::vector* list) { - std::vector& output = *list; - if (sDisplayPortList.size() > 0) { - output.resize(sDisplayPortList.size()); - unsigned i = 0; - output[i++] = mInternalDisplayId & 0xFF; - for (const auto& [port, id] : sDisplayPortList) { - if (mInternalDisplayId != id) { - output[i++] = port; - } - } - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::isHardware(bool* flag) { - *flag = true; - return ScopedAStatus::ok(); -} - -void EvsEnumerator::notifyDeviceStatusChange(const std::string_view& deviceName, - DeviceStatusType type) { - std::lock_guard lock(sLock); - if (!mCallback) { - return; - } - - std::vector status{{.id = std::string(deviceName), .status = type}}; - if (!mCallback->deviceStatusChanged(status).isOk()) { - LOG(WARNING) << "Failed to notify a device status change, name = " << deviceName - << ", type = " << static_cast(type); - } -} - -ScopedAStatus EvsEnumerator::registerStatusCallback( - const std::shared_ptr& callback) { - std::lock_guard lock(sLock); - if (mCallback) { - LOG(INFO) << "Replacing an existing device status callback"; - } - mCallback = callback; - return ScopedAStatus::ok(); -} - -void EvsEnumerator::closeCamera_impl(const std::shared_ptr& pCamera, - const std::string& cameraId) { - // Find the named camera - CameraRecord* pRecord = findCameraById(cameraId); - - // Is the display being destroyed actually the one we think is active? - if (!pRecord) { - LOG(ERROR) << "Asked to close a camera whose name isn't recognized"; - } else { - std::shared_ptr pActiveCamera = pRecord->activeInstance.lock(); - if (!pActiveCamera) { - LOG(WARNING) << "Somehow a camera is being destroyed " - << "when the enumerator didn't know one existed"; - } else if (pActiveCamera != pCamera) { - // This can happen if the camera was aggressively reopened, - // orphaning this previous instance - LOG(WARNING) << "Ignoring close of previously orphaned camera " - << "- why did a client steal?"; - } else { - // Shutdown the active camera - pActiveCamera->shutdown(); - } - } - - return; -} - -EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) { - // Find the named camera - auto found = sCameraList.find(cameraId); - if (found != sCameraList.end()) { - // Found a match! - return &found->second; - } - - // We didn't find a match - return nullptr; -} - -std::optional EvsEnumerator::ActiveDisplays::popDisplay( - int32_t id) { - std::lock_guard lck(mMutex); - const auto search = mIdToDisplay.find(id); - if (search == mIdToDisplay.end()) { - return std::nullopt; - } - const auto display_info = search->second; - mIdToDisplay.erase(search); - mDisplayToId.erase(display_info.internalDisplayRawAddr); - return display_info; -} - -std::optional EvsEnumerator::ActiveDisplays::popDisplay( - const std::shared_ptr& display) { - const auto display_ptr_val = reinterpret_cast(display.get()); - std::lock_guard lck(mMutex); - const auto display_to_id_search = mDisplayToId.find(display_ptr_val); - if (display_to_id_search == mDisplayToId.end()) { - LOG(ERROR) << "Unknown display."; - return std::nullopt; - } - const auto id = display_to_id_search->second; - const auto id_to_display_search = mIdToDisplay.find(id); - mDisplayToId.erase(display_to_id_search); - if (id_to_display_search == mIdToDisplay.end()) { - LOG(ERROR) << "No correspsonding ID for the display, probably orphaned."; - return std::nullopt; - } - const auto display_info = id_to_display_search->second; - mIdToDisplay.erase(id); - return display_info; -} - -std::unordered_map -EvsEnumerator::ActiveDisplays::getAllDisplays() { - std::lock_guard lck(mMutex); - auto id_to_display_map_copy = mIdToDisplay; - return id_to_display_map_copy; -} - -bool EvsEnumerator::ActiveDisplays::tryInsert(int32_t id, - const std::shared_ptr& display) { - std::lock_guard lck(mMutex); - const auto display_ptr_val = reinterpret_cast(display.get()); - - auto id_to_display_insert_result = - mIdToDisplay.emplace(id, DisplayInfo{ - .id = id, - .displayWeak = display, - .internalDisplayRawAddr = display_ptr_val, - }); - if (!id_to_display_insert_result.second) { - return false; - } - auto display_to_id_insert_result = mDisplayToId.emplace(display_ptr_val, id); - if (!display_to_id_insert_result.second) { - mIdToDisplay.erase(id); - return false; - } - return true; -} - -ScopedAStatus EvsEnumerator::getUltrasonicsArrayList( - [[maybe_unused]] std::vector* list) { - // TODO(b/149874793): Add implementation for EVS Manager and Sample driver - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::openUltrasonicsArray( - [[maybe_unused]] const std::string& id, - [[maybe_unused]] std::shared_ptr* obj) { - // TODO(b/149874793): Add implementation for EVS Manager and Sample driver - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsEnumerator::closeUltrasonicsArray( - [[maybe_unused]] const std::shared_ptr& obj) { - // TODO(b/149874793): Add implementation for EVS Manager and Sample driver - return ScopedAStatus::ok(); -} - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp deleted file mode 100644 index e5f8e4c84a..0000000000 --- a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2023 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 "EvsGlDisplay.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace { - -using ::aidl::android::frameworks::automotive::display::ICarDisplayProxy; -using ::aidl::android::hardware::graphics::common::BufferUsage; -using ::aidl::android::hardware::graphics::common::PixelFormat; -using ::android::base::ScopedLockAssertion; -using ::ndk::ScopedAStatus; - -constexpr auto kTimeout = std::chrono::seconds(1); - -bool debugFirstFrameDisplayed = false; - -int generateFingerPrint(buffer_handle_t handle) { - return static_cast(reinterpret_cast(handle) & 0xFFFFFFFF); -} - -} // namespace - -namespace aidl::android::hardware::automotive::evs::implementation { - -EvsGlDisplay::EvsGlDisplay(const std::shared_ptr& pDisplayProxy, - uint64_t displayId) - : mDisplayId(displayId), mDisplayProxy(pDisplayProxy) { - LOG(DEBUG) << "EvsGlDisplay instantiated"; - - // Set up our self description - // NOTE: These are arbitrary values chosen for testing - mInfo.id = std::to_string(displayId); - mInfo.vendorFlags = 3870; - - // Start a thread to render images on this display - { - std::lock_guard lock(mLock); - mState = RUN; - } - mRenderThread = std::thread([this]() { renderFrames(); }); -} - -EvsGlDisplay::~EvsGlDisplay() { - LOG(DEBUG) << "EvsGlDisplay being destroyed"; - forceShutdown(); -} - -/** - * This gets called if another caller "steals" ownership of the display - */ -void EvsGlDisplay::forceShutdown() { - LOG(DEBUG) << "EvsGlDisplay forceShutdown"; - { - std::lock_guard lock(mLock); - - // If the buffer isn't being held by a remote client, release it now as an - // optimization to release the resources more quickly than the destructor might - // get called. - if (mBuffer.handle != nullptr) { - // Report if we're going away while a buffer is outstanding - if (mBufferBusy || mState == RUN) { - LOG(ERROR) << "EvsGlDisplay going down while client is holding a buffer"; - } - mState = STOPPING; - } - - // Put this object into an unrecoverable error state since somebody else - // is going to own the display now. - mRequestedState = DisplayState::DEAD; - } - mBufferReadyToRender.notify_all(); - - if (mRenderThread.joinable()) { - mRenderThread.join(); - } -} - -/** - * Initialize GL in the context of a caller's thread and prepare a graphic - * buffer to use. - */ -bool EvsGlDisplay::initializeGlContextLocked() { - // Initialize our display window - // NOTE: This will cause the display to become "VISIBLE" before a frame is actually - // returned, which is contrary to the spec and will likely result in a black frame being - // (briefly) shown. - if (!mGlWrapper.initialize(mDisplayProxy, mDisplayId)) { - // Report the failure - LOG(ERROR) << "Failed to initialize GL display"; - return false; - } - - // Assemble the buffer description we'll use for our render target - static_assert(::aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888 == - static_cast<::aidl::android::hardware::graphics::common::PixelFormat>( - HAL_PIXEL_FORMAT_RGBA_8888)); - mBuffer.description = { - .width = static_cast(mGlWrapper.getWidth()), - .height = static_cast(mGlWrapper.getHeight()), - .layers = 1, - .format = PixelFormat::RGBA_8888, - // FIXME: Below line is not using - // ::aidl::android::hardware::graphics::common::BufferUsage because - // BufferUsage enum does not support a bitwise-OR operation; they - // should be BufferUsage::GPU_RENDER_TARGET | - // BufferUsage::COMPOSER_OVERLAY - .usage = static_cast(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER), - }; - - ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get()); - uint32_t stride = static_cast(mBuffer.description.stride); - buffer_handle_t handle = nullptr; - const ::android::status_t result = - alloc.allocate(mBuffer.description.width, mBuffer.description.height, - static_cast<::android::PixelFormat>(mBuffer.description.format), - mBuffer.description.layers, - static_cast(mBuffer.description.usage), &handle, &stride, - /* requestorName= */ "EvsGlDisplay"); - mBuffer.description.stride = stride; - mBuffer.fingerprint = generateFingerPrint(mBuffer.handle); - if (result != ::android::NO_ERROR) { - LOG(ERROR) << "Error " << result << " allocating " << mBuffer.description.width << " x " - << mBuffer.description.height << " graphics buffer."; - mGlWrapper.shutdown(); - return false; - } - - mBuffer.handle = handle; - if (mBuffer.handle == nullptr) { - LOG(ERROR) << "We didn't get a buffer handle back from the allocator"; - mGlWrapper.shutdown(); - return false; - } - - LOG(DEBUG) << "Allocated new buffer " << mBuffer.handle << " with stride " - << mBuffer.description.stride; - return true; -} - -/** - * This method runs in a separate thread and renders the contents of the buffer. - */ -void EvsGlDisplay::renderFrames() { - { - std::lock_guard lock(mLock); - - if (!initializeGlContextLocked()) { - LOG(ERROR) << "Failed to initialize GL context"; - return; - } - - // Display buffer is ready. - mBufferBusy = false; - } - mBufferReadyToUse.notify_all(); - - while (true) { - { - std::unique_lock lock(mLock); - ScopedLockAssertion lock_assertion(mLock); - mBufferReadyToRender.wait( - lock, [this]() REQUIRES(mLock) { return mBufferReady || mState != RUN; }); - if (mState != RUN) { - LOG(DEBUG) << "A rendering thread is stopping"; - break; - } - mBufferReady = false; - } - - // Update the texture contents with the provided data - if (!mGlWrapper.updateImageTexture(mBuffer.handle, mBuffer.description)) { - LOG(WARNING) << "Failed to update the image texture"; - continue; - } - - // Put the image on the screen - mGlWrapper.renderImageToScreen(); - if (!debugFirstFrameDisplayed) { - LOG(DEBUG) << "EvsFirstFrameDisplayTiming start time: " << ::android::elapsedRealtime() - << " ms."; - debugFirstFrameDisplayed = true; - } - - // Mark current frame is consumed. - { - std::lock_guard lock(mLock); - mBufferBusy = false; - } - mBufferDone.notify_all(); - } - - LOG(DEBUG) << "A rendering thread is stopped."; - - // Drop the graphics buffer we've been using - ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get()); - alloc.free(mBuffer.handle); - mBuffer.handle = nullptr; - - mGlWrapper.hideWindow(mDisplayProxy, mDisplayId); - mGlWrapper.shutdown(); - - std::lock_guard lock(mLock); - mState = STOPPED; -} - -/** - * Returns basic information about the EVS display provided by the system. - * See the description of the DisplayDesc structure for details. - */ -ScopedAStatus EvsGlDisplay::getDisplayInfo(DisplayDesc* _aidl_return) { - if (!mDisplayProxy) { - return ::ndk::ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::UNDERLYING_SERVICE_ERROR)); - } - - ::aidl::android::frameworks::automotive::display::DisplayDesc proxyDisplay; - auto status = mDisplayProxy->getDisplayInfo(mDisplayId, &proxyDisplay); - if (!status.isOk()) { - return ::ndk::ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::UNDERLYING_SERVICE_ERROR)); - } - - _aidl_return->width = proxyDisplay.width; - _aidl_return->height = proxyDisplay.height; - _aidl_return->orientation = static_cast(proxyDisplay.orientation); - _aidl_return->id = mInfo.id; // FIXME: what should be ID here? - _aidl_return->vendorFlags = mInfo.vendorFlags; - return ::ndk::ScopedAStatus::ok(); -} - -/** - * Clients may set the display state to express their desired state. - * The HAL implementation must gracefully accept a request for any state - * while in any other state, although the response may be to ignore the request. - * The display is defined to start in the NOT_VISIBLE state upon initialization. - * The client is then expected to request the VISIBLE_ON_NEXT_FRAME state, and - * then begin providing video. When the display is no longer required, the client - * is expected to request the NOT_VISIBLE state after passing the last video frame. - */ -ScopedAStatus EvsGlDisplay::setDisplayState(DisplayState state) { - LOG(DEBUG) << __FUNCTION__; - std::lock_guard lock(mLock); - - if (mRequestedState == DisplayState::DEAD) { - // This object no longer owns the display -- it's been superceeded! - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - // Ensure we recognize the requested state so we don't go off the rails - static constexpr ::ndk::enum_range kDisplayStateRange; - if (std::find(kDisplayStateRange.begin(), kDisplayStateRange.end(), state) == - kDisplayStateRange.end()) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - switch (state) { - case DisplayState::NOT_VISIBLE: - mGlWrapper.hideWindow(mDisplayProxy, mDisplayId); - break; - case DisplayState::VISIBLE: - mGlWrapper.showWindow(mDisplayProxy, mDisplayId); - break; - default: - break; - } - - // Record the requested state - mRequestedState = state; - - return ScopedAStatus::ok(); -} - -/** - * The HAL implementation should report the actual current state, which might - * transiently differ from the most recently requested state. Note, however, that - * the logic responsible for changing display states should generally live above - * the device layer, making it undesirable for the HAL implementation to - * spontaneously change display states. - */ -ScopedAStatus EvsGlDisplay::getDisplayState(DisplayState* _aidl_return) { - LOG(DEBUG) << __FUNCTION__; - std::lock_guard lock(mLock); - *_aidl_return = mRequestedState; - return ScopedAStatus::ok(); -} - -/** - * This call returns a handle to a frame buffer associated with the display. - * This buffer may be locked and written to by software and/or GL. This buffer - * must be returned via a call to returnTargetBufferForDisplay() even if the - * display is no longer visible. - */ -ScopedAStatus EvsGlDisplay::getTargetBuffer(BufferDesc* _aidl_return) { - LOG(DEBUG) << __FUNCTION__; - std::unique_lock lock(mLock); - ScopedLockAssertion lock_assertion(mLock); - if (mRequestedState == DisplayState::DEAD) { - LOG(ERROR) << "Rejecting buffer request from object that lost ownership of the display."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - // If we don't already have a buffer, allocate one now - // mBuffer.memHandle is a type of buffer_handle_t, which is equal to - // native_handle_t*. - mBufferReadyToUse.wait(lock, [this]() REQUIRES(mLock) { return !mBufferBusy; }); - - // Do we have a frame available? - if (mBufferBusy) { - // This means either we have a 2nd client trying to compete for buffers - // (an unsupported mode of operation) or else the client hasn't returned - // a previously issued buffer yet (they're behaving badly). - // NOTE: We have to make the callback even if we have nothing to provide - LOG(ERROR) << "getTargetBuffer called while no buffers available."; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::BUFFER_NOT_AVAILABLE)); - } - - // Mark our buffer as busy - mBufferBusy = true; - - // Send the buffer to the client - LOG(VERBOSE) << "Providing display buffer handle " << mBuffer.handle; - - BufferDesc bufferDescToSend = { - .buffer = - { - .handle = std::move(::android::dupToAidl(mBuffer.handle)), - .description = mBuffer.description, - }, - .pixelSizeBytes = 4, // RGBA_8888 is 4-byte-per-pixel format - .bufferId = mBuffer.fingerprint, - }; - *_aidl_return = std::move(bufferDescToSend); - - return ScopedAStatus::ok(); -} - -/** - * This call tells the display that the buffer is ready for display. - * The buffer is no longer valid for use by the client after this call. - */ -ScopedAStatus EvsGlDisplay::returnTargetBufferForDisplay(const BufferDesc& buffer) { - LOG(VERBOSE) << __FUNCTION__; - std::unique_lock lock(mLock); - ScopedLockAssertion lock_assertion(mLock); - - // Nobody should call us with a null handle - if (buffer.buffer.handle.fds.size() < 1) { - LOG(ERROR) << __FUNCTION__ << " called without a valid buffer handle."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - if (buffer.bufferId != mBuffer.fingerprint) { - LOG(ERROR) << "Got an unrecognized frame returned."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - if (!mBufferBusy) { - LOG(ERROR) << "A frame was returned with no outstanding frames."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - // If we've been displaced by another owner of the display, then we can't do anything else - if (mRequestedState == DisplayState::DEAD) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - // If we were waiting for a new frame, this is it! - if (mRequestedState == DisplayState::VISIBLE_ON_NEXT_FRAME) { - mRequestedState = DisplayState::VISIBLE; - mGlWrapper.showWindow(mDisplayProxy, mDisplayId); - } - - // Validate we're in an expected state - if (mRequestedState != DisplayState::VISIBLE) { - // Not sure why a client would send frames back when we're not visible. - LOG(WARNING) << "Got a frame returned while not visible - ignoring."; - return ScopedAStatus::ok(); - } - mBufferReady = true; - mBufferReadyToRender.notify_all(); - - if (!mBufferDone.wait_for(lock, kTimeout, [this]() REQUIRES(mLock) { return !mBufferBusy; })) { - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::UNDERLYING_SERVICE_ERROR)); - } - - return ScopedAStatus::ok(); -} - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp deleted file mode 100644 index 4b46a5ae64..0000000000 --- a/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright (C) 2023 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 "EvsMockCamera.h" -#include "ConfigManager.h" -#include "EvsEnumerator.h" - -#include -#include -#include -#include - -#include - -namespace { - -using ::aidl::android::hardware::graphics::common::BufferUsage; -using ::ndk::ScopedAStatus; - -// Arbitrary limit on number of graphics buffers allowed to be allocated -// Safeguards against unreasonable resource consumption and provides a testable limit -constexpr unsigned kMaxBuffersInFlight = 100; - -// Minimum number of buffers to run a video stream -constexpr int kMinimumBuffersInFlight = 1; - -// Colors for the colorbar test pattern in ABGR format -constexpr uint32_t kColors[] = { - 0xFFFFFFFF, // white - 0xFF00FFFF, // yellow - 0xFFFFFF00, // cyan - 0xFF00FF00, // green - 0xFFFF00FF, // fuchsia - 0xFF0000FF, // red - 0xFFFF0000, // blue - 0xFF000000, // black -}; -constexpr size_t kNumColors = sizeof(kColors) / sizeof(kColors[0]); - -} // namespace - -namespace aidl::android::hardware::automotive::evs::implementation { - -EvsMockCamera::EvsMockCamera([[maybe_unused]] Sigil sigil, const char* id, - std::unique_ptr& camInfo) - : mFramesAllowed(0), mFramesInUse(0), mStreamState(STOPPED), mCameraInfo(camInfo) { - LOG(DEBUG) << __FUNCTION__; - - /* set a camera id */ - mDescription.id = id; - - /* set camera metadata */ - if (camInfo) { - uint8_t* ptr = reinterpret_cast(camInfo->characteristics); - const size_t len = get_camera_metadata_size(camInfo->characteristics); - mDescription.metadata.insert(mDescription.metadata.end(), ptr, ptr + len); - } -} - -EvsMockCamera::~EvsMockCamera() { - LOG(DEBUG) << __FUNCTION__; - shutdown(); -} - -// This gets called if another caller "steals" ownership of the camera -void EvsMockCamera::shutdown() { - LOG(DEBUG) << __FUNCTION__; - - // Make sure our output stream is cleaned up - // (It really should be already) - stopVideoStream_impl(); - - // Claim the lock while we work on internal state - std::lock_guard lock(mAccessLock); - - // Drop all the graphics buffers we've been using - if (mBuffers.size() > 0) { - ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get()); - for (auto&& rec : mBuffers) { - if (rec.inUse) { - LOG(WARNING) << "WARNING: releasing a buffer remotely owned."; - } - alloc.free(rec.handle); - rec.handle = nullptr; - } - mBuffers.clear(); - } - - // Put this object into an unrecoverable error state since somebody else - // is going to own the underlying camera now - mStreamState = DEAD; -} - -// Methods from ::aidl::android::hardware::automotive::evs::IEvsCamera follow. -ScopedAStatus EvsMockCamera::getCameraInfo(CameraDesc* _aidl_return) { - LOG(DEBUG) << __FUNCTION__; - - // Send back our self description - *_aidl_return = mDescription; - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::setMaxFramesInFlight(int32_t bufferCount) { - LOG(DEBUG) << __FUNCTION__ << ", bufferCount = " << bufferCount; - ; - - std::lock_guard lock(mAccessLock); - - // If we've been displaced by another owner of the camera, then we can't do anything else - if (mStreamState == DEAD) { - LOG(ERROR) << "Ignoring setMaxFramesInFlight call when camera has been lost."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - // We cannot function without at least one video buffer to send data - if (bufferCount < 1) { - LOG(ERROR) << "Ignoring setMaxFramesInFlight with less than one buffer requested."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - // Update our internal state - if (!setAvailableFrames_Locked(bufferCount)) { - LOG(ERROR) << "Failed to adjust the maximum number of frames in flight."; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::BUFFER_NOT_AVAILABLE)); - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::startVideoStream(const std::shared_ptr& cb) { - LOG(DEBUG) << __FUNCTION__; - - if (!cb) { - LOG(ERROR) << "A given stream callback is invalid."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } - - std::lock_guard lock(mAccessLock); - - // If we've been displaced by another owner of the camera, then we can't do anything else - if (mStreamState == DEAD) { - LOG(ERROR) << "Ignoring startVideoStream call when camera has been lost."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::OWNERSHIP_LOST)); - } - - if (mStreamState != STOPPED) { - LOG(ERROR) << "Ignoring startVideoStream call when a stream is already running."; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::STREAM_ALREADY_RUNNING)); - } - - // If the client never indicated otherwise, configure ourselves for a single streaming buffer - if (mFramesAllowed < kMinimumBuffersInFlight && - !setAvailableFrames_Locked(kMinimumBuffersInFlight)) { - LOG(ERROR) << "Failed to start stream because we couldn't get a graphics buffer"; - return ScopedAStatus::fromServiceSpecificError( - static_cast(EvsResult::BUFFER_NOT_AVAILABLE)); - } - - // Record the user's callback for use when we have a frame ready - mStream = cb; - - // Start the frame generation thread - mStreamState = RUNNING; - mCaptureThread = std::thread([this]() { generateFrames(); }); - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::doneWithFrame(const std::vector& list) { - std::lock_guard lock(mAccessLock); - for (const auto& desc : list) { - returnBufferLocked(desc.bufferId); - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::stopVideoStream() { - LOG(DEBUG) << __FUNCTION__; - return stopVideoStream_impl(); -} - -ScopedAStatus EvsMockCamera::stopVideoStream_impl() { - std::unique_lock lock(mAccessLock); - - if (mStreamState != RUNNING) { - // Safely return here because a stream is not running. - return ScopedAStatus::ok(); - } - - // Tell the GenerateFrames loop we want it to stop - mStreamState = STOPPING; - - // Block outside the mutex until the "stop" flag has been acknowledged - // We won't send any more frames, but the client might still get some already in flight - LOG(DEBUG) << "Waiting for stream thread to end..."; - lock.unlock(); - if (mCaptureThread.joinable()) { - mCaptureThread.join(); - } - lock.lock(); - - mStreamState = STOPPED; - mStream = nullptr; - LOG(DEBUG) << "Stream marked STOPPED."; - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::getExtendedInfo(int32_t opaqueIdentifier, - std::vector* opaqueValue) { - const auto it = mExtInfo.find(opaqueIdentifier); - if (it == mExtInfo.end()) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::INVALID_ARG)); - } else { - *opaqueValue = mExtInfo[opaqueIdentifier]; - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::setExtendedInfo(int32_t opaqueIdentifier, - const std::vector& opaqueValue) { - mExtInfo.insert_or_assign(opaqueIdentifier, opaqueValue); - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::getPhysicalCameraInfo([[maybe_unused]] const std::string& id, - CameraDesc* _aidl_return) { - LOG(DEBUG) << __FUNCTION__; - - // This method works exactly same as getCameraInfo() in EVS HW module. - *_aidl_return = mDescription; - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::pauseVideoStream() { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -ScopedAStatus EvsMockCamera::resumeVideoStream() { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -ScopedAStatus EvsMockCamera::setPrimaryClient() { - /* Because EVS HW module reference implementation expects a single client at - * a time, this returns a success code always. - */ - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::forcePrimaryClient(const std::shared_ptr&) { - /* Because EVS HW module reference implementation expects a single client at - * a time, this returns a success code always. - */ - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::unsetPrimaryClient() { - /* Because EVS HW module reference implementation expects a single client at - * a time, there is no chance that this is called by the secondary client and - * therefore returns a success code always. - */ - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::getParameterList(std::vector* _aidl_return) { - if (mCameraInfo) { - _aidl_return->resize(mCameraInfo->controls.size()); - auto idx = 0; - for (auto& [name, range] : mCameraInfo->controls) { - (*_aidl_return)[idx++] = name; - } - } - - return ScopedAStatus::ok(); -} - -ScopedAStatus EvsMockCamera::getIntParameterRange([[maybe_unused]] CameraParam id, - [[maybe_unused]] ParameterRange* _aidl_return) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -ScopedAStatus EvsMockCamera::setIntParameter( - [[maybe_unused]] CameraParam id, [[maybe_unused]] int32_t value, - [[maybe_unused]] std::vector* effectiveValue) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -ScopedAStatus EvsMockCamera::getIntParameter([[maybe_unused]] CameraParam id, - [[maybe_unused]] std::vector* value) { - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -ScopedAStatus EvsMockCamera::importExternalBuffers( - [[maybe_unused]] const std::vector& buffers, - [[maybe_unused]] int32_t* _aidl_return) { - LOG(DEBUG) << "This implementation does not support an external buffer import."; - return ScopedAStatus::fromServiceSpecificError(static_cast(EvsResult::NOT_SUPPORTED)); -} - -bool EvsMockCamera::setAvailableFrames_Locked(unsigned bufferCount) { - if (bufferCount < 1) { - LOG(ERROR) << "Ignoring request to set buffer count to zero"; - return false; - } - if (bufferCount > kMaxBuffersInFlight) { - LOG(ERROR) << "Rejecting buffer request in excess of internal limit"; - return false; - } - - // Is an increase required? - if (mFramesAllowed < bufferCount) { - // An increase is required - auto needed = bufferCount - mFramesAllowed; - LOG(INFO) << "Allocating " << needed << " buffers for camera frames"; - - auto added = increaseAvailableFrames_Locked(needed); - if (added != needed) { - // If we didn't add all the frames we needed, then roll back to the previous state - LOG(ERROR) << "Rolling back to previous frame queue size"; - decreaseAvailableFrames_Locked(added); - return false; - } - } else if (mFramesAllowed > bufferCount) { - // A decrease is required - auto framesToRelease = mFramesAllowed - bufferCount; - LOG(INFO) << "Returning " << framesToRelease << " camera frame buffers"; - - auto released = decreaseAvailableFrames_Locked(framesToRelease); - if (released != framesToRelease) { - // This shouldn't happen with a properly behaving client because the client - // should only make this call after returning sufficient outstanding buffers - // to allow a clean resize. - LOG(ERROR) << "Buffer queue shrink failed -- too many buffers currently in use?"; - } - } - - return true; -} - -unsigned EvsMockCamera::increaseAvailableFrames_Locked(unsigned numToAdd) { - // Acquire the graphics buffer allocator - ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get()); - - unsigned added = 0; - while (added < numToAdd) { - unsigned pixelsPerLine = 0; - buffer_handle_t memHandle = nullptr; - auto result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage, &memHandle, - &pixelsPerLine, 0, "EvsMockCamera"); - if (result != ::android::NO_ERROR) { - LOG(ERROR) << "Error " << result << " allocating " << mWidth << " x " << mHeight - << " graphics buffer"; - break; - } - if (memHandle == nullptr) { - LOG(ERROR) << "We didn't get a buffer handle back from the allocator"; - break; - } - if (mStride > 0) { - if (mStride != pixelsPerLine) { - LOG(ERROR) << "We did not expect to get buffers with different strides!"; - } - } else { - // Gralloc defines stride in terms of pixels per line - mStride = pixelsPerLine; - } - - // Find a place to store the new buffer - auto stored = false; - for (auto&& rec : mBuffers) { - if (rec.handle == nullptr) { - // Use this existing entry - rec.handle = memHandle; - rec.inUse = false; - stored = true; - break; - } - } - if (!stored) { - // Add a BufferRecord wrapping this handle to our set of available buffers - mBuffers.push_back(BufferRecord(memHandle)); - } - - ++mFramesAllowed; - ++added; - } - - return added; -} - -unsigned EvsMockCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) { - // Acquire the graphics buffer allocator - ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get()); - - unsigned removed = 0; - for (auto&& rec : mBuffers) { - // Is this record not in use, but holding a buffer that we can free? - if ((rec.inUse == false) && (rec.handle != nullptr)) { - // Release buffer and update the record so we can recognize it as "empty" - alloc.free(rec.handle); - rec.handle = nullptr; - - --mFramesAllowed; - ++removed; - - if (removed == numToRemove) { - break; - } - } - } - - return removed; -} - -// This is the asynchronous frame generation thread that runs in parallel with the -// main serving thread. There is one for each active camera instance. -void EvsMockCamera::generateFrames() { - LOG(DEBUG) << "Frame generation loop started."; - - unsigned idx = 0; - while (true) { - bool timeForFrame = false; - const nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); - - // Lock scope for updating shared state - { - std::lock_guard lock(mAccessLock); - - if (mStreamState != RUNNING) { - // Break out of our main thread loop - break; - } - - // Are we allowed to issue another buffer? - if (mFramesInUse >= mFramesAllowed) { - // Can't do anything right now -- skip this frame - LOG(WARNING) << "Skipped a frame because too many are in flight."; - } else { - // Identify an available buffer to fill - for (idx = 0; idx < mBuffers.size(); idx++) { - if (!mBuffers[idx].inUse) { - if (mBuffers[idx].handle != nullptr) { - // Found an available record, so stop looking - break; - } - } - } - if (idx >= mBuffers.size()) { - // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed - ALOGE("Failed to find an available buffer slot\n"); - } else { - // We're going to make the frame busy - mBuffers[idx].inUse = true; - mFramesInUse++; - timeForFrame = true; - } - } - } - - if (timeForFrame) { - using AidlPixelFormat = ::aidl::android::hardware::graphics::common::PixelFormat; - - // Assemble the buffer description we'll transmit below - buffer_handle_t memHandle = mBuffers[idx].handle; - BufferDesc newBuffer = { - .buffer = - { - .description = - { - .width = static_cast(mWidth), - .height = static_cast(mHeight), - .layers = 1, - .format = static_cast(mFormat), - .usage = static_cast(mUsage), - .stride = static_cast(mStride), - }, - .handle = ::android::dupToAidl(memHandle), - }, - .bufferId = static_cast(idx), - .deviceId = mDescription.id, - .timestamp = static_cast(::android::elapsedRealtimeNano() * - 1e+3), // timestamps is in microseconds - }; - - // Write test data into the image buffer - fillMockFrame(memHandle, reinterpret_cast( - &newBuffer.buffer.description)); - - // Issue the (asynchronous) callback to the client -- can't be holding the lock - auto flag = false; - if (mStream) { - std::vector frames; - frames.push_back(std::move(newBuffer)); - flag = mStream->deliverFrame(frames).isOk(); - } - - if (flag) { - LOG(DEBUG) << "Delivered " << memHandle << ", id = " << mBuffers[idx].handle; - } else { - // This can happen if the client dies and is likely unrecoverable. - // To avoid consuming resources generating failing calls, we stop sending - // frames. Note, however, that the stream remains in the "STREAMING" state - // until cleaned up on the main thread. - LOG(ERROR) << "Frame delivery call failed in the transport layer."; - - // Since we didn't actually deliver it, mark the frame as available - std::lock_guard lock(mAccessLock); - mBuffers[idx].inUse = false; - mFramesInUse--; - } - } - - // We arbitrarily choose to generate frames at 15 fps to ensure we pass the 10fps test - // requirement - static const int kTargetFrameRate = 15; - static const nsecs_t kTargetFrameIntervalUs = 1000 * 1000 / kTargetFrameRate; - const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - const nsecs_t elapsedTimeUs = (now - startTime) / 1000; - const nsecs_t sleepDurationUs = kTargetFrameIntervalUs - elapsedTimeUs; - if (sleepDurationUs > 0) { - usleep(sleepDurationUs); - } - } - - // If we've been asked to stop, send an event to signal the actual end of stream - EvsEventDesc event = { - .aType = EvsEventType::STREAM_STOPPED, - }; - if (!mStream->notify(event).isOk()) { - ALOGE("Error delivering end of stream marker"); - } - - return; -} - -void EvsMockCamera::fillMockFrame(buffer_handle_t handle, const AHardwareBuffer_Desc* pDesc) { - // Lock our output buffer for writing - uint32_t* pixels = nullptr; - ::android::GraphicBufferMapper& mapper = ::android::GraphicBufferMapper::get(); - mapper.lock(handle, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER, - ::android::Rect(pDesc->width, pDesc->height), (void**)&pixels); - - // If we failed to lock the pixel buffer, we're about to crash, but log it first - if (!pixels) { - ALOGE("Camera failed to gain access to image buffer for writing"); - return; - } - - // Fill in the test pixels; the colorbar in ABGR format - for (unsigned row = 0; row < pDesc->height; row++) { - for (unsigned col = 0; col < pDesc->width; col++) { - const uint32_t index = col * kNumColors / pDesc->width; - pixels[col] = kColors[index]; - } - // Point to the next row - // NOTE: stride retrieved from gralloc is in units of pixels - pixels = pixels + pDesc->stride; - } - - // Release our output buffer - mapper.unlock(handle); -} - -void EvsMockCamera::returnBufferLocked(const uint32_t bufferId) { - if (bufferId >= mBuffers.size()) { - ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)", bufferId, - mBuffers.size() - 1); - return; - } - - if (!mBuffers[bufferId].inUse) { - ALOGE("ignoring doneWithFrame called on frame %d which is already free", bufferId); - return; - } - - // Mark the frame as available - mBuffers[bufferId].inUse = false; - mFramesInUse--; - - // If this frame's index is high in the array, try to move it down - // to improve locality after mFramesAllowed has been reduced. - if (bufferId >= mFramesAllowed) { - // Find an empty slot lower in the array (which should always exist in this case) - for (auto&& rec : mBuffers) { - if (rec.handle == nullptr) { - rec.handle = mBuffers[bufferId].handle; - mBuffers[bufferId].handle = nullptr; - break; - } - } - } -} - -std::shared_ptr EvsMockCamera::Create(const char* deviceName) { - std::unique_ptr nullCamInfo = nullptr; - - return Create(deviceName, nullCamInfo); -} - -std::shared_ptr EvsMockCamera::Create( - const char* deviceName, std::unique_ptr& camInfo, - [[maybe_unused]] const Stream* streamCfg) { - std::shared_ptr c = - ndk::SharedRefBase::make(Sigil{}, deviceName, camInfo); - if (!c) { - LOG(ERROR) << "Failed to instantiate EvsMockCamera."; - return nullptr; - } - - // Use the first resolution from the list for the testing - // TODO(b/214835237): Uses a given Stream configuration to choose the best - // stream configuration. - auto it = camInfo->streamConfigurations.begin(); - c->mWidth = it->second.width; - c->mHeight = it->second.height; - c->mDescription.vendorFlags = 0xFFFFFFFF; // Arbitrary test value - - c->mFormat = HAL_PIXEL_FORMAT_RGBA_8888; - c->mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE | - GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY; - - return c; -} - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp b/automotive/evs/aidl/impl/default/src/GlWrapper.cpp deleted file mode 100644 index 0ee5ecb734..0000000000 --- a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2023 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 "GlWrapper.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace { - -using ::aidl::android::frameworks::automotive::display::DisplayDesc; -using ::aidl::android::frameworks::automotive::display::ICarDisplayProxy; -using ::aidl::android::frameworks::automotive::display::Rotation; -using ::aidl::android::hardware::common::NativeHandle; -using ::aidl::android::hardware::graphics::common::HardwareBufferDescription; -using ::android::GraphicBuffer; -using ::android::sp; - -constexpr const char vertexShaderSource[] = - "attribute vec4 pos; \n" - "attribute vec2 tex; \n" - "varying vec2 uv; \n" - "void main() \n" - "{ \n" - " gl_Position = pos; \n" - " uv = tex; \n" - "} \n"; - -constexpr const char pixelShaderSource[] = - "precision mediump float; \n" - "uniform sampler2D tex; \n" - "varying vec2 uv; \n" - "void main() \n" - "{ \n" - " gl_FragColor = texture2D(tex, uv);\n" - "} \n"; - -const char* getEGLError(void) { - switch (eglGetError()) { - case EGL_SUCCESS: - return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT"; - case EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG"; - case EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY"; - case EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE"; - case EGL_BAD_MATCH: - return "EGL_BAD_MATCH"; - case EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER"; - case EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW"; - case EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST"; - default: - return "Unknown error"; - } -} - -// Given shader source, load and compile it -GLuint loadShader(GLenum type, const char* shaderSrc) { - // Create the shader object - GLuint shader = glCreateShader(type); - if (shader == 0) { - return 0; - } - - // Load and compile the shader - glShaderSource(shader, 1, &shaderSrc, nullptr); - glCompileShader(shader); - - // Verify the compilation worked as expected - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - LOG(ERROR) << "Error compiling shader"; - - GLint size = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); - if (size > 0) { - // Get and report the error message - char* infoLog = (char*)malloc(size); - glGetShaderInfoLog(shader, size, nullptr, infoLog); - LOG(ERROR) << " msg:" << std::endl << infoLog; - free(infoLog); - } - - glDeleteShader(shader); - return 0; - } - - return shader; -} - -// Create a program object given vertex and pixels shader source -GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc) { - GLuint program = glCreateProgram(); - if (program == 0) { - LOG(ERROR) << "Failed to allocate program object"; - return 0; - } - - // Compile the shaders and bind them to this program - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc); - if (vertexShader == 0) { - LOG(ERROR) << "Failed to load vertex shader"; - glDeleteProgram(program); - return 0; - } - GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc); - if (pixelShader == 0) { - LOG(ERROR) << "Failed to load pixel shader"; - glDeleteProgram(program); - glDeleteShader(vertexShader); - return 0; - } - glAttachShader(program, vertexShader); - glAttachShader(program, pixelShader); - - glBindAttribLocation(program, 0, "pos"); - glBindAttribLocation(program, 1, "tex"); - - // Link the program - glLinkProgram(program); - GLint linked = 0; - glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (!linked) { - LOG(ERROR) << "Error linking program"; - GLint size = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size); - if (size > 0) { - // Get and report the error message - char* infoLog = (char*)malloc(size); - glGetProgramInfoLog(program, size, nullptr, infoLog); - LOG(ERROR) << " msg: " << infoLog; - free(infoLog); - } - - glDeleteProgram(program); - glDeleteShader(vertexShader); - glDeleteShader(pixelShader); - return 0; - } - - return program; -} - -::android::sp convertNativeHandleToHGBP(const NativeHandle& aidlHandle) { - native_handle_t* handle = ::android::dupFromAidl(aidlHandle); - if (handle->numFds != 0 || handle->numInts < std::ceil(sizeof(size_t) / sizeof(int))) { - LOG(ERROR) << "Invalid native handle"; - return nullptr; - } - ::android::hardware::hidl_vec halToken; - halToken.setToExternal(reinterpret_cast(const_cast(&(handle->data[1]))), - handle->data[0]); - ::android::sp hgbp = - HGraphicBufferProducer::castFrom(::android::retrieveHalInterface(halToken)); - return std::move(hgbp); -} - -} // namespace - -namespace aidl::android::hardware::automotive::evs::implementation { - -// Main entry point -bool GlWrapper::initialize(const std::shared_ptr& pWindowProxy, - uint64_t displayId) { - LOG(DEBUG) << __FUNCTION__; - - if (!pWindowProxy) { - LOG(ERROR) << "Could not get ICarDisplayProxy."; - return false; - } - - DisplayDesc displayDesc; - auto status = pWindowProxy->getDisplayInfo(displayId, &displayDesc); - if (!status.isOk()) { - LOG(ERROR) << "Failed to read the display information"; - return false; - } - - mWidth = displayDesc.width; - mHeight = displayDesc.height; - if ((displayDesc.orientation != Rotation::ROTATION_0) && - (displayDesc.orientation != Rotation::ROTATION_180)) { - std::swap(mWidth, mHeight); - } - LOG(INFO) << "Display resolution is " << mWidth << "x" << mHeight; - - NativeHandle aidlHandle; - status = pWindowProxy->getHGraphicBufferProducer(displayId, &aidlHandle); - if (!status.isOk()) { - LOG(ERROR) << "Failed to get IGraphicBufferProducer from ICarDisplayProxy."; - return false; - } - - mGfxBufferProducer = convertNativeHandleToHGBP(aidlHandle); - if (!mGfxBufferProducer) { - LOG(ERROR) << "Failed to convert a NativeHandle to HGBP."; - return false; - } - - mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer); - if (mSurfaceHolder == nullptr) { - LOG(ERROR) << "Failed to get a Surface from HGBP."; - return false; - } - - mWindow = getNativeWindow(mSurfaceHolder.get()); - if (mWindow == nullptr) { - LOG(ERROR) << "Failed to get a native window from Surface."; - return false; - } - - // Set up our OpenGL ES context associated with the default display - mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (mDisplay == EGL_NO_DISPLAY) { - LOG(ERROR) << "Failed to get egl display"; - return false; - } - - EGLint major = 2; - EGLint minor = 0; - if (!eglInitialize(mDisplay, &major, &minor)) { - LOG(ERROR) << "Failed to initialize EGL: " << getEGLError(); - return false; - } - - const EGLint config_attribs[] = { - // clang-format off - // Tag Value - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_DEPTH_SIZE, 0, - EGL_NONE - // clang-format on - }; - - // Pick the default configuration without constraints (is this good enough?) - EGLConfig egl_config = {0}; - EGLint numConfigs = -1; - eglChooseConfig(mDisplay, config_attribs, &egl_config, 1, &numConfigs); - if (numConfigs != 1) { - LOG(ERROR) << "Didn't find a suitable format for our display window, " << getEGLError(); - return false; - } - - // Create the EGL render target surface - mSurface = eglCreateWindowSurface(mDisplay, egl_config, mWindow, nullptr); - if (mSurface == EGL_NO_SURFACE) { - LOG(ERROR) << "eglCreateWindowSurface failed, " << getEGLError(); - return false; - } - - // Create the EGL context - // NOTE: Our shader is (currently at least) written to require version 3, so this - // is required. - const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - mContext = eglCreateContext(mDisplay, egl_config, EGL_NO_CONTEXT, context_attribs); - if (mContext == EGL_NO_CONTEXT) { - LOG(ERROR) << "Failed to create OpenGL ES Context: " << getEGLError(); - return false; - } - - // Activate our render target for drawing - if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) { - LOG(ERROR) << "Failed to make the OpenGL ES Context current: " << getEGLError(); - return false; - } - - // Create the shader program for our simple pipeline - mShaderProgram = buildShaderProgram(vertexShaderSource, pixelShaderSource); - if (!mShaderProgram) { - LOG(ERROR) << "Failed to build shader program: " << getEGLError(); - return false; - } - - // Create a GL texture that will eventually wrap our externally created texture surface(s) - glGenTextures(1, &mTextureMap); - if (mTextureMap <= 0) { - LOG(ERROR) << "Didn't get a texture handle allocated: " << getEGLError(); - return false; - } - - // Turn off mip-mapping for the created texture surface - // (the inbound camera imagery doesn't have MIPs) - glBindTexture(GL_TEXTURE_2D, mTextureMap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - return true; -} - -void GlWrapper::shutdown() { - // Drop our device textures - if (mKHRimage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(mDisplay, mKHRimage); - mKHRimage = EGL_NO_IMAGE_KHR; - } - - // Release all GL resources - if (eglGetCurrentContext() == mContext) { - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - eglDestroySurface(mDisplay, mSurface); - eglDestroyContext(mDisplay, mContext); - eglTerminate(mDisplay); - mSurface = EGL_NO_SURFACE; - mContext = EGL_NO_CONTEXT; - mDisplay = EGL_NO_DISPLAY; - - // Release the window - mSurfaceHolder = nullptr; -} - -void GlWrapper::showWindow(const std::shared_ptr& pWindowProxy, uint64_t id) { - if (pWindowProxy) { - pWindowProxy->showWindow(id); - } else { - LOG(ERROR) << "ICarDisplayProxy is not available."; - } -} - -void GlWrapper::hideWindow(const std::shared_ptr& pWindowProxy, uint64_t id) { - if (pWindowProxy) { - pWindowProxy->hideWindow(id); - } else { - LOG(ERROR) << "ICarDisplayProxy is not available."; - } -} - -bool GlWrapper::updateImageTexture(buffer_handle_t handle, - const HardwareBufferDescription& description) { - if (mKHRimage != EGL_NO_IMAGE_KHR) { - return true; - } - - // Create a temporary GraphicBuffer to wrap the provided handle. - sp pGfxBuffer = - new GraphicBuffer(description.width, description.height, - static_cast<::android::PixelFormat>(description.format), - description.layers, static_cast(description.usage), - description.stride, const_cast(handle), - /* keepOwnership= */ false); - if (!pGfxBuffer) { - LOG(ERROR) << "Failed to allocate GraphicBuffer to wrap our native handle"; - return false; - } - - // Get a GL compatible reference to the graphics buffer we've been given - EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; - EGLClientBuffer cbuf = static_cast(pGfxBuffer->getNativeBuffer()); - mKHRimage = eglCreateImageKHR(mDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, - eglImageAttributes); - if (mKHRimage == EGL_NO_IMAGE_KHR) { - LOG(ERROR) << "Error creating EGLImage: " << getEGLError(); - return false; - } - - // Update the texture handle we already created to refer to this gralloc buffer - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTextureMap); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast(mKHRimage)); - - return true; -} - -void GlWrapper::renderImageToScreen() { - // Set the viewport - glViewport(0, 0, mWidth, mHeight); - - // Clear the color buffer - glClearColor(0.1f, 0.5f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - // Select our screen space simple texture shader - glUseProgram(mShaderProgram); - - // Bind the texture and assign it to the shader's sampler - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTextureMap); - GLint sampler = glGetUniformLocation(mShaderProgram, "tex"); - glUniform1i(sampler, 0); - - // We want our image to show up opaque regardless of alpha values - glDisable(GL_BLEND); - - // Draw a rectangle on the screen - GLfloat vertsCarPos[] = { - // clang-format off - -0.8, 0.8, 0.0f, // left top in window space - 0.8, 0.8, 0.0f, // right top - -0.8, -0.8, 0.0f, // left bottom - 0.8, -0.8, 0.0f // right bottom - // clang-format on - }; - - // NOTE: We didn't flip the image in the texture, so V=0 is actually the top of the image - GLfloat vertsCarTex[] = { - // clang-format off - 0.0f, 0.0f, // left top - 1.0f, 0.0f, // right top - 0.0f, 1.0f, // left bottom - 1.0f, 1.0f // right bottom - // clang-format on - }; - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertsCarPos); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertsCarTex); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - // Clean up and flip the rendered result to the front so it is visible - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - - glFinish(); - - if (eglSwapBuffers(mDisplay, mSurface) == EGL_FALSE) { - LOG(WARNING) << "Failed to swap EGL buffers, " << getEGLError(); - } -} - -} // namespace aidl::android::hardware::automotive::evs::implementation diff --git a/automotive/evs/aidl/impl/default/src/service.cpp b/automotive/evs/aidl/impl/default/src/service.cpp index 7532d8735f..0a0913fd3c 100644 --- a/automotive/evs/aidl/impl/default/src/service.cpp +++ b/automotive/evs/aidl/impl/default/src/service.cpp @@ -14,75 +14,38 @@ * limitations under the License. */ -#include "EvsEnumerator.h" -#include "EvsGlDisplay.h" +#define LOG_TAG "EvsService" + +#include #include #include #include -#include +using ::aidl::android::hardware::automotive::evs::implementation::DefaultEvsEnumerator; -#include -#include -#include +int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { + std::shared_ptr vhal = ndk::SharedRefBase::make(); -namespace { - -using ::aidl::android::frameworks::automotive::display::ICarDisplayProxy; -using ::aidl::android::hardware::automotive::evs::implementation::EvsEnumerator; - -constexpr std::string_view kDisplayServiceInstanceName = "/default"; -constexpr std::string_view kHwInstanceName = "/hw/0"; -constexpr int kNumBinderThreads = 1; - -} // namespace - -int main() { - LOG(INFO) << "EVS Hardware Enumerator service is starting"; - - const std::string displayServiceInstanceName = - std::string(ICarDisplayProxy::descriptor) + std::string(kDisplayServiceInstanceName); - if (!AServiceManager_isDeclared(displayServiceInstanceName.data())) { - // TODO: We may just want to disable EVS display. - LOG(ERROR) << displayServiceInstanceName << " is required."; - return EXIT_FAILURE; - } - - std::shared_ptr displayService = ICarDisplayProxy::fromBinder( - ::ndk::SpAIBinder(AServiceManager_waitForService(displayServiceInstanceName.data()))); - if (!displayService) { - LOG(ERROR) << "Cannot use " << displayServiceInstanceName << ". Exiting."; - return EXIT_FAILURE; - } - - // Register our service -- if somebody is already registered by our name, - // they will be killed (their thread pool will throw an exception). - std::shared_ptr service = - ndk::SharedRefBase::make(displayService); - if (!service) { - LOG(ERROR) << "Failed to instantiate the service"; - return EXIT_FAILURE; - } - - const std::string instanceName = - std::string(EvsEnumerator::descriptor) + std::string(kHwInstanceName); - auto err = AServiceManager_addService(service->asBinder().get(), instanceName.data()); + ALOGI("Registering as service..."); + binder_exception_t err = + AServiceManager_addService(vhal->asBinder().get(), "android.hardware.automotive.evs"); if (err != EX_NONE) { - LOG(ERROR) << "Failed to register " << instanceName << ", exception = " << err; - return EXIT_FAILURE; + ALOGE("failed to register android.hardware.automotive.evs service, exception: %d", err); + return 1; } - if (!ABinderProcess_setThreadPoolMaxThreadCount(kNumBinderThreads)) { - LOG(ERROR) << "Failed to set thread pool"; - return EXIT_FAILURE; + if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) { + ALOGE("%s", "failed to set thread pool max thread count"); + return 1; } - ABinderProcess_startThreadPool(); - LOG(INFO) << "EVS Hardware Enumerator is ready"; + + ALOGI("Evs Service Ready"); ABinderProcess_joinThreadPool(); - // In normal operation, we don't expect the thread pool to exit - LOG(INFO) << "EVS Hardware Enumerator is shutting down"; - return EXIT_SUCCESS; + + ALOGI("Evs Service Exiting"); + + return 0; }