Merge "Copy from the old version of Codec2 HAL"
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 392ebbc..9c2b02b 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -466,8 +466,8 @@
}
void CameraModule::removeCamera(int cameraId) {
- free_camera_metadata(
- const_cast<camera_metadata_t*>(mCameraInfoMap[cameraId].static_camera_characteristics));
+ free_camera_metadata(const_cast<camera_metadata_t*>(
+ mCameraInfoMap.valueFor(cameraId).static_camera_characteristics));
mCameraInfoMap.removeItem(cameraId);
mDeviceVersionMap.removeItem(cameraId);
}
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index e7361dd..b96f574 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -48,24 +48,31 @@
} // anonymous namespace
ExternalCameraDevice::ExternalCameraDevice(
- const std::string& cameraId, const ExternalCameraConfig& cfg) :
+ const std::string& cameraId, const ExternalCameraConfig& cfg) :
mCameraId(cameraId),
- mCfg(cfg) {
-
- status_t ret = initCameraCharacteristics();
- if (ret != OK) {
- ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
- mInitFailed = true;
- }
-}
+ mCfg(cfg) {}
ExternalCameraDevice::~ExternalCameraDevice() {}
bool ExternalCameraDevice::isInitFailed() {
+ Mutex::Autolock _l(mLock);
+ return isInitFailedLocked();
+}
+
+bool ExternalCameraDevice::isInitFailedLocked() {
+ if (!mInitialized) {
+ status_t ret = initCameraCharacteristics();
+ if (ret != OK) {
+ ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
+ mInitFailed = true;
+ }
+ mInitialized = true;
+ }
return mInitFailed;
}
-Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
+Return<void> ExternalCameraDevice::getResourceCost(
+ ICameraDevice::getResourceCost_cb _hidl_cb) {
CameraResourceCost resCost;
resCost.resourceCost = 100;
_hidl_cb(Status::OK, resCost);
@@ -73,11 +80,11 @@
}
Return<void> ExternalCameraDevice::getCameraCharacteristics(
- getCameraCharacteristics_cb _hidl_cb) {
+ ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
Mutex::Autolock _l(mLock);
V3_2::CameraMetadata hidlChars;
- if (isInitFailed()) {
+ if (isInitFailedLocked()) {
_hidl_cb(Status::INTERNAL_ERROR, hidlChars);
return Void();
}
@@ -94,7 +101,7 @@
}
Return<void> ExternalCameraDevice::open(
- const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
+ const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb) {
Status status = Status::OK;
sp<ExternalCameraDeviceSession> session = nullptr;
@@ -143,7 +150,7 @@
}
}
- session = new ExternalCameraDeviceSession(
+ session = createSession(
callback, mCfg, mSupportedFormats, mCroppingType,
mCameraCharacteristics, mCameraId, std::move(fd));
if (session == nullptr) {
@@ -479,52 +486,9 @@
UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
ARRAY_SIZE(availableResultKeys));
- const int32_t availableCharacteristicsKeys[] = {
- ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- ANDROID_CONTROL_AE_COMPENSATION_RANGE,
- ANDROID_CONTROL_AE_COMPENSATION_STEP,
- ANDROID_CONTROL_AE_LOCK_AVAILABLE,
- ANDROID_CONTROL_AF_AVAILABLE_MODES,
- ANDROID_CONTROL_AVAILABLE_EFFECTS,
- ANDROID_CONTROL_AVAILABLE_MODES,
- ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
- ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
- ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
- ANDROID_CONTROL_MAX_REGIONS,
- ANDROID_FLASH_INFO_AVAILABLE,
- ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
- ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
- ANDROID_LENS_FACING,
- ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
- ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
- ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
- ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
- ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
- ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
- ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
- ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- ANDROID_SCALER_CROPPING_TYPE,
- ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
- ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
- ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
- ANDROID_SENSOR_ORIENTATION,
- ANDROID_SHADING_AVAILABLE_MODES,
- ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
- ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
- ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
- ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
- ANDROID_SYNC_MAX_LATENCY};
UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
- availableCharacteristicsKeys,
- ARRAY_SIZE(availableCharacteristicsKeys));
+ AVAILABLE_CHARACTERISTICS_KEYS_3_4.data(),
+ AVAILABLE_CHARACTERISTICS_KEYS_3_4.size());
return OK;
}
@@ -931,6 +895,18 @@
}
}
+sp<ExternalCameraDeviceSession> ExternalCameraDevice::createSession(
+ const sp<ICameraDeviceCallback>& cb,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd) {
+ return new ExternalCameraDeviceSession(
+ cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd));
+}
+
} // namespace implementation
} // namespace V3_4
} // namespace device
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 653ad59..4ef5fc9 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -81,6 +81,8 @@
return locked;
}
+buffer_handle_t sEmptyBuffer = nullptr;
+
} // Anonymous namespace
// Static instances
@@ -103,11 +105,8 @@
mCroppingType(croppingType),
mCameraId(cameraId),
mV4l2Fd(std::move(v4l2Fd)),
- mOutputThread(new OutputThread(this, mCroppingType)),
mMaxThumbResolution(getMaxThumbResolution()),
- mMaxJpegResolution(getMaxJpegResolution()) {
- mInitFail = initialize();
-}
+ mMaxJpegResolution(getMaxJpegResolution()) {}
bool ExternalCameraDeviceSession::initialize() {
if (mV4l2Fd.get() < 0) {
@@ -142,6 +141,12 @@
model = card;
}
}
+
+ initOutputThread();
+ if (mOutputThread == nullptr) {
+ ALOGE("%s: init OutputThread failed!", __FUNCTION__);
+ return true;
+ }
mOutputThread->setExifMakeModel(make, model);
status_t status = initDefaultRequests();
@@ -168,6 +173,32 @@
return false;
}
+bool ExternalCameraDeviceSession::isInitFailed() {
+ Mutex::Autolock _l(mLock);
+ if (!mInitialized) {
+ mInitFail = initialize();
+ mInitialized = true;
+ }
+ return mInitFail;
+}
+
+void ExternalCameraDeviceSession::initOutputThread() {
+ mOutputThread = new OutputThread(this, mCroppingType);
+}
+
+void ExternalCameraDeviceSession::closeOutputThread() {
+ closeOutputThreadImpl();
+}
+
+void ExternalCameraDeviceSession::closeOutputThreadImpl() {
+ if (mOutputThread) {
+ mOutputThread->flush();
+ mOutputThread->requestExit();
+ mOutputThread->join();
+ mOutputThread.clear();
+ }
+}
+
Status ExternalCameraDeviceSession::initStatus() const {
Mutex::Autolock _l(mLock);
Status status = Status::OK;
@@ -181,7 +212,7 @@
ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
if (!isClosed()) {
ALOGE("ExternalCameraDeviceSession deleted before close!");
- close();
+ close(/*callerIsDtor*/true);
}
}
@@ -442,18 +473,23 @@
return Status::OK;
}
-Return<void> ExternalCameraDeviceSession::close() {
+Return<void> ExternalCameraDeviceSession::close(bool callerIsDtor) {
Mutex::Autolock _il(mInterfaceLock);
bool closed = isClosed();
if (!closed) {
- mOutputThread->flush();
- mOutputThread->requestExit();
- mOutputThread->join();
+ if (callerIsDtor) {
+ closeOutputThreadImpl();
+ } else {
+ closeOutputThread();
+ }
Mutex::Autolock _l(mLock);
// free all buffers
- for(auto pair : mStreamMap) {
- cleanupBuffersLocked(/*Stream ID*/pair.first);
+ {
+ Mutex::Autolock _l(mCbsLock);
+ for(auto pair : mStreamMap) {
+ cleanupBuffersLocked(/*Stream ID*/pair.first);
+ }
}
v4l2StreamOffLocked();
ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get());
@@ -463,10 +499,61 @@
return Void();
}
-Status ExternalCameraDeviceSession::importRequest(
+Status ExternalCameraDeviceSession::importRequestLocked(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) {
+ return importRequestLockedImpl(request, allBufPtrs, allFences);
+}
+
+Status ExternalCameraDeviceSession::importBuffer(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf) {
+ Mutex::Autolock _l(mCbsLock);
+ return importBufferLocked(streamId, bufId, buf, outBufPtr, allowEmptyBuf);
+}
+
+Status ExternalCameraDeviceSession::importBufferLocked(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf) {
+
+ if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) {
+ if (allowEmptyBuf) {
+ *outBufPtr = &sEmptyBuffer;
+ return Status::OK;
+ } else {
+ ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ }
+
+ CirculatingBuffers& cbs = mCirculatingBuffers[streamId];
+ if (cbs.count(bufId) == 0) {
+ if (buf == nullptr) {
+ ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ // Register a newly seen buffer
+ buffer_handle_t importedBuf = buf;
+ sHandleImporter.importBuffer(importedBuf);
+ if (importedBuf == nullptr) {
+ ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId);
+ return Status::INTERNAL_ERROR;
+ } else {
+ cbs[bufId] = importedBuf;
+ }
+ }
+ *outBufPtr = &cbs[bufId];
+ return Status::OK;
+}
+
+Status ExternalCameraDeviceSession::importRequestLockedImpl(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
- hidl_vec<int>& allFences) {
+ hidl_vec<int>& allFences,
+ bool allowEmptyBuf) {
size_t numOutputBufs = request.outputBuffers.size();
size_t numBufs = numOutputBufs;
// Validate all I/O buffers
@@ -485,26 +572,17 @@
streamIds[i] = request.outputBuffers[i].streamId;
}
- for (size_t i = 0; i < numBufs; i++) {
- buffer_handle_t buf = allBufs[i];
- uint64_t bufId = allBufIds[i];
- CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
- if (cbs.count(bufId) == 0) {
- if (buf == nullptr) {
- ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
- return Status::ILLEGAL_ARGUMENT;
- }
- // Register a newly seen buffer
- buffer_handle_t importedBuf = buf;
- sHandleImporter.importBuffer(importedBuf);
- if (importedBuf == nullptr) {
- ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
- return Status::INTERNAL_ERROR;
- } else {
- cbs[bufId] = importedBuf;
+ {
+ Mutex::Autolock _l(mCbsLock);
+ for (size_t i = 0; i < numBufs; i++) {
+ Status st = importBufferLocked(
+ streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i],
+ allowEmptyBuf);
+ if (st != Status::OK) {
+ // Detailed error logs printed in importBuffer
+ return st;
}
}
- allBufPtrs[i] = &cbs[bufId];
}
// All buffers are imported. Now validate output buffer acquire fences
@@ -652,7 +730,7 @@
}
}
- status = importRequest(request, allBufPtrs, allFences);
+ status = importRequestLocked(request, allBufPtrs, allFences);
if (status != Status::OK) {
return status;
}
@@ -775,9 +853,11 @@
result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
if (req->buffers[i].fenceTimeout) {
result.outputBuffers[i].status = BufferStatus::ERROR;
- native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
- handle->data[0] = req->buffers[i].acquireFence;
- result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
+ if (req->buffers[i].acquireFence > 0) {
+ native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+ handle->data[0] = req->buffers[i].acquireFence;
+ result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
+ }
notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER);
} else {
result.outputBuffers[i].status = BufferStatus::OK;
@@ -1747,6 +1827,12 @@
(req->frameIn->mFourcc >> 24) & 0xFF);
}
+ int res = requestBufferStart(req->buffers);
+ if (res != 0) {
+ ALOGE("%s: send BufferRequest failed! res %d", __FUNCTION__, res);
+ return onDeviceError("%s: failed to send buffer request!", __FUNCTION__);
+ }
+
std::unique_lock<std::mutex> lk(mBufferLock);
// Convert input V4L2 frame to YU12 of the same size
// TODO: see if we can save some computation by converting to YV12 here
@@ -1759,7 +1845,7 @@
// TODO: in some special case maybe we can decode jpg directly to gralloc output?
ATRACE_BEGIN("MJPGtoI420");
- int res = libyuv::MJPGToI420(
+ res = libyuv::MJPGToI420(
inData, inDataSize,
static_cast<uint8_t*>(mYu12FrameLayout.y),
mYu12FrameLayout.yStride,
@@ -1783,10 +1869,23 @@
return true;
}
+ ATRACE_BEGIN("Wait for BufferRequest done");
+ res = waitForBufferRequestDone(&req->buffers);
+ ATRACE_END();
+
+ if (res != 0) {
+ ALOGE("%s: wait for BufferRequest done failed! res %d", __FUNCTION__, res);
+ lk.unlock();
+ return onDeviceError("%s: failed to process buffer request error!", __FUNCTION__);
+ }
+
ALOGV("%s processing new request", __FUNCTION__);
const int kSyncWaitTimeoutMs = 500;
for (auto& halBuf : req->buffers) {
- if (halBuf.acquireFence != -1) {
+ if (*(halBuf.bufPtr) == nullptr) {
+ ALOGW("%s: buffer for stream %d missing", __FUNCTION__, halBuf.streamId);
+ halBuf.fenceTimeout = true;
+ } else if (halBuf.acquireFence != -1) {
int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
if (ret) {
halBuf.fenceTimeout = true;
@@ -2045,7 +2144,7 @@
}
void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mCbsLock);
for (auto& cache : cachesToRemove) {
auto cbsIt = mCirculatingBuffers.find(cache.streamId);
if (cbsIt == mCirculatingBuffers.end()) {
@@ -2499,30 +2598,33 @@
}
Mutex::Autolock _l(mLock);
- // Add new streams
- for (const auto& stream : config.streams) {
- if (mStreamMap.count(stream.id) == 0) {
- mStreamMap[stream.id] = stream;
- mCirculatingBuffers.emplace(stream.id, CirculatingBuffers{});
- }
- }
-
- // Cleanup removed streams
- for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
- int id = it->first;
- bool found = false;
+ {
+ Mutex::Autolock _l(mCbsLock);
+ // Add new streams
for (const auto& stream : config.streams) {
- if (id == stream.id) {
- found = true;
- break;
+ if (mStreamMap.count(stream.id) == 0) {
+ mStreamMap[stream.id] = stream;
+ mCirculatingBuffers.emplace(stream.id, CirculatingBuffers{});
}
}
- if (!found) {
- // Unmap all buffers of deleted stream
- cleanupBuffersLocked(id);
- it = mStreamMap.erase(it);
- } else {
- ++it;
+
+ // Cleanup removed streams
+ for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+ int id = it->first;
+ bool found = false;
+ for (const auto& stream : config.streams) {
+ if (id == stream.id) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // Unmap all buffers of deleted stream
+ cleanupBuffersLocked(id);
+ it = mStreamMap.erase(it);
+ } else {
+ ++it;
+ }
}
}
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 6e56596..cabeaa4 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -97,7 +97,7 @@
// Call by CameraDevice to dump active device states
void dumpState(const native_handle_t*);
// Caller must use this method to check if CameraDeviceSession ctor failed
- bool isInitFailed() { return mInitFail; }
+ bool isInitFailed();
bool isClosed();
// Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
@@ -134,7 +134,7 @@
ICameraDeviceSession::processCaptureRequest_cb);
Return<Status> flush();
- Return<void> close();
+ Return<void> close(bool callerIsDtor = false);
Return<void> configureStreams_3_3(
const V3_2::StreamConfiguration&,
@@ -170,10 +170,17 @@
std::vector<HalStreamBuffer> buffers;
};
+ static const uint64_t BUFFER_ID_NO_BUFFER = 0;
+
Status constructDefaultRequestSettingsRaw(RequestTemplate type,
V3_2::CameraMetadata *outMetadata);
bool initialize();
+ // To init/close different version of output thread
+ virtual void initOutputThread();
+ virtual void closeOutputThread();
+ void closeOutputThreadImpl();
+
Status initStatus() const;
status_t initDefaultRequests();
status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp);
@@ -195,10 +202,28 @@
bool isSupported(const Stream&);
// Validate and import request's output buffers and acquire fence
- Status importRequest(
+ virtual Status importRequestLocked(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
hidl_vec<int>& allFences);
+
+ Status importRequestLockedImpl(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences,
+ // Optional argument for ICameraDeviceSession@3.5 impl
+ bool allowEmptyBuf = false);
+
+ Status importBuffer(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf);
+
+ Status importBufferLocked(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf);
+
static void cleanupInflightFences(
hidl_vec<int>& allFences, size_t numFences);
void cleanupBuffersLocked(int id);
@@ -224,7 +249,7 @@
class OutputThread : public android::Thread {
public:
OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType);
- ~OutputThread();
+ virtual ~OutputThread();
Status allocateIntermediateBuffers(
const Size& v4lSize, const Size& thumbSize,
@@ -236,7 +261,14 @@
virtual bool threadLoop() override;
void setExifMakeModel(const std::string& make, const std::string& model);
- private:
+
+ protected:
+ // Methods to request output buffer in parallel
+ // No-op for device@3.4. Implemented in device@3.5
+ virtual int requestBufferStart(const std::vector<HalStreamBuffer>&) { return 0; }
+ virtual int waitForBufferRequestDone(
+ /*out*/std::vector<HalStreamBuffer>*) { return 0; }
+
static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') |
static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 |
static_cast<uint32_t>('X') << 24;
@@ -319,6 +351,7 @@
// - init failed
// - camera disconnected
bool mClosed = false;
+ bool mInitialized = false;
bool mInitFail = false;
bool mFirstRequest = false;
common::V1_0::helper::CameraMetadata mLatestReqSetting;
@@ -351,6 +384,8 @@
typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers;
// Stream ID -> circulating buffers map
std::map<int, CirculatingBuffers> mCirculatingBuffers;
+ // Protect mCirculatingBuffers, must not lock mLock after acquiring this lock
+ mutable Mutex mCbsLock;
std::mutex mAfTriggerLock; // protect mAfTrigger
bool mAfTrigger = false;
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index ff0cfb3..719a3ed 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -25,6 +25,8 @@
#include <hidl/MQDescriptor.h>
#include "ExternalCameraDeviceSession.h"
+#include <vector>
+
namespace android {
namespace hardware {
namespace camera {
@@ -49,7 +51,7 @@
/*
* The camera device HAL implementation is opened lazily (via the open call)
*/
-struct ExternalCameraDevice : public ICameraDevice {
+struct ExternalCameraDevice : public virtual RefBase {
// Called by external camera provider HAL.
// Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
@@ -57,33 +59,54 @@
// to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
// camera is detached.
ExternalCameraDevice(const std::string& cameraId, const ExternalCameraConfig& cfg);
- ~ExternalCameraDevice();
+ virtual ~ExternalCameraDevice();
+
+ // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+ // dealing with minor version revs and simultaneous implementation and interface inheritance
+ virtual sp<ICameraDevice> getInterface() {
+ return new TrampolineDeviceInterface_3_4(this);
+ }
// Caller must use this method to check if CameraDevice ctor failed
bool isInitFailed();
+ bool isInitFailedLocked();
/* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
// The following method can be called without opening the actual camera device
- Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
+ Return<void> getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb);
- Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
+ Return<void> getCameraCharacteristics(
+ ICameraDevice::getCameraCharacteristics_cb _hidl_cb);
- Return<Status> setTorchMode(TorchMode) override;
+ Return<Status> setTorchMode(TorchMode);
// Open the device HAL and also return a default capture session
- Return<void> open(const sp<ICameraDeviceCallback>&, open_cb) override;
+ Return<void> open(const sp<ICameraDeviceCallback>&, ICameraDevice::open_cb);
// Forward the dump call to the opened session, or do nothing
- Return<void> dumpState(const ::android::hardware::hidl_handle&) override;
+ Return<void> dumpState(const ::android::hardware::hidl_handle&);
/* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
protected:
+ // Overridden by child implementations for returning different versions of
+ // ExternalCameraDeviceSession
+ virtual sp<ExternalCameraDeviceSession> createSession(
+ const sp<ICameraDeviceCallback>&,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd);
+
// Init supported w/h/format/fps in mSupportedFormats. Caller still owns fd
void initSupportedFormatsLocked(int fd);
+ // Calls into virtual member function. Do not use it in constructor
status_t initCameraCharacteristics();
// Init non-device dependent keys
- status_t initDefaultCharsKeys(::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+ virtual status_t initDefaultCharsKeys(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
// Init camera control chars keys. Caller still owns fd
status_t initCameraControlsCharsKeys(int fd,
::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
@@ -103,6 +126,7 @@
/*inout*/std::vector<SupportedV4L2Format>* pFmts);
Mutex mLock;
+ bool mInitialized = false;
bool mInitFailed = false;
std::string mCameraId;
const ExternalCameraConfig& mCfg;
@@ -112,6 +136,84 @@
wp<ExternalCameraDeviceSession> mSession = nullptr;
::android::hardware::camera::common::V1_0::helper::CameraMetadata mCameraCharacteristics;
+
+ const std::vector<int32_t> AVAILABLE_CHARACTERISTICS_KEYS_3_4 = {
+ ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+ ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ ANDROID_CONTROL_AVAILABLE_EFFECTS,
+ ANDROID_CONTROL_AVAILABLE_MODES,
+ ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+ ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+ ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+ ANDROID_CONTROL_MAX_REGIONS,
+ ANDROID_FLASH_INFO_AVAILABLE,
+ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+ ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ ANDROID_LENS_FACING,
+ ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+ ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+ ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+ ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+ ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+ ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ ANDROID_SCALER_CROPPING_TYPE,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+ ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+ ANDROID_SENSOR_ORIENTATION,
+ ANDROID_SHADING_AVAILABLE_MODES,
+ ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+ ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+ ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+ ANDROID_SYNC_MAX_LATENCY};
+
+private:
+
+ struct TrampolineDeviceInterface_3_4 : public ICameraDevice {
+ TrampolineDeviceInterface_3_4(sp<ExternalCameraDevice> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+ override {
+ return mParent->getResourceCost(_hidl_cb);
+ }
+
+ virtual Return<void> getCameraCharacteristics(
+ V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getCameraCharacteristics(_hidl_cb);
+ }
+
+ virtual Return<Status> setTorchMode(TorchMode mode) override {
+ return mParent->setTorchMode(mode);
+ }
+
+ virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+ V3_2::ICameraDevice::open_cb _hidl_cb) override {
+ return mParent->open(callback, _hidl_cb);
+ }
+
+ virtual Return<void> dumpState(const hidl_handle& fd) override {
+ return mParent->dumpState(fd);
+ }
+
+ private:
+ sp<ExternalCameraDevice> mParent;
+ };
+
};
} // namespace implementation
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 09cf3a4..7a48865 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -20,6 +20,12 @@
export_include_dirs: ["include/device_v3_5_impl"]
}
+cc_library_headers {
+ name: "camera.device@3.5-external-impl_headers",
+ vendor: true,
+ export_include_dirs: ["include/ext_device_v3_5_impl"]
+}
+
cc_library_shared {
name: "camera.device@3.5-impl",
defaults: ["hidl_defaults"],
@@ -52,3 +58,45 @@
],
local_include_dirs: ["include/device_v3_5_impl"],
}
+
+cc_library_shared {
+ name: "camera.device@3.5-external-impl",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+ vendor: true,
+ srcs: [
+ "ExternalCameraDevice.cpp",
+ "ExternalCameraDeviceSession.cpp",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "libcutils",
+ "camera.device@3.2-impl",
+ "camera.device@3.3-impl",
+ "camera.device@3.4-external-impl",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.graphics.mapper@2.0",
+ "liblog",
+ "libhardware",
+ "libcamera_metadata",
+ "libfmq",
+ "libsync",
+ "libyuv",
+ "libjpeg",
+ "libexif",
+ "libtinyxml2"
+ ],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
+ local_include_dirs: ["include/ext_device_v3_5_impl"],
+ export_shared_lib_headers: [
+ "libfmq",
+ ],
+}
diff --git a/camera/device/3.5/default/ExternalCameraDevice.cpp b/camera/device/3.5/default/ExternalCameraDevice.cpp
new file mode 100644
index 0000000..e8d14b5
--- /dev/null
+++ b/camera/device/3.5/default/ExternalCameraDevice.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ExtCamDev@3.5"
+//#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include "ExternalCameraDevice_3_5.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+ExternalCameraDevice::ExternalCameraDevice(
+ const std::string& cameraId, const ExternalCameraConfig& cfg) :
+ V3_4::implementation::ExternalCameraDevice(cameraId, cfg) {}
+
+ExternalCameraDevice::~ExternalCameraDevice() {}
+
+Return<void> ExternalCameraDevice::getPhysicalCameraCharacteristics(const hidl_string&,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) {
+ CameraMetadata cameraCharacteristics;
+ // External camera HAL doesn't support physical camera functions
+ _hidl_cb(Status::ILLEGAL_ARGUMENT, cameraCharacteristics);
+ return Void();
+}
+
+sp<V3_4::implementation::ExternalCameraDeviceSession> ExternalCameraDevice::createSession(
+ const sp<V3_2::ICameraDeviceCallback>& cb,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd) {
+ return new ExternalCameraDeviceSession(
+ cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd));
+}
+
+#define UPDATE(tag, data, size) \
+do { \
+ if (metadata->update((tag), (data), (size))) { \
+ ALOGE("Update " #tag " failed!"); \
+ return -EINVAL; \
+ } \
+} while (0)
+
+status_t ExternalCameraDevice::initDefaultCharsKeys(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+ status_t res =
+ V3_4::implementation::ExternalCameraDevice::initDefaultCharsKeys(metadata);
+
+ if (res != OK) {
+ return res;
+ }
+
+ const uint8_t bufMgrVer = ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5;
+ UPDATE(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &bufMgrVer, 1);
+
+ std::vector<int> availableCharacteristicsKeys = AVAILABLE_CHARACTERISTICS_KEYS_3_4;
+ availableCharacteristicsKeys.reserve(availableCharacteristicsKeys.size() +
+ EXTRA_CHARACTERISTICS_KEYS_3_5.size());
+ for (const auto& key : EXTRA_CHARACTERISTICS_KEYS_3_5) {
+ availableCharacteristicsKeys.push_back(key);
+ }
+ UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+ availableCharacteristicsKeys.data(),
+ availableCharacteristicsKeys.size());
+
+ return OK;
+}
+
+#undef UPDATE
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
diff --git a/camera/device/3.5/default/ExternalCameraDeviceSession.cpp b/camera/device/3.5/default/ExternalCameraDeviceSession.cpp
new file mode 100644
index 0000000..ae7c45e
--- /dev/null
+++ b/camera/device/3.5/default/ExternalCameraDeviceSession.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ExtCamDevSsn@3.5"
+#include <android/log.h>
+
+#include <utils/Trace.h>
+#include "ExternalCameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+ExternalCameraDeviceSession::ExternalCameraDeviceSession(
+ const sp<V3_2::ICameraDeviceCallback>& callback,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd) :
+ V3_4::implementation::ExternalCameraDeviceSession(
+ callback, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd)) {
+
+ mCallback_3_5 = nullptr;
+
+ auto castResult = V3_5::ICameraDeviceCallback::castFrom(callback);
+ if (castResult.isOk()) {
+ sp<V3_5::ICameraDeviceCallback> callback3_5 = castResult;
+ if (callback3_5 != nullptr) {
+ mCallback_3_5 = callback3_5;
+ }
+ }
+
+ if (mCallback_3_5 != nullptr) {
+ mSupportBufMgr = true;
+ }
+}
+
+ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
+ closeOutputThreadImpl();
+}
+
+Return<void> ExternalCameraDeviceSession::configureStreams_3_5(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) {
+ return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+}
+
+Return<void> ExternalCameraDeviceSession::signalStreamFlush(
+ const hidl_vec<int32_t>& /*streamIds*/, uint32_t /*streamConfigCounter*/) {
+ return Void();
+}
+
+Status ExternalCameraDeviceSession::importRequestLocked(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) {
+ if (mSupportBufMgr) {
+ return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
+ }
+ return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
+}
+
+
+ExternalCameraDeviceSession::BufferRequestThread::BufferRequestThread(
+ wp<ExternalCameraDeviceSession> parent,
+ sp<V3_5::ICameraDeviceCallback> callbacks) :
+ mParent(parent),
+ mCallbacks(callbacks) {}
+
+int ExternalCameraDeviceSession::BufferRequestThread::requestBufferStart(
+ const std::vector<HalStreamBuffer>& bufReqs) {
+ if (bufReqs.empty()) {
+ ALOGE("%s: bufReqs is empty!", __FUNCTION__);
+ return -1;
+ }
+
+ {
+ std::lock_guard<std::mutex> lk(mLock);
+ if (mRequestingBuffer) {
+ ALOGE("%s: BufferRequestThread does not support more than one concurrent request!",
+ __FUNCTION__);
+ return -1;
+ }
+
+ mBufferReqs = bufReqs;
+ mRequestingBuffer = true;
+ }
+ mRequestCond.notify_one();
+ return 0;
+}
+
+int ExternalCameraDeviceSession::BufferRequestThread::waitForBufferRequestDone(
+ std::vector<HalStreamBuffer>* outBufReq) {
+ std::unique_lock<std::mutex> lk(mLock);
+ if (!mRequestingBuffer) {
+ ALOGE("%s: no pending buffer request!", __FUNCTION__);
+ return -1;
+ }
+
+ if (mPendingReturnBufferReqs.empty()) {
+ std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqProcTimeoutMs);
+ auto st = mRequestDoneCond.wait_for(lk, timeout);
+ if (st == std::cv_status::timeout) {
+ ALOGE("%s: wait for buffer request finish timeout!", __FUNCTION__);
+ return -1;
+ }
+ }
+ mRequestingBuffer = false;
+ *outBufReq = std::move(mPendingReturnBufferReqs);
+ mPendingReturnBufferReqs.clear();
+ return 0;
+}
+
+void ExternalCameraDeviceSession::BufferRequestThread::waitForNextRequest() {
+ ATRACE_CALL();
+ std::unique_lock<std::mutex> lk(mLock);
+ int waitTimes = 0;
+ while (mBufferReqs.empty()) {
+ if (exitPending()) {
+ return;
+ }
+ std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs);
+ auto st = mRequestCond.wait_for(lk, timeout);
+ if (st == std::cv_status::timeout) {
+ waitTimes++;
+ if (waitTimes == kReqWaitTimesWarn) {
+ // BufferRequestThread just wait forever for new buffer request
+ // But it will print some periodic warning indicating it's waiting
+ ALOGV("%s: still waiting for new buffer request", __FUNCTION__);
+ waitTimes = 0;
+ }
+ }
+ }
+
+ // Fill in hidl BufferRequest
+ mHalBufferReqs.resize(mBufferReqs.size());
+ for (size_t i = 0; i < mHalBufferReqs.size(); i++) {
+ mHalBufferReqs[i].streamId = mBufferReqs[i].streamId;
+ mHalBufferReqs[i].numBuffersRequested = 1;
+ }
+}
+
+bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
+ waitForNextRequest();
+ if (exitPending()) {
+ return false;
+ }
+
+ ATRACE_BEGIN("HIDL requestStreamBuffers");
+ BufferRequestStatus status;
+ hidl_vec<StreamBufferRet> bufRets;
+ auto err = mCallbacks->requestStreamBuffers(mHalBufferReqs,
+ [&status, &bufRets]
+ (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
+ status = s;
+ bufRets = std::move(rets);
+ });
+ ATRACE_END();
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return false;
+ }
+
+ std::unique_lock<std::mutex> lk(mLock);
+ if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
+ if (bufRets.size() != mHalBufferReqs.size()) {
+ ALOGE("%s: expect %zu buffer requests returned, only got %zu",
+ __FUNCTION__, mHalBufferReqs.size(), bufRets.size());
+ return false;
+ }
+
+ auto parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("%s: session has been disconnected!", __FUNCTION__);
+ return false;
+ }
+
+ hidl_vec<int> importedFences;
+ importedFences.resize(bufRets.size());
+ for (size_t i = 0; i < bufRets.size(); i++) {
+ int streamId = bufRets[i].streamId;
+ switch (bufRets[i].val.getDiscriminator()) {
+ case StreamBuffersVal::hidl_discriminator::error:
+ continue;
+ case StreamBuffersVal::hidl_discriminator::buffers: {
+ const hidl_vec<V3_2::StreamBuffer>& hBufs = bufRets[i].val.buffers();
+ if (hBufs.size() != 1) {
+ ALOGE("%s: expect 1 buffer returned, got %zu!", __FUNCTION__, hBufs.size());
+ return false;
+ }
+ const V3_2::StreamBuffer& hBuf = hBufs[0];
+
+ mBufferReqs[i].bufferId = hBuf.bufferId;
+ // TODO: create a batch import API so we don't need to lock/unlock mCbsLock
+ // repeatedly?
+ lk.unlock();
+ Status s = parent->importBuffer(streamId,
+ hBuf.bufferId, hBuf.buffer.getNativeHandle(),
+ /*out*/&mBufferReqs[i].bufPtr,
+ /*allowEmptyBuf*/false);
+ lk.lock();
+
+ if (s != Status::OK) {
+ ALOGE("%s: stream %d import buffer failed!", __FUNCTION__, streamId);
+ cleanupInflightFences(importedFences, i - 1);
+ return false;
+ }
+ if (!sHandleImporter.importFence(hBuf.acquireFence,
+ mBufferReqs[i].acquireFence)) {
+ ALOGE("%s: stream %d import fence failed!", __FUNCTION__, streamId);
+ cleanupInflightFences(importedFences, i - 1);
+ return false;
+ }
+ importedFences[i] = mBufferReqs[i].acquireFence;
+ }
+ break;
+ default:
+ ALOGE("%s: unkown StreamBuffersVal discrimator!", __FUNCTION__);
+ return false;
+ }
+ }
+ } else {
+ ALOGE("%s: requestStreamBuffers call failed!", __FUNCTION__);
+ }
+
+ mPendingReturnBufferReqs = std::move(mBufferReqs);
+ mBufferReqs.clear();
+
+ lk.unlock();
+ mRequestDoneCond.notify_one();
+ return true;
+}
+
+void ExternalCameraDeviceSession::initOutputThread() {
+ if (mSupportBufMgr) {
+ mBufferRequestThread = new BufferRequestThread(this, mCallback_3_5);
+ mBufferRequestThread->run("ExtCamBufReq", PRIORITY_DISPLAY);
+ }
+ mOutputThread = new OutputThread(this, mCroppingType, mBufferRequestThread);
+}
+
+void ExternalCameraDeviceSession::closeOutputThreadImpl() {
+ if (mBufferRequestThread) {
+ mBufferRequestThread->requestExit();
+ mBufferRequestThread->join();
+ mBufferRequestThread.clear();
+ }
+}
+
+void ExternalCameraDeviceSession::closeOutputThread() {
+ closeOutputThreadImpl();
+ V3_4::implementation::ExternalCameraDeviceSession::closeOutputThread();
+}
+
+ExternalCameraDeviceSession::OutputThread::OutputThread(
+ wp<ExternalCameraDeviceSession> parent,
+ CroppingType ct,
+ sp<BufferRequestThread> bufReqThread) :
+ V3_4::implementation::ExternalCameraDeviceSession::OutputThread(parent, ct),
+ mBufferRequestThread(bufReqThread) {}
+
+ExternalCameraDeviceSession::OutputThread::~OutputThread() {}
+
+int ExternalCameraDeviceSession::OutputThread::requestBufferStart(
+ const std::vector<HalStreamBuffer>& bufs) {
+ if (mBufferRequestThread != nullptr) {
+ return mBufferRequestThread->requestBufferStart(bufs);
+ }
+ return 0;
+}
+
+int ExternalCameraDeviceSession::OutputThread::waitForBufferRequestDone(
+ /*out*/std::vector<HalStreamBuffer>* outBufs) {
+ if (mBufferRequestThread != nullptr) {
+ return mBufferRequestThread->waitForBufferRequestDone(outBufs);
+ }
+ return 0;
+}
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
new file mode 100644
index 0000000..4d2d6b7
--- /dev/null
+++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE3SESSION_H
+
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <../../3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::BufferCache;
+using ::android::hardware::camera::device::V3_5::BufferRequest;
+using ::android::hardware::camera::device::V3_5::BufferRequestStatus;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ErrorCode;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::MsgType;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::Stream;
+using ::android::hardware::camera::device::V3_5::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamType;
+using ::android::hardware::camera::device::V3_2::DataspaceFlags;
+using ::android::hardware::camera::device::V3_2::CameraBlob;
+using ::android::hardware::camera::device::V3_2::CameraBlobId;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::camera::common::V1_0::helper::ExifUtils;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::external::common::Size;
+using ::android::hardware::camera::external::common::SizeHasher;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+using ::android::base::unique_fd;
+
+using ::android::hardware::camera::device::V3_4::implementation::SupportedV4L2Format;
+using ::android::hardware::camera::device::V3_4::implementation::CroppingType;
+
+struct ExternalCameraDeviceSession : public V3_4::implementation::ExternalCameraDeviceSession {
+
+ ExternalCameraDeviceSession(const sp<V3_2::ICameraDeviceCallback>&,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd);
+ virtual ~ExternalCameraDeviceSession();
+
+ // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+ // dealing with minor version revs and simultaneous implementation and interface inheritance
+ virtual sp<V3_4::ICameraDeviceSession> getInterface() override {
+ return new TrampolineSessionInterface_3_5(this);
+ }
+
+protected:
+ // Methods from v3.4 and earlier will trampoline to inherited implementation
+ Return<void> configureStreams_3_5(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
+
+ Return<void> signalStreamFlush(
+ const hidl_vec<int32_t>& requests,
+ uint32_t streamConfigCounter);
+
+ virtual void initOutputThread() override;
+ virtual void closeOutputThread() override;
+ void closeOutputThreadImpl();
+
+ virtual Status importRequestLocked(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) override;
+
+ class BufferRequestThread : public android::Thread {
+ public:
+ BufferRequestThread(
+ wp<ExternalCameraDeviceSession> parent,
+ sp<V3_5::ICameraDeviceCallback> callbacks);
+
+ int requestBufferStart(const std::vector<HalStreamBuffer>&);
+ int waitForBufferRequestDone(
+ /*out*/std::vector<HalStreamBuffer>*);
+
+ virtual bool threadLoop() override;
+
+ private:
+ void waitForNextRequest();
+
+ const wp<ExternalCameraDeviceSession> mParent;
+ const sp<V3_5::ICameraDeviceCallback> mCallbacks;
+
+ std::mutex mLock;
+ bool mRequestingBuffer = false;
+
+ std::vector<HalStreamBuffer> mBufferReqs;
+ std::vector<HalStreamBuffer> mPendingReturnBufferReqs;
+ // mHalBufferReqs is not under mLock protection during the HIDL transaction
+ hidl_vec<BufferRequest> mHalBufferReqs;
+
+ // request buffers takes much less time in steady state, but can take much longer
+ // when requesting 1st buffer from a stream.
+ // TODO: consider a separate timeout for new vs. steady state?
+ // TODO: or make sure framework is warming up the pipeline during configure new stream?
+ static const int kReqProcTimeoutMs = 66;
+
+ static const int kReqWaitTimeoutMs = 33;
+ static const int kReqWaitTimesWarn = 90; // 33ms * 90 ~= 3 sec
+ std::condition_variable mRequestCond; // signaled when a new buffer request incoming
+ std::condition_variable mRequestDoneCond; // signaled when a request is done
+ };
+
+ sp<BufferRequestThread> mBufferRequestThread;
+
+ class OutputThread :
+ public V3_4::implementation::ExternalCameraDeviceSession::OutputThread {
+ public:
+ // TODO: pass buffer request thread to OutputThread ctor
+ OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType,
+ sp<BufferRequestThread> bufReqThread);
+ virtual ~OutputThread();
+
+ protected:
+ // Methods to request output buffer in parallel
+ virtual int requestBufferStart(const std::vector<HalStreamBuffer>&) override;
+ virtual int waitForBufferRequestDone(
+ /*out*/std::vector<HalStreamBuffer>*) override;
+
+ const sp<BufferRequestThread> mBufferRequestThread;
+ };
+
+ sp<V3_5::ICameraDeviceCallback> mCallback_3_5;
+ bool mSupportBufMgr;
+
+private:
+
+ struct TrampolineSessionInterface_3_5 : public ICameraDeviceSession {
+ TrampolineSessionInterface_3_5(sp<ExternalCameraDeviceSession> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> constructDefaultRequestSettings(
+ RequestTemplate type,
+ V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+ return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams(
+ const V3_2::StreamConfiguration& requestedConfiguration,
+ V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+ return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+ const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+ V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+ return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+ }
+
+ virtual Return<void> getCaptureRequestMetadataQueue(
+ V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override {
+ return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+ }
+
+ virtual Return<void> getCaptureResultMetadataQueue(
+ V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override {
+ return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+ }
+
+ virtual Return<Status> flush() override {
+ return mParent->flush();
+ }
+
+ virtual Return<void> close() override {
+ return mParent->close();
+ }
+
+ virtual Return<void> configureStreams_3_3(
+ const V3_2::StreamConfiguration& requestedConfiguration,
+ configureStreams_3_3_cb _hidl_cb) override {
+ return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams_3_4(
+ const V3_4::StreamConfiguration& requestedConfiguration,
+ configureStreams_3_4_cb _hidl_cb) override {
+ return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,
+ const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+ ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+ return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams_3_5(
+ const StreamConfiguration& requestedConfiguration,
+ configureStreams_3_5_cb _hidl_cb) override {
+ return mParent->configureStreams_3_5(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> signalStreamFlush(
+ const hidl_vec<int32_t>& requests,
+ uint32_t streamConfigCounter) override {
+ return mParent->signalStreamFlush(requests, streamConfigCounter);
+ }
+
+ private:
+ sp<ExternalCameraDeviceSession> mParent;
+ };
+};
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE3SESSION_H
diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h
new file mode 100644
index 0000000..7db86dc
--- /dev/null
+++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE_H
+
+#include "utils/Mutex.h"
+#include "CameraMetadata.h"
+
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include "ExternalCameraDeviceSession.h"
+#include <../../../../3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_5::ICameraDevice;
+using ::android::hardware::camera::common::V1_0::CameraResourceCost;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::external::common::Size;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * The camera device HAL implementation is opened lazily (via the open call)
+ */
+struct ExternalCameraDevice : public V3_4::implementation::ExternalCameraDevice {
+
+ // Called by external camera provider HAL.
+ // Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
+ // be multiple CameraDevice trying to access the same physical camera. Also, provider will have
+ // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
+ // camera is detached.
+ ExternalCameraDevice(const std::string& cameraId, const ExternalCameraConfig& cfg);
+ virtual ~ExternalCameraDevice();
+
+ virtual sp<V3_2::ICameraDevice> getInterface() override {
+ return new TrampolineDeviceInterface_3_5(this);
+ }
+
+ Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb);
+
+protected:
+ virtual sp<V3_4::implementation::ExternalCameraDeviceSession> createSession(
+ const sp<V3_2::ICameraDeviceCallback>&,
+ const ExternalCameraConfig& cfg,
+ const std::vector<SupportedV4L2Format>& sortedFormats,
+ const CroppingType& croppingType,
+ const common::V1_0::helper::CameraMetadata& chars,
+ const std::string& cameraId,
+ unique_fd v4l2Fd) override;
+
+ virtual status_t initDefaultCharsKeys(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata*) override;
+
+ const std::vector<int32_t> EXTRA_CHARACTERISTICS_KEYS_3_5 = {
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION
+ };
+
+private:
+ struct TrampolineDeviceInterface_3_5 : public ICameraDevice {
+ TrampolineDeviceInterface_3_5(sp<ExternalCameraDevice> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+ override {
+ return mParent->getResourceCost(_hidl_cb);
+ }
+
+ virtual Return<void> getCameraCharacteristics(
+ V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getCameraCharacteristics(_hidl_cb);
+ }
+
+ virtual Return<Status> setTorchMode(TorchMode mode) override {
+ return mParent->setTorchMode(mode);
+ }
+
+ virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+ V3_2::ICameraDevice::open_cb _hidl_cb) override {
+ return mParent->open(callback, _hidl_cb);
+ }
+
+ virtual Return<void> dumpState(const hidl_handle& fd) override {
+ return mParent->dumpState(fd);
+ }
+
+ virtual Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb);
+ }
+ private:
+ sp<ExternalCameraDevice> mParent;
+ };
+};
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_EXTCAMERADEVICE_H
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index de02d78..167954c 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -21,6 +21,7 @@
"camera.device@3.4-impl",
"camera.device@3.5-impl",
"camera.device@3.4-external-impl",
+ "camera.device@3.5-external-impl",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
"android.hardware.graphics.mapper@2.0",
@@ -34,7 +35,8 @@
header_libs: [
"camera.device@3.4-impl_headers",
"camera.device@3.5-impl_headers",
- "camera.device@3.4-external-impl_headers"
+ "camera.device@3.4-external-impl_headers",
+ "camera.device@3.5-external-impl_headers"
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
@@ -107,6 +109,8 @@
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
],
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
index 1cec0e5..604df5c 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -24,6 +24,8 @@
#include <linux/videodev2.h>
#include "ExternalCameraProvider.h"
#include "ExternalCameraDevice_3_4.h"
+#include "ExternalCameraDevice_3_5.h"
+#include <cutils/properties.h>
namespace android {
namespace hardware {
@@ -62,6 +64,21 @@
mCfg(ExternalCameraConfig::loadFromCfg()),
mHotPlugThread(this) {
mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
+
+ mPreferredHal3MinorVersion =
+ property_get_int32("ro.vendor.camera.external.hal3TrebleMinorVersion", 4);
+ ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
+ switch(mPreferredHal3MinorVersion) {
+ case 4:
+ case 5:
+ // OK
+ break;
+ default:
+ ALOGW("Unknown minor camera device HAL version %d in property "
+ "'camera.external.hal3TrebleMinorVersion', defaulting to 4",
+ mPreferredHal3MinorVersion);
+ mPreferredHal3MinorVersion = 4;
+ }
}
ExternalCameraProvider::~ExternalCameraProvider() {
@@ -136,20 +153,43 @@
return Void();
}
- ALOGV("Constructing v3.4 external camera device");
- sp<device::V3_2::ICameraDevice> device;
- sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
- new device::V3_4::implementation::ExternalCameraDevice(
+ sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl;
+ switch (mPreferredHal3MinorVersion) {
+ case 4: {
+ ALOGV("Constructing v3.4 external camera device");
+ deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(
cameraId, mCfg);
+ break;
+ }
+ case 5: {
+ ALOGV("Constructing v3.5 external camera device");
+ deviceImpl = new device::V3_5::implementation::ExternalCameraDevice(
+ cameraId, mCfg);
+ break;
+ }
+ default:
+ ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
+ _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+ return Void();
+ }
+
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
- device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
- device = deviceImpl;
- _hidl_cb (Status::OK, device);
+ IF_ALOGV() {
+ deviceImpl->getInterface()->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Device interface chain:");
+ for (auto iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ _hidl_cb (Status::OK, deviceImpl->getInterface());
return Void();
}
@@ -157,7 +197,12 @@
void ExternalCameraProvider::addExternalCamera(const char* devName) {
ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
Mutex::Autolock _l(mLock);
- std::string deviceName = std::string("device@3.4/external/") + devName;
+ std::string deviceName;
+ if (mPreferredHal3MinorVersion == 5) {
+ deviceName = std::string("device@3.5/external/") + devName;
+ } else {
+ deviceName = std::string("device@3.4/external/") + devName;
+ }
mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
if (mCallbacks != nullptr) {
mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
@@ -199,7 +244,12 @@
void ExternalCameraProvider::deviceRemoved(const char* devName) {
Mutex::Autolock _l(mLock);
- std::string deviceName = std::string("device@3.4/external/") + devName;
+ std::string deviceName;
+ if (mPreferredHal3MinorVersion == 5) {
+ deviceName = std::string("device@3.5/external/") + devName;
+ } else {
+ deviceName = std::string("device@3.4/external/") + devName;
+ }
if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
mCameraStatusMap.erase(deviceName);
if (mCallbacks != nullptr) {
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.h b/camera/provider/2.4/default/ExternalCameraProvider.h
index c83cc70..a69cf8b 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.h
+++ b/camera/provider/2.4/default/ExternalCameraProvider.h
@@ -95,6 +95,7 @@
std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
const ExternalCameraConfig mCfg;
HotplugThread mHotPlugThread;
+ int mPreferredHal3MinorVersion;
};
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 837905c..c324d59 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -142,6 +142,11 @@
int32_t outputFormat;
};
+enum ReprocessType {
+ PRIV_REPROCESS,
+ YUV_REPROCESS,
+};
+
namespace {
// "device@<version>/legacy/<id>"
const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
@@ -559,7 +564,8 @@
};
struct DeviceCb : public V3_4::ICameraDeviceCallback {
- DeviceCb(CameraHidlTest *parent) : mParent(parent) {}
+ DeviceCb(CameraHidlTest *parent, bool checkMonochromeResult) : mParent(parent),
+ mCheckMonochromeResult(checkMonochromeResult) {}
Return<void> processCaptureResult_3_4(
const hidl_vec<V3_4::CaptureResult>& results) override;
Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
@@ -569,6 +575,7 @@
bool processCaptureResultLocked(const CaptureResult& results);
CameraHidlTest *mParent; // Parent object
+ bool mCheckMonochromeResult;
};
struct TorchProviderCb : public ICameraProviderCallback {
@@ -682,6 +689,9 @@
const hidl_vec<hidl_string>& deviceNames);
void verifyCameraCharacteristics(Status status, const CameraMetadata& chars);
void verifyRecommendedConfigs(const CameraMetadata& metadata);
+ void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion);
+ void verifyMonochromeCameraResult(
+ const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata);
static Status getAvailableOutputStreams(camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
@@ -700,6 +710,7 @@
static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
AvailableStream &hfrStream);
static Status isZSLModeAvailable(const camera_metadata_t *staticMeta);
+ static Status isZSLModeAvailable(const camera_metadata_t *staticMeta, ReprocessType reprocType);
static Status getZSLInputOutputMap(camera_metadata_t *staticMeta,
std::vector<AvailableZSLInputOutput> &inputOutputMap);
static Status findLargestSize(
@@ -707,6 +718,7 @@
int32_t format, AvailableStream &result);
static Status isAutoFocusModeAvailable(
CameraParameters &cameraParams, const char *mode) ;
+ static Status isMonochromeCamera(const camera_metadata_t *staticMeta);
protected:
@@ -1050,6 +1062,11 @@
}
request->haveResultMetadata = true;
request->collectedResult.sort();
+
+ // Verify final result metadata
+ if (mCheckMonochromeResult) {
+ mParent->verifyMonochromeCameraResult(request->collectedResult);
+ }
}
uint32_t numBuffersReturned = results.outputBuffers.size();
@@ -2080,6 +2097,7 @@
ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
verifyCameraCharacteristics(status, chars);
+ verifyMonochromeCharacteristics(chars, deviceVersion);
verifyRecommendedConfigs(chars);
verifyLogicalCameraMetadata(name, device3_x, chars, deviceVersion,
cameraDeviceNames);
@@ -2777,13 +2795,34 @@
ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
ASSERT_NE(0u, inputOutputMap.size());
+ bool supportMonoY8 = false;
+ if (Status::OK == isMonochromeCamera(staticMeta)) {
+ for (auto& it : inputStreams) {
+ if (it.format == static_cast<uint32_t>(PixelFormat::Y8)) {
+ supportMonoY8 = true;
+ break;
+ }
+ }
+ }
+
int32_t streamId = 0;
+ bool hasPrivToY8 = false, hasY8ToY8 = false, hasY8ToBlob = false;
for (auto& inputIter : inputOutputMap) {
AvailableStream input;
ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat,
input));
ASSERT_NE(0u, inputStreams.size());
+ if (inputIter.inputFormat == static_cast<uint32_t>(PixelFormat::IMPLEMENTATION_DEFINED)
+ && inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
+ hasPrivToY8 = true;
+ } else if (inputIter.inputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
+ if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::BLOB)) {
+ hasY8ToBlob = true;
+ } else if (inputIter.outputFormat == static_cast<uint32_t>(PixelFormat::Y8)) {
+ hasY8ToY8 = true;
+ }
+ }
AvailableStream outputThreshold = {INT32_MAX, INT32_MAX,
inputIter.outputFormat};
std::vector<AvailableStream> outputStreams;
@@ -2845,6 +2884,16 @@
}
}
+ if (supportMonoY8) {
+ if (Status::OK == isZSLModeAvailable(staticMeta, PRIV_REPROCESS)) {
+ ASSERT_TRUE(hasPrivToY8);
+ }
+ if (Status::OK == isZSLModeAvailable(staticMeta, YUV_REPROCESS)) {
+ ASSERT_TRUE(hasY8ToY8);
+ ASSERT_TRUE(hasY8ToBlob);
+ }
+ }
+
free_camera_metadata(staticMeta);
ret = session->close();
ASSERT_TRUE(ret.isOk());
@@ -4325,6 +4374,16 @@
// Check whether ZSL is available using the static camera
// characteristics.
Status CameraHidlTest::isZSLModeAvailable(const camera_metadata_t *staticMeta) {
+ if (Status::OK == isZSLModeAvailable(staticMeta, PRIV_REPROCESS)) {
+ return Status::OK;
+ } else {
+ return isZSLModeAvailable(staticMeta, YUV_REPROCESS);
+ }
+}
+
+Status CameraHidlTest::isZSLModeAvailable(const camera_metadata_t *staticMeta,
+ ReprocessType reprocType) {
+
Status ret = Status::METHOD_NOT_SUPPORTED;
if (nullptr == staticMeta) {
return Status::ILLEGAL_ARGUMENT;
@@ -4338,10 +4397,34 @@
}
for (size_t i = 0; i < entry.count; i++) {
- if ((ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING ==
- entry.data.u8[i]) ||
- (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING ==
- entry.data.u8[i]) ){
+ if ((reprocType == PRIV_REPROCESS &&
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING == entry.data.u8[i]) ||
+ (reprocType == YUV_REPROCESS &&
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING == entry.data.u8[i])) {
+ ret = Status::OK;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Check whether this is a monochrome camera using the static camera characteristics.
+Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) {
+ Status ret = Status::METHOD_NOT_SUPPORTED;
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ if (0 != rc) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < entry.count; i++) {
+ if (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME == entry.data.u8[i]) {
ret = Status::OK;
break;
}
@@ -4460,22 +4543,6 @@
});
ASSERT_TRUE(ret.isOk());
- sp<DeviceCb> cb = new DeviceCb(this);
- sp<ICameraDeviceSession> session;
- ret = device3_x->open(
- cb,
- [&session](auto status, const auto& newSession) {
- ALOGI("device::open returns status:%d", (int)status);
- ASSERT_EQ(Status::OK, status);
- ASSERT_NE(newSession, nullptr);
- session = newSession;
- });
- ASSERT_TRUE(ret.isOk());
-
- sp<device::V3_3::ICameraDeviceSession> session3_3;
- castSession(session, deviceVersion, &session3_3, session3_4);
- ASSERT_NE(nullptr, session3_4);
-
camera_metadata_t *staticMeta;
ret = device3_x->getCameraCharacteristics([&] (Status s,
CameraMetadata metadata) {
@@ -4494,6 +4561,24 @@
*supportsPartialResults = (*partialResultCount > 1);
}
+ bool checkMonochromeResultTags = Status::OK == isMonochromeCamera(staticMeta) &&
+ deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5;
+ sp<DeviceCb> cb = new DeviceCb(this, checkMonochromeResultTags);
+ sp<ICameraDeviceSession> session;
+ ret = device3_x->open(
+ cb,
+ [&session](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ sp<device::V3_3::ICameraDeviceSession> session3_3;
+ castSession(session, deviceVersion, &session3_3, session3_4);
+ ASSERT_NE(nullptr, session3_4);
+
outputPreviewStreams.clear();
auto rc = getAvailableOutputStreams(staticMeta,
outputPreviewStreams, previewThreshold);
@@ -4563,21 +4648,6 @@
});
ASSERT_TRUE(ret.isOk());
- sp<DeviceCb> cb = new DeviceCb(this);
- ret = device3_x->open(
- cb,
- [&](auto status, const auto& newSession) {
- ALOGI("device::open returns status:%d", (int)status);
- ASSERT_EQ(Status::OK, status);
- ASSERT_NE(newSession, nullptr);
- *session = newSession;
- });
- ASSERT_TRUE(ret.isOk());
-
- sp<device::V3_3::ICameraDeviceSession> session3_3;
- sp<device::V3_4::ICameraDeviceSession> session3_4;
- castSession(*session, deviceVersion, &session3_3, &session3_4);
-
camera_metadata_t *staticMeta;
ret = device3_x->getCameraCharacteristics([&] (Status s,
CameraMetadata metadata) {
@@ -4596,6 +4666,23 @@
*supportsPartialResults = (*partialResultCount > 1);
}
+ bool checkMonochromeResultTags = Status::OK == isMonochromeCamera(staticMeta) &&
+ deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5;
+ sp<DeviceCb> cb = new DeviceCb(this, checkMonochromeResultTags);
+ ret = device3_x->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ *session = newSession;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ sp<device::V3_3::ICameraDeviceSession> session3_3;
+ sp<device::V3_4::ICameraDeviceSession> session3_4;
+ castSession(*session, deviceVersion, &session3_3, &session3_4);
+
outputPreviewStreams.clear();
auto rc = getAvailableOutputStreams(staticMeta,
outputPreviewStreams, previewThreshold);
@@ -4723,6 +4810,7 @@
Return<void> ret = device3_5->getPhysicalCameraCharacteristics(physicalId,
[&](auto status, const auto& chars) {
verifyCameraCharacteristics(status, chars);
+ verifyMonochromeCharacteristics(chars, deviceVersion);
});
ASSERT_TRUE(ret.isOk());
@@ -4774,6 +4862,149 @@
}
}
+void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars,
+ int deviceVersion) {
+ const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+ Status rc = isMonochromeCamera(metadata);
+ if (Status::METHOD_NOT_SUPPORTED == rc) {
+ return;
+ }
+ ASSERT_EQ(Status::OK, rc);
+
+ camera_metadata_ro_entry entry;
+ // Check capabilities
+ int retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ ASSERT_EQ(std::find(entry.data.u8, entry.data.u8 + entry.count,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING),
+ entry.data.u8 + entry.count);
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) {
+ ASSERT_EQ(std::find(entry.data.u8, entry.data.u8 + entry.count,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW),
+ entry.data.u8 + entry.count);
+ }
+ }
+
+ if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) {
+ // Check Cfa
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT, &entry);
+ if ((0 == retcode) && (entry.count == 1)) {
+ ASSERT_TRUE(entry.data.i32[0] == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
+ || entry.data.i32[0] == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR);
+ }
+
+ // Check availableRequestKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ for (size_t i = 0; i < entry.count; i++) {
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_MODE);
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_TRANSFORM);
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_GAINS);
+ }
+ } else {
+ ADD_FAILURE() << "Get camera availableRequestKeys failed!";
+ }
+
+ // Check availableResultKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ for (size_t i = 0; i < entry.count; i++) {
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_GREEN_SPLIT);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_MODE);
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_TRANSFORM);
+ ASSERT_NE(entry.data.i32[i], ANDROID_COLOR_CORRECTION_GAINS);
+ }
+ } else {
+ ADD_FAILURE() << "Get camera availableResultKeys failed!";
+ }
+
+ // Check availableCharacteristicKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ for (size_t i = 0; i < entry.count; i++) {
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_REFERENCE_ILLUMINANT2);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_CALIBRATION_TRANSFORM2);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_COLOR_TRANSFORM1);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_COLOR_TRANSFORM2);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_FORWARD_MATRIX1);
+ ASSERT_NE(entry.data.i32[i], ANDROID_SENSOR_FORWARD_MATRIX2);
+ }
+ } else {
+ ADD_FAILURE() << "Get camera availableResultKeys failed!";
+ }
+
+ // Check blackLevelPattern
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_SENSOR_BLACK_LEVEL_PATTERN, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ ASSERT_EQ(entry.count, 4);
+ for (size_t i = 1; i < entry.count; i++) {
+ ASSERT_EQ(entry.data.i32[i], entry.data.i32[0]);
+ }
+ }
+ }
+}
+
+void CameraHidlTest::verifyMonochromeCameraResult(
+ const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata) {
+ camera_metadata_ro_entry entry;
+
+ // Check tags that are not applicable for monochrome camera
+ ASSERT_FALSE(metadata.exists(ANDROID_SENSOR_GREEN_SPLIT));
+ ASSERT_FALSE(metadata.exists(ANDROID_SENSOR_NEUTRAL_COLOR_POINT));
+ ASSERT_FALSE(metadata.exists(ANDROID_COLOR_CORRECTION_MODE));
+ ASSERT_FALSE(metadata.exists(ANDROID_COLOR_CORRECTION_TRANSFORM));
+ ASSERT_FALSE(metadata.exists(ANDROID_COLOR_CORRECTION_GAINS));
+
+ // Check dynamicBlackLevel
+ entry = metadata.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
+ if (entry.count > 0) {
+ ASSERT_EQ(entry.count, 4);
+ for (size_t i = 1; i < entry.count; i++) {
+ ASSERT_FLOAT_EQ(entry.data.f[i], entry.data.f[0]);
+ }
+ }
+
+ // Check noiseProfile
+ entry = metadata.find(ANDROID_SENSOR_NOISE_PROFILE);
+ if (entry.count > 0) {
+ ASSERT_EQ(entry.count, 2);
+ }
+
+ // Check lensShadingMap
+ entry = metadata.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
+ if (entry.count > 0) {
+ ASSERT_EQ(entry.count % 4, 0);
+ for (size_t i = 0; i < entry.count/4; i++) {
+ ASSERT_FLOAT_EQ(entry.data.f[i*4+1], entry.data.f[i*4]);
+ ASSERT_FLOAT_EQ(entry.data.f[i*4+2], entry.data.f[i*4]);
+ ASSERT_FLOAT_EQ(entry.data.f[i*4+3], entry.data.f[i*4]);
+ }
+ }
+
+ // Check tonemapCurve
+ camera_metadata_ro_entry curveRed = metadata.find(ANDROID_TONEMAP_CURVE_RED);
+ camera_metadata_ro_entry curveGreen = metadata.find(ANDROID_TONEMAP_CURVE_GREEN);
+ camera_metadata_ro_entry curveBlue = metadata.find(ANDROID_TONEMAP_CURVE_BLUE);
+ if (curveRed.count > 0 && curveGreen.count > 0 && curveBlue.count > 0) {
+ ASSERT_EQ(curveRed.count, curveGreen.count);
+ ASSERT_EQ(curveRed.count, curveBlue.count);
+ for (size_t i = 0; i < curveRed.count; i++) {
+ ASSERT_FLOAT_EQ(curveGreen.data.f[i], curveRed.data.f[i]);
+ ASSERT_FLOAT_EQ(curveBlue.data.f[i], curveRed.data.f[i]);
+ }
+ }
+}
+
+
// Open a device session with empty callbacks and return static metadata.
void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
sp<ICameraProvider> provider,
diff --git a/keymaster/3.0/vts/functional/authorization_set.h b/keymaster/3.0/vts/functional/authorization_set.h
index 5f92d81..60b00e4 100644
--- a/keymaster/3.0/vts/functional/authorization_set.h
+++ b/keymaster/3.0/vts/functional/authorization_set.h
@@ -201,7 +201,7 @@
void push_back(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data, size_t data_length) {
hidl_vec<uint8_t> new_blob;
new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
- push_back(ttag, std::move(new_blob));
+ push_back(ttag, new_blob);
}
/**
@@ -225,8 +225,7 @@
}
hidl_vec<KeyParameter> hidl_data() const {
- hidl_vec<KeyParameter> result;
- result.setToExternal(const_cast<KeyParameter*>(data()), size());
+ hidl_vec<KeyParameter> result(begin(), end());
return result;
}
@@ -252,7 +251,7 @@
size_t data_length) {
hidl_vec<uint8_t> new_blob;
new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
- push_back(ttag, std::move(new_blob));
+ push_back(ttag, new_blob);
return *this;
}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index ac96c86..a131423 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -214,9 +214,8 @@
}
}
- const hidl_vec<KeyParameter> hidl_data() const {
- hidl_vec<KeyParameter> result;
- result.setToExternal(const_cast<KeyParameter*>(data()), size());
+ hidl_vec<KeyParameter> hidl_data() const {
+ hidl_vec<KeyParameter> result(begin(), end());
return result;
}
@@ -242,7 +241,7 @@
size_t data_length) {
hidl_vec<uint8_t> new_blob;
new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
- push_back(ttag, std::move(new_blob));
+ push_back(ttag, new_blob);
return *this;
}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
index 90a0f1b..5e5ae8d 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -33,25 +33,19 @@
namespace support {
-inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
- bool inPlace = true) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<unsigned char*>(data), length, !inPlace);
+inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length) {
+ hidl_vec<uint8_t> result(data, data + length);
return result;
}
-inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value, bool inPlace = true) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(value.data())),
- static_cast<size_t>(value.size()), !inPlace);
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value) {
+ hidl_vec<uint8_t> result(reinterpret_cast<const uint8_t*>(value.data()),
+ reinterpret_cast<const uint8_t*>(value.data()) + value.size());
return result;
}
-inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob,
- bool inPlace = true) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size()),
- !inPlace);
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) {
+ hidl_vec<uint8_t> result(blob.data(), blob.data() + static_cast<size_t>(blob.size()));
return result;
}
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 22d0002..fe9b312 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -33,15 +33,13 @@
/**
* A tensor of 16 bit signed integers that represent real numbers.
*
- * Attached to this tensor are two numbers that are used to convert the 16
- * bit integer to the real value and vice versa. These two numbers are:
- * - scale: a 32 bit floating point value greater than zero.
- * - zeroPoint: a 32 bit integer, in range [-32768, 32767].
+ * Attached to this tensor is a number representing real value scale that is
+ * used to convert the 16 bit number to a real value in the following way:
+ * realValue = integerValue * scale.
*
- * The formula is:
- * realValue = (integerValue - zeroPoint) * scale.
+ * scale is a 32 bit floating point with value greater then zero.
*/
- TENSOR_QUANT16_ASYMM = 7,
+ TENSOR_QUANT16_SYMM = 7,
/** A tensor of 16 bit floating point values. */
TENSOR_FLOAT16 = 8,
};
@@ -115,6 +113,8 @@
UNIDIRECTIONAL_SEQUENCE_LSTM = 85,
UNIDIRECTIONAL_SEQUENCE_RNN = 86,
ROTATED_BBOX_TRANSFORM = 87,
+ ABS = 88,
+ ROI_POOLING = 89,
};
/**
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index e309642..c4f1b5e 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -161,7 +161,7 @@
case OperandType::TENSOR_FLOAT32:
case OperandType::TENSOR_INT32:
case OperandType::TENSOR_QUANT8_ASYMM:
- case OperandType::TENSOR_QUANT16_ASYMM:
+ case OperandType::TENSOR_QUANT16_SYMM:
return 0;
default:
return 0;
@@ -193,7 +193,7 @@
case OperandType::TENSOR_INT32:
return -1.0f;
case OperandType::TENSOR_QUANT8_ASYMM:
- case OperandType::TENSOR_QUANT16_ASYMM:
+ case OperandType::TENSOR_QUANT16_SYMM:
return 0.0f;
default:
return 0.0f;
@@ -225,8 +225,8 @@
return {1};
case OperandType::TENSOR_QUANT8_ASYMM:
return {-1, 256};
- case OperandType::TENSOR_QUANT16_ASYMM:
- return {-32769, 32768};
+ case OperandType::TENSOR_QUANT16_SYMM:
+ return {-32769, -1, 1, 32768};
default:
return {};
}
@@ -279,7 +279,7 @@
newOperand.zeroPoint = 0;
break;
case OperandType::TENSOR_QUANT8_ASYMM:
- case OperandType::TENSOR_QUANT16_ASYMM:
+ case OperandType::TENSOR_QUANT16_SYMM:
newOperand.dimensions =
operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index 3c65180..7012f6b 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -24,6 +24,7 @@
"CellConfigLte",
"CellInfo",
"CellInfoLte",
+ "CardStatus",
"DataProfileInfo",
"DataRegStateResult",
"EmergencyNumber",
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index 75d1501..fecd951 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -72,4 +72,19 @@
*/
oneway getDataRegistrationStateResponse_1_3(RadioResponseInfo info,
DataRegStateResult dataRegResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param cardStatus ICC card status as defined by CardStatus in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_MEMORY
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:REQUEST_NOT_SUPPORTED
+ */
+ oneway getIccCardStatusResponse_1_3(RadioResponseInfo info, CardStatus cardStatus);
};
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
index b161e0e..d3a6f78 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -33,6 +33,7 @@
import @1.2::CellInfoLte;
import @1.2::CellInfoTdscdma;
import @1.2::CellInfoWcdma;
+import @1.2::CardStatus;
import @1.2::CellIdentity;
import @1.2::DataRegStateResult;
@@ -325,3 +326,15 @@
*/
bool persistent;
};
+
+struct CardStatus {
+ @1.2::CardStatus base;
+ /**
+ * The EID is the eUICC identifier. The EID shall be stored within the ECASD and can be
+ * retrieved by the Device at any time using the standard GlobalPlatform GET DATA command.
+ *
+ * This data is mandatory and applicable only when cardState is CardState:PRESENT and SIM card
+ * supports eUICC.
+ */
+ string eid;
+};
diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp
index 11612d3..db0b148 100644
--- a/sensors/2.0/default/Android.bp
+++ b/sensors/2.0/default/Android.bp
@@ -32,6 +32,7 @@
"libhidlbase",
"libhidltransport",
"liblog",
+ "libpower",
"libutils",
],
}
diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp
index 17337e2..168b402 100644
--- a/sensors/2.0/default/Sensor.cpp
+++ b/sensors/2.0/default/Sensor.cpp
@@ -86,7 +86,7 @@
ev.sensorType = SensorType::ADDITIONAL_INFO;
ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
std::vector<Event> evs{ev};
- mCallback->postEvents(evs);
+ mCallback->postEvents(evs, isWakeUpSensor());
return Result::OK;
}
@@ -113,7 +113,7 @@
if (now >= nextSampleTime) {
mLastSampleTimeNs = now;
nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
- mCallback->postEvents(readEvents());
+ mCallback->postEvents(readEvents(), isWakeUpSensor());
}
mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now));
@@ -121,6 +121,10 @@
}
}
+bool Sensor::isWakeUpSensor() {
+ return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
+}
+
std::vector<Event> Sensor::readEvents() {
std::vector<Event> events;
Event event;
@@ -155,7 +159,7 @@
} else if (!supportsDataInjection()) {
result = Result::INVALID_OPERATION;
} else if (mMode == OperationMode::DATA_INJECTION) {
- mCallback->postEvents(std::vector<Event>{event});
+ mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor());
} else {
result = Result::BAD_VALUE;
}
diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h
index 7fb927a..3ab2299 100644
--- a/sensors/2.0/default/Sensor.h
+++ b/sensors/2.0/default/Sensor.h
@@ -40,7 +40,7 @@
class ISensorsEventCallback {
public:
virtual ~ISensorsEventCallback(){};
- virtual void postEvents(const std::vector<Event>& events) = 0;
+ virtual void postEvents(const std::vector<Event>& events, bool wakeup) = 0;
};
class Sensor {
@@ -62,6 +62,8 @@
virtual std::vector<Event> readEvents();
static void startThread(Sensor* sensor);
+ bool isWakeUpSensor();
+
bool mIsEnabled;
int64_t mSamplingPeriodNs;
int64_t mLastSampleTimeNs;
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index 4346ee1..efc8b05 100644
--- a/sensors/2.0/default/Sensors.cpp
+++ b/sensors/2.0/default/Sensors.cpp
@@ -30,8 +30,16 @@
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
+using ::android::hardware::sensors::V2_0::SensorTimeout;
-Sensors::Sensors() : mEventQueueFlag(nullptr) {
+constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
+
+Sensors::Sensors()
+ : mEventQueueFlag(nullptr),
+ mOutstandingWakeUpEvents(0),
+ mReadWakeLockQueueRun(false),
+ mAutoReleaseWakeLockTime(0),
+ mHasWakeLock(false) {
std::shared_ptr<AccelSensor> accel =
std::make_shared<AccelSensor>(1 /* sensorHandle */, this /* callback */);
mSensors[accel->getSensorInfo().sensorHandle] = accel;
@@ -39,6 +47,8 @@
Sensors::~Sensors() {
deleteEventFlag();
+ mReadWakeLockQueueRun = false;
+ mWakeLockThread.join();
}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
@@ -101,6 +111,10 @@
result = Result::BAD_VALUE;
}
+ // Start the thread to read events from the Wake Lock FMQ
+ mReadWakeLockQueueRun = true;
+ mWakeLockThread = std::thread(startReadWakeLockThread, this);
+
return result;
}
@@ -133,7 +147,7 @@
Return<void> Sensors::registerDirectChannel(const SharedMemInfo& /* mem */,
registerDirectChannel_cb _hidl_cb) {
- _hidl_cb(Result::INVALID_OPERATION, 0 /* channelHandle */);
+ _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
return Return<void>();
}
@@ -147,15 +161,67 @@
return Return<void>();
}
-void Sensors::postEvents(const std::vector<Event>& events) {
- std::lock_guard<std::mutex> l(mLock);
+void Sensors::postEvents(const std::vector<Event>& events, bool wakeup) {
+ std::lock_guard<std::mutex> lock(mWriteLock);
+ if (mEventQueue->write(events.data(), events.size())) {
+ mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
- // TODO: read events from the Wake Lock FMQ in the right place
- std::vector<uint32_t> tmp(mWakeLockQueue->availableToRead());
- mWakeLockQueue->read(tmp.data(), mWakeLockQueue->availableToRead());
+ if (wakeup) {
+ // Keep track of the number of outstanding WAKE_UP events in order to properly hold
+ // a wake lock until the framework has secured a wake lock
+ updateWakeLock(events.size(), 0 /* eventsHandled */);
+ }
+ }
+}
- mEventQueue->write(events.data(), events.size());
- mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
+void Sensors::updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
+ std::lock_guard<std::mutex> lock(mWakeLockLock);
+ int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
+ if (newVal < 0) {
+ mOutstandingWakeUpEvents = 0;
+ } else {
+ mOutstandingWakeUpEvents = newVal;
+ }
+
+ if (eventsWritten > 0) {
+ // Update the time at which the last WAKE_UP event was sent
+ mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
+ static_cast<uint32_t>(SensorTimeout::WAKE_LOCK_SECONDS) * 1000;
+ }
+
+ if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
+ mHasWakeLock = true;
+ } else if (mHasWakeLock) {
+ // Check if the wake lock should be released automatically if
+ // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written to
+ // the Wake Lock FMQ.
+ if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
+ ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
+ SensorTimeout::WAKE_LOCK_SECONDS);
+ mOutstandingWakeUpEvents = 0;
+ }
+
+ if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
+ mHasWakeLock = false;
+ }
+ }
+}
+
+void Sensors::readWakeLockFMQ() {
+ while (mReadWakeLockQueueRun.load()) {
+ constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms
+ uint32_t eventsHandled = 0;
+
+ // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to ensure
+ // that any held wake lock is able to be released if it is held for too long.
+ mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, kReadTimeoutNs);
+ updateWakeLock(0 /* eventsWritten */, eventsHandled);
+ }
+}
+
+void Sensors::startReadWakeLockThread(Sensors* sensors) {
+ sensors->readWakeLockFMQ();
}
void Sensors::deleteEventFlag() {
diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h
index f543935..eba3f97 100644
--- a/sensors/2.0/default/Sensors.h
+++ b/sensors/2.0/default/Sensors.h
@@ -21,10 +21,13 @@
#include <android/hardware/sensors/2.0/ISensors.h>
#include <fmq/MessageQueue.h>
+#include <hardware_legacy/power.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
+#include <atomic>
#include <memory>
+#include <thread>
namespace android {
namespace hardware {
@@ -80,7 +83,7 @@
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
configDirectReport_cb _hidl_cb) override;
- void postEvents(const std::vector<Event>& events) override;
+ void postEvents(const std::vector<Event>& events, bool wakeup) override;
private:
/**
@@ -88,6 +91,18 @@
*/
void deleteEventFlag();
+ /**
+ * Function to read the Wake Lock FMQ and release the wake lock when appropriate
+ */
+ void readWakeLockFMQ();
+
+ static void startReadWakeLockThread(Sensors* sensors);
+
+ /**
+ * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
+ */
+ void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled);
+
using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
@@ -117,9 +132,39 @@
std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
/**
- * Lock to protect writes and reads to the FMQs
+ * Lock to protect writes to the FMQs
*/
- std::mutex mLock;
+ std::mutex mWriteLock;
+
+ /**
+ * Lock to protect acquiring and releasing the wake lock
+ */
+ std::mutex mWakeLockLock;
+
+ /**
+ * Track the number of WAKE_UP events that have not been handled by the framework
+ */
+ uint32_t mOutstandingWakeUpEvents;
+
+ /**
+ * A thread to read the Wake Lock FMQ
+ */
+ std::thread mWakeLockThread;
+
+ /**
+ * Flag to indicate that the Wake Lock Thread should continue to run
+ */
+ std::atomic_bool mReadWakeLockQueueRun;
+
+ /**
+ * Track the time when the wake lock should automatically be released
+ */
+ int64_t mAutoReleaseWakeLockTime;
+
+ /**
+ * Flag to indicate if a wake lock has been acquired
+ */
+ bool mHasWakeLock;
};
} // namespace implementation
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 3e5837b..ac020ad 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -18,6 +18,7 @@
#include "SensorsHidlEnvironmentV2_0.h"
#include "sensors-vts-utils/SensorsHidlTestBase.h"
+#include "sensors-vts-utils/SensorsTestSharedMemory.h"
#include <android/hardware/sensors/2.0/ISensors.h>
#include <android/hardware/sensors/2.0/types.h>
@@ -26,6 +27,7 @@
#include <cinttypes>
#include <condition_variable>
+#include <cstring>
#include <map>
#include <vector>
@@ -34,7 +36,9 @@
using ::android::hardware::Void;
using ::android::hardware::sensors::V1_0::MetaDataEventType;
using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
using ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V1_0::SharedMemType;
using ::android::hardware::sensors::V1_0::Vec3;
class EventCallback : public IEventCallback {
@@ -164,7 +168,17 @@
void activateAllSensors(bool enable);
std::vector<SensorInfo> getNonOneShotSensors();
std::vector<SensorInfo> getOneShotSensors();
+ std::vector<SensorInfo> getInjectEventSensors();
int32_t getInvalidSensorHandle();
+ void verifyDirectChannel(SharedMemType memType);
+ void verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+ std::shared_ptr<SensorsTestSharedMemory> mem,
+ int32_t* directChannelHandle);
+ void verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
+ int32_t directChannelHandle);
+ void verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+ int32_t directChannelHandle);
+ void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel);
};
Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -243,6 +257,16 @@
return sensors;
}
+std::vector<SensorInfo> SensorsHidlTest::getInjectEventSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ if (info.flags & static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION)) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
int32_t SensorsHidlTest::getInvalidSensorHandle() {
// Find a sensor handle that does not exist in the sensor list
int32_t maxHandle = 0;
@@ -297,63 +321,71 @@
});
}
-// Test if sensor list returned is valid
+// Test that SetOperationMode returns the expected value
TEST_F(SensorsHidlTest, SetOperationMode) {
- std::vector<SensorInfo> sensorList = getSensorsList();
-
- bool needOperationModeSupport =
- std::any_of(sensorList.begin(), sensorList.end(),
- [](const auto& s) { return (s.flags & SensorFlagBits::DATA_INJECTION) != 0; });
- if (!needOperationModeSupport) {
- return;
+ std::vector<SensorInfo> sensors = getInjectEventSensors();
+ if (getInjectEventSensors().size() > 0) {
+ ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+ ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
+ ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+ } else {
+ ASSERT_EQ(Result::BAD_VALUE, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
}
-
- ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
- ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
- ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
}
-// Test if sensor list returned is valid
+// Test that an injected event is written back to the Event FMQ
TEST_F(SensorsHidlTest, InjectSensorEventData) {
- std::vector<SensorInfo> sensorList = getSensorsList();
- std::vector<SensorInfo> sensorSupportInjection;
-
- bool needOperationModeSupport =
- std::any_of(sensorList.begin(), sensorList.end(), [&sensorSupportInjection](const auto& s) {
- bool ret = (s.flags & SensorFlagBits::DATA_INJECTION) != 0;
- if (ret) {
- sensorSupportInjection.push_back(s);
- }
- return ret;
- });
- if (!needOperationModeSupport) {
+ std::vector<SensorInfo> sensors = getInjectEventSensors();
+ if (sensors.size() == 0) {
return;
}
- ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
- for (const auto& s : sensorSupportInjection) {
- switch (s.type) {
- case SensorType::ACCELEROMETER:
- case SensorType::GYROSCOPE:
- case SensorType::MAGNETIC_FIELD: {
- usleep(100000); // sleep 100ms
+ EventCallback callback;
+ getEnvironment()->registerCallback(&callback);
- Event dummy;
- dummy.timestamp = android::elapsedRealtimeNano();
- dummy.sensorType = s.type;
- dummy.sensorHandle = s.sensorHandle;
- Vec3 v = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
- dummy.u.vec3 = v;
+ // AdditionalInfo event should not be sent to Event FMQ
+ Event additionalInfoEvent;
+ additionalInfoEvent.sensorType = SensorType::ADDITIONAL_INFO;
+ additionalInfoEvent.timestamp = android::elapsedRealtimeNano();
- EXPECT_EQ(Result::OK, getSensors()->injectSensorData(dummy));
- break;
- }
- default:
- break;
- }
+ Event injectedEvent;
+ injectedEvent.timestamp = android::elapsedRealtimeNano();
+ Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
+ injectedEvent.u.vec3 = data;
+
+ for (const auto& s : sensors) {
+ additionalInfoEvent.sensorHandle = s.sensorHandle;
+ EXPECT_EQ(Result::OK, getSensors()->injectSensorData(additionalInfoEvent));
+
+ injectedEvent.sensorType = s.type;
+ injectedEvent.sensorHandle = s.sensorHandle;
+ EXPECT_EQ(Result::OK, getSensors()->injectSensorData(injectedEvent));
}
+
+ // Wait for events to be written back to the Event FMQ
+ callback.waitForEvents(sensors, 1000 /* timeoutMs */);
+
+ for (const auto& s : sensors) {
+ auto events = callback.getEvents(s.sensorHandle);
+ auto lastEvent = events.back();
+
+ // Verify that only a single event has been received
+ ASSERT_EQ(events.size(), 1);
+
+ // Verify that the event received matches the event injected and is not the additional
+ // info event
+ ASSERT_EQ(lastEvent.sensorType, s.type);
+ ASSERT_EQ(lastEvent.sensorType, s.type);
+ ASSERT_EQ(lastEvent.timestamp, injectedEvent.timestamp);
+ ASSERT_EQ(lastEvent.u.vec3.x, injectedEvent.u.vec3.x);
+ ASSERT_EQ(lastEvent.u.vec3.y, injectedEvent.u.vec3.y);
+ ASSERT_EQ(lastEvent.u.vec3.z, injectedEvent.u.vec3.z);
+ ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status);
+ }
+
+ getEnvironment()->unregisterCallback();
ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
}
@@ -789,6 +821,128 @@
getEnvironment()->unregisterCallback();
}
+void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle,
+ RateLevel rateLevel) {
+ configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel,
+ [&](Result result, int32_t reportToken) {
+ if (isDirectReportRateSupported(sensor, rateLevel)) {
+ ASSERT_EQ(result, Result::OK);
+ ASSERT_GT(reportToken, 0);
+ } else {
+ ASSERT_EQ(result, Result::BAD_VALUE);
+ }
+ });
+}
+
+void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+ std::shared_ptr<SensorsTestSharedMemory> mem,
+ int32_t* directChannelHandle) {
+ char* buffer = mem->getBuffer();
+ memset(buffer, 0xff, mem->getSize());
+
+ registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
+ if (isDirectChannelTypeSupported(sensor, memType)) {
+ ASSERT_EQ(result, Result::OK);
+ ASSERT_GT(channelHandle, 0);
+
+ // Verify that the memory has been zeroed
+ for (size_t i = 0; i < mem->getSize(); i++) {
+ ASSERT_EQ(buffer[i], 0x00);
+ }
+ } else {
+ ASSERT_EQ(result, Result::INVALID_OPERATION);
+ ASSERT_EQ(channelHandle, -1);
+ }
+ *directChannelHandle = channelHandle;
+ });
+}
+
+void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
+ int32_t directChannelHandle) {
+ if (isDirectChannelTypeSupported(sensor, memType)) {
+ // Verify that each rate level is properly supported
+ checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL);
+ checkRateLevel(sensor, directChannelHandle, RateLevel::FAST);
+ checkRateLevel(sensor, directChannelHandle, RateLevel::VERY_FAST);
+ checkRateLevel(sensor, directChannelHandle, RateLevel::STOP);
+
+ // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP
+ configDirectReport(
+ -1 /* sensorHandle */, directChannelHandle, RateLevel::NORMAL,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
+ configDirectReport(
+ -1 /* sensorHandle */, directChannelHandle, RateLevel::STOP,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
+ } else {
+ // Direct channel is not supported for this SharedMemType
+ configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL,
+ [](Result result, int32_t /* reportToken */) {
+ ASSERT_EQ(result, Result::INVALID_OPERATION);
+ });
+ }
+}
+
+void SensorsHidlTest::verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+ int32_t directChannelHandle) {
+ Result result = unregisterDirectChannel(directChannelHandle);
+ if (isDirectChannelTypeSupported(sensor, memType)) {
+ ASSERT_EQ(result, Result::OK);
+ } else {
+ ASSERT_EQ(result, Result::INVALID_OPERATION);
+ }
+}
+
+void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) {
+ constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+ constexpr size_t kNumEvents = 1;
+ constexpr size_t kMemSize = kNumEvents * kEventSize;
+
+ std::shared_ptr<SensorsTestSharedMemory> mem(
+ SensorsTestSharedMemory::create(memType, kMemSize));
+ ASSERT_NE(mem, nullptr);
+
+ for (const SensorInfo& sensor : getSensorsList()) {
+ int32_t directChannelHandle = 0;
+ verifyRegisterDirectChannel(sensor, memType, mem, &directChannelHandle);
+ verifyConfigure(sensor, memType, directChannelHandle);
+ verifyUnregisterDirectChannel(sensor, memType, directChannelHandle);
+ }
+}
+
+TEST_F(SensorsHidlTest, DirectChannelAshmem) {
+ verifyDirectChannel(SharedMemType::ASHMEM);
+}
+
+TEST_F(SensorsHidlTest, DirectChannelGralloc) {
+ verifyDirectChannel(SharedMemType::GRALLOC);
+}
+
+TEST_F(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+ for (const SensorInfo& sensor : getSensorsList()) {
+ if (isDirectChannelTypeSupported(sensor, SharedMemType::ASHMEM) ||
+ isDirectChannelTypeSupported(sensor, SharedMemType::GRALLOC)) {
+ // Find a supported rate level
+ RateLevel rate = RateLevel::STOP;
+ if (isDirectReportRateSupported(sensor, RateLevel::NORMAL)) {
+ rate = RateLevel::NORMAL;
+ } else if (isDirectReportRateSupported(sensor, RateLevel::FAST)) {
+ rate = RateLevel::FAST;
+ } else if (isDirectReportRateSupported(sensor, RateLevel::VERY_FAST)) {
+ rate = RateLevel::VERY_FAST;
+ }
+
+ // Ensure that at least one rate level is supported
+ ASSERT_NE(rate, RateLevel::STOP);
+
+ // Verify that an invalid channel handle produces a BAD_VALUE result
+ configDirectReport(sensor.sensorHandle, -1, rate,
+ [](Result result, int32_t /* reportToken */) {
+ ASSERT_EQ(result, Result::BAD_VALUE);
+ });
+ }
+ }
+}
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
::testing::InitGoogleTest(&argc, argv);
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
index 5096498..819e297 100644
--- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -35,6 +35,10 @@
return mBuffer;
}
+size_t SensorsTestSharedMemory::getSize() const {
+ return mSize;
+}
+
std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
index 055b8e7..002f42c 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -33,6 +33,7 @@
static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
SharedMemInfo getSharedMemInfo() const;
char* getBuffer() const;
+ size_t getSize() const;
std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
virtual ~SensorsTestSharedMemory();
diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp
index bafd148..93ce573 100644
--- a/wifi/supplicant/1.2/Android.bp
+++ b/wifi/supplicant/1.2/Android.bp
@@ -7,6 +7,8 @@
enabled: true,
},
srcs: [
+ "ISupplicant.hal",
+ "ISupplicantStaIface.hal",
"ISupplicantStaNetwork.hal",
],
interfaces: [
diff --git a/wifi/supplicant/1.2/ISupplicant.hal b/wifi/supplicant/1.2/ISupplicant.hal
new file mode 100644
index 0000000..b0ec65d
--- /dev/null
+++ b/wifi/supplicant/1.2/ISupplicant.hal
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.2;
+
+import @1.1::ISupplicant;
+
+/**
+ * Interface exposed by the supplicant HIDL service registered
+ * with the hardware service manager.
+ * This is the root level object for any the supplicant interactions.
+ * To use 1.2 features you must cast specific interfaces returned from the
+ * 1.1 HAL. For example V1_1::ISupplicant::addIface() adds V1_1::ISupplicantIface,
+ * which can be cast to V1_2::ISupplicantStaIface.
+ */
+interface ISupplicant extends @1.1::ISupplicant {
+};
diff --git a/wifi/supplicant/1.2/ISupplicantStaIface.hal b/wifi/supplicant/1.2/ISupplicantStaIface.hal
new file mode 100644
index 0000000..a338c6a
--- /dev/null
+++ b/wifi/supplicant/1.2/ISupplicantStaIface.hal
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.2;
+
+import @1.0::SupplicantStatus;
+import @1.1::ISupplicantStaIface;
+import @1.2::ISupplicantStaNetwork;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+interface ISupplicantStaIface extends @1.1::ISupplicantStaIface {
+
+ /**
+ * Get Key management capabilities of the device
+ *
+ * @return status Status of the operation, and a bitmap of key management mask.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ getKeyMgmtCapabilities()
+ generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
+};
+
diff --git a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
index 85b233d..6fd0d51 100644
--- a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
@@ -256,17 +256,4 @@
*/
setSaePasswordId(string saePasswordId)
generates (SupplicantStatus status);
-
- /**
- * Get Key management capabilities of the device
- *
- * @return status Status of the operation, and a string.
- * Possible status codes:
- * |SupplicantStatusCode.SUCCESS|,
- * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
- * |SupplicantStatusCode.FAILURE_UNKNOWN|,
- * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
- */
- getKeyMgmtCapabilities()
- generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
};