Revert "Revert "Extend EVS interfaces and data types""
This reverts commit 1b73d28c04d250b581860dde082cf92c366371dc.
diff --git a/automotive/evs/1.1/default/Android.bp b/automotive/evs/1.1/default/Android.bp
index a463471..41cb426 100644
--- a/automotive/evs/1.1/default/Android.bp
+++ b/automotive/evs/1.1/default/Android.bp
@@ -7,25 +7,41 @@
"service.cpp",
"EvsCamera.cpp",
"EvsEnumerator.cpp",
- "EvsDisplay.cpp"
+ "EvsDisplay.cpp",
+ "ConfigManager.cpp",
+ "ConfigManagerUtil.cpp",
],
init_rc: ["android.hardware.automotive.evs@1.1-service.rc"],
shared_libs: [
"android.hardware.automotive.evs@1.0",
"android.hardware.automotive.evs@1.1",
+ "android.hardware.camera.device@3.2",
"libbase",
"libbinder",
- "libcutils",
+ "liblog",
"libhardware",
"libhidlbase",
"liblog",
"libui",
"libutils",
+ "libcamera_metadata",
+ "libtinyxml2",
],
cflags: [
"-O0",
"-g",
],
+
+ required: [
+ "evs_default_configuration.xml",
+ ],
+}
+
+prebuilt_etc {
+ name: "evs_default_configuration.xml",
+
+ src: "resources/evs_default_configuration.xml",
+ sub_dir: "automotive/evs",
}
diff --git a/automotive/evs/1.1/default/ConfigManager.cpp b/automotive/evs/1.1/default/ConfigManager.cpp
new file mode 100644
index 0000000..4f46f9d
--- /dev/null
+++ b/automotive/evs/1.1/default/ConfigManager.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2019 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 <sstream>
+#include <fstream>
+#include <thread>
+
+#include <hardware/gralloc.h>
+#include <utils/SystemClock.h>
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+
+#include "ConfigManager.h"
+
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+
+
+ConfigManager::~ConfigManager() {
+ /* Nothing to do */
+}
+
+
+void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
+ if (aCameraElem == nullptr) {
+ ALOGW("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 *group_id = curElem->FindAttribute("group_id")->Value();
+
+ /* create CameraGroup */
+ unique_ptr<ConfigManager::CameraGroup> aCameraGroup(new ConfigManager::CameraGroup());
+
+ /* add a camera device to its group */
+ addCameraDevices(curElem->FindAttribute("device_id")->Value(), aCameraGroup);
+
+ /* a list of camera stream configurations */
+ const XMLElement *childElem =
+ curElem->FirstChildElement("caps")->FirstChildElement("stream");
+ while (childElem != nullptr) {
+ /* read 5 attributes */
+ const XMLAttribute *idAttr = childElem->FindAttribute("id");
+ const XMLAttribute *widthAttr = childElem->FindAttribute("width");
+ const XMLAttribute *heightAttr = childElem->FindAttribute("height");
+ const XMLAttribute *fmtAttr = childElem->FindAttribute("format");
+ const XMLAttribute *fpsAttr = childElem->FindAttribute("framerate");
+
+ const int32_t id = stoi(idAttr->Value());
+ int32_t framerate = 0;
+ if (fpsAttr != nullptr) {
+ framerate = stoi(fpsAttr->Value());
+ }
+
+ int32_t pixFormat;
+ if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
+ pixFormat)) {
+ RawStreamConfiguration cfg = {
+ id,
+ stoi(widthAttr->Value()),
+ stoi(heightAttr->Value()),
+ pixFormat,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ framerate
+ };
+ aCameraGroup->streamConfigurations[id] = cfg;
+ }
+
+ childElem = childElem->NextSiblingElement("stream");
+ }
+
+ /* camera group synchronization */
+ const char *sync = curElem->FindAttribute("synchronized")->Value();
+ aCameraGroup->synchronized =
+ static_cast<bool>(strcmp(sync, "false"));
+
+ /* add a group to hash map */
+ mCameraGroups[group_id] = std::move(aCameraGroup);
+ } else if (!strcmp(curElem->Name(), "device")) {
+ /* camera unique identifier */
+ const char *id = curElem->FindAttribute("id")->Value();
+
+ /* camera mount location */
+ const char *pos = curElem->FindAttribute("position")->Value();
+
+ /* store read camera module information */
+ mCameraInfo[id] = readCameraDeviceInfo(curElem);
+
+ /* assign a camera device to a position group */
+ mCameraPosition[pos].emplace(id);
+ } else {
+ /* ignore other device types */
+ ALOGD("Unknown element %s is ignored", curElem->Name());
+ }
+
+ curElem = curElem->NextSiblingElement();
+ }
+}
+
+
+unique_ptr<ConfigManager::CameraInfo>
+ConfigManager::readCameraDeviceInfo(const XMLElement *aDeviceElem) {
+ if (aDeviceElem == nullptr) {
+ return nullptr;
+ }
+
+ /* create a CameraInfo to be filled */
+ unique_ptr<ConfigManager::CameraInfo> aCamera(new ConfigManager::CameraInfo());
+
+ /* 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)) {
+ ALOGW("Either failed to allocate memory or "
+ "allocated memory was not large enough");
+ }
+
+ return aCamera;
+}
+
+
+size_t ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
+ unique_ptr<ConfigManager::CameraInfo> &aCamera,
+ size_t &dataSize) {
+ if (aCapElem == nullptr) {
+ return 0;
+ }
+
+ 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();;
+ const int32_t minVal = stoi(ctrlElem->FindAttribute("min")->Value());
+ const int32_t maxVal = stoi(ctrlElem->FindAttribute("max")->Value());
+
+ int32_t stepVal = 1;
+ const XMLAttribute *stepAttr = ctrlElem->FindAttribute("step");
+ if (stepAttr != nullptr) {
+ stepVal = stoi(stepAttr->Value());
+ }
+
+ CameraParam aParam;
+ if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr,
+ aParam)) {
+ aCamera->controls.emplace(
+ aParam,
+ 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");
+
+ const int32_t id = stoi(idAttr->Value());
+ int32_t framerate = 0;
+ if (fpsAttr != nullptr) {
+ framerate = stoi(fpsAttr->Value());
+ }
+
+ int32_t pixFormat;
+ if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
+ pixFormat)) {
+ RawStreamConfiguration cfg = {
+ id,
+ stoi(widthAttr->Value()),
+ stoi(heightAttr->Value()),
+ pixFormat,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ framerate
+ };
+ aCamera->streamConfigurations[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() * kStreamCfgSz
+ );
+
+ /* a single camera metadata entry contains multiple stream configurations */
+ return dataSize > 0 ? 1 : 0;
+}
+
+
+size_t ConfigManager::readCameraMetadata(const XMLElement * const aParamElem,
+ unique_ptr<ConfigManager::CameraInfo> &aCamera,
+ size_t &dataSize) {
+ if (aParamElem == 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[tag] =
+ make_pair(make_unique<void *>(data), count);
+
+ ++numEntries;
+ dataSize += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(tag), count
+ );
+
+ break;
+ }
+
+ default:
+ ALOGW("Parameter %s is not supported",
+ curElem->FindAttribute("name")->Value());
+ break;
+ }
+ }
+
+ curElem = curElem->NextSiblingElement("parameter");
+ }
+
+ return numEntries;
+}
+
+
+bool ConfigManager::constructCameraMetadata(unique_ptr<CameraInfo> &aCamera,
+ const size_t totalEntries,
+ const size_t totalDataSize) {
+ if (!aCamera->allocate(totalEntries, totalDataSize)) {
+ ALOGE("Failed to allocate memory for camera metadata");
+ return false;
+ }
+
+ const size_t numStreamConfigs = aCamera->streamConfigurations.size();
+ unique_ptr<int32_t[]> data(new int32_t[kStreamCfgSz * numStreamConfigs]);
+ int32_t *ptr = data.get();
+ for (auto &cfg : aCamera->streamConfigurations) {
+ for (auto i = 0; i < kStreamCfgSz; ++i) {
+ *ptr++ = cfg.second[i];
+ }
+ }
+ int32_t err = add_camera_metadata_entry(aCamera->characteristics,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ data.get(),
+ numStreamConfigs * kStreamCfgSz);
+
+ if (err) {
+ ALOGE("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.get(),
+ entry.second);
+ if (err) {
+ ALOGE("Failed to add an entry with a tag 0x%X", tag);
+
+ /* may exceed preallocated capacity */
+ ALOGE("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
+ get_camera_metadata_entry_count(aCamera->characteristics),
+ get_camera_metadata_entry_capacity(aCamera->characteristics),
+ get_camera_metadata_data_count(aCamera->characteristics),
+ get_camera_metadata_data_capacity(aCamera->characteristics));
+ ALOGE("\tCurrent metadata entry requires %ld bytes",
+ calculate_camera_metadata_entry_data_size(tag, entry.second));
+
+ success = false;
+ }
+ }
+
+ ALOGV("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
+ get_camera_metadata_entry_count(aCamera->characteristics),
+ get_camera_metadata_entry_capacity(aCamera->characteristics),
+ get_camera_metadata_data_count(aCamera->characteristics),
+ get_camera_metadata_data_capacity(aCamera->characteristics));
+
+ 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) {
+ mSystemInfo.numCameras =
+ stoi(xmlElem->FindAttribute("value")->Value());
+ }
+}
+
+
+void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
+ if (aDisplayElem == nullptr) {
+ ALOGW("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();
+ //const char *pos = curDev->FirstAttribute("position")->Value();
+
+ unique_ptr<DisplayInfo> dpy(new DisplayInfo());
+ if (dpy == nullptr) {
+ ALOGE("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");
+
+ const int32_t id = stoi(idAttr->Value());
+ int32_t pixFormat;
+ if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
+ pixFormat)) {
+ RawStreamConfiguration cfg = {
+ id,
+ stoi(widthAttr->Value()),
+ stoi(heightAttr->Value()),
+ pixFormat,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
+ 0 // unused
+ };
+ dpy->streamConfigurations[id] = cfg;
+ }
+
+ curStream = curStream->NextSiblingElement("stream");
+ }
+ }
+
+ mDisplayInfo[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(mConfigFilePath);
+ if (xmlDoc.ErrorID() != XML_SUCCESS) {
+ ALOGE("Failed to load and/or parse a configuration file, %s", xmlDoc.ErrorStr());
+ return false;
+ }
+
+ /* retrieve the root element */
+ const XMLElement *rootElem = xmlDoc.RootElement();
+ if (strcmp(rootElem->Name(), "configuration")) {
+ ALOGE("A configuration file is not in the required format. "
+ "See /etc/automotive/evs/evs_configuration.dtd");
+ return false;
+ }
+
+ /*
+ * 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"));
+
+ const int64_t parsingEnd = android::elapsedRealtimeNano();
+ ALOGI("Parsing configuration file takes %lf (ms)",
+ (double)(parsingEnd - parsingStart) / 1000000.0);
+
+
+ return true;
+}
+
+
+void ConfigManager::addCameraDevices(const char *devices,
+ unique_ptr<CameraGroup> &aGroup) {
+ stringstream device_list(devices);
+ string token;
+ while (getline(device_list, token, ',')) {
+ aGroup->devices.emplace(token);
+ }
+}
+
+
+std::unique_ptr<ConfigManager> ConfigManager::Create(const char *path) {
+ unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
+
+ /*
+ * 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;
+ }
+}
+
diff --git a/automotive/evs/1.1/default/ConfigManager.h b/automotive/evs/1.1/default/ConfigManager.h
new file mode 100644
index 0000000..0275f90
--- /dev/null
+++ b/automotive/evs/1.1/default/ConfigManager.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2019 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 CONFIG_MANAGER_H
+#define CONFIG_MANAGER_H
+
+#include <vector>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <tinyxml2.h>
+
+#include <system/camera_metadata.h>
+#include <log/log.h>
+#include <android/hardware/automotive/evs/1.1/types.h>
+
+#include "ConfigManagerUtil.h"
+
+using namespace std;
+using namespace tinyxml2;
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::camera::device::V3_2::Stream;
+using ::android::hardware::automotive::evs::V1_1::CameraParam;
+
+/*
+ * Plese 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.
+ */
+const size_t kStreamCfgSz = 6;
+typedef std::array<int32_t, kStreamCfgSz> RawStreamConfiguration;
+
+class ConfigManager {
+public:
+ static std::unique_ptr<ConfigManager> Create(const char *path = "");
+ ConfigManager(const ConfigManager&) = delete;
+ ConfigManager& operator=(const ConfigManager&) = delete;
+
+ virtual ~ConfigManager();
+
+ /* Camera device's capabilities and metadata */
+ class CameraInfo {
+ public:
+ CameraInfo() :
+ characteristics(nullptr) {
+ /* Nothing to do */
+ }
+
+ virtual ~CameraInfo() {
+ free_camera_metadata(characteristics);
+ }
+
+ /* Allocate memory for camera_metadata_t */
+ bool allocate(size_t entry_cap, size_t data_cap) {
+ if (characteristics != nullptr) {
+ ALOGE("Camera metadata is already allocated");
+ return false;
+ }
+
+ characteristics = allocate_camera_metadata(entry_cap, data_cap);
+ return characteristics != nullptr;
+ }
+
+ /*
+ * List of supported controls that the master client can program.
+ * Paraemters are stored with its valid range
+ */
+ unordered_map<CameraParam,
+ tuple<int32_t, int32_t, int32_t>> controls;
+
+ /* List of supported frame rates */
+ unordered_set<int32_t> frameRates;
+
+ /*
+ * List of supported output stream configurations; each array stores
+ * format, width, height, and direction values in the order.
+ */
+ unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
+
+ /*
+ * Internal storage for camera metadata. Each entry holds a pointer to
+ * data and number of elements
+ */
+ unordered_map<camera_metadata_tag_t,
+ pair<unique_ptr<void *>, size_t>> cameraMetadata;
+
+ /* Camera module characteristics */
+ camera_metadata_t *characteristics;
+ };
+
+ class CameraGroup {
+ public:
+ CameraGroup() {}
+
+ /* ID of member camera devices */
+ unordered_set<string> devices;
+
+ /* The capture operation of member camera devices are synchronized */
+ bool synchronized = false;
+
+ /*
+ * List of stream configurations that are supposed by all camera devices
+ * in this group.
+ */
+ unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
+ };
+
+ class SystemInfo {
+ public:
+ /* number of available cameras */
+ int32_t numCameras = 0;
+ };
+
+ class DisplayInfo {
+ public:
+ /*
+ * List of supported input stream configurations; each array stores
+ * format, width, height, and direction values in the order.
+ */
+ unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
+ };
+
+ /*
+ * Return system information
+ *
+ * @return SystemInfo
+ * Constant reference of SystemInfo.
+ */
+ const SystemInfo &getSystemInfo() {
+ return mSystemInfo;
+ }
+
+ /*
+ * Return a list of cameras
+ *
+ * This function assumes that it is not being called frequently.
+ *
+ * @return vector<string>
+ * A vector that contains unique camera device identifiers.
+ */
+ vector<string> getCameraList() {
+ vector<string> aList;
+ for (auto &v : mCameraInfo) {
+ aList.emplace_back(v.first);
+ }
+
+ return aList;
+ }
+
+
+ /*
+ * Return a list of cameras
+ *
+ * @return CameraGroup
+ * A pointer to a camera group identified by a given id.
+ */
+ unique_ptr<CameraGroup>& getCameraGroup(const string& gid) {
+ return mCameraGroups[gid];
+ }
+
+
+ /*
+ * Return a camera metadata
+ *
+ * @param cameraId
+ * Unique camera node identifier in string
+ *
+ * @return unique_ptr<CameraInfo>
+ * 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.
+ */
+ unique_ptr<CameraInfo>& getCameraInfo(const string cameraId) noexcept {
+ return mCameraInfo[cameraId];
+ }
+
+private:
+ /* Constructors */
+ ConfigManager(const char *xmlPath) :
+ mConfigFilePath(xmlPath) {
+ }
+
+ /* System configuration */
+ SystemInfo mSystemInfo;
+
+ /* Internal data structure for camera device information */
+ unordered_map<string, unique_ptr<CameraInfo>> mCameraInfo;
+
+ /* Internal data structure for camera device information */
+ unordered_map<string, unique_ptr<DisplayInfo>> mDisplayInfo;
+
+ /* Camera groups are stored in <groud id, CameraGroup> hash map */
+ unordered_map<string, unique_ptr<CameraGroup>> mCameraGroups;
+
+ /*
+ * Camera positions are stored in <position, camera id set> hash map.
+ * The position must be one of front, rear, left, and right.
+ */
+ unordered_map<string, unordered_set<string>> mCameraPosition;
+
+ /* A path to XML configuration file */
+ const char *mConfigFilePath;
+
+ /*
+ * 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 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 XMLElement * const aCameraElem);
+
+ /*
+ * read display device information
+ *
+ * @param aDisplayElem
+ * A pointer to "display" XML element that may contain multiple
+ * "device" elements.
+ */
+ void readDisplayInfo(const XMLElement * const aDisplayElem);
+
+ /*
+ * read camera device information
+ *
+ * @param aDeviceElem
+ * A pointer to "device" XML element that contains camera module
+ * capability info and its characteristics.
+ *
+ * @return unique_ptr<CameraInfo>
+ * A pointer to CameraInfo class that contains camera module
+ * capability and characteristics. Please note that this transfers
+ * the ownership of created CameraInfo to the caller.
+ */
+ unique_ptr<CameraInfo> readCameraDeviceInfo(const 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 XMLElement * const aCapElem,
+ unique_ptr<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 XMLElement * const aParamElem,
+ unique_ptr<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(unique_ptr<CameraInfo> &aCamera,
+ const size_t totalEntries,
+ const size_t totalDataSize);
+
+ /*
+ * parse a comma-separated list of camera devices and add them to
+ * CameraGroup.
+ *
+ * @param devices
+ * A comma-separated list of camera device identifiers.
+ * @param aGroup
+ * Camera group which cameras will be added to.
+ */
+ void addCameraDevices(const char *devices,
+ unique_ptr<CameraGroup> &aGroup);
+};
+#endif // CONFIG_MANAGER_H
+
diff --git a/automotive/evs/1.1/default/ConfigManagerUtil.cpp b/automotive/evs/1.1/default/ConfigManagerUtil.cpp
new file mode 100644
index 0000000..8206daa
--- /dev/null
+++ b/automotive/evs/1.1/default/ConfigManagerUtil.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 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 <string>
+#include <sstream>
+#include <linux/videodev2.h>
+
+#include <log/log.h>
+#include <system/graphics-base-v1.0.h>
+
+
+bool ConfigManagerUtil::convertToEvsCameraParam(const string &id,
+ CameraParam &camParam) {
+ 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 string &format,
+ int32_t &pixFormat) {
+ string trimmed = ConfigManagerUtil::trimString(format);
+ bool success = true;
+
+ if (!trimmed.compare("RGBA_8888")) {
+ pixFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ } else if (!trimmed.compare("YCRCB_420_SP")) {
+ pixFormat = HAL_PIXEL_FORMAT_YCRCB_420_SP;
+ } else if (!trimmed.compare("YCBCR_422_I")) {
+ pixFormat = HAL_PIXEL_FORMAT_YCBCR_422_I;
+ } else {
+ success = false;
+ }
+
+ return success;
+}
+
+
+bool ConfigManagerUtil::convertToMetadataTag(const char *name,
+ camera_metadata_tag &aTag) {
+ if (!strcmp(name, "LENS_DISTORTION")) {
+ aTag = ANDROID_LENS_DISTORTION;
+ } else if (!strcmp(name, "LENS_INTRINSIC_CALIBRATION")) {
+ aTag = ANDROID_LENS_INTRINSIC_CALIBRATION;
+ } else if (!strcmp(name, "LENS_POSE_ROTATION")) {
+ aTag = ANDROID_LENS_POSE_ROTATION;
+ } else if (!strcmp(name, "LENS_POSE_TRANSLATION")) {
+ aTag = ANDROID_LENS_POSE_TRANSLATION;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+
+float *ConfigManagerUtil::convertFloatArray(const char *sz, const char *vals,
+ size_t &count, const char delimiter) {
+ string size_string(sz);
+ string value_string(vals);
+
+ count = stoi(size_string);
+ float *result = new float[count];
+ stringstream values(value_string);
+
+ int32_t idx = 0;
+ string token;
+ while (getline(values, token, delimiter)) {
+ result[idx++] = stof(token);
+ }
+
+ return result;
+}
+
+
+string ConfigManagerUtil::trimString(const string &src, const string &ws) {
+ const auto s = src.find_first_not_of(ws);
+ if (s == 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/1.1/default/ConfigManagerUtil.h b/automotive/evs/1.1/default/ConfigManagerUtil.h
new file mode 100644
index 0000000..8c89ae7
--- /dev/null
+++ b/automotive/evs/1.1/default/ConfigManagerUtil.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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 CONFIG_MANAGER_UTIL_H
+#define CONFIG_MANAGER_UTIL_H
+
+#include <utility>
+#include <string>
+#include <system/camera_metadata.h>
+#include <android/hardware/automotive/evs/1.1/types.h>
+
+using namespace std;
+using ::android::hardware::automotive::evs::V1_1::CameraParam;
+
+
+class ConfigManagerUtil {
+public:
+ /**
+ * Convert a given string into V4L2_CID_*
+ */
+ static bool convertToEvsCameraParam(const string &id,
+ CameraParam &camParam);
+ /**
+ * Convert a given string into android.hardware.graphics.common.PixelFormat
+ */
+ static bool convertToPixelFormat(const string &format,
+ int32_t &pixelFormat);
+ /**
+ * Convert a given string into corresponding camera metadata data tag defined in
+ * system/media/camera/include/system/camera_metadta_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 string trimString(const string &src,
+ const string &ws = " \n\r\t\f\v");
+};
+
+#endif // CONFIG_MANAGER_UTIL_H
+
diff --git a/automotive/evs/1.1/default/EvsCamera.cpp b/automotive/evs/1.1/default/EvsCamera.cpp
index 2d55566..5ba753d 100644
--- a/automotive/evs/1.1/default/EvsCamera.cpp
+++ b/automotive/evs/1.1/default/EvsCamera.cpp
@@ -40,28 +40,21 @@
const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
-EvsCamera::EvsCamera(const char *id) :
+EvsCamera::EvsCamera(const char *id,
+ unique_ptr<ConfigManager::CameraInfo> &camInfo) :
mFramesAllowed(0),
mFramesInUse(0),
- mStreamState(STOPPED) {
+ mStreamState(STOPPED),
+ mCameraInfo(camInfo) {
ALOGD("EvsCamera instantiated");
- mDescription.cameraId = id;
+ /* set a camera id */
+ mDescription.v1.cameraId = id;
- // Set up dummy data for testing
- if (mDescription.cameraId == kCameraName_Backup) {
- mWidth = 640; // full NTSC/VGA
- mHeight = 480; // full NTSC/VGA
- mDescription.vendorFlags = 0xFFFFFFFF; // Arbitrary value
- } else {
- mWidth = 320; // 1/2 NTSC/VGA
- mHeight = 240; // 1/2 NTSC/VGA
- }
-
- mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
- mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
- GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
+ /* set camera metadata */
+ mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
+ get_camera_metadata_size(camInfo->characteristics));
}
@@ -109,7 +102,7 @@
ALOGD("getCameraInfo");
// Send back our self description
- _hidl_cb(mDescription);
+ _hidl_cb(mDescription.v1);
return Void();
}
@@ -194,7 +187,7 @@
// 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
- ALOGD("Waiting for stream thread to end..");
+ ALOGD("Waiting for stream thread to end...");
lock.unlock();
mCaptureThread.join();
lock.lock();
@@ -238,6 +231,15 @@
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
+Return<void> EvsCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
+ ALOGD("getCameraInfo_1_1");
+
+ // Send back our self description
+ _hidl_cb(mDescription);
+ return Void();
+}
+
+
Return<EvsResult> EvsCamera::doneWithFrame_1_1(const BufferDesc_1_1& bufDesc) {
std::lock_guard <std::mutex> lock(mAccessLock);
returnBuffer(bufDesc.bufferId, bufDesc.buffer.nativeHandle);
@@ -278,8 +280,29 @@
}
-Return<void> EvsCamera::setParameter(CameraParam id, int32_t value,
- setParameter_cb _hidl_cb) {
+Return<void> EvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
+ hidl_vec<CameraParam> hidlCtrls;
+ hidlCtrls.resize(mCameraInfo->controls.size());
+ unsigned idx = 0;
+ for (auto& [cid, cfg] : mCameraInfo->controls) {
+ hidlCtrls[idx++] = cid;
+ }
+
+ _hidl_cb(hidlCtrls);
+ return Void();
+}
+
+
+Return<void> EvsCamera::getIntParameterRange(CameraParam id,
+ getIntParameterRange_cb _hidl_cb) {
+ auto range = mCameraInfo->controls[id];
+ _hidl_cb(get<0>(range), get<1>(range), get<2>(range));
+ return Void();
+}
+
+
+Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
+ setIntParameter_cb _hidl_cb) {
// Default implementation does not support this.
(void)id;
(void)value;
@@ -288,7 +311,8 @@
}
-Return<void> EvsCamera::getParameter(CameraParam id, getParameter_cb _hidl_cb) {
+Return<void> EvsCamera::getIntParameter(CameraParam id,
+ getIntParameter_cb _hidl_cb) {
// Default implementation does not support this.
(void)id;
_hidl_cb(EvsResult::INVALID_ARG, 0);
@@ -471,9 +495,7 @@
fillTestFrame(newBuffer);
// Issue the (asynchronous) callback to the client -- can't be holding the lock
- EvsEvent event;
- event.buffer(newBuffer);
- auto result = mStream->notifyEvent(event);
+ auto result = mStream->deliverFrame_1_1(newBuffer);
if (result.isOk()) {
ALOGD("Delivered %p as id %d",
newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
@@ -506,10 +528,8 @@
// If we've been asked to stop, send an event to signal the actual end of stream
EvsEvent event;
- InfoEventDesc desc = {};
- desc.aType = InfoEventType::STREAM_STOPPED;
- event.info(desc);
- auto result = mStream->notifyEvent(event);
+ event.aType = EvsEventType::STREAM_STOPPED;
+ auto result = mStream->notify(event);
if (!result.isOk()) {
ALOGE("Error delivering end of stream marker");
}
@@ -616,6 +636,38 @@
}
+sp<EvsCamera> EvsCamera::Create(const char *deviceName) {
+ unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
+
+ return Create(deviceName, nullCamInfo);
+}
+
+
+sp<EvsCamera> EvsCamera::Create(const char *deviceName,
+ unique_ptr<ConfigManager::CameraInfo> &camInfo,
+ const Stream *streamCfg) {
+ sp<EvsCamera> evsCamera = new EvsCamera(deviceName, camInfo);
+ if (evsCamera == nullptr) {
+ return nullptr;
+ }
+
+ /* default implementation does not use a given configuration */
+ (void)streamCfg;
+
+ /* Use the first resolution from the list for the testing */
+ auto it = camInfo->streamConfigurations.begin();
+ evsCamera->mWidth = it->second[1];
+ evsCamera->mHeight = it->second[2];
+ evsCamera->mDescription.v1.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
+
+ evsCamera->mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ evsCamera->mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
+ GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
+
+ return evsCamera;
+}
+
+
} // namespace implementation
} // namespace V1_0
} // namespace evs
diff --git a/automotive/evs/1.1/default/EvsCamera.h b/automotive/evs/1.1/default/EvsCamera.h
index 47a3164..c15b4b1 100644
--- a/automotive/evs/1.1/default/EvsCamera.h
+++ b/automotive/evs/1.1/default/EvsCamera.h
@@ -25,6 +25,8 @@
#include <thread>
+#include "ConfigManager.h"
+
using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
using IEvsCameraStream_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
@@ -59,18 +61,28 @@
Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) override;
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
+ Return<void> getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) override;
Return<EvsResult> pauseVideoStream() override;
Return<EvsResult> resumeVideoStream() override;
Return<EvsResult> doneWithFrame_1_1(const BufferDesc_1_1& buffer) override;
Return<EvsResult> setMaster() override;
Return<EvsResult> forceMaster(const sp<IEvsDisplay>& display) override;
Return<EvsResult> unsetMaster() override;
- Return<void> setParameter(CameraParam id, int32_t value,
- setParameter_cb _hidl_cb) override;
- Return<void> getParameter(CameraParam id, getParameter_cb _hidl_cb) override;
+ Return<void> getParameterList(getParameterList_cb _hidl_cb) override;
+ Return<void> getIntParameterRange(CameraParam id,
+ getIntParameterRange_cb _hidl_cb) override;
+ Return<void> setIntParameter(CameraParam id, int32_t value,
+ setIntParameter_cb _hidl_cb) override;
+ Return<void> getIntParameter(CameraParam id,
+ getIntParameter_cb _hidl_cb) override;
- // Implementation details
- EvsCamera(const char *id);
+ static sp<EvsCamera> Create(const char *deviceName);
+ static sp<EvsCamera> Create(const char *deviceName,
+ unique_ptr<ConfigManager::CameraInfo> &camInfo,
+ const Stream *streamCfg = nullptr);
+ EvsCamera(const EvsCamera&) = delete;
+ EvsCamera& operator=(const EvsCamera&) = delete;
+
virtual ~EvsCamera() override;
void forceShutdown(); // This gets called if another caller "steals" ownership of the camera
@@ -79,7 +91,10 @@
static const char kCameraName_Backup[];
private:
+ EvsCamera(const char *id,
+ unique_ptr<ConfigManager::CameraInfo> &camInfo);
// 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);
@@ -124,6 +139,9 @@
// Synchronization necessary to deconflict mCaptureThread from the main service thread
std::mutex mAccessLock;
+
+ // Static camera module information
+ unique_ptr<ConfigManager::CameraInfo> &mCameraInfo;
};
} // namespace implementation
diff --git a/automotive/evs/1.1/default/EvsEnumerator.cpp b/automotive/evs/1.1/default/EvsEnumerator.cpp
index b324907..a010729 100644
--- a/automotive/evs/1.1/default/EvsEnumerator.cpp
+++ b/automotive/evs/1.1/default/EvsEnumerator.cpp
@@ -33,6 +33,7 @@
// constructs a new instance for each client.
std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
+unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
EvsEnumerator::EvsEnumerator() {
@@ -40,9 +41,11 @@
// Add sample camera data to our list of cameras
// In a real driver, this would be expected to can the available hardware
- sCameraList.emplace_back(EvsCamera::kCameraName_Backup);
- sCameraList.emplace_back("LaneView");
- sCameraList.emplace_back("right turn");
+ sConfigManager =
+ ConfigManager::Create("/etc/automotive/evs/evs_sample_configuration.xml");
+ for (auto v : sConfigManager->getCameraList()) {
+ sCameraList.emplace_back(v.c_str());
+ }
}
@@ -57,7 +60,7 @@
std::vector<CameraDesc_1_0> descriptions;
descriptions.reserve(numCameras);
for (const auto& cam : sCameraList) {
- descriptions.push_back( cam.desc );
+ descriptions.push_back( cam.desc.v1 );
}
// Encapsulate our camera descriptions in the HIDL vec type
@@ -78,7 +81,7 @@
// Find the named camera
CameraRecord *pRecord = nullptr;
for (auto &&cam : sCameraList) {
- if (cam.desc.cameraId == cameraId) {
+ if (cam.desc.v1.cameraId == cameraId) {
// Found a match!
pRecord = &cam;
break;
@@ -99,7 +102,12 @@
}
// Construct a camera instance for the caller
- pActiveCamera = new EvsCamera(cameraId.c_str());
+ if (sConfigManager == nullptr) {
+ pActiveCamera = EvsCamera::Create(cameraId.c_str());
+ } else {
+ pActiveCamera = EvsCamera::Create(cameraId.c_str(),
+ sConfigManager->getCameraInfo(cameraId));
+ }
pRecord->activeInstance = pActiveCamera;
if (pActiveCamera == nullptr) {
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
@@ -120,15 +128,15 @@
// Get the camera id so we can find it in our list
std::string cameraId;
- pCamera_1_1->getCameraInfo([&cameraId](CameraDesc desc) {
- cameraId = desc.cameraId;
+ pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
+ cameraId = desc.v1.cameraId;
}
);
// Find the named camera
CameraRecord *pRecord = nullptr;
for (auto &&cam : sCameraList) {
- if (cam.desc.cameraId == cameraId) {
+ if (cam.desc.v1.cameraId == cameraId) {
// Found a match!
pRecord = &cam;
break;
@@ -209,6 +217,89 @@
}
+// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
+Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) {
+ ALOGD("getCameraList");
+
+ const unsigned numCameras = sCameraList.size();
+
+ // Build up a packed array of CameraDesc for return
+ // NOTE: Only has to live until the callback returns
+ std::vector<CameraDesc_1_1> descriptions;
+ descriptions.reserve(numCameras);
+ for (const auto& cam : sCameraList) {
+ descriptions.push_back( cam.desc );
+ }
+
+ // Encapsulate our camera descriptions in the HIDL vec type
+ hidl_vec<CameraDesc_1_1> hidlCameras(descriptions);
+
+ // Send back the results
+ ALOGD("reporting %zu cameras available", hidlCameras.size());
+ _hidl_cb(hidlCameras);
+
+ // HIDL convention says we return Void if we sent our result back via callback
+ return Void();
+}
+
+Return<sp<IEvsCamera_1_1>>
+EvsEnumerator::openCamera_1_1(const hidl_string& cameraId,
+ const Stream& streamCfg) {
+ // Find the named camera
+ CameraRecord *pRecord = nullptr;
+ for (auto &&cam : sCameraList) {
+ if (cam.desc.v1.cameraId == cameraId) {
+ // Found a match!
+ pRecord = &cam;
+ break;
+ }
+ }
+
+ // Is this a recognized camera id?
+ if (!pRecord) {
+ ALOGE("Requested camera %s not found", cameraId.c_str());
+ return nullptr;
+ }
+
+ // Has this camera already been instantiated by another caller?
+ sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
+ if (pActiveCamera != nullptr) {
+ ALOGW("Killing previous camera because of new caller");
+ closeCamera(pActiveCamera);
+ }
+
+ // Construct a camera instance for the caller
+ if (sConfigManager == nullptr) {
+ pActiveCamera = EvsCamera::Create(cameraId.c_str());
+ } else {
+ pActiveCamera = EvsCamera::Create(cameraId.c_str(),
+ sConfigManager->getCameraInfo(cameraId),
+ &streamCfg);
+ }
+
+ pRecord->activeInstance = pActiveCamera;
+ if (pActiveCamera == nullptr) {
+ ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
+ }
+
+ return pActiveCamera;
+}
+
+
+EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
+ // Find the named camera
+ CameraRecord *pRecord = nullptr;
+ for (auto &&cam : sCameraList) {
+ if (cam.desc.v1.cameraId == cameraId) {
+ // Found a match!
+ pRecord = &cam;
+ break;
+ }
+ }
+
+ return pRecord;
+}
+
} // namespace implementation
} // namespace V1_1
} // namespace evs
diff --git a/automotive/evs/1.1/default/EvsEnumerator.h b/automotive/evs/1.1/default/EvsEnumerator.h
index 11c2170..475ec76 100644
--- a/automotive/evs/1.1/default/EvsEnumerator.h
+++ b/automotive/evs/1.1/default/EvsEnumerator.h
@@ -17,18 +17,20 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
-#include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
+#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
#include <list>
+#include "ConfigManager.h"
+
using ::android::hardware::automotive::evs::V1_0::EvsResult;
using ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
using ::android::hardware::automotive::evs::V1_0::DisplayState;
-using ::android::hardware::automotive::evs::V1_0::IEvsEnumerator;
using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
using CameraDesc_1_0 = ::android::hardware::automotive::evs::V1_0::CameraDesc;
+using CameraDesc_1_1 = ::android::hardware::automotive::evs::V1_1::CameraDesc;
namespace android {
@@ -53,6 +55,11 @@
Return<void> closeDisplay(const ::android::sp<IEvsDisplay>& display) override;
Return<DisplayState> getDisplayState() override;
+ // Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
+ Return<void> getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) override;
+ Return<sp<IEvsCamera_1_1>> openCamera_1_1(const hidl_string& cameraId,
+ const Stream& streamCfg) override;
+
// Implementation details
EvsEnumerator();
@@ -61,14 +68,20 @@
// That is to say, this is effectively a singleton despite the fact that HIDL
// constructs a new instance for each client.
struct CameraRecord {
- CameraDesc_1_0 desc;
+ CameraDesc_1_1 desc;
wp<EvsCamera> activeInstance;
- CameraRecord(const char *cameraId) : desc() { desc.cameraId = cameraId; }
+ CameraRecord(const char *cameraId) : desc() { desc.v1.cameraId = cameraId; }
};
- static std::list<CameraRecord> sCameraList;
- static wp<EvsDisplay> sActiveDisplay; // Weak pointer. Object destructs if client dies.
+ static CameraRecord* findCameraById(const std::string& cameraId);
+
+ static std::list<CameraRecord> sCameraList;
+
+ // Weak pointer. Object destructs if client dies.
+ static wp<EvsDisplay> sActiveDisplay;
+
+ static unique_ptr<ConfigManager> sConfigManager;
};
} // namespace implementation
diff --git a/automotive/evs/1.1/default/resources/evs_default_configuration.xml b/automotive/evs/1.1/default/resources/evs_default_configuration.xml
new file mode 100644
index 0000000..692102e
--- /dev/null
+++ b/automotive/evs/1.1/default/resources/evs_default_configuration.xml
@@ -0,0 +1,68 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<!-- Exterior View System Example Configuration
+
+ Android Automotive axes are used to define coordinates.
+ See https://source.android.com/devices/sensors/sensor-types#auto_axes
+
+ Use evs_configuration.dtd with xmllint tool, to validate XML configuration file
+-->
+
+<configuration>
+ <!-- system configuration -->
+ <system>
+ <!-- number of cameras available to EVS -->
+ <num_cameras value='1'/>
+ </system>
+
+ <!-- camera device information -->
+ <camera>
+ <!-- camera device starts -->
+ <device id='/dev/video1' position='rear'>
+ <caps>
+ <!-- list of supported controls -->
+ <supported_controls>
+ <control name='BRIGHTNESS' min='0' max='255'/>
+ <control name='CONTRAST' min='0' max='255'/>
+ </supported_controls>
+
+ <stream id='0' width='640' height='360' format='RGBA_8888' framerate='30'/>
+ </caps>
+
+ <!-- list of parameters -->
+ <characteristics>
+ <!-- Camera intrinsic calibration matrix. See
+ https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_INTRINSIC_CALIBRATION
+ -->
+ <parameter
+ name='LENS_INTRINSIC_CALIBRATION'
+ type='float'
+ size='5'
+ value='0.0,0.0,0.0,0.0,0.0'
+ />
+ </characteristics>
+ </device>
+ </camera>
+ <display>
+ <device id='display0' position='driver'>
+ <caps>
+ <!-- list of supported inpu stream configurations -->
+ <stream id='0' width='1280' height='720' format='RGBA_8888' framerate='30'/>
+ </caps>
+ </device>
+ </display>
+</configuration>
+
diff --git a/automotive/evs/1.1/default/service.cpp b/automotive/evs/1.1/default/service.cpp
index 128a14a..5135864 100644
--- a/automotive/evs/1.1/default/service.cpp
+++ b/automotive/evs/1.1/default/service.cpp
@@ -33,7 +33,7 @@
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
-using android::hardware::automotive::evs::V1_0::IEvsEnumerator;
+using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
using android::hardware::automotive::evs::V1_0::IEvsDisplay;
// The namespace in which all our implementation code lives