Merge "Revert "Extend EVS interfaces and data types""

This commit is contained in:
Changyeon Jo 2019-10-11 17:32:01 +00:00 committed by Android (Google) Code Review
commit 851a9ce685
20 changed files with 413 additions and 2229 deletions

View file

@ -10,15 +10,13 @@ hidl_interface {
"types.hal",
"IEvsCamera.hal",
"IEvsCameraStream.hal",
"IEvsEnumerator.hal",
],
interfaces: [
"android.hardware.automotive.evs@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
"android.hidl.base@1.0",
],
gen_java: false,
gen_java: true,
}

View file

@ -25,14 +25,6 @@ import IEvsCameraStream;
* Represents a single camera and is the primary interface for capturing images.
*/
interface IEvsCamera extends @1.0::IEvsCamera {
/**
* Returns the description of this camera.
*
* @return info The description of this camera. This must be the same value as
* reported by EvsEnumerator::getCameraList_1_1().
*/
getCameraInfo_1_1() generates (CameraDesc info);
/**
* Requests to pause EVS camera stream events.
*
@ -108,27 +100,7 @@ interface IEvsCamera extends @1.0::IEvsCamera {
unsetMaster() generates (EvsResult result);
/**
* Retrieves a list of parameters this camera supports.
*
* @return params A list of CameraParam that this camera supports.
*/
getParameterList() generates (vec<CameraParam> params);
/**
* Requests a valid value range of a camera parameter
*
* @param id The identifier of camera parameter, CameraParam enum.
*
* @return min The lower bound of valid parameter value range.
* @return max The upper bound of valid parameter value range.
* @return step The resolution of values in valid range.
*/
getIntParameterRange(CameraParam id)
generates (int32_t min, int32_t max, int32_t step);
/**
* Requests to set a camera parameter. Only a request from the master
* client will be processed successfully.
* Requests to set a camera parameter.
*
* @param id The identifier of camera parameter, CameraParam enum.
* value A desired parameter value.
@ -142,7 +114,7 @@ interface IEvsCamera extends @1.0::IEvsCamera {
* from what the client gives if, for example, the
* driver does not support a target parameter.
*/
setIntParameter(CameraParam id, int32_t value)
setParameter(CameraParam id, int32_t value)
generates (EvsResult result, int32_t effectiveValue);
/**
@ -154,5 +126,5 @@ interface IEvsCamera extends @1.0::IEvsCamera {
* not supported.
* value A value of requested camera parameter.
*/
getIntParameter(CameraParam id) generates(EvsResult result, int32_t value);
getParameter(CameraParam id) generates(EvsResult result, int32_t value);
};

View file

@ -17,32 +17,15 @@
package android.hardware.automotive.evs@1.1;
import @1.0::IEvsCameraStream;
import @1.1::BufferDesc;
import @1.1::EvsEvent;
/**
* Implemented on client side to receive asynchronous streaming event deliveries.
*/
interface IEvsCameraStream extends @1.0::IEvsCameraStream {
/**
* Receives calls from the HAL each time a video frame is ready for inspection.
* Buffer handles received by this method must be returned via calls to
* IEvsCamera::doneWithFrame_1_1(). When the video stream is stopped via a call
* to IEvsCamera::stopVideoStream(), this callback may continue to happen for
* some time as the pipeline drains. Each frame must still be returned.
* When the last frame in the stream has been delivered, STREAM_STOPPED
* event must be delivered. No further frame deliveries may happen
* thereafter.
*
* @param buffer a buffer descriptor of a delivered image frame.
*/
oneway deliverFrame_1_1(BufferDesc buffer);
/**
* Receives calls from the HAL each time an event happens.
*
* @param event EVS event with possible event information.
*/
oneway notify(EvsEvent event);
oneway notifyEvent(EvsEvent event);
};

View file

@ -1,50 +0,0 @@
/*
* 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.
*/
package android.hardware.automotive.evs@1.1;
import IEvsCamera;
import @1.0::IEvsEnumerator;
import @1.0::EvsResult;
import android.hardware.camera.device@3.2::Stream;
/**
* Provides the mechanism for EVS camera discovery
*/
interface IEvsEnumerator extends @1.0::IEvsEnumerator {
/**
* Returns a list of all EVS cameras available to the system
*
* @return cameras A list of cameras availale for EVS service.
*/
getCameraList_1_1() generates (vec<CameraDesc> cameras);
/**
* Gets the IEvsCamera associated with a cameraId from a CameraDesc
*
* Given a camera's unique cameraId from CameraDesc, returns the
* IEvsCamera interface associated with the specified camera. When
* done using the camera, the caller may release it by calling closeCamera().
*
* @param cameraId A unique identifier of the camera.
* @param streamCfg A stream configuration the client wants to use.
* @return evsCamera EvsCamera object associated with a given cameraId.
* Returned object would be null if a camera device does
* not support a given stream configuration or is already
* configured differently by another client.
*/
openCamera_1_1(string cameraId, Stream streamCfg) generates (IEvsCamera evsCamera);
};

View file

@ -7,41 +7,25 @@ cc_binary {
"service.cpp",
"EvsCamera.cpp",
"EvsEnumerator.cpp",
"EvsDisplay.cpp",
"ConfigManager.cpp",
"ConfigManagerUtil.cpp",
"EvsDisplay.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",
"liblog",
"libcutils",
"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",
}

View file

@ -1,487 +0,0 @@
/*
* 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;
}
}

View file

@ -1,336 +0,0 @@
/*
* 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

View file

@ -1,131 +0,0 @@
/*
* 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);
}

View file

@ -1,61 +0,0 @@
/*
* 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

View file

@ -40,21 +40,28 @@ const char EvsCamera::kCameraName_Backup[] = "backup";
const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
EvsCamera::EvsCamera(const char *id,
unique_ptr<ConfigManager::CameraInfo> &camInfo) :
EvsCamera::EvsCamera(const char *id) :
mFramesAllowed(0),
mFramesInUse(0),
mStreamState(STOPPED),
mCameraInfo(camInfo) {
mStreamState(STOPPED) {
ALOGD("EvsCamera instantiated");
/* set a camera id */
mDescription.v1.cameraId = id;
mDescription.cameraId = id;
/* set camera metadata */
mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
get_camera_metadata_size(camInfo->characteristics));
// 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;
}
@ -102,7 +109,7 @@ Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
ALOGD("getCameraInfo");
// Send back our self description
_hidl_cb(mDescription.v1);
_hidl_cb(mDescription);
return Void();
}
@ -187,7 +194,7 @@ Return<void> EvsCamera::stopVideoStream() {
// 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();
@ -231,15 +238,6 @@ Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int3
// 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);
@ -280,29 +278,8 @@ Return<EvsResult> EvsCamera::unsetMaster() {
}
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) {
Return<void> EvsCamera::setParameter(CameraParam id, int32_t value,
setParameter_cb _hidl_cb) {
// Default implementation does not support this.
(void)id;
(void)value;
@ -311,8 +288,7 @@ Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
}
Return<void> EvsCamera::getIntParameter(CameraParam id,
getIntParameter_cb _hidl_cb) {
Return<void> EvsCamera::getParameter(CameraParam id, getParameter_cb _hidl_cb) {
// Default implementation does not support this.
(void)id;
_hidl_cb(EvsResult::INVALID_ARG, 0);
@ -495,7 +471,9 @@ void EvsCamera::generateFrames() {
fillTestFrame(newBuffer);
// Issue the (asynchronous) callback to the client -- can't be holding the lock
auto result = mStream->deliverFrame_1_1(newBuffer);
EvsEvent event;
event.buffer(newBuffer);
auto result = mStream->notifyEvent(event);
if (result.isOk()) {
ALOGD("Delivered %p as id %d",
newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
@ -528,8 +506,10 @@ void EvsCamera::generateFrames() {
// If we've been asked to stop, send an event to signal the actual end of stream
EvsEvent event;
event.aType = EvsEventType::STREAM_STOPPED;
auto result = mStream->notify(event);
InfoEventDesc desc = {};
desc.aType = InfoEventType::STREAM_STOPPED;
event.info(desc);
auto result = mStream->notifyEvent(event);
if (!result.isOk()) {
ALOGE("Error delivering end of stream marker");
}
@ -636,38 +616,6 @@ void EvsCamera::returnBuffer(const uint32_t bufferId, const buffer_handle_t memH
}
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

View file

@ -25,8 +25,6 @@
#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;
@ -61,28 +59,18 @@ public:
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> 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;
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;
Return<void> setParameter(CameraParam id, int32_t value,
setParameter_cb _hidl_cb) override;
Return<void> getParameter(CameraParam id, getParameter_cb _hidl_cb) override;
// Implementation details
EvsCamera(const char *id);
virtual ~EvsCamera() override;
void forceShutdown(); // This gets called if another caller "steals" ownership of the camera
@ -91,10 +79,7 @@ public:
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);
@ -139,9 +124,6 @@ private:
// Synchronization necessary to deconflict mCaptureThread from the main service thread
std::mutex mAccessLock;
// Static camera module information
unique_ptr<ConfigManager::CameraInfo> &mCameraInfo;
};
} // namespace implementation

View file

@ -33,7 +33,6 @@ namespace implementation {
// constructs a new instance for each client.
std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
EvsEnumerator::EvsEnumerator() {
@ -41,11 +40,9 @@ EvsEnumerator::EvsEnumerator() {
// Add sample camera data to our list of cameras
// In a real driver, this would be expected to can the available hardware
sConfigManager =
ConfigManager::Create("/etc/automotive/evs/evs_sample_configuration.xml");
for (auto v : sConfigManager->getCameraList()) {
sCameraList.emplace_back(v.c_str());
}
sCameraList.emplace_back(EvsCamera::kCameraName_Backup);
sCameraList.emplace_back("LaneView");
sCameraList.emplace_back("right turn");
}
@ -60,7 +57,7 @@ Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
std::vector<CameraDesc_1_0> descriptions;
descriptions.reserve(numCameras);
for (const auto& cam : sCameraList) {
descriptions.push_back( cam.desc.v1 );
descriptions.push_back( cam.desc );
}
// Encapsulate our camera descriptions in the HIDL vec type
@ -81,7 +78,7 @@ Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId
// Find the named camera
CameraRecord *pRecord = nullptr;
for (auto &&cam : sCameraList) {
if (cam.desc.v1.cameraId == cameraId) {
if (cam.desc.cameraId == cameraId) {
// Found a match!
pRecord = &cam;
break;
@ -102,12 +99,7 @@ Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId
}
// 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));
}
pActiveCamera = new EvsCamera(cameraId.c_str());
pRecord->activeInstance = pActiveCamera;
if (pActiveCamera == nullptr) {
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
@ -128,15 +120,15 @@ Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera_1_0>& pCa
// Get the camera id so we can find it in our list
std::string cameraId;
pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
cameraId = desc.v1.cameraId;
pCamera_1_1->getCameraInfo([&cameraId](CameraDesc desc) {
cameraId = desc.cameraId;
}
);
// Find the named camera
CameraRecord *pRecord = nullptr;
for (auto &&cam : sCameraList) {
if (cam.desc.v1.cameraId == cameraId) {
if (cam.desc.cameraId == cameraId) {
// Found a match!
pRecord = &cam;
break;
@ -217,89 +209,6 @@ Return<DisplayState> EvsEnumerator::getDisplayState() {
}
// 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

View file

@ -17,20 +17,18 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <android/hardware/automotive/evs/1.0/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 {
@ -55,11 +53,6 @@ public:
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();
@ -68,20 +61,14 @@ private:
// 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_1 desc;
CameraDesc_1_0 desc;
wp<EvsCamera> activeInstance;
CameraRecord(const char *cameraId) : desc() { desc.v1.cameraId = cameraId; }
CameraRecord(const char *cameraId) : desc() { desc.cameraId = cameraId; }
};
static std::list<CameraRecord> sCameraList;
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;
static wp<EvsDisplay> sActiveDisplay; // Weak pointer. Object destructs if client dies.
};
} // namespace implementation

View file

@ -1,68 +0,0 @@
<?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>

View file

@ -33,7 +33,7 @@ using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
using android::hardware::automotive::evs::V1_0::IEvsEnumerator;
using android::hardware::automotive::evs::V1_0::IEvsDisplay;
// The namespace in which all our implementation code lives

View file

@ -21,22 +21,6 @@ import @1.0::DisplayDesc;
import @1.0::DisplayState;
import @1.0::EvsResult;
import android.hardware.graphics.common@1.2::HardwareBuffer;
import android.hardware.camera.device@3.2::CameraMetadata;
/**
* Structure describing the basic properties of an EVS camera, extended from its
* v1.0 declaration.
*
* The HAL is responsible for filling out this structure for each
* EVS camera in the system.
*/
struct CameraDesc {
@1.0::CameraDesc v1;
/**
* Store camera metadata such as lens characteristics.
*/
CameraMetadata metadata;
};
/**
* Structure representing an image buffer through our APIs
@ -66,7 +50,7 @@ struct BufferDesc {
/**
* Types of informative streaming events
*/
enum EvsEventType : uint32_t {
enum InfoEventType : uint32_t {
/**
* Video stream is started
*/
@ -97,17 +81,31 @@ enum EvsEventType : uint32_t {
/**
* Structure that describes informative events occurred during EVS is streaming
*/
struct EvsEvent {
struct InfoEventDesc {
/**
* Type of an informative event
*/
EvsEventType aType;
InfoEventType aType;
/**
* Possible additional information
*/
uint32_t[4] payload;
};
/**
* EVS event definition
*/
safe_union EvsEvent {
/**
* A buffer descriptor of an image frame
*/
BufferDesc buffer;
/**
* General streaming events
*/
InfoEventDesc info;
};
/**
* EVS Camera Parameter
*/
@ -128,6 +126,14 @@ enum CameraParam : uint32_t {
* Gain control
*/
GAIN,
/**
* Mirror the image horizontally
*/
HFLIP,
/**
* Mirror the image vertically
*/
VFLIP,
/**
* Automatic Whitebalance
*/
@ -149,6 +155,11 @@ enum CameraParam : uint32_t {
* Manual exposure time of the camera
*/
ABSOLUTE_EXPOSURE,
/**
* When AEC is running in either auto or aperture priority, this parameter
* sets whether a frame rate varies.
*/
AUTO_EXPOSURE_PRIORITY,
/**
* Set the focal point of the camera to the specified position. This
* parameter may not be effective when auto focus is enabled.

View file

@ -23,7 +23,6 @@ cc_test {
defaults: ["VtsHalTargetTestDefaults"],
shared_libs: [
"libui",
"libcamera_metadata",
],
static_libs: [
"android.hardware.automotive.evs@1.0",
@ -32,7 +31,6 @@ cc_test {
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
"android.hardware.camera.device@3.2",
],
test_suites: ["general-tests"],
cflags: [

View file

@ -138,93 +138,93 @@ Return<void> FrameHandler::deliverFrame(const BufferDesc_1_0& bufferArg) {
}
Return<void> FrameHandler::deliverFrame_1_1(const BufferDesc_1_1& bufDesc) {
const AHardwareBuffer_Desc* pDesc =
reinterpret_cast<const AHardwareBuffer_Desc *>(&bufDesc.buffer.description);
ALOGD("Received a frame from the camera (%p)",
bufDesc.buffer.nativeHandle.getNativeHandle());
// Store a dimension of a received frame.
mFrameWidth = pDesc->width;
mFrameHeight = pDesc->height;
// If we were given an opened display at construction time, then send the received
// image back down the camera.
if (mDisplay.get()) {
// Get the output buffer we'll use to display the imagery
BufferDesc_1_0 tgtBuffer = {};
mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc_1_0& buff) {
tgtBuffer = buff;
}
);
if (tgtBuffer.memHandle == nullptr) {
printf("Didn't get target buffer - frame lost\n");
ALOGE("Didn't get requested output buffer -- skipping this frame.");
Return<void> FrameHandler::notifyEvent(const EvsEvent& event) {
// Local flag we use to keep track of when the stream is stopping
auto type = event.getDiscriminator();
if (type == EvsEvent::hidl_discriminator::info) {
mLock.lock();
mLatestEventDesc = event.info();
if (mLatestEventDesc.aType == InfoEventType::STREAM_STOPPED) {
// Signal that the last frame has been received and the stream is stopped
mRunning = false;
} else if (mLatestEventDesc.aType == InfoEventType::PARAMETER_CHANGED) {
ALOGD("Camera parameter 0x%X is changed to 0x%X",
mLatestEventDesc.payload[0], mLatestEventDesc.payload[1]);
} else {
// Copy the contents of the of buffer.memHandle into tgtBuffer
copyBufferContents(tgtBuffer, bufDesc);
ALOGD("Received an event %s", eventToString(mLatestEventDesc.aType));
}
mLock.unlock();
mEventSignal.notify_all();
} else {
auto bufDesc = event.buffer();
const AHardwareBuffer_Desc* pDesc =
reinterpret_cast<const AHardwareBuffer_Desc *>(&bufDesc.buffer.description);
ALOGD("Received a frame from the camera (%p)",
bufDesc.buffer.nativeHandle.getNativeHandle());
// Send the target buffer back for display
Return<EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
if (!result.isOk()) {
printf("HIDL error on display buffer (%s)- frame lost\n",
result.description().c_str());
ALOGE("Error making the remote function call. HIDL said %s",
result.description().c_str());
} else if (result != EvsResult::OK) {
printf("Display reported error - frame lost\n");
ALOGE("We encountered error %d when returning a buffer to the display!",
(EvsResult) result);
// Store a dimension of a received frame.
mFrameWidth = pDesc->width;
mFrameHeight = pDesc->height;
// If we were given an opened display at construction time, then send the received
// image back down the camera.
if (mDisplay.get()) {
// Get the output buffer we'll use to display the imagery
BufferDesc_1_0 tgtBuffer = {};
mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc_1_0& buff) {
tgtBuffer = buff;
}
);
if (tgtBuffer.memHandle == nullptr) {
printf("Didn't get target buffer - frame lost\n");
ALOGE("Didn't get requested output buffer -- skipping this frame.");
} else {
// Everything looks good!
// Keep track so tests or watch dogs can monitor progress
mLock.lock();
mFramesDisplayed++;
mLock.unlock();
// Copy the contents of the of buffer.memHandle into tgtBuffer
copyBufferContents(tgtBuffer, bufDesc);
// Send the target buffer back for display
Return<EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
if (!result.isOk()) {
printf("HIDL error on display buffer (%s)- frame lost\n",
result.description().c_str());
ALOGE("Error making the remote function call. HIDL said %s",
result.description().c_str());
} else if (result != EvsResult::OK) {
printf("Display reported error - frame lost\n");
ALOGE("We encountered error %d when returning a buffer to the display!",
(EvsResult) result);
} else {
// Everything looks good!
// Keep track so tests or watch dogs can monitor progress
mLock.lock();
mFramesDisplayed++;
mLock.unlock();
}
}
}
switch (mReturnMode) {
case eAutoReturn:
// Send the camera buffer back now that the client has seen it
ALOGD("Calling doneWithFrame");
// TODO: Why is it that we get a HIDL crash if we pass back the cloned buffer?
mCamera->doneWithFrame_1_1(bufDesc);
break;
case eNoAutoReturn:
// Hang onto the buffer handle for now -- the client will return it explicitly later
mHeldBuffers.push(bufDesc);
}
mLock.lock();
++mFramesReceived;
mLock.unlock();
mFrameSignal.notify_all();
ALOGD("Frame handling complete");
}
switch (mReturnMode) {
case eAutoReturn:
// Send the camera buffer back now that the client has seen it
ALOGD("Calling doneWithFrame");
mCamera->doneWithFrame_1_1(bufDesc);
break;
case eNoAutoReturn:
// Hang onto the buffer handle for now -- the client will return it explicitly later
mHeldBuffers.push(bufDesc);
}
mLock.lock();
++mFramesReceived;
mLock.unlock();
mFrameSignal.notify_all();
ALOGD("Frame handling complete");
return Void();
}
Return<void> FrameHandler::notify(const EvsEvent& event) {
// Local flag we use to keep track of when the stream is stopping
mLock.lock();
mLatestEventDesc = event;
if (mLatestEventDesc.aType == EvsEventType::STREAM_STOPPED) {
// Signal that the last frame has been received and the stream is stopped
mRunning = false;
} else if (mLatestEventDesc.aType == EvsEventType::PARAMETER_CHANGED) {
ALOGD("Camera parameter 0x%X is changed to 0x%X",
mLatestEventDesc.payload[0], mLatestEventDesc.payload[1]);
} else {
ALOGD("Received an event %s", eventToString(mLatestEventDesc.aType));
}
mLock.unlock();
mEventSignal.notify_all();
return Void();
}
@ -342,18 +342,18 @@ void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
}
}
bool FrameHandler::waitForEvent(const EvsEventType aTargetEvent,
EvsEvent &event) {
bool FrameHandler::waitForEvent(const InfoEventType aTargetEvent,
InfoEventDesc &eventDesc) {
// Wait until we get an expected parameter change event.
std::unique_lock<std::mutex> lock(mLock);
auto now = std::chrono::system_clock::now();
bool result = mEventSignal.wait_until(lock, now + 5s,
[this, aTargetEvent, &event](){
[this, aTargetEvent, &eventDesc](){
bool flag = mLatestEventDesc.aType == aTargetEvent;
if (flag) {
event.aType = mLatestEventDesc.aType;
event.payload[0] = mLatestEventDesc.payload[0];
event.payload[1] = mLatestEventDesc.payload[1];
eventDesc.aType = mLatestEventDesc.aType;
eventDesc.payload[0] = mLatestEventDesc.payload[0];
eventDesc.payload[1] = mLatestEventDesc.payload[1];
}
return flag;
@ -363,22 +363,21 @@ bool FrameHandler::waitForEvent(const EvsEventType aTargetEvent,
return !result;
}
const char *FrameHandler::eventToString(const EvsEventType aType) {
const char *FrameHandler::eventToString(const InfoEventType aType) {
switch (aType) {
case EvsEventType::STREAM_STARTED:
case InfoEventType::STREAM_STARTED:
return "STREAM_STARTED";
case EvsEventType::STREAM_STOPPED:
case InfoEventType::STREAM_STOPPED:
return "STREAM_STOPPED";
case EvsEventType::FRAME_DROPPED:
case InfoEventType::FRAME_DROPPED:
return "FRAME_DROPPED";
case EvsEventType::TIMEOUT:
case InfoEventType::TIMEOUT:
return "TIMEOUT";
case EvsEventType::PARAMETER_CHANGED:
case InfoEventType::PARAMETER_CHANGED:
return "PARAMETER_CHANGED";
case EvsEventType::MASTER_RELEASED:
case InfoEventType::MASTER_RELEASED:
return "MASTER_RELEASED";
default:
return "Unknown";
}
}

View file

@ -33,6 +33,7 @@ using ::android::hardware::hidl_handle;
using ::android::sp;
using ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
using ::android::hardware::automotive::evs::V1_0::EvsResult;
using ::android::hardware::automotive::evs::V1_0::CameraDesc;
using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
@ -55,13 +56,6 @@ public:
FrameHandler(android::sp <IEvsCamera> pCamera, CameraDesc cameraInfo,
android::sp <IEvsDisplay> pDisplay = nullptr,
BufferControlFlag mode = eAutoReturn);
virtual ~FrameHandler() {
if (mCamera != nullptr) {
/* shutdown a camera explicitly */
shutdown();
}
}
void shutdown();
bool startStream();
@ -73,22 +67,19 @@ public:
bool isRunning();
void waitForFrameCount(unsigned frameCount);
bool waitForEvent(const EvsEventType aTargetEvent,
EvsEvent &eventDesc);
bool waitForEvent(const InfoEventType aTargetEvent,
InfoEventDesc &eventDesc);
void getFramesCounters(unsigned* received, unsigned* displayed);
void getFrameDimension(unsigned* width, unsigned* height);
private:
// Implementation for ::android::hardware::automotive::evs::V1_0::IEvsCameraStream
Return<void> deliverFrame(const BufferDesc_1_0& buffer) override;
// Implementation for ::android::hardware::automotive::evs::V1_1::IEvsCameraStream
Return<void> deliverFrame_1_1(const BufferDesc_1_1& buffer) override;
Return<void> notify(const EvsEvent& event) override;
Return<void> deliverFrame(const BufferDesc_1_0& buffer) override;
Return<void> notifyEvent(const EvsEvent& event) override;
// Local implementation details
bool copyBufferContents(const BufferDesc_1_0& tgtBuffer, const BufferDesc_1_1& srcBuffer);
const char *eventToString(const EvsEventType aType);
const char *eventToString(const InfoEventType aType);
// Values initialized as startup
android::sp <IEvsCamera> mCamera;
@ -109,7 +100,7 @@ private:
unsigned mFramesDisplayed = 0; // Simple counter -- rolls over eventually!
unsigned mFrameWidth = 0;
unsigned mFrameHeight = 0;
EvsEvent mLatestEventDesc;
InfoEventDesc mLatestEventDesc;
};

File diff suppressed because it is too large Load diff