Update a default HIDL EVS HAL implementation
This CL modifies a default implementation of HIDL EVS HAL v1.1 to
properly emulate IEvsCamera and generate a test pattern (SMPTE color
bars) on the cuttlefish.
Bug: 147743625
Test: launch_cvd --gpu_mode=gfxstream && atest VtsHalEvsV1_1TargetTest
Change-Id: I36b141c250efcc27e9a455d504fe897c69349ad9
diff --git a/automotive/evs/1.1/default/Android.bp b/automotive/evs/1.1/default/Android.bp
index ea1851f..4c08ef3 100644
--- a/automotive/evs/1.1/default/Android.bp
+++ b/automotive/evs/1.1/default/Android.bp
@@ -13,48 +13,46 @@
proprietary: true,
relative_install_path: "hw",
srcs: [
- "service.cpp",
- "EvsCamera.cpp",
- "EvsEnumerator.cpp",
- "EvsDisplay.cpp",
- "ConfigManager.cpp",
- "ConfigManagerUtil.cpp",
- "EvsUltrasonicsArray.cpp",
+ "*.cpp",
],
init_rc: ["android.hardware.automotive.evs@1.1-service.rc"],
-
shared_libs: [
+ "android.frameworks.automotive.display@1.0",
"android.hardware.automotive.evs@1.0",
"android.hardware.automotive.evs@1.1",
"android.hardware.camera.device@3.3",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "android.hidl.token@1.0-utils",
+ "libEGL",
+ "libGLESv2",
"libbase",
"libbinder",
- "liblog",
+ "libbufferqueueconverter",
+ "libcamera_metadata",
"libhardware",
"libhidlbase",
"libhidlmemory",
"liblog",
+ "libtinyxml2",
"libui",
"libutils",
- "libcamera_metadata",
- "libtinyxml2",
- "android.hidl.token@1.0-utils",
- "android.frameworks.automotive.display@1.0",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
],
-
cflags: [
"-O0",
"-g",
+ "-DLOG_TAG=\"MockEvsDriver\"",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
],
-
+ include_dirs: [
+ "frameworks/native/include/",
+ ],
required: [
"evs_default_configuration.xml",
],
-
vintf_fragments: [
"manifest_android.hardware.automotive.evs@1.1-service.xml",
],
diff --git a/automotive/evs/1.1/default/ConfigManager.cpp b/automotive/evs/1.1/default/ConfigManager.cpp
index 986793e..ca8cfae 100644
--- a/automotive/evs/1.1/default/ConfigManager.cpp
+++ b/automotive/evs/1.1/default/ConfigManager.cpp
@@ -14,38 +14,40 @@
* 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;
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <hardware/gralloc.h>
+#include <utils/SystemClock.h>
+#include <fstream>
+#include <sstream>
+#include <thread>
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+using namespace std;
+using namespace tinyxml2;
+using hardware::camera::device::V3_2::StreamRotation;
ConfigManager::~ConfigManager() {
/* Nothing to do */
}
-
-void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
+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();
+ const XMLElement* curElem = aCameraElem->FirstChildElement();
while (curElem != nullptr) {
if (!strcmp(curElem->Name(), "group")) {
/* camera group identifier */
- const char *id = curElem->FindAttribute("id")->Value();
+ const char* id = curElem->FindAttribute("id")->Value();
/* create a camera group to be filled */
- CameraGroupInfo *aCamera = new CameraGroupInfo();
+ CameraGroupInfo* aCamera = new CameraGroupInfo();
/* read camera device information */
if (!readCameraDeviceInfo(aCamera, curElem)) {
@@ -55,28 +57,26 @@
}
/* camera group synchronization */
- const char *sync = curElem->FindAttribute("synchronized")->Value();
+ const char* sync = curElem->FindAttribute("synchronized")->Value();
if (!strcmp(sync, "CALIBRATED")) {
- aCamera->synchronized =
- ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED;
+ aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED;
} else if (!strcmp(sync, "APPROXIMATE")) {
- aCamera->synchronized =
- ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE;
+ aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE;
} else {
- aCamera->synchronized = 0; // Not synchronized
+ aCamera->synchronized = 0; // Not synchronized
}
/* add a group to hash map */
mCameraGroupInfos.insert_or_assign(id, unique_ptr<CameraGroupInfo>(aCamera));
} else if (!strcmp(curElem->Name(), "device")) {
/* camera unique identifier */
- const char *id = curElem->FindAttribute("id")->Value();
+ const char* id = curElem->FindAttribute("id")->Value();
/* camera mount location */
- const char *pos = curElem->FindAttribute("position")->Value();
+ const char* pos = curElem->FindAttribute("position")->Value();
/* create a camera device to be filled */
- CameraInfo *aCamera = new CameraInfo();
+ CameraInfo* aCamera = new CameraInfo();
/* read camera device information */
if (!readCameraDeviceInfo(aCamera, curElem)) {
@@ -99,10 +99,7 @@
}
}
-
-bool
-ConfigManager::readCameraDeviceInfo(CameraInfo *aCamera,
- const XMLElement *aDeviceElem) {
+bool ConfigManager::readCameraDeviceInfo(CameraInfo* aCamera, const XMLElement* aDeviceElem) {
if (aCamera == nullptr || aDeviceElem == nullptr) {
return false;
}
@@ -113,16 +110,11 @@
/* read device capabilities */
totalEntries +=
- readCameraCapabilities(aDeviceElem->FirstChildElement("caps"),
- aCamera,
- totalDataSize);
-
+ readCameraCapabilities(aDeviceElem->FirstChildElement("caps"), aCamera, totalDataSize);
/* read camera metadata */
- totalEntries +=
- readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"),
- aCamera,
- totalDataSize);
+ totalEntries += readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"), aCamera,
+ totalDataSize);
/* construct camera_metadata_t */
if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
@@ -133,40 +125,34 @@
return true;
}
-
-size_t
-ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
- CameraInfo *aCamera,
- size_t &dataSize) {
+size_t ConfigManager::readCameraCapabilities(const XMLElement* const aCapElem, CameraInfo* aCamera,
+ size_t& dataSize) {
if (aCapElem == nullptr || aCamera == nullptr) {
return 0;
}
string token;
- const XMLElement *curElem = nullptr;
+ 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");
+ const XMLElement* ctrlElem = curElem->FirstChildElement("control");
while (ctrlElem != nullptr) {
- const char *nameAttr = ctrlElem->FindAttribute("name")->Value();;
+ 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");
+ 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)
- );
+ if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) {
+ aCamera->controls.emplace(aParam, make_tuple(minVal, maxVal, stepVal));
}
ctrlElem = ctrlElem->NextSiblingElement("control");
@@ -177,11 +163,11 @@
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 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;
@@ -190,16 +176,13 @@
}
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
- };
+ 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.insert_or_assign(id, cfg);
}
@@ -207,70 +190,58 @@
}
dataSize = calculate_camera_metadata_entry_data_size(
- get_camera_metadata_tag_type(
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
- ),
- aCamera->streamConfigurations.size() * kStreamCfgSz
- );
+ 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,
- CameraInfo *aCamera,
- size_t &dataSize) {
+size_t ConfigManager::readCameraMetadata(const XMLElement* const aParamElem, CameraInfo* aCamera,
+ size_t& dataSize) {
if (aParamElem == nullptr || aCamera == nullptr) {
return 0;
}
- const XMLElement *curElem = aParamElem->FirstChildElement("parameter");
+ 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) {
+ 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
- );
+ void* data = ConfigManagerUtil::convertFloatArray(
+ curElem->FindAttribute("size")->Value(),
+ curElem->FindAttribute("value")->Value(), count);
aCamera->cameraMetadata.insert_or_assign(
- tag, make_pair(make_unique<void *>(data), count)
- );
+ tag, make_pair(make_unique<void*>(data), count));
++numEntries;
dataSize += calculate_camera_metadata_entry_data_size(
- get_camera_metadata_tag_type(tag), count
- );
+ get_camera_metadata_tag_type(tag), count);
break;
}
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
- camera_metadata_enum_android_request_available_capabilities_t *data =
- new camera_metadata_enum_android_request_available_capabilities_t[1];
+ camera_metadata_enum_android_request_available_capabilities_t* data =
+ new camera_metadata_enum_android_request_available_capabilities_t[1];
if (ConfigManagerUtil::convertToCameraCapability(
- curElem->FindAttribute("value")->Value(), *data)) {
- curElem->FindAttribute("value")->Value(),
- aCamera->cameraMetadata.insert_or_assign(
- tag, make_pair(make_unique<void *>(data), 1)
- );
+ curElem->FindAttribute("value")->Value(), *data)) {
+ curElem->FindAttribute("value")->Value(),
+ aCamera->cameraMetadata.insert_or_assign(
+ tag, make_pair(make_unique<void*>(data), 1));
++numEntries;
dataSize += calculate_camera_metadata_entry_data_size(
- get_camera_metadata_tag_type(tag), 1
- );
+ get_camera_metadata_tag_type(tag), 1);
}
break;
}
@@ -278,13 +249,11 @@
case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
/* a comma-separated list of physical camera devices */
size_t len = strlen(curElem->FindAttribute("value")->Value());
- char *data = new char[len + 1];
- memcpy(data,
- curElem->FindAttribute("value")->Value(),
- len * sizeof(char));
+ char* data = new char[len + 1];
+ memcpy(data, curElem->FindAttribute("value")->Value(), len * sizeof(char));
/* replace commas with null char */
- char *p = data;
+ char* p = data;
while (*p != '\0') {
if (*p == ',') {
*p = '\0';
@@ -293,19 +262,16 @@
}
aCamera->cameraMetadata.insert_or_assign(
- tag, make_pair(make_unique<void *>(data), len)
- );
+ tag, make_pair(make_unique<void*>(data), len));
++numEntries;
dataSize += calculate_camera_metadata_entry_data_size(
- get_camera_metadata_tag_type(tag), len
- );
+ get_camera_metadata_tag_type(tag), len);
break;
}
default:
- ALOGW("Parameter %s is not supported",
- curElem->FindAttribute("name")->Value());
+ ALOGW("Parameter %s is not supported", curElem->FindAttribute("name")->Value());
break;
}
}
@@ -316,11 +282,8 @@
return numEntries;
}
-
-bool
-ConfigManager::constructCameraMetadata(CameraInfo *aCamera,
- const size_t totalEntries,
- const size_t totalDataSize) {
+bool ConfigManager::constructCameraMetadata(CameraInfo* aCamera, const size_t totalEntries,
+ const size_t totalDataSize) {
if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
ALOGE("Failed to allocate memory for camera metadata");
return false;
@@ -328,16 +291,15 @@
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) {
+ int32_t* ptr = data.get();
+ for (auto& cfg : aCamera->streamConfigurations) {
for (auto i = 0; i < kStreamCfgSz; ++i) {
- *ptr++ = cfg.second[i];
+ *ptr++ = cfg.second[i];
}
}
int32_t err = add_camera_metadata_entry(aCamera->characteristics,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- data.get(),
- numStreamConfigs * kStreamCfgSz);
+ data.get(), numStreamConfigs * kStreamCfgSz);
if (err) {
ALOGE("Failed to add stream configurations to metadata, ignored");
@@ -345,11 +307,9 @@
}
bool success = true;
- for (auto &[tag, entry] : aCamera->cameraMetadata) {
+ 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(),
+ 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);
@@ -376,8 +336,7 @@
return success;
}
-
-void ConfigManager::readSystemInfo(const XMLElement * const aSysElem) {
+void ConfigManager::readSystemInfo(const XMLElement* const aSysElem) {
if (aSysElem == nullptr) {
return;
}
@@ -389,24 +348,22 @@
*/
/* read number of cameras available in the system */
- const XMLElement *xmlElem = aSysElem->FirstChildElement("num_cameras");
+ const XMLElement* xmlElem = aSysElem->FirstChildElement("num_cameras");
if (xmlElem != nullptr) {
- mSystemInfo.numCameras =
- stoi(xmlElem->FindAttribute("value")->Value());
+ mSystemInfo.numCameras = stoi(xmlElem->FindAttribute("value")->Value());
}
}
-
-void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
+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");
+ const XMLElement* curDev = aDisplayElem->FirstChildElement("device");
while (curDev != nullptr) {
- const char *id = curDev->FindAttribute("id")->Value();
- //const char *pos = curDev->FirstAttribute("position")->Value();
+ const char* id = curDev->FindAttribute("id")->Value();
+ // const char *pos = curDev->FirstAttribute("position")->Value();
unique_ptr<DisplayInfo> dpy(new DisplayInfo());
if (dpy == nullptr) {
@@ -414,27 +371,26 @@
return;
}
- const XMLElement *cap = curDev->FirstChildElement("caps");
+ const XMLElement* cap = curDev->FirstChildElement("caps");
if (cap != nullptr) {
- const XMLElement *curStream = cap->FirstChildElement("stream");
+ 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 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)) {
+ if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), pixFormat)) {
RawStreamConfiguration cfg = {
- id,
- stoi(widthAttr->Value()),
- stoi(heightAttr->Value()),
- pixFormat,
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
- 0 // unused
+ id,
+ stoi(widthAttr->Value()),
+ stoi(heightAttr->Value()),
+ pixFormat,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
+ 0 // unused
};
dpy->streamConfigurations.insert_or_assign(id, cfg);
}
@@ -450,7 +406,6 @@
return;
}
-
bool ConfigManager::readConfigDataFromXML() noexcept {
XMLDocument xmlDoc;
@@ -464,7 +419,7 @@
}
/* retrieve the root element */
- const XMLElement *rootElem = xmlDoc.RootElement();
+ 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");
@@ -487,12 +442,10 @@
ALOGI("Parsing configuration file takes %lf (ms)",
(double)(parsingEnd - parsingStart) / 1000000.0);
-
return true;
}
-
-std::unique_ptr<ConfigManager> ConfigManager::Create(const char *path) {
+std::unique_ptr<ConfigManager> ConfigManager::Create(const char* path) {
unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
/*
@@ -510,3 +463,4 @@
}
}
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/ConfigManager.h b/automotive/evs/1.1/default/ConfigManager.h
index b0b2670..0a15360 100644
--- a/automotive/evs/1.1/default/ConfigManager.h
+++ b/automotive/evs/1.1/default/ConfigManager.h
@@ -13,28 +13,26 @@
* 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>
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGER_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGER_H
#include "ConfigManagerUtil.h"
-using namespace std;
-using namespace tinyxml2;
+#include <android/hardware/automotive/evs/1.1/types.h>
+#include <log/log.h>
+#include <system/camera_metadata.h>
+#include <tinyxml2.h>
-using ::android::hardware::hidl_vec;
-using ::android::hardware::camera::device::V3_2::Stream;
-using ::android::hardware::automotive::evs::V1_1::CameraParam;
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+using hardware::hidl_vec;
+using hardware::automotive::evs::V1_1::CameraParam;
+using hardware::camera::device::V3_2::Stream;
/*
* Plese note that this is different from what is defined in
@@ -45,8 +43,8 @@
typedef std::array<int32_t, kStreamCfgSz> RawStreamConfiguration;
class ConfigManager {
-public:
- static std::unique_ptr<ConfigManager> Create(const char *path = "");
+ public:
+ static std::unique_ptr<ConfigManager> Create(const char* path = "");
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
@@ -54,15 +52,11 @@
/* Camera device's capabilities and metadata */
class CameraInfo {
- public:
- CameraInfo() :
- characteristics(nullptr) {
- /* Nothing to do */
+ public:
+ CameraInfo() : characteristics(nullptr) { /* Nothing to do */
}
- virtual ~CameraInfo() {
- free_camera_metadata(characteristics);
- }
+ virtual ~CameraInfo() { free_camera_metadata(characteristics); }
/* Allocate memory for camera_metadata_t */
bool allocate(size_t entry_cap, size_t data_cap) {
@@ -79,50 +73,49 @@
* List of supported controls that the primary client can program.
* Paraemters are stored with its valid range
*/
- unordered_map<CameraParam,
- tuple<int32_t, int32_t, int32_t>> controls;
+ std::unordered_map<CameraParam, std::tuple<int32_t, int32_t, int32_t>> controls;
/*
* List of supported output stream configurations; each array stores
* format, width, height, and direction values in the order.
*/
- unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
+ std::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;
+ std::unordered_map<camera_metadata_tag_t, std::pair<std::unique_ptr<void*>, size_t>>
+ cameraMetadata;
/* Camera module characteristics */
- camera_metadata_t *characteristics;
+ camera_metadata_t* characteristics;
};
class CameraGroupInfo : public CameraInfo {
- public:
+ public:
CameraGroupInfo() {}
/* ID of member camera devices */
- unordered_set<string> devices;
+ std::unordered_set<std::string> devices;
/* The capture operation of member camera devices are synchronized */
bool synchronized = false;
};
class SystemInfo {
- public:
+ public:
/* number of available cameras */
int32_t numCameras = 0;
};
class DisplayInfo {
- public:
+ 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;
+ std::unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
};
/*
@@ -131,80 +124,74 @@
* @return SystemInfo
* Constant reference of SystemInfo.
*/
- const SystemInfo &getSystemInfo() {
- return mSystemInfo;
- }
+ const SystemInfo& getSystemInfo() { return mSystemInfo; }
/*
* Return a list of cameras
*
* This function assumes that it is not being called frequently.
*
- * @return vector<string>
+ * @return std::vector<std::string>
* A vector that contains unique camera device identifiers.
*/
- vector<string> getCameraList() {
- vector<string> aList;
- for (auto &v : mCameraInfo) {
- aList.emplace_back(v.first);
+ std::vector<std::string> getCameraList() {
+ std::vector<std::string> aList;
+ for (auto& v : mCameraInfo) {
+ aList.push_back(v.first);
}
return aList;
}
-
/*
* Return a list of cameras
*
* @return CameraGroupInfo
* A pointer to a camera group identified by a given id.
*/
- unique_ptr<CameraGroupInfo>& getCameraGroupInfo(const string& gid) {
+ std::unique_ptr<CameraGroupInfo>& getCameraGroupInfo(const std::string& gid) {
return mCameraGroupInfos[gid];
}
-
/*
* Return a camera metadata
*
* @param cameraId
- * Unique camera node identifier in string
+ * Unique camera node identifier in std::string
*
- * @return unique_ptr<CameraInfo>
+ * @return std::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 {
+ std::unique_ptr<CameraInfo>& getCameraInfo(const std::string cameraId) noexcept {
return mCameraInfo[cameraId];
}
-private:
+ private:
/* Constructors */
- ConfigManager(const char *xmlPath) :
- mConfigFilePath(xmlPath) {
- }
+ ConfigManager(const char* xmlPath) : mConfigFilePath(xmlPath) {}
/* System configuration */
SystemInfo mSystemInfo;
/* Internal data structure for camera device information */
- unordered_map<string, unique_ptr<CameraInfo>> mCameraInfo;
+ std::unordered_map<std::string, std::unique_ptr<CameraInfo>> mCameraInfo;
/* Internal data structure for camera device information */
- unordered_map<string, unique_ptr<DisplayInfo>> mDisplayInfo;
+ std::unordered_map<std::string, std::unique_ptr<DisplayInfo>> mDisplayInfo;
/* Camera groups are stored in <groud id, CameraGroupInfo> hash map */
- unordered_map<string, unique_ptr<CameraGroupInfo>> mCameraGroupInfos;
+ std::unordered_map<std::string, std::unique_ptr<CameraGroupInfo>> mCameraGroupInfos;
/*
* 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;
+ std::unordered_map<std::string, std::unordered_set<std::string>> mCameraPosition;
/* A path to XML configuration file */
- const char *mConfigFilePath;
+ const char* mConfigFilePath;
/*
* Parse a given EVS configuration file and store the information
@@ -221,7 +208,7 @@
* @param aSysElem
* A pointer to "system" XML element.
*/
- void readSystemInfo(const XMLElement * const aSysElem);
+ void readSystemInfo(const tinyxml2::XMLElement* const aSysElem);
/*
* read the information of camera devices
@@ -230,7 +217,7 @@
* A pointer to "camera" XML element that may contain multiple
* "device" elements.
*/
- void readCameraInfo(const XMLElement * const aCameraElem);
+ void readCameraInfo(const tinyxml2::XMLElement* const aCameraElem);
/*
* read display device information
@@ -239,7 +226,7 @@
* A pointer to "display" XML element that may contain multiple
* "device" elements.
*/
- void readDisplayInfo(const XMLElement * const aDisplayElem);
+ void readDisplayInfo(const tinyxml2::XMLElement* const aDisplayElem);
/*
* read camera device information
@@ -255,8 +242,7 @@
* Return false upon any failure in reading and processing camera
* device information.
*/
- bool readCameraDeviceInfo(CameraInfo *aCamera,
- const XMLElement *aDeviceElem);
+ bool readCameraDeviceInfo(CameraInfo* aCamera, const tinyxml2::XMLElement* aDeviceElem);
/*
* read camera metadata
@@ -273,9 +259,8 @@
* @return size_t
* Number of camera metadata entries
*/
- size_t readCameraCapabilities(const XMLElement * const aCapElem,
- CameraInfo *aCamera,
- size_t &dataSize);
+ size_t readCameraCapabilities(const tinyxml2::XMLElement* const aCapElem, CameraInfo* aCamera,
+ size_t& dataSize);
/*
* read camera metadata
@@ -291,9 +276,8 @@
* @return size_t
* Number of camera metadata entries
*/
- size_t readCameraMetadata(const XMLElement * const aParamElem,
- CameraInfo *aCamera,
- size_t &dataSize);
+ size_t readCameraMetadata(const tinyxml2::XMLElement* const aParamElem, CameraInfo* aCamera,
+ size_t& dataSize);
/*
* construct camera_metadata_t from camera capabilities and metadata
@@ -310,9 +294,9 @@
* or its size is not large enough to add all found camera metadata
* entries.
*/
- bool constructCameraMetadata(CameraInfo *aCamera,
- const size_t totalEntries,
+ bool constructCameraMetadata(CameraInfo* aCamera, const size_t totalEntries,
const size_t totalDataSize);
};
-#endif // CONFIG_MANAGER_H
+} // namespace android::hardware::automotive::evs::V1_1::implementation
+#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGER_H
diff --git a/automotive/evs/1.1/default/ConfigManagerUtil.cpp b/automotive/evs/1.1/default/ConfigManagerUtil.cpp
index d10f236..5edd405 100644
--- a/automotive/evs/1.1/default/ConfigManagerUtil.cpp
+++ b/automotive/evs/1.1/default/ConfigManagerUtil.cpp
@@ -16,43 +16,45 @@
#include "ConfigManagerUtil.h"
-#include <string>
-#include <sstream>
-#include <linux/videodev2.h>
-
#include <log/log.h>
#include <system/graphics-base-v1.0.h>
+#include <linux/videodev2.h>
+#include <sstream>
+#include <string>
-bool ConfigManagerUtil::convertToEvsCameraParam(const string &id,
- CameraParam &camParam) {
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+using namespace std;
+
+bool ConfigManagerUtil::convertToEvsCameraParam(const string& id, CameraParam& camParam) {
string trimmed = ConfigManagerUtil::trimString(id);
bool success = true;
if (!trimmed.compare("BRIGHTNESS")) {
- camParam = CameraParam::BRIGHTNESS;
+ camParam = CameraParam::BRIGHTNESS;
} else if (!trimmed.compare("CONTRAST")) {
- camParam = CameraParam::CONTRAST;
+ camParam = CameraParam::CONTRAST;
} else if (!trimmed.compare("AUTOGAIN")) {
- camParam = CameraParam::AUTOGAIN;
+ camParam = CameraParam::AUTOGAIN;
} else if (!trimmed.compare("GAIN")) {
- camParam = CameraParam::GAIN;
+ camParam = CameraParam::GAIN;
} else if (!trimmed.compare("AUTO_WHITE_BALANCE")) {
- camParam = CameraParam::AUTO_WHITE_BALANCE;
+ camParam = CameraParam::AUTO_WHITE_BALANCE;
} else if (!trimmed.compare("WHITE_BALANCE_TEMPERATURE")) {
- camParam = CameraParam::WHITE_BALANCE_TEMPERATURE;
+ camParam = CameraParam::WHITE_BALANCE_TEMPERATURE;
} else if (!trimmed.compare("SHARPNESS")) {
- camParam = CameraParam::SHARPNESS;
+ camParam = CameraParam::SHARPNESS;
} else if (!trimmed.compare("AUTO_EXPOSURE")) {
- camParam = CameraParam::AUTO_EXPOSURE;
+ camParam = CameraParam::AUTO_EXPOSURE;
} else if (!trimmed.compare("ABSOLUTE_EXPOSURE")) {
- camParam = CameraParam::ABSOLUTE_EXPOSURE;
+ camParam = CameraParam::ABSOLUTE_EXPOSURE;
} else if (!trimmed.compare("ABSOLUTE_FOCUS")) {
- camParam = CameraParam::ABSOLUTE_FOCUS;
+ camParam = CameraParam::ABSOLUTE_FOCUS;
} else if (!trimmed.compare("AUTO_FOCUS")) {
- camParam = CameraParam::AUTO_FOCUS;
+ camParam = CameraParam::AUTO_FOCUS;
} else if (!trimmed.compare("ABSOLUTE_ZOOM")) {
- camParam = CameraParam::ABSOLUTE_ZOOM;
+ camParam = CameraParam::ABSOLUTE_ZOOM;
} else {
success = false;
}
@@ -60,18 +62,16 @@
return success;
}
-
-bool ConfigManagerUtil::convertToPixelFormat(const string &format,
- int32_t &pixFormat) {
+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;
+ pixFormat = HAL_PIXEL_FORMAT_RGBA_8888;
} else if (!trimmed.compare("YCRCB_420_SP")) {
- pixFormat = HAL_PIXEL_FORMAT_YCRCB_420_SP;
+ pixFormat = HAL_PIXEL_FORMAT_YCRCB_420_SP;
} else if (!trimmed.compare("YCBCR_422_I")) {
- pixFormat = HAL_PIXEL_FORMAT_YCBCR_422_I;
+ pixFormat = HAL_PIXEL_FORMAT_YCBCR_422_I;
} else {
success = false;
}
@@ -79,21 +79,19 @@
return success;
}
-
-bool ConfigManagerUtil::convertToMetadataTag(const char *name,
- camera_metadata_tag &aTag) {
+bool ConfigManagerUtil::convertToMetadataTag(const char* name, camera_metadata_tag& aTag) {
if (!strcmp(name, "LENS_DISTORTION")) {
- aTag = ANDROID_LENS_DISTORTION;
+ aTag = ANDROID_LENS_DISTORTION;
} else if (!strcmp(name, "LENS_INTRINSIC_CALIBRATION")) {
- aTag = ANDROID_LENS_INTRINSIC_CALIBRATION;
+ aTag = ANDROID_LENS_INTRINSIC_CALIBRATION;
} else if (!strcmp(name, "LENS_POSE_ROTATION")) {
- aTag = ANDROID_LENS_POSE_ROTATION;
+ aTag = ANDROID_LENS_POSE_ROTATION;
} else if (!strcmp(name, "LENS_POSE_TRANSLATION")) {
- aTag = ANDROID_LENS_POSE_TRANSLATION;
+ aTag = ANDROID_LENS_POSE_TRANSLATION;
} else if (!strcmp(name, "REQUEST_AVAILABLE_CAPABILITIES")) {
- aTag = ANDROID_REQUEST_AVAILABLE_CAPABILITIES;
+ aTag = ANDROID_REQUEST_AVAILABLE_CAPABILITIES;
} else if (!strcmp(name, "LOGICAL_MULTI_CAMERA_PHYSICAL_IDS")) {
- aTag = ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS;
+ aTag = ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS;
} else {
return false;
}
@@ -101,11 +99,8 @@
return true;
}
-
bool ConfigManagerUtil::convertToCameraCapability(
- const char *name,
- camera_metadata_enum_android_request_available_capabilities_t &cap) {
-
+ const char* name, camera_metadata_enum_android_request_available_capabilities_t& cap) {
if (!strcmp(name, "DEPTH_OUTPUT")) {
cap = ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT;
} else if (!strcmp(name, "LOGICAL_MULTI_CAMERA")) {
@@ -121,14 +116,13 @@
return true;
}
-
-float *ConfigManagerUtil::convertFloatArray(const char *sz, const char *vals,
- size_t &count, const char delimiter) {
+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];
+ float* result = new float[count];
stringstream values(value_string);
int32_t idx = 0;
@@ -140,8 +134,7 @@
return result;
}
-
-string ConfigManagerUtil::trimString(const string &src, const string &ws) {
+string ConfigManagerUtil::trimString(const string& src, const string& ws) {
const auto s = src.find_first_not_of(ws);
if (s == string::npos) {
return "";
@@ -153,3 +146,4 @@
return src.substr(s, r);
}
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/ConfigManagerUtil.h b/automotive/evs/1.1/default/ConfigManagerUtil.h
index 1710cac..9d42ec1 100644
--- a/automotive/evs/1.1/default/ConfigManagerUtil.h
+++ b/automotive/evs/1.1/default/ConfigManagerUtil.h
@@ -13,57 +13,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef CONFIG_MANAGER_UTIL_H
-#define CONFIG_MANAGER_UTIL_H
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGERUTIL_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGERUTIL_H
-#include <utility>
-#include <string>
-#include <system/camera_metadata.h>
#include <android/hardware/automotive/evs/1.1/types.h>
+#include <system/camera_metadata.h>
+#include <string>
+#include <utility>
-using namespace std;
-using ::android::hardware::automotive::evs::V1_1::CameraParam;
-
+namespace android::hardware::automotive::evs::V1_1::implementation {
class ConfigManagerUtil {
-public:
+ public:
/**
* Convert a given string into V4L2_CID_*
*/
- static bool convertToEvsCameraParam(const string &id,
- CameraParam &camParam);
+ static bool convertToEvsCameraParam(const std::string& id, CameraParam& camParam);
/**
* Convert a given string into android.hardware.graphics.common.PixelFormat
*/
- static bool convertToPixelFormat(const string &format,
- int32_t &pixelFormat);
+ static bool convertToPixelFormat(const std::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);
+ 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,
+ 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");
+ static std::string trimString(const std::string& src, const std::string& ws = " \n\r\t\f\v");
/**
* Convert a given string to corresponding camera capabilities
*/
static bool convertToCameraCapability(
- const char *name,
- camera_metadata_enum_android_request_available_capabilities_t &cap);
-
+ const char* name, camera_metadata_enum_android_request_available_capabilities_t& cap);
};
-#endif // CONFIG_MANAGER_UTIL_H
+} // namespace android::hardware::automotive::evs::V1_1::implementation
+#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_CONFIGMANAGERUTIL_H
diff --git a/automotive/evs/1.1/default/EvsCamera.cpp b/automotive/evs/1.1/default/EvsCamera.cpp
index 0e69ed4..b671c23 100644
--- a/automotive/evs/1.1/default/EvsCamera.cpp
+++ b/automotive/evs/1.1/default/EvsCamera.cpp
@@ -14,69 +14,69 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.automotive.evs@1.1-service"
-
#include "EvsCamera.h"
+#include "ConfigManager.h"
#include "EvsEnumerator.h"
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
#include <utils/SystemClock.h>
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
-
-
-// Special camera names for which we'll initialize alternate test data
-const char EvsCamera::kCameraName_Backup[] = "backup";
-
+namespace {
// Arbitrary limit on number of graphics buffers allowed to be allocated
// Safeguards against unreasonable resource consumption and provides a testable limit
-const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
+constexpr unsigned kMaxBuffersInFlight = 100;
+// Minimum number of buffers to run a video stream
+constexpr int kMinimumBuffersInFlight = 1;
-EvsCamera::EvsCamera(const char *id,
- unique_ptr<ConfigManager::CameraInfo> &camInfo) :
- mFramesAllowed(0),
- mFramesInUse(0),
- mStreamState(STOPPED),
- mCameraInfo(camInfo) {
+// Colors for the colorbar test pattern in ABGR format
+constexpr uint32_t kColors[] = {
+ 0xFFFFFFFF, // white
+ 0xFF00FFFF, // yellow
+ 0xFFFFFF00, // cyan
+ 0xFF00FF00, // green
+ 0xFFFF00FF, // fuchsia
+ 0xFF0000FF, // red
+ 0xFFFF0000, // blue
+ 0xFF000000, // black
+};
+constexpr uint32_t kNumColors = sizeof(kColors) / sizeof(kColors[0]);
- ALOGD("EvsCamera instantiated");
+} // namespace
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+using V1_0::EvsResult;
+
+EvsCamera::EvsCamera(const char* id, std::unique_ptr<ConfigManager::CameraInfo>& camInfo)
+ : mFramesAllowed(0), mFramesInUse(0), mStreamState(STOPPED), mCameraInfo(camInfo) {
+ ALOGD("%s", __FUNCTION__);
/* set a camera id */
mDescription.v1.cameraId = id;
/* set camera metadata */
- mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
+ mDescription.metadata.setToExternal((uint8_t*)camInfo->characteristics,
get_camera_metadata_size(camInfo->characteristics));
}
-
EvsCamera::~EvsCamera() {
- ALOGD("EvsCamera being destroyed");
+ ALOGD("%s", __FUNCTION__);
forceShutdown();
}
-
-//
// This gets called if another caller "steals" ownership of the camera
-//
-void EvsCamera::forceShutdown()
-{
- ALOGD("EvsCamera forceShutdown");
+void EvsCamera::forceShutdown() {
+ ALOGD("%s", __FUNCTION__);
// Make sure our output stream is cleaned up
// (It really should be already)
stopVideoStream();
// Claim the lock while we work on internal state
- std::lock_guard <std::mutex> lock(mAccessLock);
+ std::lock_guard<std::mutex> lock(mAccessLock);
// Drop all the graphics buffers we've been using
if (mBuffers.size() > 0) {
@@ -96,19 +96,18 @@
mStreamState = DEAD;
}
-
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
- ALOGD("getCameraInfo");
+ ALOGD("%s", __FUNCTION__);
// Send back our self description
_hidl_cb(mDescription.v1);
- return Void();
+ return {};
}
-
Return<EvsResult> EvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
- ALOGD("setMaxFramesInFlight");
+ ALOGD("%s, bufferCount = %u", __FUNCTION__, bufferCount);
+
std::lock_guard<std::mutex> lock(mAccessLock);
// If we've been displaced by another owner of the camera, then we can't do anything else
@@ -131,9 +130,9 @@
}
}
+Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<V1_0::IEvsCameraStream>& stream) {
+ ALOGD("%s", __FUNCTION__);
-Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStream_1_0>& stream) {
- ALOGD("startVideoStream");
std::lock_guard<std::mutex> lock(mAccessLock);
// If we've been displaced by another owner of the camera, then we can't do anything else
@@ -141,82 +140,86 @@
ALOGE("ignoring startVideoStream call when camera has been lost.");
return EvsResult::OWNERSHIP_LOST;
}
+
if (mStreamState != STOPPED) {
ALOGE("ignoring startVideoStream call when a stream is already running.");
return EvsResult::STREAM_ALREADY_RUNNING;
}
// If the client never indicated otherwise, configure ourselves for a single streaming buffer
- if (mFramesAllowed < 1) {
- if (!setAvailableFrames_Locked(1)) {
+ if (mFramesAllowed < kMinimumBuffersInFlight) {
+ if (!setAvailableFrames_Locked(kMinimumBuffersInFlight)) {
ALOGE("Failed to start stream because we couldn't get a graphics buffer");
return EvsResult::BUFFER_NOT_AVAILABLE;
}
}
// Record the user's callback for use when we have a frame ready
- mStream = IEvsCameraStream_1_1::castFrom(stream).withDefault(nullptr);
- if (mStream == nullptr) {
+ mStream = IEvsCameraStream::castFrom(stream).withDefault(nullptr);
+ if (!mStream) {
ALOGE("Default implementation does not support v1.0 IEvsCameraStream");
return EvsResult::INVALID_ARG;
}
// Start the frame generation thread
mStreamState = RUNNING;
- mCaptureThread = std::thread([this](){ generateFrames(); });
+ mCaptureThread = std::thread([this]() { generateFrames(); });
return EvsResult::OK;
}
-
-Return<void> EvsCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
- std::lock_guard <std::mutex> lock(mAccessLock);
- returnBuffer(buffer.bufferId, buffer.memHandle);
-
- return Void();
-}
-
-
-Return<void> EvsCamera::stopVideoStream() {
- ALOGD("stopVideoStream");
- std::unique_lock <std::mutex> lock(mAccessLock);
-
- if (mStreamState == RUNNING) {
- // Tell the GenerateFrames loop we want it to stop
- mStreamState = STOPPING;
-
- // Block outside the mutex until the "stop" flag has been acknowledged
- // We won't send any more frames, but the client might still get some already in flight
- ALOGD("Waiting for stream thread to end...");
- lock.unlock();
- mCaptureThread.join();
- lock.lock();
-
- mStreamState = STOPPED;
- mStream = nullptr;
- ALOGD("Stream marked STOPPED.");
- }
-
- return Void();
-}
-
-
-Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
- ALOGD("getExtendedInfo");
+Return<void> EvsCamera::doneWithFrame(const V1_0::BufferDesc& buffer) {
std::lock_guard<std::mutex> lock(mAccessLock);
+ returnBufferLocked(buffer.bufferId, buffer.memHandle);
- // For any single digit value, return the index itself as a test value
- if (opaqueIdentifier <= 9) {
- return opaqueIdentifier;
- }
-
- // Return zero by default as required by the spec
- return 0;
+ return {};
}
+Return<void> EvsCamera::stopVideoStream() {
+ ALOGD("%s", __FUNCTION__);
-Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int32_t /*opaqueValue*/) {
- ALOGD("setExtendedInfo");
+ std::unique_lock<std::mutex> lock(mAccessLock);
+
+ if (mStreamState != RUNNING) {
+ return {};
+ }
+
+ // Tell the GenerateFrames loop we want it to stop
+ mStreamState = STOPPING;
+
+ // Block outside the mutex until the "stop" flag has been acknowledged
+ // We won't send any more frames, but the client might still get some already in flight
+ ALOGD("Waiting for stream thread to end...");
+ lock.unlock();
+ if (mCaptureThread.joinable()) {
+ mCaptureThread.join();
+ }
+ lock.lock();
+
+ mStreamState = STOPPED;
+ mStream = nullptr;
+ ALOGD("Stream marked STOPPED.");
+
+ return {};
+}
+
+Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
+ ALOGD("%s", __FUNCTION__);
+
+ std::lock_guard<std::mutex> lock(mAccessLock);
+ const auto it = mExtInfo.find(opaqueIdentifier);
+ if (it == mExtInfo.end()) {
+ // Return zero by default as required by the spec
+ return 0;
+ } else {
+ return it->second[0];
+ }
+}
+
+Return<EvsResult> EvsCamera::setExtendedInfo([[maybe_unused]] uint32_t opaqueIdentifier,
+ [[maybe_unused]] int32_t opaqueValue) {
+ ALOGD("%s", __FUNCTION__);
+
std::lock_guard<std::mutex> lock(mAccessLock);
// If we've been displaced by another owner of the camera, then we can't do anything else
@@ -225,76 +228,73 @@
return EvsResult::OWNERSHIP_LOST;
}
- // We don't store any device specific information in this implementation
- return EvsResult::INVALID_ARG;
+ mExtInfo.insert_or_assign(opaqueIdentifier, opaqueValue);
+ return EvsResult::OK;
}
-
// 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");
+ ALOGD("%s", __FUNCTION__);
// Send back our self description
_hidl_cb(mDescription);
- return Void();
+ return {};
}
-
-Return<void> EvsCamera::getPhysicalCameraInfo(const hidl_string& id,
+Return<void> EvsCamera::getPhysicalCameraInfo([[maybe_unused]] const hidl_string& id,
getCameraInfo_1_1_cb _hidl_cb) {
ALOGD("%s", __FUNCTION__);
// This works exactly same as getCameraInfo_1_1() in default implementation.
- (void)id;
_hidl_cb(mDescription);
- return Void();
+ return {};
}
+Return<EvsResult> EvsCamera::doneWithFrame_1_1(const hidl_vec<BufferDesc>& buffers) {
+ ALOGD("%s", __FUNCTION__);
-Return<EvsResult> EvsCamera::doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffers) {
- std::lock_guard <std::mutex> lock(mAccessLock);
-
+ std::lock_guard<std::mutex> lock(mAccessLock);
for (auto&& buffer : buffers) {
- returnBuffer(buffer.bufferId, buffer.buffer.nativeHandle);
+ returnBufferLocked(buffer.bufferId, buffer.buffer.nativeHandle);
}
-
return EvsResult::OK;
}
-
Return<EvsResult> EvsCamera::pauseVideoStream() {
+ ALOGD("%s", __FUNCTION__);
// Default implementation does not support this.
return EvsResult::UNDERLYING_SERVICE_ERROR;
}
-
Return<EvsResult> EvsCamera::resumeVideoStream() {
+ ALOGD("%s", __FUNCTION__);
// Default implementation does not support this.
return EvsResult::UNDERLYING_SERVICE_ERROR;
}
-
Return<EvsResult> EvsCamera::setMaster() {
+ ALOGD("%s", __FUNCTION__);
// Default implementation does not expect multiple subscribers and therefore
// return a success code always.
return EvsResult::OK;
}
-Return<EvsResult> EvsCamera::forceMaster(const sp<IEvsDisplay_1_0>& ) {
+Return<EvsResult> EvsCamera::forceMaster(const sp<V1_0::IEvsDisplay>&) {
+ ALOGD("%s", __FUNCTION__);
// Default implementation does not expect multiple subscribers and therefore
// return a success code always.
return EvsResult::OK;
}
-
Return<EvsResult> EvsCamera::unsetMaster() {
+ ALOGD("%s", __FUNCTION__);
// Default implementation does not expect multiple subscribers and therefore
// return a success code always.
return EvsResult::OK;
}
-
Return<void> EvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
hidl_vec<CameraParam> hidlCtrls;
hidlCtrls.resize(mCameraInfo->controls.size());
unsigned idx = 0;
@@ -303,72 +303,132 @@
}
_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;
- _hidl_cb(EvsResult::INVALID_ARG, 0);
- return Void();
-}
-
-
-Return<void> EvsCamera::getIntParameter(CameraParam id,
- getIntParameter_cb _hidl_cb) {
- // Default implementation does not support this.
- (void)id;
- _hidl_cb(EvsResult::INVALID_ARG, 0);
- return Void();
-}
-
-
-Return<EvsResult> EvsCamera::setExtendedInfo_1_1(uint32_t opaqueIdentifier,
- const hidl_vec<uint8_t>& opaqueValue) {
- // Default implementation does not use an extended info.
- (void)opaqueIdentifier;
- (void)opaqueValue;
- return EvsResult::INVALID_ARG;
-}
-
-
-Return<void> EvsCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
- getExtendedInfo_1_1_cb _hidl_cb) {
- // Default implementation does not use an extended info.
- (void)opaqueIdentifier;
-
- hidl_vec<uint8_t> value;
- _hidl_cb(EvsResult::INVALID_ARG, value);
- return Void();
-}
-
-
-Return<void>
-EvsCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& /* buffers */,
- importExternalBuffers_cb _hidl_cb) {
- ALOGW("%s is not implemented yet.", __FUNCTION__);
- _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
return {};
}
+Return<void> EvsCamera::getIntParameterRange(CameraParam id, getIntParameterRange_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
+ auto it = mCameraInfo->controls.find(id);
+ if (it == mCameraInfo->controls.end()) {
+ _hidl_cb(0, 0, 0);
+ } else {
+ _hidl_cb(std::get<0>(it->second), std::get<1>(it->second), std::get<2>(it->second));
+ }
+ return {};
+}
+
+Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
+ setIntParameter_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
+ mParams.insert_or_assign(id, value);
+ _hidl_cb(EvsResult::OK, {value});
+ return {};
+}
+
+Return<void> EvsCamera::getIntParameter([[maybe_unused]] CameraParam id,
+ getIntParameter_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
+ auto it = mParams.find(id);
+ std::vector<int32_t> values;
+ if (it == mParams.end()) {
+ _hidl_cb(EvsResult::INVALID_ARG, values);
+ } else {
+ values.push_back(it->second);
+ _hidl_cb(EvsResult::OK, values);
+ }
+ return {};
+}
+
+Return<EvsResult> EvsCamera::setExtendedInfo_1_1(uint32_t opaqueIdentifier,
+ const hidl_vec<uint8_t>& opaqueValue) {
+ ALOGD("%s", __FUNCTION__);
+ mExtInfo.insert_or_assign(opaqueIdentifier, opaqueValue);
+ return EvsResult::OK;
+}
+
+Return<void> EvsCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
+ getExtendedInfo_1_1_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
+ auto status = EvsResult::OK;
+ hidl_vec<uint8_t> value;
+ const auto it = mExtInfo.find(opaqueIdentifier);
+ if (it == mExtInfo.end()) {
+ status = EvsResult::INVALID_ARG;
+ } else {
+ value = it->second;
+ }
+ _hidl_cb(status, value);
+ return {};
+}
+
+Return<void> EvsCamera::importExternalBuffers([[maybe_unused]] const hidl_vec<BufferDesc>& buffers,
+ importExternalBuffers_cb _hidl_cb) {
+ auto numBuffersToAdd = buffers.size();
+ if (numBuffersToAdd < 1) {
+ ALOGD("No buffers to add");
+ _hidl_cb(EvsResult::OK, mFramesAllowed);
+ return {};
+ }
+
+ {
+ std::scoped_lock<std::mutex> lock(mAccessLock);
+
+ if (numBuffersToAdd > (kMaxBuffersInFlight - mFramesAllowed)) {
+ numBuffersToAdd -= (kMaxBuffersInFlight - mFramesAllowed);
+ ALOGW("Exceed the limit on number of buffers. %" PRIu64 " buffers will be added only.",
+ numBuffersToAdd);
+ }
+
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ const auto before = mFramesAllowed;
+ for (auto i = 0; i < numBuffersToAdd; ++i) {
+ // TODO: reject if external buffer is configured differently.
+ auto& b = buffers[i];
+ const AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<const AHardwareBuffer_Desc*>(&b.buffer.description);
+
+ // Import a buffer to add
+ buffer_handle_t memHandle = nullptr;
+ status_t result =
+ mapper.importBuffer(b.buffer.nativeHandle, pDesc->width, pDesc->height, 1,
+ pDesc->format, pDesc->usage, pDesc->stride, &memHandle);
+ if (result != android::NO_ERROR || !memHandle) {
+ ALOGW("Failed to import a buffer %d", b.bufferId);
+ continue;
+ }
+
+ auto stored = false;
+ for (auto&& rec : mBuffers) {
+ if (rec.handle == nullptr) {
+ // Use this existing entry
+ rec.handle = memHandle;
+ rec.inUse = false;
+
+ stored = true;
+ break;
+ }
+ }
+
+ if (!stored) {
+ // Add a BufferRecord wrapping this handle to our set of available buffers
+ mBuffers.emplace_back(memHandle);
+ }
+
+ ++mFramesAllowed;
+ }
+
+ _hidl_cb(EvsResult::OK, mFramesAllowed - before);
+ return {};
+ }
+}
bool EvsCamera::setAvailableFrames_Locked(unsigned bufferCount) {
- if (bufferCount < 1) {
- ALOGE("Ignoring request to set buffer count to zero");
+ if (bufferCount < kMinimumBuffersInFlight) {
+ ALOGE("Ignoring request to set buffer count below the minimum number of buffers to run a "
+ "video stream");
return false;
}
- if (bufferCount > MAX_BUFFERS_IN_FLIGHT) {
+ if (bufferCount > kMaxBuffersInFlight) {
ALOGE("Rejecting buffer request in excess of internal limit");
return false;
}
@@ -403,17 +463,16 @@
return true;
}
-
unsigned EvsCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
// Acquire the graphics buffer allocator
- GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+ GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
unsigned added = 0;
while (added < numToAdd) {
buffer_handle_t memHandle = nullptr;
- status_t result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage,
- &memHandle, &mStride, 0, "EvsCamera");
+ status_t result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage, &memHandle, &mStride,
+ 0, "EvsCamera");
if (result != NO_ERROR) {
ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
break;
@@ -436,7 +495,7 @@
}
if (!stored) {
// Add a BufferRecord wrapping this handle to our set of available buffers
- mBuffers.emplace_back(memHandle);
+ mBuffers.push_back(std::move(BufferRecord(memHandle)));
}
mFramesAllowed++;
@@ -446,10 +505,9 @@
return added;
}
-
unsigned EvsCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
// Acquire the graphics buffer allocator
- GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+ GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
unsigned removed = 0;
@@ -472,14 +530,12 @@
return removed;
}
-
// This is the asynchronous frame generation thread that runs in parallel with the
// main serving thread. There is one for each active camera instance.
void EvsCamera::generateFrames() {
ALOGD("Frame generation loop started");
unsigned idx;
-
while (true) {
bool timeForFrame = false;
nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -521,9 +577,9 @@
if (timeForFrame) {
// Assemble the buffer description we'll transmit below
- BufferDesc_1_1 newBuffer = {};
+ BufferDesc newBuffer = {};
AHardwareBuffer_Desc* pDesc =
- reinterpret_cast<AHardwareBuffer_Desc *>(&newBuffer.buffer.description);
+ reinterpret_cast<AHardwareBuffer_Desc*>(&newBuffer.buffer.description);
pDesc->width = mWidth;
pDesc->height = mHeight;
pDesc->layers = 1;
@@ -534,19 +590,16 @@
newBuffer.pixelSize = sizeof(uint32_t);
newBuffer.bufferId = idx;
newBuffer.deviceId = mDescription.v1.cameraId;
- newBuffer.timestamp = elapsedRealtimeNano();
+ newBuffer.timestamp = elapsedRealtimeNano() * 1e+3; // timestamps is in microseconds
// Write test data into the image buffer
fillTestFrame(newBuffer);
// Issue the (asynchronous) callback to the client -- can't be holding the lock
- hidl_vec<BufferDesc_1_1> frames;
- frames.resize(1);
- frames[0] = newBuffer;
- auto result = mStream->deliverFrame_1_1(frames);
+ auto result = mStream->deliverFrame_1_1({newBuffer});
if (result.isOk()) {
- ALOGD("Delivered %p as id %d",
- newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
+ ALOGD("Delivered %p as id %d", newBuffer.buffer.nativeHandle.getNativeHandle(),
+ newBuffer.bufferId);
} else {
// This can happen if the client dies and is likely unrecoverable.
// To avoid consuming resources generating failing calls, we stop sending
@@ -563,63 +616,50 @@
}
}
- // We arbitrarily choose to generate frames at 12 fps to ensure we pass the 10fps test requirement
- static const int kTargetFrameRate = 12;
- static const nsecs_t kTargetFrameTimeUs = 1000*1000 / kTargetFrameRate;
+ // We arbitrarily choose to generate frames at 15 fps to ensure we pass the 10fps test
+ // requirement
+ static const int kTargetFrameRate = 15;
+ static const nsecs_t kTargetFrameIntervalUs = 1000 * 1000 / kTargetFrameRate;
const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- const nsecs_t workTimeUs = (now - startTime) / 1000;
- const nsecs_t sleepDurationUs = kTargetFrameTimeUs - workTimeUs;
+ const nsecs_t elapsedTimeUs = (now - startTime) / 1000;
+ const nsecs_t sleepDurationUs = kTargetFrameIntervalUs - elapsedTimeUs;
if (sleepDurationUs > 0) {
usleep(sleepDurationUs);
}
}
// If we've been asked to stop, send an event to signal the actual end of stream
- EvsEventDesc event;
- event.aType = EvsEventType::STREAM_STOPPED;
- auto result = mStream->notify(event);
- if (!result.isOk()) {
+ EvsEventDesc event = {
+ .aType = EvsEventType::STREAM_STOPPED,
+ };
+ if (!mStream->notify(event).isOk()) {
ALOGE("Error delivering end of stream marker");
}
return;
}
-
-void EvsCamera::fillTestFrame(const BufferDesc_1_1& buff) {
+void EvsCamera::fillTestFrame(const BufferDesc& buff) {
// Lock our output buffer for writing
- uint32_t *pixels = nullptr;
+ uint32_t* pixels = nullptr;
const AHardwareBuffer_Desc* pDesc =
- reinterpret_cast<const AHardwareBuffer_Desc *>(&buff.buffer.description);
- GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+ reinterpret_cast<const AHardwareBuffer_Desc*>(&buff.buffer.description);
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
mapper.lock(buff.buffer.nativeHandle,
GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
- android::Rect(pDesc->width, pDesc->height),
- (void **) &pixels);
+ android::Rect(pDesc->width, pDesc->height), (void**)&pixels);
// If we failed to lock the pixel buffer, we're about to crash, but log it first
if (!pixels) {
ALOGE("Camera failed to gain access to image buffer for writing");
+ return;
}
- // Fill in the test pixels
+ // Fill in the test pixels; the colorbar in ABGR format
for (unsigned row = 0; row < pDesc->height; row++) {
for (unsigned col = 0; col < pDesc->width; col++) {
- // Index into the row to check the pixel at this column.
- // We expect 0xFF in the LSB channel, a vertical gradient in the
- // second channel, a horitzontal gradient in the third channel, and
- // 0xFF in the MSB.
- // The exception is the very first 32 bits which is used for the
- // time varying frame signature to avoid getting fooled by a static image.
- uint32_t expectedPixel = 0xFF0000FF | // MSB and LSB
- ((row & 0xFF) << 8) | // vertical gradient
- ((col & 0xFF) << 16); // horizontal gradient
- if ((row | col) == 0) {
- static uint32_t sFrameTicker = 0;
- expectedPixel = (sFrameTicker) & 0xFF;
- sFrameTicker++;
- }
- pixels[col] = expectedPixel;
+ const uint32_t index = col * kNumColors / pDesc->width;
+ pixels[col] = kColors[index];
}
// Point to the next row
// NOTE: stride retrieved from gralloc is in units of pixels
@@ -630,39 +670,35 @@
mapper.unlock(buff.buffer.nativeHandle);
}
-
-void EvsCamera::fillTestFrame(const BufferDesc_1_0& buff) {
- BufferDesc_1_1 newBufDesc = {};
- AHardwareBuffer_Desc desc = {
- buff.width, // width
- buff.height, // height
- 1, // layers, always 1 for EVS
- buff.format, // One of AHardwareBuffer_Format
- buff.usage, // Combination of AHardwareBuffer_UsageFlags
- buff.stride, // Row stride in pixels
- 0, // Reserved
- 0 // Reserved
+void EvsCamera::fillTestFrame(const V1_0::BufferDesc& buff) {
+ BufferDesc newBuffer = {
+ .buffer.nativeHandle = buff.memHandle,
+ .pixelSize = buff.pixelSize,
+ .bufferId = buff.bufferId,
};
- memcpy(&desc, &newBufDesc.buffer.description, sizeof(desc));
- newBufDesc.buffer.nativeHandle = buff.memHandle;
- newBufDesc.pixelSize = buff.pixelSize;
- newBufDesc.bufferId = buff.bufferId;
-
- return fillTestFrame(newBufDesc);
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc*>(&newBuffer.buffer.description);
+ *pDesc = {
+ buff.width, // width
+ buff.height, // height
+ 1, // layers, always 1 for EVS
+ buff.format, // One of AHardwareBuffer_Format
+ buff.usage, // Combination of AHardwareBuffer_UsageFlags
+ buff.stride, // Row stride in pixels
+ 0, // Reserved
+ 0 // Reserved
+ };
+ return fillTestFrame(newBuffer);
}
-
-void EvsCamera::returnBuffer(const uint32_t bufferId, const buffer_handle_t memHandle) {
- std::lock_guard <std::mutex> lock(mAccessLock);
-
+void EvsCamera::returnBufferLocked(const uint32_t bufferId, const buffer_handle_t memHandle) {
if (memHandle == nullptr) {
ALOGE("ignoring doneWithFrame called with null handle");
} else if (bufferId >= mBuffers.size()) {
- ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)",
- bufferId, mBuffers.size()-1);
+ ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)", bufferId,
+ mBuffers.size() - 1);
} else if (!mBuffers[bufferId].inUse) {
- ALOGE("ignoring doneWithFrame called on frame %d which is already free",
- bufferId);
+ ALOGE("ignoring doneWithFrame called on frame %d which is already free", bufferId);
} else {
// Mark the frame as available
mBuffers[bufferId].inUse = false;
@@ -683,42 +719,33 @@
}
}
-
-sp<EvsCamera> EvsCamera::Create(const char *deviceName) {
- unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
+sp<EvsCamera> EvsCamera::Create(const char* deviceName) {
+ std::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::Create(const char* deviceName,
+ std::unique_ptr<ConfigManager::CameraInfo>& camInfo,
+ [[maybe_unused]] 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 */
+ // Use the first resolution from the list for the testing
+ // TODO(b/214835237): Uses a given Stream configuration to choose the best
+ // stream configuration.
auto it = camInfo->streamConfigurations.begin();
evsCamera->mWidth = it->second[1];
evsCamera->mHeight = it->second[2];
- evsCamera->mDescription.v1.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
+ 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;
+ 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
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/EvsCamera.h b/automotive/evs/1.1/default/EvsCamera.h
index 6163a34..1ea1186 100644
--- a/automotive/evs/1.1/default/EvsCamera.h
+++ b/automotive/evs/1.1/default/EvsCamera.h
@@ -17,91 +17,70 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERA_H
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERA_H
-#include <android/hardware/automotive/evs/1.1/types.h>
+#include "ConfigManager.h"
+
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
#include <android/hardware/automotive/evs/1.1/IEvsCameraStream.h>
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
+#include <android/hardware/automotive/evs/1.1/types.h>
#include <ui/GraphicBuffer.h>
#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;
-using IEvsCameraStream_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCameraStream;
-using ::android::hardware::automotive::evs::V1_0::EvsResult;
-using ::android::hardware::automotive::evs::V1_0::CameraDesc;
-using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
-using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
-
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
-
+namespace android::hardware::automotive::evs::V1_1::implementation {
// From EvsEnumerator.h
class EvsEnumerator;
-
class EvsCamera : public IEvsCamera {
-public:
+ public:
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
- Return<void> getCameraInfo(getCameraInfo_cb _hidl_cb) override;
- Return<EvsResult> setMaxFramesInFlight(uint32_t bufferCount) override;
- Return<EvsResult> startVideoStream(const ::android::sp<IEvsCameraStream_1_0>& stream) override;
- Return<void> stopVideoStream() override;
- Return<void> doneWithFrame(const BufferDesc_1_0& buffer) override;
+ Return<void> getCameraInfo(getCameraInfo_cb _hidl_cb) override;
+ Return<V1_0::EvsResult> setMaxFramesInFlight(uint32_t bufferCount) override;
+ Return<V1_0::EvsResult> startVideoStream(const sp<V1_0::IEvsCameraStream>& stream) override;
+ Return<void> stopVideoStream() override;
+ Return<void> doneWithFrame(const V1_0::BufferDesc& buffer) override;
- Return<int32_t> getExtendedInfo(uint32_t opaqueIdentifier) override;
- Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) override;
+ Return<int32_t> getExtendedInfo(uint32_t opaqueIdentifier) override;
+ Return<V1_0::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<void> getPhysicalCameraInfo(const hidl_string& id,
- getPhysicalCameraInfo_cb _hidl_cb) override;
- Return<EvsResult> pauseVideoStream() override;
- Return<EvsResult> resumeVideoStream() override;
- Return<EvsResult> doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffer) override;
- Return<EvsResult> setMaster() override;
- Return<EvsResult> forceMaster(const sp<IEvsDisplay_1_0>& 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;
- Return<EvsResult> setExtendedInfo_1_1(uint32_t opaqueIdentifier,
- const hidl_vec<uint8_t>& opaqueValue) override;
- Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
- getExtendedInfo_1_1_cb _hidl_cb) override;
- Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
- importExternalBuffers_cb _hidl_cb) override;
+ Return<void> getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) override;
+ Return<void> getPhysicalCameraInfo(const hidl_string& id,
+ getPhysicalCameraInfo_cb _hidl_cb) override;
+ Return<V1_0::EvsResult> pauseVideoStream() override;
+ Return<V1_0::EvsResult> resumeVideoStream() override;
+ Return<V1_0::EvsResult> doneWithFrame_1_1(const hidl_vec<BufferDesc>& buffer) override;
+ Return<V1_0::EvsResult> setMaster() override;
+ Return<V1_0::EvsResult> forceMaster(const sp<V1_0::IEvsDisplay>& display) override;
+ Return<V1_0::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;
+ Return<V1_0::EvsResult> setExtendedInfo_1_1(uint32_t opaqueIdentifier,
+ const hidl_vec<uint8_t>& opaqueValue) override;
+ Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
+ getExtendedInfo_1_1_cb _hidl_cb) override;
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc>& buffers,
+ importExternalBuffers_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);
+ static sp<EvsCamera> Create(const char* deviceName);
+ static sp<EvsCamera> Create(const char* deviceName,
+ std::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
+ void forceShutdown(); // This gets called if another caller "steals" ownership of the camera
const CameraDesc& getDesc() { return mDescription; };
- static const char kCameraName_Backup[];
-
-private:
- EvsCamera(const char *id,
- unique_ptr<ConfigManager::CameraInfo> &camInfo);
+ private:
+ EvsCamera(const char* id, std::unique_ptr<ConfigManager::CameraInfo>& camInfo);
// These three functions are expected to be called while mAccessLock is held
//
bool setAvailableFrames_Locked(unsigned bufferCount);
@@ -109,34 +88,34 @@
unsigned decreaseAvailableFrames_Locked(unsigned numToRemove);
void generateFrames();
- void fillTestFrame(const BufferDesc_1_0& buff);
- void fillTestFrame(const BufferDesc_1_1& buff);
- void returnBuffer(const uint32_t bufferId, const buffer_handle_t memHandle);
+ void fillTestFrame(const V1_0::BufferDesc& buff);
+ void fillTestFrame(const BufferDesc& buff);
+ void returnBufferLocked(const uint32_t bufferId, const buffer_handle_t memHandle);
sp<EvsEnumerator> mEnumerator; // The enumerator object that created this camera
- CameraDesc mDescription = {}; // The properties of this camera
+ CameraDesc mDescription = {}; // The properties of this camera
- std::thread mCaptureThread; // The thread we'll use to synthesize frames
+ std::thread mCaptureThread; // The thread we'll use to synthesize frames
- uint32_t mWidth = 0; // Horizontal pixel count in the buffers
- uint32_t mHeight = 0; // Vertical pixel count in the buffers
- uint32_t mFormat = 0; // Values from android_pixel_format_t
- uint64_t mUsage = 0; // Values from from Gralloc.h
- uint32_t mStride = 0; // Bytes per line in the buffers
+ uint32_t mWidth = 0; // Horizontal pixel count in the buffers
+ uint32_t mHeight = 0; // Vertical pixel count in the buffers
+ uint32_t mFormat = 0; // Values from android_pixel_format_t
+ uint64_t mUsage = 0; // Values from from Gralloc.h
+ uint32_t mStride = 0; // Bytes per line in the buffers
- sp<IEvsCameraStream_1_1> mStream = nullptr; // The callback used to deliver each frame
+ sp<IEvsCameraStream> mStream = nullptr; // The callback used to deliver each frame
struct BufferRecord {
buffer_handle_t handle;
bool inUse;
- explicit BufferRecord(buffer_handle_t h) : handle(h), inUse(false) {};
+ explicit BufferRecord(buffer_handle_t h) : handle(h), inUse(false){};
};
- std::vector <BufferRecord> mBuffers; // Graphics buffers to transfer images
- unsigned mFramesAllowed; // How many buffers are we currently using
- unsigned mFramesInUse; // How many buffers are currently outstanding
+ std::vector<BufferRecord> mBuffers; // Graphics buffers to transfer images
+ unsigned mFramesAllowed; // How many buffers are we currently using
+ unsigned mFramesInUse; // How many buffers are currently outstanding
enum StreamStateValues {
STOPPED,
@@ -150,14 +129,13 @@
std::mutex mAccessLock;
// Static camera module information
- unique_ptr<ConfigManager::CameraInfo> &mCameraInfo;
+ std::unique_ptr<ConfigManager::CameraInfo>& mCameraInfo;
+
+ // For the extended info
+ std::unordered_map<uint32_t, hidl_vec<uint8_t>> mExtInfo;
+ std::unordered_map<CameraParam, int32_t> mParams;
};
-} // namespace implementation
-} // namespace V1_1
-} // namespace evs
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERA_H
diff --git a/automotive/evs/1.1/default/EvsDisplay.cpp b/automotive/evs/1.1/default/EvsDisplay.cpp
index 2b5a4a9..f7169e5 100644
--- a/automotive/evs/1.1/default/EvsDisplay.cpp
+++ b/automotive/evs/1.1/default/EvsDisplay.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.automotive.evs@1.1-service"
-
#include "EvsDisplay.h"
#include <ui/GraphicBufferAllocator.h>
@@ -23,51 +21,53 @@
using ::android::frameworks::automotive::display::V1_0::HwDisplayConfig;
using ::android::frameworks::automotive::display::V1_0::HwDisplayState;
+using ::android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
+using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
+using ::android::hardware::automotive::evs::V1_0::DisplayState;
+using ::android::hardware::automotive::evs::V1_0::EvsResult;
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
+namespace {
+ // Arbitrary magic number for self-recognition
+ constexpr uint32_t kDefaultDisplayBufferId = 0x3870;
+
+} // namespace
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
EvsDisplay::EvsDisplay() {
EvsDisplay(nullptr, 0);
}
-
EvsDisplay::EvsDisplay(sp<IAutomotiveDisplayProxyService> pDisplayProxy, uint64_t displayId)
: mDisplayProxy(pDisplayProxy),
- mDisplayId(displayId) {
+ mDisplayId(displayId),
+ mGlWrapper(std::make_unique<GlWrapper>()) {
ALOGD("EvsDisplay instantiated");
// Set up our self description
// NOTE: These are arbitrary values chosen for testing
- mInfo.displayId = "Mock Display";
- mInfo.vendorFlags = 3870;
+ mInfo.displayId = "Mock Display";
+ mInfo.vendorFlags = 3870;
// Assemble the buffer description we'll use for our render target
- mBuffer.width = 320;
- mBuffer.height = 240;
- mBuffer.format = HAL_PIXEL_FORMAT_RGBA_8888;
- mBuffer.usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
- mBuffer.bufferId = 0x3870; // Arbitrary magic number for self recognition
- mBuffer.pixelSize = 4;
+ mBuffer.width = 640;
+ mBuffer.height = 360;
+ mBuffer.format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mBuffer.usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
+ mBuffer.bufferId = kDefaultDisplayBufferId;
+ mBuffer.pixelSize = 4;
}
-
EvsDisplay::~EvsDisplay() {
ALOGD("EvsDisplay being destroyed");
forceShutdown();
}
-
/**
* This gets called if another caller "steals" ownership of the display
*/
-void EvsDisplay::forceShutdown()
-{
+void EvsDisplay::forceShutdown() {
ALOGD("EvsDisplay forceShutdown");
std::lock_guard<std::mutex> lock(mAccessLock);
@@ -84,6 +84,11 @@
GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
alloc.free(mBuffer.memHandle);
mBuffer.memHandle = nullptr;
+
+ if (mGlWrapper) {
+ mGlWrapper->hideWindow(mDisplayProxy, mDisplayId);
+ mGlWrapper->shutdown();
+ }
}
// Put this object into an unrecoverable error state since somebody else
@@ -91,20 +96,18 @@
mRequestedState = DisplayState::DEAD;
}
-
/**
* Returns basic information about the EVS display provided by the system.
* See the description of the DisplayDesc structure for details.
*/
-Return<void> EvsDisplay::getDisplayInfo(getDisplayInfo_cb _hidl_cb) {
+Return<void> EvsDisplay::getDisplayInfo(getDisplayInfo_cb _hidl_cb) {
ALOGD("getDisplayInfo");
// Send back our self description
_hidl_cb(mInfo);
- return Void();
+ return {};
}
-
/**
* Clients may set the display state to express their desired state.
* The HAL implementation must gracefully accept a request for any state
@@ -124,18 +127,28 @@
}
// Ensure we recognize the requested state so we don't go off the rails
- if (state < DisplayState::NUM_STATES) {
- // Record the requested state
- mRequestedState = state;
- return EvsResult::OK;
- }
- else {
- // Turn off the display if asked for an unrecognized state
- mRequestedState = DisplayState::NOT_VISIBLE;
+ if (state >= DisplayState::NUM_STATES) {
return EvsResult::INVALID_ARG;
}
-}
+ if (!mGlWrapper) {
+ switch (state) {
+ case DisplayState::NOT_VISIBLE:
+ mGlWrapper->hideWindow(mDisplayProxy, mDisplayId);
+ break;
+ case DisplayState::VISIBLE:
+ mGlWrapper->showWindow(mDisplayProxy, mDisplayId);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Record the requested state
+ mRequestedState = state;
+
+ return EvsResult::OK;
+}
/**
* The HAL implementation should report the actual current state, which might
@@ -144,14 +157,13 @@
* the device layer, making it undesirable for the HAL implementation to
* spontaneously change display states.
*/
-Return<DisplayState> EvsDisplay::getDisplayState() {
+Return<DisplayState> EvsDisplay::getDisplayState() {
ALOGD("getDisplayState");
std::lock_guard<std::mutex> lock(mAccessLock);
return mRequestedState;
}
-
/**
* This call returns a handle to a frame buffer associated with the display.
* This buffer may be locked and written to by software and/or GL. This buffer
@@ -159,43 +171,55 @@
* display is no longer visible.
*/
// TODO: We need to know if/when our client dies so we can get the buffer back! (blocked b/31632518)
-Return<void> EvsDisplay::getTargetBuffer(getTargetBuffer_cb _hidl_cb) {
+Return<void> EvsDisplay::getTargetBuffer(getTargetBuffer_cb _hidl_cb) {
ALOGD("getTargetBuffer");
std::lock_guard<std::mutex> lock(mAccessLock);
if (mRequestedState == DisplayState::DEAD) {
ALOGE("Rejecting buffer request from object that lost ownership of the display.");
- BufferDesc_1_0 nullBuff = {};
- _hidl_cb(nullBuff);
- return Void();
+ _hidl_cb({});
+ return {};
}
// If we don't already have a buffer, allocate one now
if (!mBuffer.memHandle) {
+ // Initialize our display window
+ // NOTE: This will cause the display to become "VISIBLE" before a frame is actually
+ // returned, which is contrary to the spec and will likely result in a black frame being
+ // (briefly) shown.
+ if (mGlWrapper->initialize(mDisplayProxy, mDisplayId)) {
+ // Assemble the buffer description we'll use for our render target
+ mBuffer.width = mGlWrapper->getWidth();
+ mBuffer.height = mGlWrapper->getHeight();
+ mBuffer.format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mBuffer.usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
+ mBuffer.bufferId = kDefaultDisplayBufferId;
+ mBuffer.pixelSize = 4;
+ } else {
+ // If we failed to initialize a EGL, then we're not going to display
+ // any.
+ mGlWrapper = nullptr;
+ }
+
// Allocate the buffer that will hold our displayable image
buffer_handle_t handle = nullptr;
GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
- status_t result = alloc.allocate(
- mBuffer.width, mBuffer.height, mBuffer.format, 1, mBuffer.usage,
- &handle, &mBuffer.stride, 0, "EvsDisplay");
- if (result != NO_ERROR) {
- ALOGE("Error %d allocating %d x %d graphics buffer",
- result, mBuffer.width, mBuffer.height);
- BufferDesc_1_0 nullBuff = {};
- _hidl_cb(nullBuff);
- return Void();
- }
- if (!handle) {
- ALOGE("We didn't get a buffer handle back from the allocator");
- BufferDesc_1_0 nullBuff = {};
- _hidl_cb(nullBuff);
- return Void();
+ status_t result = alloc.allocate(mBuffer.width, mBuffer.height, mBuffer.format, 1,
+ mBuffer.usage, &handle, &mBuffer.stride, 0, "EvsDisplay");
+ if (result != NO_ERROR || !handle) {
+ ALOGE("Error %d allocating %d x %d graphics buffer", result, mBuffer.width,
+ mBuffer.height);
+ if (mGlWrapper) {
+ mGlWrapper->shutdown();
+ }
+ _hidl_cb({});
+ return {};
}
mBuffer.memHandle = handle;
mFrameBusy = false;
- ALOGD("Allocated new buffer %p with stride %u",
- mBuffer.memHandle.getNativeHandle(), mBuffer.stride);
+ ALOGD("Allocated new buffer %p with stride %u", mBuffer.memHandle.getNativeHandle(),
+ mBuffer.stride);
}
// Do we have a frame available?
@@ -205,41 +229,40 @@
// a previously issued buffer yet (they're behaving badly).
// NOTE: We have to make the callback even if we have nothing to provide
ALOGE("getTargetBuffer called while no buffers available.");
- BufferDesc_1_0 nullBuff = {};
- _hidl_cb(nullBuff);
- return Void();
+ _hidl_cb({});
+ return {};
} else {
// Mark our buffer as busy
mFrameBusy = true;
// Send the buffer to the client
- ALOGD("Providing display buffer handle %p as id %d",
- mBuffer.memHandle.getNativeHandle(), mBuffer.bufferId);
+ ALOGD("Providing display buffer handle %p as id %d", mBuffer.memHandle.getNativeHandle(),
+ mBuffer.bufferId);
_hidl_cb(mBuffer);
- return Void();
+ return {};
}
}
-
/**
* This call tells the display that the buffer is ready for display.
* The buffer is no longer valid for use by the client after this call.
*/
-Return<EvsResult> EvsDisplay::returnTargetBufferForDisplayImpl(const uint32_t bufferId, const buffer_handle_t memHandle) {
+Return<EvsResult> EvsDisplay::returnTargetBufferForDisplayImpl(const uint32_t bufferId,
+ const buffer_handle_t memHandle) {
ALOGD("returnTargetBufferForDisplay %p", memHandle);
std::lock_guard<std::mutex> lock(mAccessLock);
// Nobody should call us with a null handle
if (!memHandle) {
- ALOGE ("returnTargetBufferForDisplay called without a valid buffer handle.\n");
+ ALOGE("returnTargetBufferForDisplay called without a valid buffer handle.\n");
return EvsResult::INVALID_ARG;
}
if (bufferId != mBuffer.bufferId) {
- ALOGE ("Got an unrecognized frame returned.\n");
+ ALOGE("Got an unrecognized frame returned.\n");
return EvsResult::INVALID_ARG;
}
if (!mFrameBusy) {
- ALOGE ("A frame was returned with no outstanding frames.\n");
+ ALOGE("A frame was returned with no outstanding frames.\n");
return EvsResult::BUFFER_NOT_AVAILABLE;
}
@@ -253,23 +276,32 @@
// If we were waiting for a new frame, this is it!
if (mRequestedState == DisplayState::VISIBLE_ON_NEXT_FRAME) {
mRequestedState = DisplayState::VISIBLE;
+ if (mGlWrapper) {
+ mGlWrapper->showWindow(mDisplayProxy, mDisplayId);
+ }
}
// Validate we're in an expected state
if (mRequestedState != DisplayState::VISIBLE) {
// We shouldn't get frames back when we're not visible.
- ALOGE ("Got an unexpected frame returned while not visible - ignoring.\n");
- } else {
+ ALOGE("Got an unexpected frame returned while not visible - ignoring.\n");
+ } else if (mGlWrapper) {
// This is where the buffer would be made visible.
- // For now we simply validate it has the data we expect in it by reading it back
+ if (!mGlWrapper->updateImageTexture(mBuffer)) {
+ return EvsResult::UNDERLYING_SERVICE_ERROR;
+ }
+ // Put the image on the screen
+ mGlWrapper->renderImageToScreen();
+ } else {
+ // TODO: Move below validation logic to somewhere else
+#if 0
+ // For now we simply validate it has the data we expect in it by reading it back
// Lock our display buffer for reading
uint32_t* pixels = nullptr;
- GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- mapper.lock(mBuffer.memHandle,
- GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
- android::Rect(mBuffer.width, mBuffer.height),
- (void **)&pixels);
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ mapper.lock(mBuffer.memHandle, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
+ android::Rect(mBuffer.width, mBuffer.height), (void**)&pixels);
// If we failed to lock the pixel buffer, we're about to crash, but log it first
if (!pixels) {
@@ -286,8 +318,8 @@
// 0xFF in the MSB.
// The exception is the very first 32 bits which is used for the
// time varying frame signature to avoid getting fooled by a static image.
- uint32_t expectedPixel = 0xFF0000FF | // MSB and LSB
- ((row & 0xFF) << 8) | // vertical gradient
+ uint32_t expectedPixel = 0xFF0000FF | // MSB and LSB
+ ((row & 0xFF) << 8) | // vertical gradient
((col & 0xFF) << 16); // horizontal gradient
if ((row | col) == 0) {
// we'll check the "uniqueness" of the frame signature below
@@ -318,39 +350,31 @@
ALOGE("Duplicate, likely stale frame buffer detected");
}
-
// Release our output buffer
mapper.unlock(mBuffer.memHandle);
if (!frameLooksGood) {
return EvsResult::UNDERLYING_SERVICE_ERROR;
}
+#endif
}
return EvsResult::OK;
}
-
-Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const BufferDesc_1_0& buffer) {
+Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const V1_0::BufferDesc& buffer) {
return returnTargetBufferForDisplayImpl(buffer.bufferId, buffer.memHandle);
}
-
Return<void> EvsDisplay::getDisplayInfo_1_1(getDisplayInfo_1_1_cb _info_cb) {
if (mDisplayProxy != nullptr) {
return mDisplayProxy->getDisplayInfo(mDisplayId, _info_cb);
} else {
HwDisplayConfig nullConfig;
- HwDisplayState nullState;
+ HwDisplayState nullState;
_info_cb(nullConfig, nullState);
- return Void();
+ return {};
}
}
-
-} // namespace implementation
-} // namespace V1_1
-} // namespace evs
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/EvsDisplay.h b/automotive/evs/1.1/default/EvsDisplay.h
index 9b2ed90..b2ec3e8 100644
--- a/automotive/evs/1.1/default/EvsDisplay.h
+++ b/automotive/evs/1.1/default/EvsDisplay.h
@@ -17,64 +17,48 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSDISPLAY_H
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSDISPLAY_H
-#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
+#include "GlWrapper.h"
+
#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
+#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
#include <ui/GraphicBuffer.h>
-using ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
-using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
-using ::android::hardware::automotive::evs::V1_0::DisplayState;
-using ::android::hardware::automotive::evs::V1_0::EvsResult;
-using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
-using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
-
+namespace android::hardware::automotive::evs::V1_1::implementation {
class EvsDisplay : public IEvsDisplay {
-public:
+ public:
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsDisplay follow.
- Return<void> getDisplayInfo(getDisplayInfo_cb _hidl_cb) override;
- Return<EvsResult> setDisplayState(DisplayState state) override;
- Return<DisplayState> getDisplayState() override;
- Return<void> getTargetBuffer(getTargetBuffer_cb _hidl_cb) override;
- Return<EvsResult> returnTargetBufferForDisplay(const BufferDesc_1_0& buffer) override;
+ Return<void> getDisplayInfo(getDisplayInfo_cb _hidl_cb) override;
+ Return<V1_0::EvsResult> setDisplayState(V1_0::DisplayState state) override;
+ Return<V1_0::DisplayState> getDisplayState() override;
+ Return<void> getTargetBuffer(getTargetBuffer_cb _hidl_cb) override;
+ Return<V1_0::EvsResult> returnTargetBufferForDisplay(const V1_0::BufferDesc& buffer) override;
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsDisplay follow.
- Return<void> getDisplayInfo_1_1(getDisplayInfo_1_1_cb _info_cb) override;
+ Return<void> getDisplayInfo_1_1(getDisplayInfo_1_1_cb _info_cb) override;
// Implementation details
EvsDisplay();
- EvsDisplay(sp<IAutomotiveDisplayProxyService> pDisplayProxy, uint64_t displayId);
+ EvsDisplay(
+ sp<frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService> pDisplayProxy,
+ uint64_t displayId);
virtual ~EvsDisplay() override;
- void forceShutdown(); // This gets called if another caller "steals" ownership of the display
- Return<EvsResult> returnTargetBufferForDisplayImpl(const uint32_t bufferId,
- const buffer_handle_t memHandle);
+ void forceShutdown(); // This gets called if another caller "steals" ownership of the display
+ Return<V1_0::EvsResult> returnTargetBufferForDisplayImpl(const uint32_t bufferId,
+ const buffer_handle_t memHandle);
-private:
- DisplayDesc mInfo = {};
- BufferDesc_1_0 mBuffer = {}; // A graphics buffer into which we'll store images
-
- bool mFrameBusy = false; // A flag telling us our buffer is in use
- DisplayState mRequestedState = DisplayState::NOT_VISIBLE;
-
- std::mutex mAccessLock;
-
- sp<IAutomotiveDisplayProxyService> mDisplayProxy;
- uint64_t mDisplayId;
+ private:
+ V1_0::DisplayDesc mInfo = {};
+ V1_0::BufferDesc mBuffer = {}; // A graphics buffer into which we'll store images
+ V1_0::DisplayState mRequestedState = V1_0::DisplayState::NOT_VISIBLE;
+ bool mFrameBusy = false; // A flag telling us our buffer is in use
+ std::mutex mAccessLock;
+ sp<frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService> mDisplayProxy;
+ uint64_t mDisplayId;
+ std::unique_ptr<GlWrapper> mGlWrapper;
};
-} // namespace implementation
-} // namespace V1_1
-} // namespace evs
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSDISPLAY_H
diff --git a/automotive/evs/1.1/default/EvsEnumerator.cpp b/automotive/evs/1.1/default/EvsEnumerator.cpp
index d066471..b84268a 100644
--- a/automotive/evs/1.1/default/EvsEnumerator.cpp
+++ b/automotive/evs/1.1/default/EvsEnumerator.cpp
@@ -14,184 +14,171 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.automotive.evs@1.1-service"
-
#include "EvsEnumerator.h"
#include "EvsCamera.h"
#include "EvsDisplay.h"
#include "EvsUltrasonicsArray.h"
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
+using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
+using android::hardware::automotive::evs::V1_0::EvsResult;
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+namespace evs_v1_0 = ::android::hardware::automotive::evs::V1_0;
// NOTE: All members values are static so that all clients operate on the same state
// That is to say, this is effectively a singleton despite the fact that HIDL
// constructs a new instance for each client.
-std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
-wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
-unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
-sp<IAutomotiveDisplayProxyService> EvsEnumerator::sDisplayProxyService;
-std::unordered_map<uint8_t, uint64_t> EvsEnumerator::sDisplayPortList;
-std::list<EvsEnumerator::UltrasonicsArrayRecord> EvsEnumerator::sUltrasonicsArrayRecordList;
+std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
+wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
+std::unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
+sp<IAutomotiveDisplayProxyService> EvsEnumerator::sDisplayProxyService;
+std::unordered_map<uint8_t, uint64_t> EvsEnumerator::sDisplayPortList;
+std::list<EvsEnumerator::UltrasonicsArrayRecord> EvsEnumerator::sUltrasonicsArrayRecordList;
+uint64_t EvsEnumerator::sInternalDisplayId;
-EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
- ALOGD("EvsEnumerator created");
+EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService>& windowService) {
+ ALOGD("%s", __FUNCTION__);
// 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("/vendor/etc/automotive/evs/evs_default_configuration.xml");
+ ConfigManager::Create("/vendor/etc/automotive/evs/evs_default_configuration.xml");
// Add available cameras
for (auto v : sConfigManager->getCameraList()) {
- sCameraList.emplace_back(v.c_str());
+ CameraRecord rec(v.data());
+ std::unique_ptr<ConfigManager::CameraInfo>& pInfo = sConfigManager->getCameraInfo(v);
+ if (pInfo) {
+ rec.desc.metadata.setToExternal(reinterpret_cast<uint8_t*>(pInfo->characteristics),
+ get_camera_metadata_size(pInfo->characteristics));
+ }
+ sCameraList.push_back(std::move(rec));
}
- if (sDisplayProxyService == nullptr) {
+ if (!sDisplayProxyService) {
/* sets a car-window service handle */
sDisplayProxyService = windowService;
}
// Add available displays
- if (sDisplayProxyService != nullptr) {
+ if (sDisplayProxyService) {
// Get a display ID list.
- sDisplayProxyService->getDisplayIdList([](const auto& displayIds) {
- for (const auto& id : displayIds) {
- const auto port = id & 0xF;
- sDisplayPortList.insert_or_assign(port, id);
+ auto status = sDisplayProxyService->getDisplayIdList([](const auto& displayIds) {
+ if (displayIds.size() > 0) {
+ sInternalDisplayId = displayIds[0];
+ for (const auto& id : displayIds) {
+ const auto port = id & 0xF;
+ sDisplayPortList.insert_or_assign(port, id);
+ }
}
});
+
+ if (!status.isOk()) {
+ ALOGE("Failed to read a display list");
+ }
}
// Add ultrasonics array desc.
- sUltrasonicsArrayRecordList.emplace_back(
- EvsUltrasonicsArray::GetMockArrayDesc("front_array"));
+ sUltrasonicsArrayRecordList.emplace_back(EvsUltrasonicsArray::GetMockArrayDesc("front_array"));
}
-
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
-Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
- ALOGD("getCameraList");
+Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
- const unsigned numCameras = sCameraList.size();
+ const auto 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_0> descriptions;
+ std::vector<evs_v1_0::CameraDesc> descriptions;
descriptions.reserve(numCameras);
for (const auto& cam : sCameraList) {
- descriptions.push_back( cam.desc.v1 );
+ descriptions.push_back(cam.desc.v1);
}
// Encapsulate our camera descriptions in the HIDL vec type
- hidl_vec<CameraDesc_1_0> hidlCameras(descriptions);
+ hidl_vec<evs_v1_0::CameraDesc> 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 {};
}
-
-Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
- ALOGD("openCamera");
+Return<sp<evs_v1_0::IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
+ ALOGD("%s", __FUNCTION__);
// 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) {
+ auto it = std::find_if(sCameraList.begin(), sCameraList.end(), [&cameraId](const auto& cam) {
+ return cameraId == cam.desc.v1.cameraId;
+ });
+ if (it == sCameraList.end()) {
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();
+ sp<EvsCamera> pActiveCamera = it->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) {
+ if (!sConfigManager) {
pActiveCamera = EvsCamera::Create(cameraId.c_str());
} else {
- pActiveCamera = EvsCamera::Create(cameraId.c_str(),
- sConfigManager->getCameraInfo(cameraId));
+ pActiveCamera =
+ EvsCamera::Create(cameraId.c_str(), sConfigManager->getCameraInfo(cameraId));
}
- pRecord->activeInstance = pActiveCamera;
- if (pActiveCamera == nullptr) {
+ it->activeInstance = pActiveCamera;
+ if (!pActiveCamera) {
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
}
return pActiveCamera;
}
+Return<void> EvsEnumerator::closeCamera(const ::android::sp<evs_v1_0::IEvsCamera>& pCamera) {
+ ALOGD("%s", __FUNCTION__);
-Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera_1_0>& pCamera) {
- ALOGD("closeCamera");
-
- auto pCamera_1_1 = IEvsCamera_1_1::castFrom(pCamera).withDefault(nullptr);
- if (pCamera_1_1 == nullptr) {
+ auto pCamera_1_1 = IEvsCamera::castFrom(pCamera).withDefault(nullptr);
+ if (!pCamera_1_1) {
ALOGE("Ignoring call to closeCamera with null camera ptr");
- return Void();
+ return {};
}
// 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_1_1([&cameraId](CameraDesc desc) { cameraId = desc.v1.cameraId; });
// Find the named camera
- CameraRecord *pRecord = nullptr;
- for (auto &&cam : sCameraList) {
- if (cam.desc.v1.cameraId == cameraId) {
- // Found a match!
- pRecord = &cam;
- break;
- }
+ auto it = std::find_if(sCameraList.begin(), sCameraList.end(), [&cameraId](const auto& cam) {
+ return cameraId == cam.desc.v1.cameraId;
+ });
+ if (it == sCameraList.end()) {
+ ALOGE("Ignores a request to close unknown camera, %s", cameraId.data());
+ return {};
}
- // Is the display being destroyed actually the one we think is active?
- if (!pRecord) {
- ALOGE("Asked to close a camera who's name isn't recognized");
+ sp<EvsCamera> pActiveCamera = it->activeInstance.promote();
+ if (!pActiveCamera) {
+ ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed");
+ } else if (pActiveCamera != pCamera_1_1) {
+ // This can happen if the camera was aggressively reopened, orphaning this previous instance
+ ALOGW("Ignoring close of previously orphaned camera - why did a client steal?");
} else {
- sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
-
- if (pActiveCamera == nullptr) {
- ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed");
- } else if (pActiveCamera != pCamera_1_1) {
- // This can happen if the camera was aggressively reopened, orphaning this previous instance
- ALOGW("Ignoring close of previously orphaned camera - why did a client steal?");
- } else {
- // Drop the active camera
- pActiveCamera->forceShutdown();
- pRecord->activeInstance = nullptr;
- }
+ // Drop the active camera
+ pActiveCamera->forceShutdown();
+ it->activeInstance = nullptr;
}
- return Void();
+ return {};
}
-
-Return<sp<IEvsDisplay_1_0>> EvsEnumerator::openDisplay() {
- ALOGD("openDisplay");
+Return<sp<V1_0::IEvsDisplay>> EvsEnumerator::openDisplay() {
+ ALOGD("%s", __FUNCTION__);
// If we already have a display active, then we need to shut it down so we can
// give exclusive access to the new caller.
@@ -202,28 +189,25 @@
}
// Create a new display interface and return it
- pActiveDisplay = new EvsDisplay();
+ pActiveDisplay = new EvsDisplay(sDisplayProxyService, sInternalDisplayId);
sActiveDisplay = pActiveDisplay;
ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
return pActiveDisplay;
}
-
Return<void> EvsEnumerator::getDisplayIdList(getDisplayIdList_cb _list_cb) {
hidl_vec<uint8_t> ids;
-
ids.resize(sDisplayPortList.size());
+
unsigned i = 0;
- for (const auto& [port, id] : sDisplayPortList) {
- ids[i++] = port;
- }
+ std::for_each(sDisplayPortList.begin(), sDisplayPortList.end(),
+ [&](const auto& element) { ids[i++] = element.first; });
_list_cb(ids);
- return Void();
+ return {};
}
-
Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay_1_1(uint8_t port) {
ALOGD("%s", __FUNCTION__);
@@ -243,10 +227,8 @@
return pActiveDisplay;
}
-
-
-Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay_1_0>& pDisplay) {
- ALOGD("closeDisplay");
+Return<void> EvsEnumerator::closeDisplay(const ::android::sp<V1_0::IEvsDisplay>& pDisplay) {
+ ALOGD("%s", __FUNCTION__);
// Do we still have a display object we think should be active?
sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
@@ -260,123 +242,111 @@
sActiveDisplay = nullptr;
}
- return Void();
+ return {};
}
-
-Return<DisplayState> EvsEnumerator::getDisplayState() {
- ALOGD("getDisplayState");
+Return<V1_0::DisplayState> EvsEnumerator::getDisplayState() {
+ ALOGD("%s", __FUNCTION__);
// Do we still have a display object we think should be active?
sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote();
if (pActiveDisplay != nullptr) {
return pActiveDisplay->getDisplayState();
} else {
- return DisplayState::NOT_OPEN;
+ return V1_0::DisplayState::NOT_OPEN;
}
}
-
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
-Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) {
- ALOGD("getCameraList");
+Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
- const unsigned numCameras = sCameraList.size();
+ const auto 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;
+ std::vector<CameraDesc> descriptions;
descriptions.reserve(numCameras);
- for (const auto& cam : sCameraList) {
- descriptions.push_back( cam.desc );
- }
+ std::for_each(sCameraList.begin(), sCameraList.end(),
+ [&](const auto& cam) { descriptions.push_back(cam.desc); });
// Encapsulate our camera descriptions in the HIDL vec type
- hidl_vec<CameraDesc_1_1> hidlCameras(descriptions);
+ hidl_vec<CameraDesc> 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 {};
}
-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;
- }
- }
+Return<sp<IEvsCamera>> EvsEnumerator::openCamera_1_1(const hidl_string& cameraId,
+ const Stream& streamCfg) {
+ ALOGD("%s", __FUNCTION__);
- // Is this a recognized camera id?
- if (!pRecord) {
+ // Find the named camera
+ auto it = std::find_if(sCameraList.begin(), sCameraList.end(), [&cameraId](const auto& cam) {
+ return cameraId == cam.desc.v1.cameraId;
+ });
+ if (it == sCameraList.end()) {
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();
+ sp<EvsCamera> pActiveCamera = it->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) {
+ if (!sConfigManager) {
pActiveCamera = EvsCamera::Create(cameraId.c_str());
} else {
- pActiveCamera = EvsCamera::Create(cameraId.c_str(),
- sConfigManager->getCameraInfo(cameraId),
+ pActiveCamera = EvsCamera::Create(cameraId.c_str(), sConfigManager->getCameraInfo(cameraId),
&streamCfg);
}
- pRecord->activeInstance = pActiveCamera;
- if (pActiveCamera == nullptr) {
+ it->activeInstance = pActiveCamera;
+ if (!pActiveCamera) {
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;
- }
- }
+ ALOGD("%s", __FUNCTION__);
- return pRecord;
+ // Find the named camera
+ auto it = std::find_if(sCameraList.begin(), sCameraList.end(), [&cameraId](const auto& cam) {
+ return cameraId == cam.desc.v1.cameraId;
+ });
+ return (it != sCameraList.end()) ? &*it : nullptr;
}
EvsEnumerator::UltrasonicsArrayRecord* EvsEnumerator::findUltrasonicsArrayById(
const std::string& ultrasonicsArrayId) {
- auto recordIt = std::find_if(
- sUltrasonicsArrayRecordList.begin(), sUltrasonicsArrayRecordList.end(),
- [&ultrasonicsArrayId](const UltrasonicsArrayRecord& record) {
- return ultrasonicsArrayId == record.desc.ultrasonicsArrayId;});
+ ALOGD("%s", __FUNCTION__);
+
+ auto recordIt =
+ std::find_if(sUltrasonicsArrayRecordList.begin(), sUltrasonicsArrayRecordList.end(),
+ [&ultrasonicsArrayId](const UltrasonicsArrayRecord& record) {
+ return ultrasonicsArrayId == record.desc.ultrasonicsArrayId;
+ });
return (recordIt != sUltrasonicsArrayRecordList.end()) ? &*recordIt : nullptr;
}
Return<void> EvsEnumerator::getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb) {
+ ALOGD("%s", __FUNCTION__);
+
hidl_vec<UltrasonicsArrayDesc> desc;
desc.resize(sUltrasonicsArrayRecordList.size());
// Copy over desc from sUltrasonicsArrayRecordList.
for (auto p = std::make_pair(sUltrasonicsArrayRecordList.begin(), desc.begin());
- p.first != sUltrasonicsArrayRecordList.end(); p.first++, p.second++) {
+ p.first != sUltrasonicsArrayRecordList.end(); p.first++, p.second++) {
*p.second = p.first->desc;
}
@@ -385,11 +355,13 @@
_hidl_cb(desc);
// HIDL convention says we return Void if we sent our result back via callback
- return Void();
+ return {};
}
Return<sp<IEvsUltrasonicsArray>> EvsEnumerator::openUltrasonicsArray(
const hidl_string& ultrasonicsArrayId) {
+ ALOGD("%s", __FUNCTION__);
+
// Find the named ultrasonic array.
UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);
@@ -419,10 +391,11 @@
Return<void> EvsEnumerator::closeUltrasonicsArray(
const sp<IEvsUltrasonicsArray>& pEvsUltrasonicsArray) {
+ ALOGD("%s", __FUNCTION__);
if (pEvsUltrasonicsArray.get() == nullptr) {
ALOGE("Ignoring call to closeUltrasonicsArray with null ultrasonics array");
- return Void();
+ return {};
}
// Get the ultrasonics array id so we can find it in our list.
@@ -435,7 +408,7 @@
UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);
if (!pRecord) {
ALOGE("Asked to close a ultrasonics array whose name isnt not found");
- return Void();
+ return {};
}
sp<EvsUltrasonicsArray> pActiveUltrasonicsArray = pRecord->activeInstance.promote();
@@ -453,12 +426,7 @@
pRecord->activeInstance = nullptr;
}
- return Void();
+ return {};
}
-} // namespace implementation
-} // namespace V1_1
-} // namespace evs
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/EvsEnumerator.h b/automotive/evs/1.1/default/EvsEnumerator.h
index d80124b..513fc8d 100644
--- a/automotive/evs/1.1/default/EvsEnumerator.h
+++ b/automotive/evs/1.1/default/EvsEnumerator.h
@@ -17,56 +17,41 @@
#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 "ConfigManager.h"
+
+#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
-#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
+#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArray.h>
#include <list>
-#include "ConfigManager.h"
+namespace android::hardware::automotive::evs::V1_1::implementation {
-using ::android::hardware::automotive::evs::V1_0::EvsResult;
-using ::android::hardware::automotive::evs::V1_0::DisplayState;
-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;
-using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
-using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
-using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
+namespace evs_v1_0 = ::android::hardware::automotive::evs::V1_0;
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace evs {
-namespace V1_1 {
-namespace implementation {
-
-
-class EvsCamera; // from EvsCamera.h
-class EvsDisplay; // from EvsDisplay.h
+class EvsCamera; // from EvsCamera.h
+class EvsDisplay; // from EvsDisplay.h
class EvsUltrasonicsArray; // from EvsUltrasonicsArray.h
-
class EvsEnumerator : public IEvsEnumerator {
-public:
+ public:
// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
- Return<void> getCameraList(getCameraList_cb _hidl_cb) override;
- Return<sp<IEvsCamera_1_0>> openCamera(const hidl_string& cameraId) override;
- Return<void> closeCamera(const ::android::sp<IEvsCamera_1_0>& carCamera) override;
- Return<sp<IEvsDisplay_1_0>> openDisplay() override;
- Return<void> closeDisplay(const ::android::sp<IEvsDisplay_1_0>& display) override;
- Return<DisplayState> getDisplayState() override;
+ Return<void> getCameraList(getCameraList_cb _hidl_cb) override;
+ Return<sp<evs_v1_0::IEvsCamera>> openCamera(const hidl_string& cameraId) override;
+ Return<void> closeCamera(const ::android::sp<evs_v1_0::IEvsCamera>& carCamera) override;
+ Return<sp<evs_v1_0::IEvsDisplay>> openDisplay() override;
+ Return<void> closeDisplay(const ::android::sp<evs_v1_0::IEvsDisplay>& display) override;
+ Return<V1_0::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;
+ Return<void> getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) override;
+ Return<sp<IEvsCamera>> openCamera_1_1(const hidl_string& cameraId,
+ const Stream& streamCfg) override;
Return<bool> isHardware() override { return true; }
- Return<void> getDisplayIdList(getDisplayIdList_cb _list_cb) override;
- Return<sp<IEvsDisplay_1_1>> openDisplay_1_1(uint8_t port) override;
+ Return<void> getDisplayIdList(getDisplayIdList_cb _list_cb) override;
+ Return<sp<IEvsDisplay>> openDisplay_1_1(uint8_t port) override;
Return<void> getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb) override;
Return<sp<IEvsUltrasonicsArray>> openUltrasonicsArray(
const hidl_string& ultrasonicsArrayId) override;
@@ -74,49 +59,40 @@
const ::android::sp<IEvsUltrasonicsArray>& evsUltrasonicsArray) override;
// Implementation details
- EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService = nullptr);
+ EvsEnumerator(sp<frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService>&
+ windowService);
-private:
+ private:
// NOTE: All members values are static so that all clients operate on the same state
// That is to say, this is effectively a singleton despite the fact that HIDL
// constructs a new instance for each client.
struct CameraRecord {
- CameraDesc_1_1 desc;
- wp<EvsCamera> activeInstance;
+ CameraDesc desc;
+ wp<EvsCamera> activeInstance;
- CameraRecord(const char *cameraId) : desc() { desc.v1.cameraId = cameraId; }
+ CameraRecord(const char* cameraId) : desc() { desc.v1.cameraId = cameraId; }
};
struct UltrasonicsArrayRecord {
UltrasonicsArrayDesc desc;
wp<EvsUltrasonicsArray> activeInstance;
- UltrasonicsArrayRecord(const UltrasonicsArrayDesc& arrayDesc) : desc(arrayDesc) {};
+ UltrasonicsArrayRecord(const UltrasonicsArrayDesc& arrayDesc) : desc(arrayDesc){};
};
static CameraRecord* findCameraById(const std::string& cameraId);
-
- static std::list<CameraRecord> sCameraList;
-
+ static std::list<CameraRecord> sCameraList;
static UltrasonicsArrayRecord* findUltrasonicsArrayById(const std::string& ultrasonicsArrayId);
-
static std::list<UltrasonicsArrayRecord> sUltrasonicsArrayRecordList;
- // Weak pointer. Object destructs if client dies.
- static wp<EvsDisplay> sActiveDisplay;
-
- static unique_ptr<ConfigManager> sConfigManager;
-
- static sp<IAutomotiveDisplayProxyService> sDisplayProxyService;
- static std::unordered_map<uint8_t,
- uint64_t> sDisplayPortList;
+ static wp<EvsDisplay> sActiveDisplay; // Weak pointer. Object destructs if client dies.
+ static uint64_t sInternalDisplayId;
+ static sp<frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService>
+ sDisplayProxyService;
+ static std::unordered_map<uint8_t, uint64_t> sDisplayPortList;
+ static std::unique_ptr<ConfigManager> sConfigManager;
};
-} // namespace implementation
-} // namespace V1_1
-} // namespace evs
-} // namespace automotive
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::automotive::evs::V1_1::implementation
#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
index ebd47c6..951937a 100644
--- a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
+++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
@@ -113,10 +113,9 @@
dataFrameDesc.receiversReadingsCountList = receiversReadingsCountList;
const std::vector<WaveformData> waveformDataList = {
- {recvIdList[0], { {1000, 0.1f}, {2000, 0.8f} }},
- {recvIdList[1], { {1000, 0.1f}, {2000, 1.0f} }},
- {recvIdList[2], { {1000, 0.1f}, {2000, 0.2f}, {4000, 0.2f}, {5000, 0.1f} }}
- };
+ {recvIdList[0], {{1000, 0.1f}, {2000, 0.8f}}},
+ {recvIdList[1], {{1000, 0.1f}, {2000, 1.0f}}},
+ {recvIdList[2], {{1000, 0.1f}, {2000, 0.2f}, {4000, 0.2f}, {5000, 0.1f}}}};
if (pIMemory.get() == nullptr) {
return false;
diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.h b/automotive/evs/1.1/default/EvsUltrasonicsArray.h
index 88aa600..681f68f 100644
--- a/automotive/evs/1.1/default/EvsUltrasonicsArray.h
+++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.h
@@ -119,7 +119,7 @@
std::mutex mAccessLock;
std::vector<DataFrameRecord> mDataFrames GUARDED_BY(mAccessLock); // Shared memory buffers.
unsigned mFramesAllowed GUARDED_BY(mAccessLock); // How many buffers are we currently using.
- unsigned mFramesInUse GUARDED_BY(mAccessLock); // How many buffers are currently outstanding.
+ unsigned mFramesInUse GUARDED_BY(mAccessLock); // How many buffers are currently outstanding.
StreamStateValues mStreamState GUARDED_BY(mAccessLock);
};
diff --git a/automotive/evs/1.1/default/GlWrapper.cpp b/automotive/evs/1.1/default/GlWrapper.cpp
new file mode 100644
index 0000000..357b67c
--- /dev/null
+++ b/automotive/evs/1.1/default/GlWrapper.cpp
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlWrapper.h"
+
+#include <ui/DisplayMode.h>
+#include <ui/DisplayState.h>
+#include <ui/GraphicBuffer.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <utility>
+
+using android::GraphicBuffer;
+using android::sp;
+
+namespace {
+
+// Defines a default color to clear the screen in RGBA format
+constexpr float kDefaultColorInRgba[] = {0.1f, 0.5f, 0.1f, 1.0f};
+
+// Defines the size of the preview area relative to the entire display
+constexpr float kDisplayAreaRatio = 0.8f;
+
+constexpr const char vertexShaderSource[] =
+ ""
+ "#version 300 es \n"
+ "layout(location = 0) in vec4 pos; \n"
+ "layout(location = 1) in vec2 tex; \n"
+ "out vec2 uv; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = pos; \n"
+ " uv = tex; \n"
+ "} \n";
+
+constexpr const char pixelShaderSource[] =
+ "#version 300 es \n"
+ "precision mediump float; \n"
+ "uniform sampler2D tex; \n"
+ "in vec2 uv; \n"
+ "out vec4 color; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texel = texture(tex, uv); \n"
+ " color = texel; \n"
+ "} \n";
+
+const char* getEGLError(void) {
+ switch (eglGetError()) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "Unknown error";
+ }
+}
+
+// Given shader source, load and compile it
+GLuint loadShader(GLenum type, const char* shaderSrc) {
+ // Create the shader object
+ GLuint shader = glCreateShader(type);
+ if (shader == 0) {
+ LOG(ERROR) << "glCreateSharder() failed with error = " << glGetError();
+ return 0;
+ }
+
+ // Load and compile the shader
+ glShaderSource(shader, 1, &shaderSrc, nullptr);
+ glCompileShader(shader);
+
+ // Verify the compilation worked as expected
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ LOG(ERROR) << "Error compiling shader";
+
+ GLint size = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
+ if (size > 0) {
+ // Get and report the error message
+ char infoLog[size];
+ glGetShaderInfoLog(shader, size, nullptr, infoLog);
+ LOG(ERROR) << " msg:" << std::endl << infoLog;
+ }
+
+ glDeleteShader(shader);
+ return 0;
+ }
+
+ return shader;
+}
+
+// Create a program object given vertex and pixels shader source
+GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc) {
+ GLuint program = glCreateProgram();
+ if (program == 0) {
+ LOG(ERROR) << "Failed to allocate program object";
+ return 0;
+ }
+
+ // Compile the shaders and bind them to this program
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc);
+ if (vertexShader == 0) {
+ LOG(ERROR) << "Failed to load vertex shader";
+ glDeleteProgram(program);
+ return 0;
+ }
+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc);
+ if (pixelShader == 0) {
+ LOG(ERROR) << "Failed to load pixel shader";
+ glDeleteProgram(program);
+ glDeleteShader(vertexShader);
+ return 0;
+ }
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, pixelShader);
+
+ // Link the program
+ glLinkProgram(program);
+ GLint linked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ if (!linked) {
+ LOG(ERROR) << "Error linking program";
+ GLint size = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
+ if (size > 0) {
+ // Get and report the error message
+ char* infoLog = (char*)malloc(size);
+ glGetProgramInfoLog(program, size, nullptr, infoLog);
+ LOG(ERROR) << " msg: " << infoLog;
+ free(infoLog);
+ }
+
+ glDeleteProgram(program);
+ glDeleteShader(vertexShader);
+ glDeleteShader(pixelShader);
+ return 0;
+ }
+
+ return program;
+}
+
+} // namespace
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+// Main entry point
+bool GlWrapper::initialize(const sp<IAutomotiveDisplayProxyService>& service, uint64_t displayId) {
+ LOG(DEBUG) << __FUNCTION__;
+
+ if (!service) {
+ LOG(WARNING) << "IAutomotiveDisplayProxyService is invalid.";
+ return false;
+ }
+
+ // We will use the first display in the list as the primary.
+ service->getDisplayInfo(displayId, [this](auto dpyConfig, auto dpyState) {
+ ui::DisplayMode* pConfig = reinterpret_cast<ui::DisplayMode*>(dpyConfig.data());
+ mWidth = pConfig->resolution.getWidth();
+ mHeight = pConfig->resolution.getHeight();
+
+ ui::DisplayState* pState = reinterpret_cast<ui::DisplayState*>(dpyState.data());
+ if (pState->orientation != ui::ROTATION_0 && pState->orientation != ui::ROTATION_180) {
+ // rotate
+ std::swap(mWidth, mHeight);
+ }
+
+ LOG(DEBUG) << "Display resolution is " << mWidth << " x " << mHeight;
+ });
+
+ mGfxBufferProducer = service->getIGraphicBufferProducer(displayId);
+ if (mGfxBufferProducer == nullptr) {
+ LOG(ERROR) << "Failed to get IGraphicBufferProducer from IAutomotiveDisplayProxyService.";
+ return false;
+ }
+
+ mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer);
+ if (mSurfaceHolder == nullptr) {
+ LOG(ERROR) << "Failed to get a Surface from HGBP.";
+ return false;
+ }
+
+ mWindow = getNativeWindow(mSurfaceHolder.get());
+ if (mWindow == nullptr) {
+ LOG(ERROR) << "Failed to get a native window from Surface.";
+ return false;
+ }
+
+ // Set up our OpenGL ES context associated with the default display
+ mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mDisplay == EGL_NO_DISPLAY) {
+ LOG(ERROR) << "Failed to get egl display";
+ return false;
+ }
+
+ EGLint major = 3;
+ EGLint minor = 0;
+ if (!eglInitialize(mDisplay, &major, &minor)) {
+ LOG(ERROR) << "Failed to initialize EGL: " << getEGLError();
+ return false;
+ }
+
+ const EGLint config_attribs[] = {
+ // Tag Value
+ EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE};
+
+ // Pick the default configuration without constraints (is this good enough?)
+ EGLConfig egl_config = {0};
+ EGLint numConfigs = -1;
+ eglChooseConfig(mDisplay, config_attribs, &egl_config, 1, &numConfigs);
+ if (numConfigs != 1) {
+ LOG(ERROR) << "Didn't find a suitable format for our display window";
+ return false;
+ }
+
+ // Create the EGL render target surface
+ mSurface = eglCreateWindowSurface(mDisplay, egl_config, mWindow, nullptr);
+ if (mSurface == EGL_NO_SURFACE) {
+ LOG(ERROR) << "eglCreateWindowSurface failed: " << getEGLError();
+ ;
+ return false;
+ }
+
+ // Create the EGL context
+ // NOTE: Our shader is (currently at least) written to require version 3, so this
+ // is required.
+ const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+ mContext = eglCreateContext(mDisplay, egl_config, EGL_NO_CONTEXT, context_attribs);
+ if (mContext == EGL_NO_CONTEXT) {
+ LOG(ERROR) << "Failed to create OpenGL ES Context: " << getEGLError();
+ return false;
+ }
+
+ // Activate our render target for drawing
+ if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) {
+ LOG(ERROR) << "Failed to make the OpenGL ES Context current: " << getEGLError();
+ return false;
+ }
+
+ // Create the shader program for our simple pipeline
+ mShaderProgram = buildShaderProgram(vertexShaderSource, pixelShaderSource);
+ if (!mShaderProgram) {
+ LOG(ERROR) << "Failed to build shader program: " << getEGLError();
+ return false;
+ }
+
+ // Create a GL texture that will eventually wrap our externally created texture surface(s)
+ glGenTextures(1, &mTextureMap);
+ if (mTextureMap <= 0) {
+ LOG(ERROR) << "Didn't get a texture handle allocated: " << getEGLError();
+ return false;
+ }
+
+ // Turn off mip-mapping for the created texture surface
+ // (the inbound camera imagery doesn't have MIPs)
+ glBindTexture(GL_TEXTURE_2D, mTextureMap);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return true;
+}
+
+void GlWrapper::shutdown() {
+ // Drop our device textures
+ if (mKHRimage != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mDisplay, mKHRimage);
+ mKHRimage = EGL_NO_IMAGE_KHR;
+ }
+
+ // Release all GL resources
+ eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(mDisplay, mSurface);
+ eglDestroyContext(mDisplay, mContext);
+ eglTerminate(mDisplay);
+ mSurface = EGL_NO_SURFACE;
+ mContext = EGL_NO_CONTEXT;
+ mDisplay = EGL_NO_DISPLAY;
+
+ // Release the window
+ mSurfaceHolder = nullptr;
+}
+
+void GlWrapper::showWindow(sp<IAutomotiveDisplayProxyService>& service, uint64_t id) {
+ if (service != nullptr) {
+ service->showWindow(id);
+ } else {
+ LOG(ERROR) << "IAutomotiveDisplayProxyService is not available.";
+ }
+}
+
+void GlWrapper::hideWindow(sp<IAutomotiveDisplayProxyService>& service, uint64_t id) {
+ if (service != nullptr) {
+ service->hideWindow(id);
+ } else {
+ LOG(ERROR) << "IAutomotiveDisplayProxyService is not available.";
+ }
+}
+
+bool GlWrapper::updateImageTexture(const V1_0::BufferDesc& buffer) {
+ BufferDesc newBuffer = {
+ .buffer =
+ {
+ .nativeHandle = buffer.memHandle,
+ },
+ .pixelSize = buffer.pixelSize,
+ .bufferId = buffer.bufferId,
+ };
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc*>(&newBuffer.buffer.description);
+ *pDesc = {
+ .width = buffer.width,
+ .height = buffer.height,
+ .layers = 1,
+ .format = buffer.format,
+ .usage = buffer.usage,
+ };
+ return updateImageTexture(newBuffer);
+}
+
+bool GlWrapper::updateImageTexture(const BufferDesc& aFrame) {
+ // If we haven't done it yet, create an "image" object to wrap the gralloc buffer
+ if (mKHRimage == EGL_NO_IMAGE_KHR) {
+ // create a temporary GraphicBuffer to wrap the provided handle
+ const AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<const AHardwareBuffer_Desc*>(&aFrame.buffer.description);
+ sp<GraphicBuffer> pGfxBuffer = new GraphicBuffer(
+ pDesc->width, pDesc->height, pDesc->format, pDesc->layers, pDesc->usage,
+ pDesc->stride,
+ const_cast<native_handle_t*>(aFrame.buffer.nativeHandle.getNativeHandle()),
+ false /* keep ownership */
+ );
+ if (pGfxBuffer.get() == nullptr) {
+ LOG(ERROR) << "Failed to allocate GraphicBuffer to wrap our native handle";
+ return false;
+ }
+
+ // Get a GL compatible reference to the graphics buffer we've been given
+ EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(pGfxBuffer->getNativeBuffer());
+ mKHRimage = eglCreateImageKHR(mDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf,
+ eglImageAttributes);
+ if (mKHRimage == EGL_NO_IMAGE_KHR) {
+ LOG(ERROR) << "Error creating EGLImage: " << getEGLError();
+ return false;
+ }
+
+ // Update the texture handle we already created to refer to this gralloc buffer
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mTextureMap);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(mKHRimage));
+ }
+
+ return true;
+}
+
+void GlWrapper::renderImageToScreen() {
+ // Set the viewport
+ glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ glClearColor(kDefaultColorInRgba[0], kDefaultColorInRgba[1],
+ kDefaultColorInRgba[2], kDefaultColorInRgba[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // Select our screen space simple texture shader
+ glUseProgram(mShaderProgram);
+
+ // Bind the texture and assign it to the shader's sampler
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mTextureMap);
+ GLint sampler = glGetUniformLocation(mShaderProgram, "tex");
+ glUniform1i(sampler, 0);
+
+ // We want our image to show up opaque regardless of alpha values
+ glDisable(GL_BLEND);
+
+ // Draw a rectangle on the screen
+ GLfloat vertsCarPos[] = {
+ -kDisplayAreaRatio, kDisplayAreaRatio, 0.0f, // left top in window space
+ kDisplayAreaRatio, kDisplayAreaRatio, 0.0f, // right top
+ -kDisplayAreaRatio, -kDisplayAreaRatio, 0.0f, // left bottom
+ kDisplayAreaRatio, -kDisplayAreaRatio, 0.0f // right bottom
+ };
+
+ // NOTE: We didn't flip the image in the texture, so V=0 is actually the top of the image
+ GLfloat vertsCarTex[] = {
+ 0.0f, 0.0f, // left top
+ 1.0f, 0.0f, // right top
+ 0.0f, 1.0f, // left bottom
+ 1.0f, 1.0f // right bottom
+ };
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertsCarPos);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertsCarTex);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ // Clean up and flip the rendered result to the front so it is visible
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+
+ glFinish();
+
+ eglSwapBuffers(mDisplay, mSurface);
+}
+
+} // namespace android::hardware::automotive::evs::V1_1::implementation
diff --git a/automotive/evs/1.1/default/GlWrapper.h b/automotive/evs/1.1/default/GlWrapper.h
new file mode 100644
index 0000000..44c206f
--- /dev/null
+++ b/automotive/evs/1.1/default/GlWrapper.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_DISPLAY_GLWRAPPER_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_DISPLAY_GLWRAPPER_H
+
+#include <android-base/logging.h>
+#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
+#include <android/hardware/automotive/evs/1.1/types.h>
+#include <bufferqueueconverter/BufferQueueConverter.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+
+namespace android::hardware::automotive::evs::V1_1::implementation {
+
+using frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
+using hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer;
+
+class GlWrapper {
+ public:
+ GlWrapper() : mSurfaceHolder(android::SurfaceHolderUniquePtr(nullptr, nullptr)) {}
+ bool initialize(const sp<IAutomotiveDisplayProxyService>& service, uint64_t displayId);
+ void shutdown();
+
+ bool updateImageTexture(const V1_0::BufferDesc& buffer);
+ bool updateImageTexture(const BufferDesc& buffer);
+ void renderImageToScreen();
+
+ void showWindow(sp<IAutomotiveDisplayProxyService>& service, uint64_t id);
+ void hideWindow(sp<IAutomotiveDisplayProxyService>& service, uint64_t id);
+
+ unsigned getWidth() { return mWidth; };
+ unsigned getHeight() { return mHeight; };
+
+ private:
+ sp<IGraphicBufferProducer> mGfxBufferProducer;
+
+ EGLDisplay mDisplay;
+ EGLSurface mSurface;
+ EGLContext mContext;
+
+ unsigned mWidth = 0;
+ unsigned mHeight = 0;
+
+ EGLImageKHR mKHRimage = EGL_NO_IMAGE_KHR;
+
+ GLuint mTextureMap = 0;
+ GLuint mShaderProgram = 0;
+
+ // Opaque handle for a native hardware buffer defined in
+ // frameworks/native/opengl/include/EGL/eglplatform.h
+ ANativeWindow* mWindow;
+
+ // Pointer to a Surface wrapper.
+ android::SurfaceHolderUniquePtr mSurfaceHolder;
+};
+
+} // namespace android::hardware::automotive::evs::V1_1::implementation
+
+#endif // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_DISPLAY_GLWRAPPER_H
diff --git a/automotive/evs/1.1/default/android.hardware.automotive.evs@1.1-service.rc b/automotive/evs/1.1/default/android.hardware.automotive.evs@1.1-service.rc
index 284b3fd..5d4daf9 100644
--- a/automotive/evs/1.1/default/android.hardware.automotive.evs@1.1-service.rc
+++ b/automotive/evs/1.1/default/android.hardware.automotive.evs@1.1-service.rc
@@ -1,5 +1,8 @@
service vendor.evs-hal-mock /vendor/bin/hw/android.hardware.automotive.evs@1.1-service
class hal
- user automotive_evs
- group automotive_evs
- disabled
+ priority -20
+ user graphics
+ group automotive_evs camera
+ onrestart restart automotive_display
+ onrestart restart evs_manager
+ disabled # will not automatically start with its class; must be explicitly started.
diff --git a/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml b/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml
index d4d9b17..d975701 100644
--- a/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml
+++ b/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml
@@ -15,12 +15,8 @@
-->
<manifest version="1.0" type="device" >
<hal format="hidl">
- <name>android.hardware.automotive.evs</name>
<transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>IEvsEnumerator</name>
- <instance>hw/0</instance>
- </interface>
+ <name>android.hardware.automotive.evs</name>
+ <fqname>@1.1::IEvsEnumerator/hw/0</fqname>
</hal>
</manifest>
diff --git a/automotive/evs/1.1/default/resources/evs_default_configuration.xml b/automotive/evs/1.1/default/resources/evs_default_configuration.xml
index a79e7c2..6cbc18e 100644
--- a/automotive/evs/1.1/default/resources/evs_default_configuration.xml
+++ b/automotive/evs/1.1/default/resources/evs_default_configuration.xml
@@ -30,31 +30,8 @@
<!-- camera information -->
<camera>
- <!-- camera group starts -->
- <group id='group1' synchronized='APPROXIMATE'>
- <caps>
- <stream id='0' width='640' height='360' format='RGBA_8888' framerate='30'/>
- </caps>
-
- <!-- list of parameters -->
- <characteristics>
- <parameter
- name='REQUEST_AVAILABLE_CAPABILITIES'
- type='enum'
- size='1'
- value='LOGICAL_MULTI_CAMERA'
- />
- <parameter
- name='LOGICAL_MULTI_CAMERA_PHYSICAL_IDS'
- type='byte[]'
- size='1'
- value='/dev/video1'
- />
- </characteristics>
- </group>
-
<!-- camera device starts -->
- <device id='/dev/video1' position='rear'>
+ <device id='/dev/video10' position='rear'>
<caps>
<!-- list of supported controls -->
<supported_controls>
diff --git a/automotive/evs/1.1/default/service.cpp b/automotive/evs/1.1/default/service.cpp
index 374b646..2764a26 100644
--- a/automotive/evs/1.1/default/service.cpp
+++ b/automotive/evs/1.1/default/service.cpp
@@ -14,42 +14,42 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.automotive.evs@1.1-service"
-
-#include <unistd.h>
+#include "EvsDisplay.h"
+#include "EvsEnumerator.h"
+#include "ServiceNames.h"
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include "ServiceNames.h"
-#include "EvsEnumerator.h"
-#include "EvsDisplay.h"
+#include <unistd.h>
-
-// libhidl:
+using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
-
-// Generated HIDL files
+using android::hardware::automotive::evs::V1_0::DisplayState;
using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
-
-// The namespace in which all our implementation code lives
-using namespace android::hardware::automotive::evs::V1_1::implementation;
-using namespace android;
-
+using android::hardware::automotive::evs::V1_1::implementation::EvsEnumerator;
int main() {
ALOGI("EVS Hardware Enumerator service is starting");
- android::sp<IEvsEnumerator> service = new EvsEnumerator();
+
+ android::sp<IAutomotiveDisplayProxyService> carWindowService =
+ IAutomotiveDisplayProxyService::getService("default");
+ if (carWindowService == nullptr) {
+ ALOGE("Cannot use AutomotiveDisplayProxyService. Exiting.");
+ return EXIT_FAILURE;
+ }
+
+ android::sp<IEvsEnumerator> service = new EvsEnumerator(carWindowService);
configureRpcThreadpool(1, true /* callerWillJoin */);
// Register our service -- if somebody is already registered by our name,
// they will be killed (their thread pool will throw an exception).
- status_t status = service->registerAsService(kEnumeratorServiceName);
- if (status == OK) {
+ auto status = service->registerAsService(kEnumeratorServiceName);
+ if (status == android::OK) {
ALOGD("%s is ready.", kEnumeratorServiceName);
joinRpcThreadpool();
} else {
@@ -58,5 +58,5 @@
// In normal operation, we don't expect the thread pool to exit
ALOGE("EVS Hardware Enumerator is shutting down");
- return 1;
+ return EXIT_SUCCESS;
}