Merge "Migrate broadcast radio default HAL to the new logging API."
diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index 84de75e..e6ae03e 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -57,7 +57,4 @@
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
endif
-# b/117506164
-LOCAL_SANITIZE := never
-
include $(BUILD_EXECUTABLE)
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index a634441..b615227 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -5,11 +5,3 @@
group bluetooth
writepid /dev/stune/foreground/tasks
-on property:vts.native_server.on=1 && property:ro.build.type=userdebug
- stop vendor.bluetooth-1-0
-on property:vts.native_server.on=1 && property:ro.build.type=eng
- stop vendor.bluetooth-1-0
-on property:vts.native_server.on=0 && property:ro.build.type=userdebug
- start vendor.bluetooth-1-0
-on property:vts.native_server.on=0 && property:ro.build.type=eng
- start vendor.bluetooth-1-0
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index e5f02f3..d56e344 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -294,6 +294,7 @@
lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
lib_interface_->cleanup();
+ lib_interface_ = nullptr;
}
if (lib_handle_ != nullptr) {
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index 36f4e1b..1d69040 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -58,15 +58,15 @@
void HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet);
- void* lib_handle_;
- bt_vendor_interface_t* lib_interface_;
+ void* lib_handle_ = nullptr;
+ bt_vendor_interface_t* lib_interface_ = nullptr;
async::AsyncFdWatcher fd_watcher_;
InitializeCompleteCallback initialize_complete_cb_;
- hci::HciProtocol* hci_;
+ hci::HciProtocol* hci_ = nullptr;
PacketReadCallback event_cb_;
- FirmwareStartupTimer* firmware_startup_timer_;
+ FirmwareStartupTimer* firmware_startup_timer_ = nullptr;
};
} // namespace implementation
diff --git a/bluetooth/1.0/vts/OWNERS b/bluetooth/1.0/vts/OWNERS
new file mode 100644
index 0000000..58d3a66
--- /dev/null
+++ b/bluetooth/1.0/vts/OWNERS
@@ -0,0 +1,8 @@
+zachoverflow@google.com
+siyuanh@google.com
+mylesgw@google.com
+jpawlowski@google.com
+apanicke@google.com
+stng@google.com
+hsz@google.com
+
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index 88d4234..90fbb3f 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -26,7 +26,10 @@
#include <VtsHalHidlTargetCallbackBase.h>
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <chrono>
#include <queue>
+#include <thread>
using ::android::sp;
using ::android::hardware::hidl_death_recipient;
@@ -46,6 +49,7 @@
#define WAIT_FOR_HCI_EVENT_TIMEOUT std::chrono::milliseconds(2000)
#define WAIT_FOR_SCO_DATA_TIMEOUT std::chrono::milliseconds(1000)
#define WAIT_FOR_ACL_DATA_TIMEOUT std::chrono::milliseconds(1000)
+#define INTERFACE_CLOSE_DELAY_MS std::chrono::milliseconds(200)
#define COMMAND_HCI_SHOULD_BE_UNKNOWN \
{ 0xff, 0x3B, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }
@@ -197,8 +201,10 @@
}
virtual void TearDown() override {
+ ALOGI("TearDown");
// Should not be checked in production code
ASSERT_TRUE(bluetooth->close().isOk());
+ std::this_thread::sleep_for(INTERFACE_CLOSE_DELAY_MS);
handle_no_ops();
EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
@@ -222,9 +228,10 @@
class BluetoothHciDeathRecipient : public hidl_death_recipient {
public:
- virtual void serviceDied(
+ void serviceDied(
uint64_t /*cookie*/,
- const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/)
+ override {
FAIL();
}
};
@@ -308,7 +315,7 @@
if (event_is_no_op) {
event_queue.pop();
} else {
- return;
+ break;
}
}
}
diff --git a/bluetooth/a2dp/1.0/vts/OWNERS b/bluetooth/a2dp/1.0/vts/OWNERS
new file mode 100644
index 0000000..58d3a66
--- /dev/null
+++ b/bluetooth/a2dp/1.0/vts/OWNERS
@@ -0,0 +1,8 @@
+zachoverflow@google.com
+siyuanh@google.com
+mylesgw@google.com
+jpawlowski@google.com
+apanicke@google.com
+stng@google.com
+hsz@google.com
+
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/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal
index 67b4e44..cef0397 100644
--- a/camera/metadata/3.2/types.hal
+++ b/camera/metadata/3.2/types.hal
@@ -1396,7 +1396,8 @@
*
* <p>The arrangement of color filters on sensor;
* represents the colors in the top-left 2x2 section of
- * the sensor, in reading order.</p>
+ * the sensor, in reading order, for a Bayer camera, or the
+ * light spectrum it captures for MONOCHROME camera.</p>
*/
ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
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/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index e117a98..fd996fb 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -145,7 +145,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.drm</name>
- <version>1.0</version>
+ <version>1.0-1</version>
<interface>
<name>ICryptoFactory</name>
<regex-instance>.*</regex-instance>
@@ -157,7 +157,7 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.drm</name>
- <version>1.1</version>
+ <version>1.2</version>
<interface>
<name>ICryptoFactory</name>
<regex-instance>.*</regex-instance>
diff --git a/current.txt b/current.txt
index 8b10648..e19fb63 100644
--- a/current.txt
+++ b/current.txt
@@ -388,8 +388,10 @@
2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
f61b616732d8f374e030f90575d7eba3ecc99d209a05b945949ba892bcb81e1d android.hardware.camera.device@3.2::ICameraDeviceSession
684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
+291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types
dd2436f251a90f3e5e7ed773b1aeae21e381b00ae26b10ebe3a1001c894e5980 android.hardware.camera.metadata@3.3::types
da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback
d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp
new file mode 100644
index 0000000..66a1bd8
--- /dev/null
+++ b/drm/1.2/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.drm@1.2",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "ICryptoFactory.hal",
+ "IDrmFactory.hal",
+ "IDrmPlugin.hal",
+ ],
+ interfaces: [
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "KeySetId",
+ "OfflineLicenseState",
+ ],
+ gen_java: false,
+}
+
diff --git a/drm/1.2/ICryptoFactory.hal b/drm/1.2/ICryptoFactory.hal
new file mode 100644
index 0000000..c4a9b4b
--- /dev/null
+++ b/drm/1.2/ICryptoFactory.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.2;
+
+import @1.1::ICryptoFactory;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ *
+ * The 1.2 factory must always create 1.2 ICryptoPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.2 features the caller must cast the returned interface to a
+ * 1.2 HAL, using V1_2::IDrmPlugin::castFrom().
+ *
+ * The ICryptoFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
+ */
+interface ICryptoFactory extends @1.1::ICryptoFactory {
+};
diff --git a/drm/1.2/IDrmFactory.hal b/drm/1.2/IDrmFactory.hal
new file mode 100644
index 0000000..c94e4bb
--- /dev/null
+++ b/drm/1.2/IDrmFactory.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.2;
+
+import @1.1::IDrmFactory;
+import @1.1::IDrmPlugin;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ *
+ * The 1.2 factory must always create 1.2 IDrmPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.2 features the caller must cast the returned interface to a
+ * 1.2 HAL, using V1_2::IDrmPlugin::castFrom().
+ *
+ * The IDrmFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
+ */
+
+interface IDrmFactory extends @1.1::IDrmFactory {
+};
diff --git a/drm/1.2/IDrmPlugin.hal b/drm/1.2/IDrmPlugin.hal
new file mode 100644
index 0000000..88338d6
--- /dev/null
+++ b/drm/1.2/IDrmPlugin.hal
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+package android.hardware.drm@1.2;
+
+import @1.1::IDrmPlugin;
+import @1.0::Status;
+
+/**
+ * IDrmPlugin is used to interact with a specific drm plugin that was created by
+ * IDrm::createPlugin. A drm plugin provides methods for obtaining drm keys that
+ * may be used by a codec to decrypt protected video content.
+ */
+interface IDrmPlugin extends @1.1::IDrmPlugin {
+
+ /**
+ * The keys in an offline license allow protected content to be
+ * played even if the device is not connected to a network.
+ * Offline licenses are stored on the device after a key
+ * request/response exchange when the key request KeyType is
+ * OFFLINE. Normally each app is responsible for keeping track of
+ * the KeySetIds it has created. In some situations however, it
+ * may be necessary to request the list of stored offline license
+ * KeySetIds. If an app loses the KeySetId for any stored licenses
+ * that it created, for example, it must be able to recover the
+ * stored KeySetIds so those licenses can be removed when they
+ * expire or when the app is uninstalled.
+ * <p>
+ * This method returns a list of the KeySetIds for all offline
+ * licenses. The offline license KeySetId may be used to query
+ * the status of an offline license or remove it.
+ *
+ * @return status the status of the call. May be OK or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * KeySetIds can't be returned.
+ * @return a list of offline license keySetIds. If there are no offline
+ * licenses, the list must be empty and OK must be returned as the
+ * status.
+ */
+ getOfflineLicenseKeySetIds() generates (Status status, vec<KeySetId> keySetIds);
+
+ /**
+ * Normally offline licenses are released using a key
+ * request/response exchange using getKeyRequest where the KeyType
+ * is RELEASE, followed by provideKeyResponse. This allows the
+ * server to cryptographically confirm that the license has been
+ * removed and then adjust the count of offline licenses allocated
+ * to the device.
+ * <p>
+ * In some exceptional situations it may be necessary to directly
+ * remove offline licenses without notifying the server, which may
+ * be performed using this method.
+ *
+ * @param keySetId the id of the offline license to remove
+ * @return status the status of the call. May be one of OK on
+ * success, BAD_VALUE if the license is not found or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * KeySetIds can't be returned.
+ */
+ removeOfflineLicense(KeySetId keySetId) generates (Status status);
+
+ /**
+ * Request the state of an offline license. An offline license may
+ * be usable or inactive. The keys in a usable offline license are
+ * available for decryption. When the offline license state is
+ * inactive, the keys have been marked for release using
+ * getKeyRequest with KeyType RELEASE but the key response has not
+ * been received. The keys in an inactive offline license are not
+ * usable for decryption.
+ *
+ * @param keySetId the id of the offline license
+ * @return status the status of the call. May be one of OK on
+ * success, BAD_VALUE if the license is not found or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * offline license state can't be queried.
+ * @return the offline license state, one of USABLE or INACTIVE.
+ * If the return status is not OK then state must be set to
+ * UNKNOWN.
+ */
+ getOfflineLicenseState(KeySetId keySetId) generates (Status status,
+ OfflineLicenseState state);
+};
diff --git a/drm/1.2/types.hal b/drm/1.2/types.hal
new file mode 100644
index 0000000..8770c79
--- /dev/null
+++ b/drm/1.2/types.hal
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+package android.hardware.drm@1.2;
+
+enum OfflineLicenseState : uint32_t {
+ /**
+ * Offline license state is unknown
+ */
+ UNKNOWN,
+
+ /**
+ * Offline license state is usable, the keys may be used for decryption.
+ */
+ USABLE,
+
+ /**
+ * Offline license state is inactive, the keys have been marked for
+ * release using {@link #getKeyRequest} with KEY_TYPE_RELEASE but the
+ * key response has not been received.
+ */
+ INACTIVE
+};
+
+/**
+ * KeySetId is an identifier that references a set of keys in an
+ * offline license. The keySetId is created by the HAL implementation
+ * and returned from provideKeyResponse and getOfflineLicenseIds. The
+ * framework passes KeySetId back to the HAL when referring to the key
+ * set in methods that take a KeySetId as an input parameter.
+ */
+typedef vec<uint8_t> KeySetId;
diff --git a/gnss/1.0/IGnssCallback.hal b/gnss/1.0/IGnssCallback.hal
index 7fb38c5..d62676f 100644
--- a/gnss/1.0/IGnssCallback.hal
+++ b/gnss/1.0/IGnssCallback.hal
@@ -115,9 +115,9 @@
/**
* Carrier frequency of the signal tracked, for example it can be the
* GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
- * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it
- * is the primary common use central frequency, e.g. L1 = 1575.45 MHz
- * for GPS.
+ * 1176.45 MHz, varying GLO channels, etc. If the field is zero, it is
+ * the primary common use central frequency, e.g. L1 = 1575.45 MHz for
+ * GPS.
*
* For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
* time, two GnssSvInfo structs must be reported for this same
@@ -125,8 +125,7 @@
* to L1 must be filled, and in the other all of the values related to
* L5 must be filled.
*
- * If the data is available, gnssClockFlags must contain
- * HAS_CARRIER_FREQUENCY.
+ * If the data is available, svFlag must contain HAS_CARRIER_FREQUENCY.
*/
float carrierFrequencyHz;
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
index a6871fb..c760d0a 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -132,24 +132,13 @@
Return<void> getRenderIntents(Display display, ColorMode mode,
IComposerClient::getRenderIntents_cb hidl_cb) override {
-#ifdef USES_DISPLAY_RENDER_INTENTS
std::vector<RenderIntent> intents;
Error err = mHal->getRenderIntents(display, mode, &intents);
hidl_cb(err, intents);
-#else
- (void)display;
- (void)mode;
- hidl_cb(Error::NONE, hidl_vec<RenderIntent>({RenderIntent::COLORIMETRIC}));
-#endif
return Void();
}
Return<Error> setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
-#ifndef USES_DISPLAY_RENDER_INTENTS
- if (intent != RenderIntent::COLORIMETRIC) {
- return Error::BAD_PARAMETER;
- }
-#endif
return mHal->setColorMode_2_2(display, mode, intent);
}
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/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index afbcdac..d6b50f5 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -18,6 +18,8 @@
#include <assert.h>
+#include <android-base/logging.h>
+
namespace android {
namespace hardware {
namespace keymaster {
@@ -97,10 +99,10 @@
if (prev->tag == Tag::INVALID) continue;
if (!keyParamEqual(*prev, *curr)) {
- result.emplace_back(std::move(*prev));
+ result.push_back(std::move(*prev));
}
}
- result.emplace_back(std::move(*prev));
+ result.push_back(std::move(*prev));
std::swap(data_, result);
}
@@ -127,6 +129,16 @@
}
}
+void AuthorizationSet::Filter(std::function<bool(const KeyParameter&)> doKeep) {
+ std::vector<KeyParameter> result;
+ for (auto& param : data_) {
+ if (doKeep(param)) {
+ result.push_back(std::move(param));
+ }
+ }
+ std::swap(data_, result);
+}
+
KeyParameter& AuthorizationSet::operator[](int at) {
return data_[at];
}
@@ -191,6 +203,7 @@
struct OutStreams {
std::ostream& indirect;
std::ostream& elements;
+ size_t skipped;
};
OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
@@ -229,6 +242,7 @@
OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
// skip invalid entries.
+ ++out.skipped;
return out;
}
template <typename T>
@@ -248,7 +262,12 @@
template <>
struct choose_serializer<> {
- static OutStreams& serialize(OutStreams& out, const KeyParameter&) { return out; }
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ LOG(WARNING) << "Trying to serialize unknown tag " << unsigned(param.tag)
+ << ". Did you forget to add it to all_tags_t?";
+ ++out.skipped;
+ return out;
+ }
};
template <TagType tag_type, Tag tag, typename... Tail>
@@ -269,7 +288,7 @@
std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
std::stringstream indirect;
std::stringstream elements;
- OutStreams streams = {indirect, elements};
+ OutStreams streams = {indirect, elements, 0};
for (const auto& param : params) {
serialize(streams, param);
}
@@ -289,7 +308,7 @@
return out;
}
uint32_t elements_size = pos;
- uint32_t element_count = params.size();
+ uint32_t element_count = params.size() - streams.skipped;
out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
@@ -310,6 +329,7 @@
struct InStreams {
std::istream& indirect;
std::istream& elements;
+ size_t invalids;
};
InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
@@ -331,6 +351,7 @@
InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
// there should be no invalid KeyParamaters but if handle them as zero sized.
+ ++in.invalids;
return in;
}
@@ -398,13 +419,28 @@
// TODO write one-shot stream buffer to avoid copying here
std::stringstream indirect(indirect_buffer);
std::stringstream elements(elements_buffer);
- InStreams streams = {indirect, elements};
+ InStreams streams = {indirect, elements, 0};
params->resize(element_count);
for (uint32_t i = 0; i < element_count; ++i) {
deserialize(streams, &(*params)[i]);
}
+
+ /*
+ * There are legacy blobs which have invalid tags in them due to a bug during serialization.
+ * This makes sure that invalid tags are filtered from the result before it is returned.
+ */
+ if (streams.invalids > 0) {
+ std::vector<KeyParameter> filtered(element_count - streams.invalids);
+ auto ifiltered = filtered.begin();
+ for (auto& p : *params) {
+ if (p.tag != Tag::INVALID) {
+ *ifiltered++ = std::move(p);
+ }
+ }
+ *params = std::move(filtered);
+ }
return in;
}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
index 83b1d69..458053a 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -20,6 +20,9 @@
#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <memory>
+#include <vector>
+
namespace android {
namespace hardware {
namespace keymaster {
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 193e4ea..a131423 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -142,6 +142,11 @@
std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
/**
+ * Modifies this Authorization set such that it only keeps the entries for which doKeep
+ * returns true.
+ */
+ void Filter(std::function<bool(const KeyParameter&)> doKeep);
+ /**
* Returns the nth element of the set.
* Like for std::vector::operator[] there is no range check performed. Use of out of range
* indices is undefined.
@@ -210,8 +215,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;
}
@@ -237,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_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 9e7d252..61c444c 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -122,6 +122,7 @@
DECLARE_TYPED_TAG(CREATION_DATETIME);
DECLARE_TYPED_TAG(DIGEST);
DECLARE_TYPED_TAG(EC_CURVE);
+DECLARE_TYPED_TAG(HARDWARE_TYPE);
DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
DECLARE_TYPED_TAG(INVALID);
DECLARE_TYPED_TAG(KEY_SIZE);
@@ -162,12 +163,13 @@
TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
- TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
- TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
- TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t,
- TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
- TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
- TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
+ TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
+ TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
+ TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t,
+ TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
+ TAG_DIGEST_t, TAG_PADDING_t, TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t,
+ TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
template <typename TypedTagType>
struct TypedTag2ValueType;
@@ -220,6 +222,7 @@
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, f.hardwareType)
template <TagType tag_type, Tag tag, typename ValueT>
inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
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/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index 3c99b6a..28829d2 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -17,11 +17,9 @@
"IInputSurfaceConnection.hal",
],
interfaces: [
- "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.bufferpool@1.0",
"android.hardware.media.omx@1.0",
"android.hardware.media@1.0",
"android.hidl.base@1.0",
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
index 822b24e..deb9255 100644
--- a/media/c2/1.0/IComponent.hal
+++ b/media/c2/1.0/IComponent.hal
@@ -16,25 +16,19 @@
package android.hardware.media.c2@1.0;
-import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
import android.hardware.media.omx@1.0::IGraphicBufferSource;
import IConfigurable;
import IComponentInterface;
import IComponentListener;
-import IInputSurface;
-import IInputSurfaceConnection;
/**
- * Interface for a Codec2 component corresponding to API level 1.0 or below.
- * Components have two states: stopped and running. The running state has three
- * sub-states: executing, tripped and error.
- *
- * All methods in `IComponent` must not block. If a method call cannot be
- * completed in a timely manner, it must return `TIMED_OUT` in the return
- * status.
+ * Interface for a Codec 2.0 component corresponding to API level 1.0 or
+ * below. Components have two states: stopped and running. The running
+ * state has three sub-states: executing, tripped and error.
*/
-interface IComponent {
+interface IComponent extends IComponentInterface {
// METHODS AVAILABLE WHEN RUNNING
// =========================================================================
@@ -44,42 +38,44 @@
*
* This method must be supported in running (including tripped) states.
*
- * It is acceptable for this method to return `OK` and return an error value
- * using the IComponentListener::onWorkDone() callback.
+ * This method must return within 1ms
*
- * @param workBundle `WorkBundle` object containing a list of `Work` objects
- * to queue to the component.
+ * It is acceptable for this method to return OK and return an error value
+ * using the onWorkDone() callback.
+ *
+ * @param workBundle WorkBundle object containing Works to queue to the
+ * component.
* @return status Status of the call, which may be
- * - `OK` - Works in @p workBundle were successfully queued.
- * - `BAD_INDEX` - Some component id in some `Worklet` is not valid.
- * - `CANNOT_DO` - The components are not tunneled but some `Work` object
- * contains tunneling information.
- * - `NO_MEMORY` - Not enough memory to queue @p workBundle.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - Works in \p workBundle were successfully queued.
+ * - BAD_INDEX - Some component(s) in some Work do(es) not exist.
+ * - CANNOT_DO - The components are not tunneled.
+ * - NO_MEMORY - Not enough memory to queue \p workBundle.
+ * - CORRUPTED - Some unknown error prevented queuing the Works.
+ * (unexpected).
*/
queue(WorkBundle workBundle) generates (Status status);
/**
- * Discards and abandons any pending `Work` items for the component.
+ * Discards and abandons any pending work for the component.
*
* This method must be supported in running (including tripped) states.
*
- * `Work` that could be immediately abandoned/discarded must be returned in
- * @p flushedWorkBundle. The order in which queued `Work` items are
- * discarded can be arbitrary.
+ * This method must return within 5ms.
*
- * `Work` that could not be abandoned or discarded immediately must be
- * marked to be discarded at the earliest opportunity, and must be returned
- * via IComponentListener::onWorkDone(). This must be completed within
- * 500ms.
+ * Work that could be immediately abandoned/discarded must be returned in
+ * \p flushedWorks; this can be done in an arbitrary order.
+ *
+ * Work that could not be abandoned or discarded immediately must be marked
+ * to be discarded at the earliest opportunity, and must be returned via
+ * the onWorkDone() callback. This must be completed within 500ms.
*
* @return status Status of the call, which may be
- * - `OK` - The component has been successfully flushed.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return flushedWorkBundle `WorkBundle` object containing flushed `Work`
- * items.
+ * - OK - The component has been successfully flushed.
+ * - TIMED_OUT - The flush could not be completed within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented flushing from
+ * completion. (unexpected)
+ * @return flushedWorkBundle WorkBundle object containing flushed Works.
*/
flush(
) generates (
@@ -91,39 +87,42 @@
* Drains the component, and optionally downstream components. This is a
* signalling method; as such it does not wait for any work completion.
*
- * The last `Work` item is marked as "drain-till-here", so the component is
- * notified not to wait for further `Work` before it processes what is
- * already queued. This method can also be used to set the end-of-stream
- * flag after `Work` has been queued. Client can continue to queue further
- * `Work` immediately after this method returns.
+ * Marks last work item as "drain-till-here", so component is notified not
+ * to wait for further work before it processes work already queued. This
+ * method can also be used to set the end-of-stream flag after work has been
+ * queued. Client can continue to queue further work immediately after this
+ * method returns.
*
* This method must be supported in running (including tripped) states.
*
- * `Work` that is completed must be returned via
- * IComponentListener::onWorkDone().
+ * This method must return within 1ms.
+ *
+ * Work that is completed must be returned via the onWorkDone() callback.
*
* @param withEos Whether to drain the component with marking end-of-stream.
* @return status Status of the call, which may be
- * - `OK` - The drain request has been successfully recorded.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The drain request has been successfully recorded.
+ * - TIMED_OUT - The flush could not be completed within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented flushing from completion.
+ * (unexpected)
*/
drain(bool withEos) generates (Status status);
/**
* Starts using a surface for output.
*
- * This method must not block.
- *
- * @param blockPoolId Id of the `C2BlockPool` to be associated with the
- * output surface.
- * @param surface Output surface.
+ * @param blockPoolId The id of the BlockPool to be associated with the
+ * output surface.
+ * @param surface A surface to use for codec output.
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `CANNOT_DO` - The component does not support an output surface.
- * - `REFUSED` - The output surface cannot be accessed.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an output surface.
+ * - REFUSED - The output surface cannot be accessed.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
*/
setOutputSurface(
uint64_t blockPoolId,
@@ -133,101 +132,65 @@
);
/**
- * Starts using an input surface.
+ * Starts using a persistent OMX input surface for a component.
*
* The component must be in running state.
*
- * @param inputSurface Input surface to connect to.
+ * @param producer Producer component of an OMX persistent input surface.
+ * @param source Source component of an OMX persistent input surface.
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `CANNOT_DO` - The component does not support an input surface.
- * - `BAD_STATE` - The component is not in running state.
- * - `DUPLICATE` - The component is already connected to an input surface.
- * - `REFUSED` - The input surface is already in use.
- * - `NO_MEMORY` - Not enough memory to start the component.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return connection `IInputSurfaceConnection` object, which can be used to
- * query and configure properties of the connection. This cannot be
- * null.
- */
- connectToInputSurface(
- IInputSurface inputSurface
- ) generates (
- Status status,
- IInputSurfaceConnection connection
- );
-
- /**
- * Starts using an OMX input surface.
- *
- * The component must be in running state.
- *
- * This method is similar to connectToInputSurface(), but it takes an OMX
- * input surface (as a pair of `IGraphicBufferProducer` and
- * `IGraphicBufferSource`) instead of Codec2's own `IInputSurface`.
- *
- * @param producer Producer component of an OMX input surface.
- * @param source Source component of an OMX input surface.
- * @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `CANNOT_DO` - The component does not support an OMX input surface.
- * - `BAD_STATE` - The component is not in running state.
- * - `DUPLICATE` - The component is already connected to an input surface.
- * - `REFUSED` - The input surface is already in use.
- * - `NO_MEMORY` - Not enough memory to start the component.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return connection `IInputSurfaceConnection` object, which can be used to
- * query and configure properties of the connection. This cannot be
- * null.
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an input surface.
+ * - BAD_STATE - Component is not in running state.
+ * - DUPLICATE - The component is already connected to an input surface.
+ * - REFUSED - The input surface is already in use.
+ * - NO_MEMORY - Not enough memory to start the component.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
*/
connectToOmxInputSurface(
IGraphicBufferProducer producer,
IGraphicBufferSource source
- ) generates (
- Status status,
- IInputSurfaceConnection connection
- );
+ ) generates (Status status);
/**
* Stops using an input surface.
*
+ * This call is used for both Codec 2.0 and OMX input surfaces.
+ *
* The component must be in running state.
*
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `CANNOT_DO` - The component does not support an input surface.
- * - `BAD_STATE` - The component is not in running state.
- * - `NOT_FOUND` - The component is not connected to an input surface.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an input surface.
+ * - BAD_STATE - Component is not in running state.
+ * - NOT_FOUND - The component is not connected to an input surface.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
*/
disconnectFromInputSurface() generates (Status Status);
/**
- * Creates a local `C2BlockPool` backed by the given allocator and returns
- * its id.
+ * Creates a local block pool backed by the given allocator and returns its
+ * identifier.
*
- * The returned @p blockPoolId is the only way the client can refer to a
- * `C2BlockPool` object in the component. The id can be passed to
- * setOutputSurface() or used in some C2Param objects later.
+ * This call must return within 100 msec.
*
- * The created `C2BlockPool` object can be destroyed by calling
- * destroyBlockPool(), reset() or release(). reset() and release() must
- * destroy all `C2BlockPool` objects that have been created.
- *
- * @param allocatorId Id of a `C2Allocator`.
+ * @param allocatorId The Codec 2.0 allocator ID
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `NO_MEMORY` - Not enough memory to create the pool.
- * - `BAD_VALUE` - @p allocatorId is not recognized.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return blockPoolId Id of the created C2BlockPool object. This may be
- * used in setOutputSurface() if the allocator
- * @return configurable Configuration interface for the created pool. This
- * must not be null.
+ * - OK - The operation completed successfully.
+ * - NO_MEMORY - Not enough memory to create the pool.
+ * - BAD_VALUE - Invalid allocator.
+ * - TIMED_OUT - The pool could not be created within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented creating the pool.
+ * (unexpected)
+ * @return blockPoolId The Codec 2.0 blockpool ID for the created pool.
+ * @return configurable Configuration interface for the created pool.
*/
createBlockPool(uint32_t allocatorId) generates (
Status status,
@@ -238,13 +201,17 @@
/**
* Destroys a local block pool previously created by createBlockPool().
*
- * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
+ * This call must return within 100 msec.
+ *
+ * @param blockPoolId The block pool id previously returned by
* createBlockPool().
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `NOT_FOUND` - The supplied blockPoolId is not valid.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The operation completed successfully.
+ * - NOT_FOUND - The supplied blockPoolId is not valid.
+ * - TIMED_OUT - The pool could not be destroyedwithin the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented destruction of the pool.
+ * (unexpected)
*/
destroyBlockPool(uint64_t blockPoolId) generates (Status status);
@@ -256,24 +223,28 @@
*
* This method must be supported in stopped state as well as tripped state.
*
- * If the return value is `OK`, the component must be in the running state.
- * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
- * expected as a response to this call. Otherwise, the component must be in
- * the stopped state.
+ * If the return value is OK, the component must be in the running state.
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * Otherwise, the component must be in the stopped state.
*
* If a component is in the tripped state and start() is called while the
- * component configuration still results in a trip, start() must succeed and
- * a new onTripped() callback must be used to communicate the configuration
+ * component configuration still results in a trip, start must succeed and
+ * a new onTripped callback must be used to communicate the configuration
* conflict that results in the new trip.
*
+ * This method must return within 500ms.
+ *
* @return status Status of the call, which may be
- * - `OK` - The component has started successfully.
- * - `BAD_STATE` - Component is not in stopped or tripped state.
- * - `DUPLICATE` - When called during another start call from another
- * thread.
- * - `NO_MEMORY` - Not enough memory to start the component.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The component has started successfully.
+ * - BAD_STATE - Component is not in stopped or tripped state.
+ * - DUPLICATE - When called during another start call from another
+ * thread.
+ * - NO_MEMORY - Not enough memory to start the component.
+ * - TIMED_OUT - The component could not be started within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented starting the component.
+ * (unexpected)
*/
start() generates (Status status);
@@ -284,22 +255,22 @@
*
* This method must return withing 500ms.
*
- * Upon this call, all pending `Work` must be abandoned.
- *
- * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
- * expected as a response to this call. For all other return values, the
- * component must be in the stopped state.
+ * Upon this call, all pending work must be abandoned.
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * For all other return values, the component must be in the stopped state.
*
* This does not alter any settings and tunings that may have resulted in a
* tripped state.
*
* @return status Status of the call, which may be
- * - `OK` - The component has stopped successfully.
- * - `BAD_STATE` - Component is not in running state.
- * - `DUPLICATE` - When called during another stop call from another
- * thread.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The component has stopped successfully.
+ * - BAD_STATE - Component is not in running state.
+ * - DUPLICATE - When called during another stop call from another thread.
+ * - TIMED_OUT - The component could not be stopped within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented starting the component.
+ * (unexpected)
*/
stop() generates (Status status);
@@ -313,24 +284,25 @@
*
* This method must return withing 500ms.
*
- * When this call returns, if @p status is `OK`, all `Work` items must
- * have been abandoned, and all resources (including `C2BlockPool` objects
- * previously created by createBlockPool()) must have been released.
+ * After this call returns all work must have been abandoned, all references
+ * must have been released.
*
- * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
- * expected as a response to this call. For all other return values, the
- * component must be in the stopped state.
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * For all other return values, the component shall be in the stopped state.
*
- * This brings settings back to their default, "guaranteeing" no tripped
+ * This brings settings back to their default - "guaranteeing" no tripped
* state.
*
* @return status Status of the call, which may be
- * - `OK` - The component has been reset.
- * - `BAD_STATE` - Component is in released state.
- * - `DUPLICATE` - When called during another reset call from another
- * thread.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The component has been reset.
+ * - BAD_STATE - Component is in released state.
+ * - DUPLICATE - When called during another reset call from another
+ * thread.
+ * - TIMED_OUT - The component could not be reset within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented resetting the component.
+ * (unexpected)
*/
reset() generates (Status status);
@@ -339,27 +311,19 @@
*
* This method must be supported in stopped state.
*
- * This method destroys the component. Upon return, if @p status is `OK` or
- * `DUPLICATE`, all resources must have been released.
+ * This method must return withing 500ms. Upon return all references must
+ * be abandoned.
*
* @return status Status of the call, which may be
- * - `OK` - The component has been released.
- * - `BAD_STATE` - The component is running.
- * - `DUPLICATE` - The component is already released.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The component has been released.
+ * - BAD_STATE - The component is running.
+ * - DUPLICATE - The component is already released.
+ * - TIMED_OUT - The component could not be released within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented releasing the component.
+ * (unexpected)
*/
release() generates (Status status);
- /**
- * Returns the @ref IComponentInterface instance associated to this
- * component.
- *
- * An @p IConfigurable instance for the component can be obtained by calling
- * IComponentInterface::getConfigurable() on the returned @p intf.
- *
- * @return intf `IComponentInterface` instance. This must not be null.
- */
- getInterface() generates (IComponentInterface intf);
};
diff --git a/media/c2/1.0/IComponentInterface.hal b/media/c2/1.0/IComponentInterface.hal
index a007d02..d4b30b1 100644
--- a/media/c2/1.0/IComponentInterface.hal
+++ b/media/c2/1.0/IComponentInterface.hal
@@ -19,20 +19,21 @@
import IConfigurable;
/**
- * Component interface object. This object contains all of the configurations of
+ * Component interface object. This object contains all of the configuration of
* a potential or actual component. It can be created and used independently of
- * an actual Codec2 component to query supported parameters for various
- * component settings, and configurations for a potential component.
- *
- * An actual component exposes this interface via IComponent::getInterface().
+ * an actual Codec 2.0 component instance to query support and parameters for
+ * various component settings and configurations for a potential component.
+ * Actual components also expose this interface.
*/
-interface IComponentInterface {
- /**
- * Returns the @ref IConfigurable instance associated to this component
- * interface.
+interface IComponentInterface extends IConfigurable {
+ /*
+ * There are no additional methods to IConfigurable interface.
*
- * @return configurable `IConfigurable` instance. This must not be null.
+ * Component interfaces have no states.
+ *
+ * The name of the component or component interface object is a unique name
+ * for that component or component interface 'class'; however, multiple
+ * instances of that component must have the same name.
*/
- getConfigurable() generates (IConfigurable configurable);
};
diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal
index 70d5fb2..eb71ecb 100644
--- a/media/c2/1.0/IComponentListener.hal
+++ b/media/c2/1.0/IComponentListener.hal
@@ -17,112 +17,54 @@
package android.hardware.media.c2@1.0;
/**
- * Callback interface for handling notifications from @ref IComponent.
+ * This callback interface is used for handling notifications from IComponent.
*/
interface IComponentListener {
/**
- * Notify the listener that some `Work` items have been completed.
- *
- * All the input buffers in the returned `Work` objects must not be used by
- * the component after onWorkDone() is called.
- *
- * @param workBundle List of completed `Work` objects.
+ * Notify the listener that some works have been completed.
*/
oneway onWorkDone(WorkBundle workBundle);
/**
* Notify the listener that the component is tripped.
- *
- * @param settingResults List of failures.
*/
oneway onTripped(vec<SettingResult> settingResults);
/**
* Notify the listener of an error.
*
- * @param status Error type. @p status may be `OK`, which means that an
- * error has occurred, but the error type does not fit into the type
- * `Status`. In this case, additional information is provided by
- * @p errorCode.
- * @param errorCode Additional error information. The framework may not
- * recognize the meaning of this value.
+ * @param status Error type. \p status may be `OK`, which means that an
+ * error has occurred, but the error type is unknown.
+ * @param errorCode Additional error code. The framework may not recognize
+ * this.
*/
oneway onError(Status status, uint32_t errorCode);
/**
- * Information about rendering of a frame to a `Surface`.
+ * Information about rendering of a frame.
*/
struct RenderedFrame {
/**
- * Id of the `BufferQueue` containing the rendered buffer.
- *
- * This value must have been obtained by an earlier call to
- * IGraphicBufferProducer::getUniqueId().
+ * Id of the buffer queue containing the rendered buffer.
*/
uint64_t bufferQueueId;
/**
* Id of the slot of the rendered buffer.
- *
- * This value must have been obtained by an earlier call to
- * IGraphicBufferProducer::dequeueBuffer() or
- * IGraphicBufferProducer::attachBuffer().
*/
int32_t slotId;
/**
- * Timestamp the rendering happened.
- *
- * The reference point for the timestamp is determined by the
- * `BufferQueue` that performed the rendering.
+ * Timestamp of the rendering (consistent with timestamps in
+ * the associated BufferQueue).
*/
int64_t timestampNs;
};
/**
- * Notify the listener that frames have been rendered.
+ * Notify the listener that frames are rendered.
*
- * @param renderedFrames List of @ref RenderedFrame objects.
+ * @param renderedFrames List of information about renderings of frames.
*/
oneway onFramesRendered(vec<RenderedFrame> renderedFrames);
-
- /**
- * Identifying information for an input buffer previously queued to the
- * component via IComponent::queue().
- */
- struct InputBuffer {
- /**
- * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
- * object that was previously queued.
- */
- uint64_t frameIndex;
- /**
- * This value is an index into `Work::input.buffers` (which is an array)
- * in a `Work` object that was previously queued.
- */
- uint32_t arrayIndex;
- };
-
- /**
- * Notify the listener that some input buffers are no longer needed by the
- * component, and hence can be released or reused by the client.
- *
- * Input buffers that are contained in a `Work` object returned by an
- * earlier onWorkDone() call are assumed released, so they must not appear
- * in any onInputBuffersReleased() calls. That means
- * onInputBuffersReleased() must only report input buffers that are released
- * before the output in the same `Work` item is produced. However, it is
- * possible for an input buffer to be returned by onWorkDone() after it has
- * been reported by onInputBuffersReleased().
- *
- * @note onWorkDone() and onInputBuffersReleased() both notify the client
- * that input buffers are no longer needed. However, in order to minimize
- * IPC calls, onInputBuffersReleased() should be called only when
- * onWorkDone() cannot be called, e.g., the component needs more input
- * before an output can be produced.
- *
- * @param inputBuffers List of `InputBuffer` objects, identifying input
- * buffers that are no longer needed by the component.
- */
- oneway onInputBuffersReleased(vec<InputBuffer> inputBuffers);
};
diff --git a/media/c2/1.0/IComponentStore.hal b/media/c2/1.0/IComponentStore.hal
index 6a57c38..d2474cc 100644
--- a/media/c2/1.0/IComponentStore.hal
+++ b/media/c2/1.0/IComponentStore.hal
@@ -16,40 +16,34 @@
package android.hardware.media.c2@1.0;
-import android.hardware.media.bufferpool@2.0::IClientManager;
+import android.hardware.media.bufferpool@1.0::IClientManager;
import IComponentInterface;
import IComponentListener;
import IComponent;
import IConfigurable;
import IInputSurface;
-/**
- * Entry point for Codec2 HAL.
- *
- * All methods in `IComponentStore` must not block. If a method call cannot be
- * completed in a timely manner, it must return `TIMED_OUT` in the return
- * status. The only exceptions are getPoolClientManager() and getConfigurable(),
- * which must always return immediately.
- */
-interface IComponentStore {
+interface IComponentStore extends IConfigurable {
/**
* Creates a component by name.
*
- * @param name Name of the component to create. This must match one of the
- * names returned by listComponents().
- * @param listener Callback receiver.
- * @param pool `IClientManager` object of the BufferPool in the client
- * process. This may be null if the client does not own a BufferPool.
- * @return status Status of the call, which may be
- * - `OK` - The component was created successfully.
- * - `NOT_FOUND` - There is no component with the given name.
- * - `NO_MEMORY` - Not enough memory to create the component.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return comp The created component if @p status is `OK`.
+ * This method must return within 100ms.
*
- * @sa IComponentListener.
+ * @param name Name of the component to create. This should match one of the
+ * names returned by listComponents().
+ * @param listener The component listener to use for the component.
+ * @param pool The buffer pool client manager of the component listener.
+ * This must be null if the listener process does not own a buffer pool.
+ * @return status Status of the call, which may be
+ * - OK - The component was created successfully.
+ * - NOT_FOUND - There is no component with the given name.
+ * - NO_MEMORY - Not enough memory to create the component.
+ * - TIMED_OUT - The component could not be created within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented the creation of the
+ * component. (unexpected)
+ * @return comp The created component if `Status = OK`.
*/
createComponent(
string name,
@@ -63,15 +57,19 @@
/**
* Creates a component interface by name.
*
+ * This method must return within 100ms.
+ *
* @param name Name of the component interface to create. This should match
* one of the names returned by listComponents().
* @return status Status of the call, which may be
- * - `OK - The component interface was created successfully.
- * - `NOT_FOUND` - There is no component interface with the given name.
- * - `NO_MEMORY` - Not enough memory to create the component interface.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return compIntf The created component interface if @p status is `OK`.
+ * - OK - The component interface was created successfully.
+ * - NOT_FOUND - There is no component interface with the given name.
+ * - NO_MEMORY - Not enough memory to create the component interface.
+ * - TIMED_OUT - The component interface could not be created within the
+ * time limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented the creation of the
+ * component interface. (unexpected)
+ * @return compIntf The created component interface if `Status = OK`.
*/
createInterface(
string name
@@ -85,49 +83,57 @@
*/
struct ComponentTraits {
/**
- * Name of the component. This must be unique for each component.
- *
- * This name is use to identify the component to create in
- * createComponent() and createComponentInterface().
+ * Name of the component.
*/
string name;
enum Domain : uint32_t {
- OTHER = 0,
- VIDEO,
AUDIO,
- IMAGE,
+ VIDEO,
+ OTHER = 0xffffffff,
};
/**
- * Component domain.
+ * Component domain. The framework may not recognize `OTHER`.
*/
Domain domain;
+ /**
+ * If #domain is `OTHER`, #domainOther can be used to provide additional
+ * information. Otherwise, #domainOther is ignored. The framework may
+ * not inspect this value.
+ */
+ uint32_t domainOther;
enum Kind : uint32_t {
- OTHER = 0,
DECODER,
ENCODER,
+ OTHER = 0xffffffff,
};
/**
- * Component kind.
+ * Component kind. The framework may not recognize `OTHER`.
*/
Kind kind;
+ /**
+ * If #kind is `OTHER`, #kindOther can be used to provide additional
+ * information. Otherwise, #kindOther is ignored. The framework may not
+ * inspect this value.
+ */
+ uint32_t kindOther;
/**
- * Rank used by `MediaCodecList` to determine component ordering. Lower
+ * Rank used by MediaCodecList to determine component ordering. Lower
* value means higher priority.
*/
uint32_t rank;
/**
- * MIME type.
+ * Media type.
*/
string mediaType;
/**
* Aliases for component name for backward compatibility.
*
- * Multiple components can have the same alias (but not the same
+ * \note Multiple components can have the same alias (but not the same
* component name) as long as their media types differ.
*/
vec<string> aliases;
@@ -136,51 +142,36 @@
/**
* Returns the list of components supported by this component store.
*
- * @return status Status of the call, which may be
- * - `OK - The operation was successful.
- * - `NO_MEMORY` - Not enough memory to complete this method.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return traits List of component traits for all components supported by
- * this store (in no particular order).
+ * This method must return within 500ms.
+ *
+ * @return traits List of component traits for all components supported by this store in no
+ * particular order.
*/
- listComponents() generates (
- Status status,
- vec<ComponentTraits> traits
- );
+ listComponents() generates (vec<ComponentTraits> traits);
/**
* Creates a persistent input surface that can be used as an input surface
* for any IComponent instance
*
- * @return status Status of the call, which may be
- * - `OK - The operation was successful.
- * - `NO_MEMORY` - Not enough memory to complete this method.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return surface A persistent input surface. This may be null to indicate
- * an error.
+ * This method must return within 100ms.
+ *
+ * @return surface A persistent input surface
*/
- createInputSurface() generates (
- Status status,
- IInputSurface surface
- );
+ createInputSurface() generates (IInputSurface surface);
/**
- * Returns a list of `StructDescriptor` objects for a set of requested
- * C2Param structure indices that this store is aware of.
+ * Returns a list of StructDescriptor object for a set of requested
+ * structures that this store is aware of.
*
* This operation must be performed at best effort, e.g. the component
* store must simply ignore all struct indices that it is not aware of.
*
- * @param indices Indices of C2Param structures to describe.
+ * @param indices struct indices to return des
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `NOT_FOUND` - Some indices were not known.
- * - `NO_MEMORY` - Not enough memory to complete this method.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return structs List of `StructDescriptor` objects.
+ * - OK - The operation completed successfully.
+ * - NOT_FOUND - Some indices were not known.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * @return structs List of StructDescriptor objects.
*/
getStructDescriptors(
vec<ParamIndex> indices
@@ -190,35 +181,33 @@
);
/**
- * Copies the contents of @p src into @p dst without changing the format of
- * @p dst.
+ * Returns information required for using BufferPool API in buffer passing.
+ * If the returned pool is not null, the client can call registerSender() to
+ * register its IAccessor instance, hence allowing the client to send
+ * buffers to components hosted by this process.
+ *
+ * @return pool If the component store supports receiving buffers via
+ * BufferPool API, \p pool must be a valid `IClientManager` instance.
+ * Otherwise, \p pool must be null.
+ */
+ getPoolClientManager(
+ ) generates (
+ IClientManager pool
+ );
+
+ /**
+ * The store must copy the contents of \p src into \p dst without changing
+ * the format of \p dst.
*
* @param src Source buffer.
* @param dst Destination buffer.
* @return status Status of the call, which may be
- * - `OK` - The copy is successful.
- * - `CANNOT_DO` - @p src and @p dst are not compatible.
- * - `REFUSED` - No permission to copy.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
+ * - OK - The copy is successful.
+ * - CANNOT_DO - \p src and \p dst are not compatible.
+ * - REFUSED - No permission to copy.
+ * - CORRUPTED - The copy cannot be done. (unexpected)
*/
copyBuffer(Buffer src, Buffer dst) generates (Status status);
- /**
- * Returns the `IClientManager` object for the component's BufferPool.
- *
- * @return pool If the component store supports receiving buffers via
- * BufferPool API, @p pool must be a valid `IClientManager` instance.
- * Otherwise, @p pool must be null.
- */
- getPoolClientManager() generates (IClientManager pool);
-
- /**
- * Returns the @ref IConfigurable instance associated to this component
- * store.
- *
- * @return configurable `IConfigurable` instance. This must not be null.
- */
- getConfigurable() generates (IConfigurable configurable);
};
diff --git a/media/c2/1.0/IConfigurable.hal b/media/c2/1.0/IConfigurable.hal
index 31dc4d3..cd4dd10 100644
--- a/media/c2/1.0/IConfigurable.hal
+++ b/media/c2/1.0/IConfigurable.hal
@@ -17,78 +17,43 @@
package android.hardware.media.c2@1.0;
/**
- * Generic configuration interface presented by all configurable Codec2 objects.
+ * Generic configuration interface used by all configurable Codec 2.0
+ * components.
*
- * This interface must be supported in all states of the owning object, and must
- * not change the state of the owning object.
+ * This interface must be supported in all states of the inheriting
+ * object, and must not change the state of the inheriting object.
*/
interface IConfigurable {
/**
- * Returns the id of the object. This must be unique among all objects of
- * the same type hosted by the same store.
+ * Returns the name of this object. This must match the name that was
+ * supplied during the creation of the object.
*
- * @return id Id of the object.
- */
- getId() generates (uint32_t id);
-
- /**
- * Returns the name of the object.
- *
- * This must match the name that was supplied during the creation of the
- * object.
- *
- * @return name Name of the object.
+ * @return name Name of this object.
*/
getName() generates (string name);
/**
- * Queries a set of parameters from the object.
+ * Queries a set of parameters from the object. Querying is performed at
+ * best effort: the object must query all supported parameters and skip
+ * unsupported ones, or parameters that could not be allocated. Any errors
+ * are communicated in the return value.
*
- * Querying is performed at best effort: the object must query all supported
- * parameters and skip unsupported ones (which may include parameters that
- * could not be allocated). Any errors are communicated in the return value.
+ * \note Parameter values do not depend on the order of query.
*
- * If @p mayBlock is false, this method must not block. All parameter
- * queries that require blocking must be skipped.
+ * This method must return within 1ms if \p mayBlock is DONT_BLOCK, and
+ * within 5ms otherwise.
*
- * If @p mayBlock is true, a query may block, but the whole method call
- * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
- *
- * If @p mayBlock is false, this method must not block. Otherwise, this
- * method is allowed to block for a certain period of time before completing
- * the operation. If the operation is not completed in a timely manner,
- * `status = TIMED_OUT` is returned.
- *
- * @note The order of C2Param objects in @p param does not depend on the
- * order of C2Param structure indices in @p indices.
- *
- * \par For IComponent
- *
- * When the object type is @ref IComponent, this method must be supported in
- * any state except released. This call must not change the state nor the
- * internal configuration of the component.
- *
- * The blocking behavior of this method differs among states:
- * - In the stopped state, this must be non-blocking. @p mayBlock is
- * ignored. (The method operates as if @p mayBlock was false.)
- * - In any of the running states, this method may block momentarily if
- * @p mayBlock is true. However, if the call cannot be completed in a
- * timely manner, `status = TIMED_OUT` is returned.
- *
- * @param indices List of C2Param structure indices to query.
+ * @param indices List of param indices for params to be queried.
* @param mayBlock Whether this call may block or not.
* @return status Status of the call, which may be
- * - `OK` - All parameters could be queried.
- * - `BAD_INDEX` - All supported parameters could be queried, but some
- * parameters were not supported.
- * - `NO_MEMORY` - Could not allocate memory for a supported parameter.
- * - `BLOCKING` - Querying some parameters requires blocking, but
- * @p mayBlock is false.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return params Flattened representation of C2Param objects.
- *
- * @sa Params.
+ * - OK - All parameters could be queried.
+ * - BAD_INDEX - All supported parameters could be queried, but some
+ * parameters were not supported.
+ * - NO_MEMORY - Could not allocate memory for a supported parameter.
+ * - BLOCKING - Querying some parameters requires blocking.
+ * - CORRUPTED - Some unknown error prevented the querying of the
+ * parameters. (unexpected)
+ * @return params List of params queried corresponding to \p indices.
*/
query(
vec<ParamIndex> indices,
@@ -99,60 +64,31 @@
);
/**
- * Sets a set of parameters for the object.
+ * Sets a set of parameters for the object. Tuning is performed at best
+ * effort: the object must update all supported configuration at best
+ * effort and skip unsupported parameters. Any errors are communicated in
+ * the return value and in \p failures.
*
- * Tuning is performed at best effort: the object must update all supported
- * configurations at best effort and skip unsupported parameters. Any errors
- * are communicated in the return value and in @p failures.
+ * \note Parameter tuning DOES depend on the order of the tuning parameters.
+ * E.g. some parameter update may allow some subsequent parameter update.
*
- * A non-strict parameter update with an unsupported value shall cause an
- * update to the closest supported value. A strict parameter update with an
- * unsupported value shall be skipped and a failure shall be returned.
- *
- * If @p mayBlock is false, this method must not block. An update that
- * requires blocking shall be skipped and a failure shall be returned.
- *
- * If @p mayBlock is true, an update may block, but the whole method call
- * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
- *
- * The final values for all parameters set are propagated back to the caller
- * in @p params.
- *
- * \par For IComponent
- *
- * When the object type is @ref IComponent, this method must be supported in
- * any state except released.
- *
- * The blocking behavior of this method differs among states:
- * - In the stopped state, this must be non-blocking. @p mayBlock is
- * ignored. (The method operates as if @p mayBlock was false.)
- * - In any of the running states, this method may block momentarily if
- * @p mayBlock is true. However, if the call cannot be completed in a
- * timely manner, `status = TIMED_OUT` is returned.
- *
- * @note Parameter tuning @e does depend on the order of the tuning
- * parameters, e.g., some parameter update may enable some subsequent
- * parameter update.
+ * This method must return within 1ms if \p mayBlock is false, and within
+ * 5ms otherwise.
*
* @param inParams Requested parameter updates.
* @param mayBlock Whether this call may block or not.
* @return status Status of the call, which may be
- * - `OK` - All parameters could be updated successfully.
- * - `BAD_INDEX` - All supported parameters could be updated successfully,
- * but some parameters were not supported.
- * - `NO_MEMORY` - Some supported parameters could not be updated
- * successfully because they contained unsupported values.
- * These are returned in @p failures.
- * - `BLOCKING` - Setting some parameters requires blocking, but
- * @p mayBlock is false.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return failures List of update failures.
- * @return outParams Flattened representation of configured parameters. The
- * order of parameters in @p outParams is based on the order of
- * requested updates in @p inParams.
- *
- * @sa SettingResult.
+ * - OK - All parameters could be updated successfully.
+ * - BAD_INDEX - All supported parameters could be updated successfully,
+ * but some parameters were not supported.
+ * - NO_MEMORY - Some supported parameters could not be updated
+ * successfully because they contained unsupported values.
+ * These are returned in \p failures.
+ * - BLOCKING - Setting some parameters requires blocking.
+ * - CORRUPTED - Some unknown error prevented the update of the
+ * parameters. (unexpected)
+ * @return failures List of parameter failures.
+ * @return outParams Resulting values for the configured parameters.
*/
config(
Params inParams,
@@ -167,19 +103,22 @@
// =========================================================================
/**
- * Returns a list of supported parameters within a selected range of C2Param
- * structure indices.
+ * Returns a selected range of the set of supported parameters.
*
- * @param start The first index of the selected range.
- * @param count The length of the selected range.
+ * The set of supported parameters are represented in a vector with a
+ * start index of 0, and the selected range are indices into this vector.
+ * Fewer than \p count parameters are returned if the selected range is
+ * not fully/not at all part of the available vector indices.
+ *
+ * This method must return within 1ms.
+ *
+ * @param start start index of selected range
+ * @param count size of the selected
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `NO_MEMORY` - Not enough memory to complete this method.
- * @return params List of supported parameters in the selected range. This
- * list may have fewer than @p count elements if some indices in the
- * range are not supported.
- *
- * @sa ParamDescriptor.
+ * - OK - The operation completed successfully.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * @return params Vector containing the selected range of supported
+ * parameters.
*/
querySupportedParams(
uint32_t start,
@@ -192,42 +131,23 @@
/**
* Retrieves the supported values for the queried fields.
*
- * The object must process all fields queried even if some queries fail.
+ * Upon return the object must fill in the supported
+ * values for the fields listed as well as a status for each field.
+ * Object shall process all fields queried even if some queries fail.
*
- * If @p mayBlock is false, this method must not block. Otherwise, this
- * method is allowed to block for a certain period of time before completing
- * the operation. If the operation cannot be completed in a timely manner,
- * `status = TIMED_OUT` is returned.
+ * This method must return within 1ms if \p mayBlock is false, and within
+ * 5ms otherwise.
*
- * \par For IComponent
- *
- * When the object type is @ref IComponent, this method must be supported in
- * any state except released.
- *
- * The blocking behavior of this method differs among states:
- * - In the stopped state, this must be non-blocking. @p mayBlock is
- * ignored. (The method operates as if @p mayBlock was false.)
- * - In any of the running states, this method may block momentarily if
- * @p mayBlock is true. However, if the call cannot be completed in a
- * timely manner, `status = TIMED_OUT` is returned.
- *
- * @param inFields List of field queries.
+ * @param inFields Vector of field queries.
* @param mayBlock Whether this call may block or not.
* @return status Status of the call, which may be
- * - `OK` - The operation completed successfully.
- * - `BLOCKING` - Querying some parameters requires blocking, but
- * @p mayBlock is false.
- * - `NO_MEMORY` - Not enough memory to complete this method.
- * - `BAD_INDEX` - At least one field was not recognized as a component
- * field.
- * - `BLOCKING` - Querying some fields requires blocking, but @p mayblock
- * is false.
- * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
- * - `CORRUPTED` - Some unknown error occurred.
- * @return outFields List of supported values and results for the
- * supplied queries.
- *
- * @sa FieldSupportedValuesQuery, FieldSupportedValuesQueryResult.
+ * - OK - The operation completed successfully.
+ * - BLOCKING - Querying some parameters requires blocking.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * - BAD_INDEX - At least one field was not recognized as a component
+ * field.
+ * @return outFields Vector containing supported values and query result
+ * for the selected fields.
*/
querySupportedValues(
vec<FieldSupportedValuesQuery> inFields,
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
index 0a1b56d..c083a21 100644
--- a/media/c2/1.0/IInputSurface.hal
+++ b/media/c2/1.0/IInputSurface.hal
@@ -16,36 +16,46 @@
package android.hardware.media.c2@1.0;
-import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
import IConfigurable;
+import IComponent;
+import IInputSurfaceConnection;
/**
- * Input surface for a Codec2 component.
- *
- * An <em>input surface</em> is an instance of `IInputSurface`, which may be
- * created by calling IComponentStore::createInputSurface(). Once created, the
- * client may
- * 1. write data to it via the `IGraphicBufferProducer` interface; and
- * 2. use it as input to a Codec2 encoder.
- *
- * @sa IInputSurfaceConnection, IComponentStore::createInputSurface(),
- * IComponent::connectToInputSurface().
+ * Input surface that can be configured for the IComponent.
*/
-interface IInputSurface {
- /**
- * Returns the producer interface into the internal buffer queue.
- *
- * @return producer `IGraphicBufferProducer` instance. This must not be
- * null.
- */
- getGraphicBufferProducer() generates (IGraphicBufferProducer producer);
+interface IInputSurface extends IGraphicBufferProducer {
/**
- * Returns the @ref IConfigurable instance associated to this input surface.
+ * Connects this input surface to a component.
*
- * @return configurable `IConfigurable` instance. This must not be null.
+ * This call must return within 100 ms.
+ *
+ * @param component The component to connect to. This must have type
+ * IComponent.
+ * @return status Status of the call, which may be
+ * - OK - The operation succeeded.
+ * - BAD_STATE - The component is in running state.
+ * - DUPLICATE - The surface is already connected to a component.
+ * - NO_MEMORY - Could not allocate memory to connect to the component.
+ * - CORRUPTED - Some unknown error prevented the connection. (unexpected)
+ * @return connection Connection object that is used to disconnect
+ * from the component.
+ */
+ connectToComponent(
+ IComponent component
+ ) generates (
+ Status status,
+ IInputSurfaceConnection connection
+ );
+
+ /**
+ * Returns the Codec 2.0 configuration object for this surface.
+ *
+ * @return configurable The configuration object for this surface.
*/
getConfigurable() generates (IConfigurable configurable);
+
};
diff --git a/media/c2/1.0/IInputSurfaceConnection.hal b/media/c2/1.0/IInputSurfaceConnection.hal
index efd9c6e..500091d 100644
--- a/media/c2/1.0/IInputSurfaceConnection.hal
+++ b/media/c2/1.0/IInputSurfaceConnection.hal
@@ -16,22 +16,20 @@
package android.hardware.media.c2@1.0;
-import IConfigurable;
-
-/**
- * Connection between a component and an input surface.
- *
- * An instance of `IInputSurfaceConnection` contains an `IConfigurable`
- * interface for querying and configuring properties of the connection.
- */
interface IInputSurfaceConnection {
+
/**
- * Returns the @ref IConfigurable instance associated to this connection.
+ * Disconnects this input surface from the component.
*
- * This can be used to customize the connection.
+ * This call must return within 100 ms.
*
- * @return configurable `IConfigurable` instance. This must not be null.
+ * @return status Status of the call, which may be
+ * - OK - The operation succeeded.
+ * - BAD_STATE - The component is not in running state.
+ * - NOT_FOUND - The surface is not connected to a component.
+ * - CORRUPTED - Some unknown error prevented the connection. (unexpected)
*/
- getConfigurable() generates (IConfigurable configurable);
+ disconnect() generates (Status status);
+
};
diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal
index 7b75041..c06b415 100644
--- a/media/c2/1.0/types.hal
+++ b/media/c2/1.0/types.hal
@@ -16,280 +16,222 @@
package android.hardware.media.c2@1.0;
-import android.hardware.media.bufferpool@2.0::BufferStatusMessage;
+import android.hardware.media.bufferpool@1.0::BufferStatusMessage;
-/**
- * Common return values for Codec2 operations.
- */
enum Status : int32_t {
- /** Operation completed successfully. */
+ /** operation completed successfully */
OK = 0,
// bad input
- /** Argument has invalid value (user error). */
+ /** argument has invalid value (user error) */
BAD_VALUE = -22,
- /** Argument uses invalid index (user error). */
+ /** argument uses invalid index (user error) */
BAD_INDEX = -75,
- /** Argument/Index is valid but not possible. */
+ /** argument/index is valid but not possible */
CANNOT_DO = -2147483646,
// bad sequencing of events
- /** Object already exists. */
+ /** object already exists */
DUPLICATE = -17,
- /** Object not found. */
+ /** object not found */
NOT_FOUND = -2,
- /** Operation is not permitted in the current state. */
+ /** operation is not permitted in the current state */
BAD_STATE = -38,
- /** Operation would block but blocking is not permitted. */
+ /** operation would block but blocking is not permitted */
BLOCKING = -9930,
// bad environment
- /** Not enough memory to complete operation. */
+ /** not enough memory to complete operation */
NO_MEMORY = -12,
- /** Missing permission to complete operation. */
+ /** missing permission to complete operation */
REFUSED = -1,
- /** Operation did not complete within timeout. */
+ /** operation did not complete within timeout */
TIMED_OUT = -110,
// missing functionality
- /** Operation is not implemented/supported (optional only). */
+ /** operation is not implemented/supported (optional only) */
OMITTED = -74,
// unknown fatal
- /** Some unexpected error prevented the operation. */
+ /** some unexpected error prevented the operation */
CORRUPTED = -2147483648,
// uninitialized
- /** Status has not been initialized. */
+ /** status has not been initialized */
NO_INIT = -19,
};
/**
- * C2Param structure index.
- *
- * This is a number that is unique for each C2Param structure type.
- *
- * @sa Codec 2.0 standard.
+ * Codec 2.0 parameter index
*/
typedef uint32_t ParamIndex;
/**
- * Flattened representation of C2Param objects.
+ * Codec 2.0 parameter structure
*
- * The `Params` type is an array of bytes made up by concatenating a list of
- * C2Param objects. The start index (offset into @ref Params) of each C2Param
- * object in the list is divisible by 8. Up to 7 padding bytes may be added
- * after each C2Param object to achieve this 64-bit alignment.
- *
- * Each C2Param object has the following layout:
- * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
- * type of the C2Param object.
- * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
- * - (size - 8) bytes: data of the C2Param object.
- *
- * In order to interpret each C2Param object correctly, its structure must be
- * described by IComponentStore::getStructDescriptors().
- *
- * @note Please refer to the Codec 2.0 standard for the list of standard
- * parameter structures.
- *
- * @sa Codec 2.0 standard.
+ * The description of a Params is provided by supplying a ParamIndex to
+ * IComponentStore::getStructDescriptors().
*/
typedef vec<uint8_t> Params;
/**
- * Identifying information of a field relative to a known C2Param structure.
- *
- * Within a given C2Param structure, each field is uniquely identified by @ref
- * FieldId.
+ * Struct uniquely specifying a field in an arbitrary parameter structure.
*/
struct FieldId {
- /** Offset of the field in bytes. */
+ /** Offset of the field in bytes */
uint32_t offset;
- /** Size of the field in bytes. */
+ /** Size of the field in bytes */
uint32_t size;
};
/**
- * Reference to a field in a C2Param structure.
+ * Struct representing a location of a field in a parameter with a given index.
*/
struct ParamField {
- /** Index of the C2Param structure. */
+ /** Index of the parameter */
ParamIndex index;
- /** Identifier of the field inside the C2Param structure. */
+ /** Field identifier */
FieldId fieldId;
};
/**
- * Usage description of a C2Param structure.
- *
- * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
+ * Struct describing basic properties of a parameter with a given index.
*/
struct ParamDescriptor {
- /**
- * Index of the C2Param structure being described.
- */
+ /** Parameter index */
ParamIndex index;
enum Attrib : uint32_t {
/**
- * The parameter is required to be specified.
+ * Parameter is required to be specified.
*/
REQUIRED = 1u << 0,
/**
- * The parameter retains its value.
+ * Parameter retains its value.
*/
PERSISTENT = 1u << 1,
/**
- * The parameter is strict.
+ * Parameter is strict.
*/
STRICT = 1u << 2,
/**
- * The parameter is publicly read-only.
+ * Parameter is publicly read-only.
*/
READ_ONLY = 1u << 3,
/**
- * The parameter must not be visible to clients.
+ * Parameter must not be visible to clients.
*/
HIDDEN = 1u << 4,
/**
- * The parameter must not be used by framework (other than testing).
+ * Parameter must not be used by framework (other than testing).
*/
INTERNAL = 1u << 5,
/**
- * The parameter is publicly constant (hence read-only).
+ * Parameter is publicly constant (hence read-only).
*/
CONST = 1u << 6,
};
+ /** Parameter attributes */
bitfield<Attrib> attrib;
- /**
- * Name of the structure. This must be unique for each structure.
- */
+ /** Parameter name */
string name;
- /**
- * Indices of other C2Param structures that this C2Param structure depends
- * on.
- */
+ /** index of other parameters that this parameter depends on */
vec<ParamIndex> dependencies;
};
-// Generic way to describe supported numeric values for Codec2 interfaces.
+// Generic way to describe supported numeric values for Codec 2.0 interfaces.
/**
- * An untyped value that can fit in 64 bits, the type of which is communicated
- * via a separate channel (@ref FieldSupportedValues.type).
+ * An untyped value that can fit on 64 bits - the type of which is communicated
+ * via a separate channel (FieldType).
*/
typedef uint64_t PrimitiveValue;
/*
- * Description of supported values for a field.
+ * Generic supported values for a field.
*
- * This can be a continuous range or a discrete set of values.
+ * This can be either a range or a set of values. The range can be linear or
+ * geometric with clear minimum and maximum values, and can have an optional
+ * step size or geometric ratio. Values can optionally represent flags.
*/
struct FieldSupportedValues {
- /**
- * Used if #type is `RANGE`.
- *
- * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
- * structure represents a closed interval bounded by `min` and `max`.
- *
- * Otherwise, the #Range structure represents a finite sequence of numbers
- * produced from the following recurrence relation:
- *
- * @code
- * v[0] = min
- * v[i] = v[i - 1] * num / denom + step ; i >= 1
- * @endcode
- *
- * Both the ratio `num / denom` and the value `step` must be positive. The
- * last number in the sequence described by this #Range structure is the
- * largest number in the sequence that is smaller than or equal to `max`.
- *
- * @note
- * The division in the formula may truncate the result if the data type of
- * these values is an integral type.
- */
struct Range {
- /**
- * Lower end of the range (inclusive).
- */
PrimitiveValue min;
- /**
- * Upper end of the range (inclusive).
- */
PrimitiveValue max;
- /**
- * The non-homogeneous term in the recurrence relation.
- */
PrimitiveValue step;
- /**
- * The numerator of the scale coefficient in the recurrence relation.
- */
PrimitiveValue num;
- /**
- * The denominator of the scale coefficient in the recurrence relation.
- */
PrimitiveValue denom;
};
enum Type : int32_t {
/** No supported values */
- EMPTY = 0,
- /** Numeric range, described in a #Range structure */
+ EMPTY,
+ /** Numeric range that can be continuous or discrete */
RANGE,
/** List of values */
VALUES,
/** List of flags that can be OR-ed */
FLAGS,
+ /** Other representations */
+ OTHER = 0xffffffff,
};
/**
- * Type of the supported values.
+ * Type of the supported values. The framework may not recognize `OTHER`.
*/
Type type;
+ /**
+ * Codec2.0 type code of the supported values.
+ * * If #type is `OTHER`, #typeOther can be used to give more information.
+ * In this case, the interpretation of this structure is
+ * implementation-defined.
+ * * For all other values of #type, #typeOther is not used.
+ * The framework may not inspect this value.
+ */
+ int32_t typeOther;
+
+ /*
+ * If #type = EMPTY, #range and #value are unused.
+ */
/**
- * When #type is #Type.RANGE, #range shall specify the range of possible
- * values.
+ * If #type = RANGE, #range will specify the range of possible values.
*
- * The intended type of members of #range shall be clear in the context
- * where `FieldSupportedValues` is used.
+ * The intended type of members of #range will be clear in the context where
+ * FieldSupportedValues is used.
*/
Range range;
/**
- * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported
- * values/flags.
+ * If #type is `VALUES` or `FLAGS`, #value will list supported values.
*
- * The intended type of components of #value shall be clear in the context
- * where `FieldSupportedValues` is used.
+ * The intended type of components of #value will be clear in the context
+ * where FieldSupportedValues is used.
*/
vec<PrimitiveValue> values;
};
/**
- * Supported values for a field.
+ * Supported values for a specific field.
*
* This is a pair of the field specifier together with an optional supported
* values object. This structure is used when reporting parameter configuration
* failures and conflicts.
*/
struct ParamFieldValues {
- /**
- * Reference to a field or a C2Param structure.
- */
+ /** the field or parameter */
ParamField paramOrField;
/**
- * Optional supported values for the field if #paramOrField specifies an
+ * optional supported values for the field if paramOrField specifies an
* actual field that is numeric (non struct, blob or string). Supported
* values for arrays (including string and blobs) describe the supported
* values for each element (character for string, and bytes for blobs). It
@@ -299,18 +241,18 @@
};
/**
- * Description of a field inside a C2Param structure.
+ * Field descriptor.
*/
struct FieldDescriptor {
- /** Location of the field in the C2Param structure */
+ /** Field id */
FieldId fieldId;
/**
- * Possible types of the field.
+ * Possible types of a field.
*/
enum Type : uint32_t {
- NO_INIT = 0,
+ NO_INIT,
INT32,
UINT32,
CNTR32,
@@ -319,227 +261,186 @@
CNTR64,
FLOAT,
/**
- * Fixed-size string (POD).
+ * Fixed-size string (POD)
*/
STRING = 0x100,
/**
- * A blob has no sub-elements and can be thought of as an array of
- * bytes. However, bytes cannot be individually addressed by clients.
+ * blobs have no sub-elements and can be thought of as byte arrays.
+ * However, bytes cannot be individually addressed by clients.
*/
BLOB,
/**
- * The field is a structure that may contain other fields.
+ * Structs. Marked with this flag in addition to their coreIndex.
*/
- STRUCT = 0x20000,
+ STRUCT_FLAG = 0x20000,
};
/**
* Type of the field.
*/
bitfield<Type> type;
- /**
- * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
- * otherwise, #structIndex is not used.
+ /** Extent of the field */
+ uint32_t length;
+ /*
+ * Note: the last member of a param struct can be of arbitrary length (e.g.
+ * if it is T[] array, which extends to the last byte of the parameter.)
+ * This is marked with extent 0.
*/
- ParamIndex structIndex;
- /**
- * Extent of the field.
- * - For a non-array field, #extent is 1.
- * - For a fixed-length array field, #extent is the length. An array field
- * of length 1 is indistinguishable from a non-array field.
- * - For a variable-length array field, #extent is 0. This can only occur as
- * the last member of a C2Param structure.
- */
- uint32_t extent;
-
- /**
- * Name of the field. This must be unique for each field in the same
- * structure.
- */
+ /** Name of the field */
string name;
-
- /**
- * Named value type. This is used for defining an enum value for a numeric
- * type.
- */
+ /** Named value type */
struct NamedValue {
- /**
- * Name of the enum value. This must be unique for each enum value in
- * the same field.
- */
string name;
- /**
- * Underlying value of the enum value. Multiple enum names may have the
- * same underlying value.
- */
PrimitiveValue value;
};
- /**
- * List of enum values. This is not used when #type is not one of the
- * numeric types.
- */
+ /** Named values for the field */
vec<NamedValue> namedValues;
};
/**
- * Description of a C2Param structure. It consists of an index and a list of
- * `FieldDescriptor`s.
+ * Struct descriptor.
*/
struct StructDescriptor {
- /**
- * Index of the structure.
- */
+ /** Struct type */
ParamIndex type;
- /**
- * List of fields in the structure.
- *
- * Fields are ordered by their offsets. A field that is a structure is
- * ordered before its members.
- */
+ /** Field descriptors for each field */
vec<FieldDescriptor> fields;
};
/**
- * Information describing the reason the parameter settings may fail, or may be
- * overridden.
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
*/
struct SettingResult {
- /** Failure code */
+ /** Failure code (of Codec 2.0 SettingResult failure type) */
enum Failure : uint32_t {
+ /** Parameter is read-only and cannot be set. */
+ READ_ONLY,
+ /** Parameter mismatches input data. */
+ MISMATCH,
+ /** Parameter does not accept value. */
+ BAD_VALUE,
/** Parameter is not supported. */
BAD_TYPE,
/** Parameter is not supported on the specific port. */
BAD_PORT,
/** Parameter is not supported on the specific stream. */
BAD_INDEX,
- /** Parameter is read-only and cannot be set. */
- READ_ONLY,
- /** Parameter mismatches input data. */
- MISMATCH,
- /** Strict parameter does not accept value for the field at all. */
- BAD_VALUE,
- /**
- * Strict parameter field value is in conflict with an/other
- * setting(s).
- */
+ /** Parameter is in conflict with an/other setting(s). */
CONFLICT,
/**
- * Parameter field is out of range due to other settings. (This failure
- * mode can only be used for strict calculated parameters.)
+ * Parameter is out of range due to other settings. (This failure mode
+ * can only be used for strict parameters.)
*/
UNSUPPORTED,
/**
- * Field does not access the requested parameter value at all. It has
- * been corrected to the closest supported value. This failure mode is
- * provided to give guidance as to what are the currently supported
- * values for this field (which may be a subset of the at-all-potential
- * values).
- */
- INFO_BAD_VALUE,
- /**
* Requested parameter value is in conflict with an/other setting(s)
* and has been corrected to the closest supported value. This failure
- * mode is given to provide guidance as to what are the currently
- * supported values as well as to optionally provide suggestion to the
- * client as to how to enable the requested parameter value.
- */
+ * mode is given to provide suggestion to the client as to how to enable
+ * the requested parameter value. */
INFO_CONFLICT,
+ /**
+ * This failure mode is reported when all the above failure modes do not
+ * apply.
+ */
+ OTHER = 0xffffffff,
};
+ /**
+ * The failure type. The framework might not recognize `OTHER`.
+ */
Failure failure;
+ /**
+ * The failure code.
+ * * If #failure is `OTHER`, #failureOther can be used to give more
+ * information.
+ * * For all other values of #failure, #failureOther is not used.
+ * The framework may not inspect this value.
+ */
+ uint32_t failureOther;
/**
- * Failing (or corrected) field or parameter and optionally, currently
- * supported values for the field. Values must only be set for field
- * failures other than `BAD_VALUE`, and only if they are different from the
- * globally supported values (e.g. due to restrictions by another parameter
- * or input data).
+ * Failing (or corrected) field. Currently supported values for the field.
+ * This is set if different from the globally supported values (e.g. due to
+ * restrictions by another param or input data)
*/
ParamFieldValues field;
/**
- * Conflicting parameters or fields with (optional) suggested values for any
- * conflicting fields to avoid the conflict. Values must only be set for
- * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
+ * Conflicting parameters or fields with
+ * (optional) suggested values for any conflicting fields to avoid the conflict.
*/
vec<ParamFieldValues> conflicts;
};
/**
- * Ordering information of @ref FrameData objects. Each member is used for
- * comparing urgency: a smaller difference from a reference value indicates that
- * the associated Work object is more urgent. The reference value for each
- * member is initialized the first time it is communicated between the client
- * and the codec, and it may be updated to later values that are communicated.
- *
- * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
- * order it represents is derived by subtracting the reference value, then
- * interpreting the result as a signed number with the same storage size (using
- * two's complement).
- *
- * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
- * Codec 2.0 standard.
+ * Data structure for ordering Work objects. Each member is used for comparing
+ * urgency in the same fashion: a smaller value indicates that the associated
+ * Work object is more urgent.
*/
struct WorkOrdinal {
/**
- * Timestamp in microseconds.
+ * Timestamp in microseconds - can wrap around.
*/
uint64_t timestampUs;
/**
- * Frame index.
+ * Frame index - can wrap around.
*/
uint64_t frameIndex;
/**
- * Component specific frame ordinal.
+ * Component specific frame ordinal - can wrap around.
*/
uint64_t customOrdinal;
};
/**
- * Storage type for `BaseBlock`.
- *
- * A `BaseBlock` is a representation of a codec memory block. Coded data,
- * decoded data, codec-specific data, and other codec-related data are all sent
- * in the form of BaseBlocks.
+ * A structure that holds information of a Block. There are two types of Blocks:
+ * NATIVE and POOLED. Each type has its own way of identifying blocks.
*/
-safe_union BaseBlock {
+struct BaseBlock {
+ enum Type : int32_t {
+ NATIVE,
+ POOLED,
+ };
/**
- * #nativeBlock is the opaque representation of a buffer.
+ * There are two types of blocks: NATIVE and POOLED.
+ */
+ Type type;
+
+ /**
+ * A "NATIVE" block is represented by a native handle.
*/
handle nativeBlock;
- /**
- * #pooledBlock is a reference to a buffer handled by a BufferPool.
+
+ /*
+ * A "POOLED" block is represented by `BufferStatusMessage`.
*/
BufferStatusMessage pooledBlock;
};
/**
- * Reference to a @ref BaseBlock within a @ref WorkBundle.
- *
- * `Block` contains additional attributes that `BaseBlock` does not. These
- * attributes may differ among `Block` objects that refer to the same
- * `BaseBlock` in the same `WorkBundle`.
+ * A Block in transfer consists of an index into an array of BaseBlock plus some
+ * extra information. One BaseBlock may occur in multiple blocks in one
+ * `WorkBundle`.
*/
struct Block {
/**
- * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
- * #WorkBundle.baseBlocks.
+ * Identity of the BaseBlock within a WorkBundle. This is an index into the
+ * `baseBlocks` array of a `WorkBundle` object.
*/
uint32_t index;
/**
- * Metadata associated with this `Block`.
+ * Metadata associated with the block.
*/
Params meta;
/**
- * Fence for synchronizing `Block` access.
+ * Fence for synchronizing block access.
*/
handle fence;
};
/**
- * A codec buffer, which is a collection of @ref Block objects and metadata.
- *
- * This is a part of @ref FrameData.
+ * Type of buffers processed by a component.
*/
struct Buffer {
/**
@@ -553,37 +454,23 @@
};
/**
- * An extension of @ref Buffer that also contains a C2Param structure index.
- *
- * This is a part of @ref FrameData.
+ * An extension of Buffer that also contains an index.
*/
struct InfoBuffer {
- /**
- * A C2Param structure index.
- */
ParamIndex index;
- /**
- * Associated @ref Buffer object.
- */
Buffer buffer;
};
/**
- * Data for an input frame or an output frame.
- *
- * This structure represents a @e frame with its metadata. A @e frame consists
- * of an ordered set of buffers, configuration changes, and info buffers along
- * with some non-configuration metadata.
- *
- * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
- * standard.
+ * This structure represents a frame with its metadata. A frame consists of an
+ * ordered set of buffers, configuration changes, and info buffers along with
+ * some non-configuration metadata.
*/
struct FrameData {
enum Flags : uint32_t {
/**
- * For input frames: no output frame shall be generated when processing
+ * For input frames: no output frame will be generated when processing
* this frame, but metadata must still be processed.
- *
* For output frames: this frame must be discarded but metadata is still
* valid.
*/
@@ -595,183 +482,92 @@
END_OF_STREAM = (1 << 1),
/**
* This frame must be discarded with its metadata.
- *
- * This flag is only set by components, e.g. as a response to the flush
+ * This flag is only set by components - e.g. as a response to the flush
* command.
*/
DISCARD_FRAME = (1 << 2),
/**
- * This frame is not the last frame produced for the input.
- *
- * This flag is normally set by the component - e.g. when an input frame
- * results in multiple output frames, this flag is set on all but the
- * last output frame.
- *
- * Also, when components are chained, this flag should be propagated
- * down the work chain. That is, if set on an earlier frame of a
- * work-chain, it should be propagated to all later frames in that
- * chain. Additionally, components down the chain could set this flag
- * even if not set earlier, e.g. if multiple output frames are generated
- * at that component for the input frame.
- */
- FLAG_INCOMPLETE = (1 << 3),
- /**
* This frame contains only codec-specific configuration data, and no
* actual access unit.
*
- * @deprecated Pass codec configuration with the codec-specific
+ * \deprecated Pass codec configuration with the codec-specific
* configuration info together with the access unit.
*/
CODEC_CONFIG = (1u << 31),
};
/**
- * Frame flags, as described in #Flags.
+ * Frame flags.
*/
bitfield<Flags> flags;
/**
- * @ref WorkOrdinal of the frame.
+ * Ordinal of the frame.
*/
WorkOrdinal ordinal;
/**
- * List of frame buffers.
+ * Frame buffers.
*/
vec<Buffer> buffers;
/**
- * List of configuration updates.
+ * Params determining a configuration update.
*/
Params configUpdate;
/**
- * List of info buffers.
+ * Info buffers.
*/
vec<InfoBuffer> infoBuffers;
};
/**
- * In/out structure containing some instructions for and results from output
- * processing.
- *
- * This is a part of @ref Work. One `Worklet` corresponds to one output
- * @ref FrameData. The client must construct an original `Worklet` object inside
- * a @ref Work object for each expected output before calling
- * IComponent::queue().
+ * Struct for
*/
struct Worklet {
/**
- * Component id. (Input)
- *
- * This is used only when tunneling is enabled.
- *
- * When used, this must match the return value from IConfigurable::getId().
+ * List of Params describing tunings.
*/
- uint32_t componentId;
+ vec<Params> tunings;
/**
- * List of C2Param objects describing tunings to be applied before
- * processing this `Worklet`. (Input)
- */
- Params tunings;
-
- /**
- * Flag determining whether this `Worklet` has output or not.
- */
- bool hasOutput;
-
- /**
- * List of failures. (Output)
+ * List of failures.
*/
vec<SettingResult> failures;
/**
- * Output frame data. (Output)
+ * Output frame data.
*/
FrameData output;
+
+ /* Note: Component id is not necessary as tunneling is not supported. */
};
/**
- * A collection of input data to and output data from the component.
- *
- * A `Work` object holds information about a single work item. It is created by
- * the client and passed to the component via IComponent::queue(). The component
- * has two ways of returning a `Work` object to the client:
- * 1. If the queued `Work` object has been successfully processed,
- * IComponentListener::onWorkDone() shall be called to notify the listener,
- * and the output shall be included in the returned `Work` object.
- * 2. If the client calls IComponent::flush(), a `Work` object that has not
- * been processed shall be returned.
- *
- * `Work` is a part of @ref WorkBundle.
+ * This structure holds information about a single work item. It must be passed
+ * by the client to the component.
*/
struct Work {
/**
- * Additional work chain info not part of this work.
- */
- Params chainInfo;
-
- /**
- * @ref FrameData for the input.
+ * FrameData for the input. Indices of Blocks inside #input refer to
+ * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
*/
FrameData input;
-
/**
- * The chain of `Worklet`s.
- *
- * The length of #worklets is 1 when tunneling is not enabled.
- *
- * If #worklets has more than a single element, the tunnels between
- * successive components of the work chain must have been successfully
- * pre-registered at the time that the `Work` is submitted. Allocating the
- * output buffers in the `Worklet`s is the responsibility of each component
- * in the chain.
- *
- * Upon `Work` submission, #worklets must be an appropriately sized vector
- * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
- * successful processing, all but the final `Worklet` in the returned
- * #worklets must have @ref Worklet.hasOutput set to `false`.
+ * Worklet. Indices of Blocks inside `worklet.output` refer to
+ * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
*/
- vec<Worklet> worklets;
-
+ Worklet worklet;
/**
- * The number of `Worklet`s successfully processed in this chain.
- *
- * This must be initialized to 0 by the client when the `Work` is submitted,
- * and it must contain the number of `Worklet`s that were successfully
- * processed when the `Work` is returned to the client.
- *
- * #workletsProcessed cannot exceed the length of #worklets. If
- * #workletsProcessed is smaller than the length of #worklets, #result
- * cannot be `OK`.
+ * Whether the worklet was processed or not.
*/
- uint32_t workletsProcessed;
-
- /**
- * The final outcome of the `Work` (corresponding to #workletsProcessed).
- *
- * The value of @ref Status.OK implies that all `Worklet`s have been
- * successfully processed.
- */
+ bool workletProcessed;
Status result;
};
/**
- * List of `Work` objects.
- *
- * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
- * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
- * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
- * objects together provides two benefits:
- * 1. Batching of `Work` objects can reduce the number of IPC calls.
- * 2. If multiple `Work` objects contain `Block`s that refer to the same
- * `BaseBlock`, the number of `BaseBlock`s that is sent between processes
- * is also reduced.
- *
- * @note `WorkBundle` is the HIDL counterpart of the vector of `C2Work` in the
- * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
- * data transferred over an IPC.
+ * This structure holds a list of Work objects and a list of BaseBlocks.
*/
struct WorkBundle {
/**
@@ -785,48 +581,27 @@
};
/**
- * Query information for supported values of a field. This is used as input to
- * IConfigurable::querySupportedValues().
+ * This structure describes a query for supported values of a field. This is
+ * used as input to IConfigurable::queryFieldSupportedValues().
*/
struct FieldSupportedValuesQuery {
- /**
- * Identity of the field to query.
- */
- ParamField field;
-
enum Type : uint32_t {
- /** Query all possible values regardless of other settings. */
+ /** Query all possible values regardless of other settings */
POSSIBLE,
- /** Query currently possible values given dependent settings. */
+ /** Query currently possible values given dependent settings */
CURRENT,
};
- /**
- * Type of the query. See #Type for more information.
- */
+
+ ParamField field;
Type type;
};
/**
* This structure is used to hold the result from
- * IConfigurable::querySupportedValues().
+ * IConfigurable::queryFieldSupportedValues().
*/
struct FieldSupportedValuesQueryResult {
- /**
- * Result of the query. Possible values are
- * - `OK`: The query was successful.
- * - `BAD_STATE`: The query was requested when the `IConfigurable` instance
- * was in a bad state.
- * - `BAD_INDEX`: The requested field was not recognized.
- * - `TIMED_OUT`: The query could not be completed in a timely manner.
- * - `BLOCKING`: The query must block, but the parameter `mayBlock` in the
- * call to `querySupportedValues()` was `false`.
- * - `CORRUPTED`: Some unknown error occurred.
- */
Status status;
-
- /**
- * Supported values. This is meaningful only when #status is `OK`.
- */
FieldSupportedValues values;
};
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 1b5e338..234527a 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -80,6 +80,5 @@
srcs: [
"BasicTests.cpp",
"GeneratedTests.cpp",
- "ValidationTests.cpp",
],
}
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 1f66c43..802d018 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -45,6 +45,7 @@
using ::test_helper::Int32Operands;
using ::test_helper::MixedTyped;
using ::test_helper::MixedTypedExample;
+using ::test_helper::MixedTypedIndex;
using ::test_helper::Quant8Operands;
using ::test_helper::resize_accordingly;
@@ -63,14 +64,16 @@
copy_back_<int32_t>(dst, ra, src);
copy_back_<uint8_t>(dst, ra, src);
copy_back_<int16_t>(dst, ra, src);
- static_assert(4 == std::tuple_size<MixedTyped>::value,
+ copy_back_<_Float16>(dst, ra, src);
+ static_assert(5 == std::tuple_size<MixedTyped>::value,
"Number of types in MixedTyped changed, but copy_back function wasn't updated");
}
// Top level driver for models and examples generated by test_generator.py
// Test driver for those generated from ml/nn/runtime/test/spec
void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples, float fpAtol = 1e-5f,
+ const std::vector<MixedTypedExample>& examples,
+ bool hasRelaxedFloat32Model = false, float fpAtol = 1e-5f,
float fpRtol = 1e-5f) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
@@ -78,13 +81,20 @@
int example_no = 1;
for (auto& example : examples) {
SCOPED_TRACE(example_no++);
-
const MixedTyped& inputs = example.operands.first;
const MixedTyped& golden = example.operands.second;
+ const bool hasFloat16Inputs = !std::get<MixedTypedIndex<_Float16>::index>(inputs).empty();
+ if (hasRelaxedFloat32Model || hasFloat16Inputs) {
+ // TODO: Adjust the error limit based on testing.
+ // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
+ fpAtol = 5.0f * 0.0009765625f;
+ // Set the relative tolerance to be 5ULP of the corresponding FP precision.
+ fpRtol = 5.0f * 0.0009765625f;
+ }
+
std::vector<RequestArgument> inputs_info, outputs_info;
uint32_t inputSize = 0, outputSize = 0;
-
// This function only partially specifies the metadata (vector of RequestArguments).
// The contents are copied over below.
for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
@@ -228,7 +238,8 @@
ASSERT_NE(nullptr, preparedModel.get());
float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
- EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples,
+ /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol);
}
void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
@@ -272,13 +283,8 @@
EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
ASSERT_NE(nullptr, preparedModel.get());
- // TODO: Adjust the error limit based on testing.
- // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
- float fpAtol = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f;
- // Set the relative tolerance to be 5ULP of the corresponding FP precision.
- float fpRtol = !model.relaxComputationFloat32toFloat16 ? 5.0f * 1.1920928955078125e-7f
- : 5.0f * 0.0009765625f;
- EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples,
+ model.relaxComputationFloat32toFloat16);
}
// TODO: Reduce code duplication.
@@ -323,13 +329,8 @@
EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
ASSERT_NE(nullptr, preparedModel.get());
- // TODO: Adjust the error limit based on testing.
- // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
- float fpAtol = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f;
- // Set the relative tolerance to be 5ULP of the corresponding FP precision.
- float fpRtol = !model.relaxComputationFloat32toFloat16 ? 5.0f * 1.1920928955078125e-7f
- : 5.0f * 0.0009765625f;
- EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples,
+ model.relaxComputationFloat32toFloat16);
}
} // namespace generated_tests
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index ac1ae60..26b4d8b 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
deleted file mode 100644
index 268e671..0000000
--- a/neuralnetworks/1.0/vts/functional/Models.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
-#define VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) \
- FN(add_broadcast_quant8) \
- FN(add) \
- FN(add_quant8) \
- FN(avg_pool_float_1) \
- FN(avg_pool_float_2) \
- FN(avg_pool_float_3) \
- FN(avg_pool_float_4) \
- FN(avg_pool_float_5) \
- FN(avg_pool_quant8_1) \
- FN(avg_pool_quant8_2) \
- FN(avg_pool_quant8_3) \
- FN(avg_pool_quant8_4) \
- FN(avg_pool_quant8_5) \
- FN(concat_float_1) \
- FN(concat_float_2) \
- FN(concat_float_3) \
- FN(concat_quant8_1) \
- FN(concat_quant8_2) \
- FN(concat_quant8_3) \
- FN(conv_1_h3_w2_SAME) \
- FN(conv_1_h3_w2_VALID) \
- FN(conv_3_h3_w2_SAME) \
- FN(conv_3_h3_w2_VALID) \
- FN(conv_float_2) \
- FN(conv_float_channels) \
- FN(conv_float_channels_weights_as_inputs) \
- FN(conv_float_large) \
- FN(conv_float_large_weights_as_inputs) \
- FN(conv_float) \
- FN(conv_float_weights_as_inputs) \
- FN(conv_quant8_2) \
- FN(conv_quant8_channels) \
- FN(conv_quant8_channels_weights_as_inputs) \
- FN(conv_quant8_large) \
- FN(conv_quant8_large_weights_as_inputs) \
- FN(conv_quant8) \
- FN(conv_quant8_overflow) \
- FN(conv_quant8_overflow_weights_as_inputs) \
- FN(conv_quant8_weights_as_inputs) \
- FN(depth_to_space_float_1) \
- FN(depth_to_space_float_2) \
- FN(depth_to_space_float_3) \
- FN(depth_to_space_quant8_1) \
- FN(depth_to_space_quant8_2) \
- FN(depthwise_conv2d_float_2) \
- FN(depthwise_conv2d_float_large_2) \
- FN(depthwise_conv2d_float_large_2_weights_as_inputs) \
- FN(depthwise_conv2d_float_large) \
- FN(depthwise_conv2d_float_large_weights_as_inputs) \
- FN(depthwise_conv2d_float) \
- FN(depthwise_conv2d_float_weights_as_inputs) \
- FN(depthwise_conv2d_quant8_2) \
- FN(depthwise_conv2d_quant8_large) \
- FN(depthwise_conv2d_quant8_large_weights_as_inputs) \
- FN(depthwise_conv2d_quant8) \
- FN(depthwise_conv2d_quant8_weights_as_inputs) \
- FN(depthwise_conv) \
- FN(dequantize) \
- FN(embedding_lookup) \
- FN(floor) \
- FN(fully_connected_float_2) \
- FN(fully_connected_float_large) \
- FN(fully_connected_float_large_weights_as_inputs) \
- FN(fully_connected_float) \
- FN(fully_connected_float_weights_as_inputs) \
- FN(fully_connected_quant8_2) \
- FN(fully_connected_quant8_large) \
- FN(fully_connected_quant8_large_weights_as_inputs) \
- FN(fully_connected_quant8) \
- FN(fully_connected_quant8_weights_as_inputs) \
- FN(hashtable_lookup_float) \
- FN(hashtable_lookup_quant8) \
- FN(l2_normalization_2) \
- FN(l2_normalization_large) \
- FN(l2_normalization) \
- FN(l2_pool_float_2) \
- FN(l2_pool_float_large) \
- FN(l2_pool_float) \
- FN(local_response_norm_float_1) \
- FN(local_response_norm_float_2) \
- FN(local_response_norm_float_3) \
- FN(local_response_norm_float_4) \
- FN(logistic_float_1) \
- FN(logistic_float_2) \
- FN(logistic_quant8_1) \
- FN(logistic_quant8_2) \
- FN(lsh_projection_2) \
- FN(lsh_projection) \
- FN(lsh_projection_weights_as_inputs) \
- FN(lstm2) \
- FN(lstm2_state2) \
- FN(lstm2_state) \
- FN(lstm3) \
- FN(lstm3_state2) \
- FN(lstm3_state3) \
- FN(lstm3_state) \
- FN(lstm) \
- FN(lstm_state2) \
- FN(lstm_state) \
- FN(max_pool_float_1) \
- FN(max_pool_float_2) \
- FN(max_pool_float_3) \
- FN(max_pool_float_4) \
- FN(max_pool_quant8_1) \
- FN(max_pool_quant8_2) \
- FN(max_pool_quant8_3) \
- FN(max_pool_quant8_4) \
- FN(mobilenet_224_gender_basic_fixed) \
- FN(mobilenet_quantized) \
- FN(mul_broadcast_quant8) \
- FN(mul) \
- FN(mul_quant8) \
- FN(mul_relu) \
- FN(relu1_float_1) \
- FN(relu1_float_2) \
- FN(relu1_quant8_1) \
- FN(relu1_quant8_2) \
- FN(relu6_float_1) \
- FN(relu6_float_2) \
- FN(relu6_quant8_1) \
- FN(relu6_quant8_2) \
- FN(relu_float_1) \
- FN(relu_float_2) \
- FN(relu_quant8_1) \
- FN(relu_quant8_2) \
- FN(reshape) \
- FN(reshape_quant8) \
- FN(reshape_quant8_weights_as_inputs) \
- FN(reshape_weights_as_inputs) \
- FN(resize_bilinear_2) \
- FN(resize_bilinear) \
- FN(rnn) \
- FN(rnn_state) \
- FN(softmax_float_1) \
- FN(softmax_float_2) \
- FN(softmax_quant8_1) \
- FN(softmax_quant8_2) \
- FN(space_to_depth_float_1) \
- FN(space_to_depth_float_2) \
- FN(space_to_depth_float_3) \
- FN(space_to_depth_quant8_1) \
- FN(space_to_depth_quant8_2) \
- FN(svdf2) \
- FN(svdf) \
- FN(svdf_state) \
- FN(tanh)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
deleted file mode 100644
index d3cbcff..0000000
--- a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "Models.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<::test_helper::MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index df1ac67..07c9b6e 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -20,7 +20,6 @@
defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
srcs: [
"GeneratedTestsV1_0.cpp",
- "ValidationTestsV1_0.cpp",
],
}
@@ -31,6 +30,5 @@
srcs: [
"BasicTests.cpp",
"GeneratedTests.cpp",
- "ValidationTests.cpp",
],
}
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
index d16f181..290a9d3 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_1_vts_tests.cpp"
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
index e2acd7d..a36b24c 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.1/vts/functional/Models.h b/neuralnetworks/1.1/vts/functional/Models.h
deleted file mode 100644
index 57da010..0000000
--- a/neuralnetworks/1.1/vts/functional/Models.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
-#define VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) \
- FN(add_relaxed) \
- FN(avg_pool_float_1_relaxed) \
- FN(avg_pool_float_2_relaxed) \
- FN(avg_pool_float_3_relaxed) \
- FN(avg_pool_float_4_relaxed) \
- FN(avg_pool_float_5_relaxed) \
- FN(batch_to_space) \
- FN(batch_to_space_float_1) \
- FN(batch_to_space_float_1_relaxed) \
- FN(batch_to_space_quant8_1) \
- FN(batch_to_space_relaxed) \
- FN(concat_float_1_relaxed) \
- FN(concat_float_2_relaxed) \
- FN(concat_float_3_relaxed) \
- FN(conv_1_h3_w2_SAME_relaxed) \
- FN(conv_1_h3_w2_VALID_relaxed) \
- FN(conv_3_h3_w2_SAME_relaxed) \
- FN(conv_3_h3_w2_VALID_relaxed) \
- FN(conv_float_2_relaxed) \
- FN(conv_float_channels_relaxed) \
- FN(conv_float_channels_weights_as_inputs_relaxed) \
- FN(conv_float_large_relaxed) \
- FN(conv_float_large_weights_as_inputs_relaxed) \
- FN(conv_float_relaxed) \
- FN(conv_float_weights_as_inputs_relaxed) \
- FN(depth_to_space_float_1_relaxed) \
- FN(depth_to_space_float_2_relaxed) \
- FN(depth_to_space_float_3_relaxed) \
- FN(depthwise_conv2d_float_2_relaxed) \
- FN(depthwise_conv2d_float_large_2_relaxed) \
- FN(depthwise_conv2d_float_large_2_weights_as_inputs_relaxed) \
- FN(depthwise_conv2d_float_large_relaxed) \
- FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed) \
- FN(depthwise_conv2d_float_relaxed) \
- FN(depthwise_conv2d_float_weights_as_inputs_relaxed) \
- FN(depthwise_conv_relaxed) \
- FN(dequantize_relaxed) \
- FN(div) \
- FN(div_broadcast_float) \
- FN(div_broadcast_float_relaxed) \
- FN(div_relaxed) \
- FN(embedding_lookup_relaxed) \
- FN(floor_relaxed) \
- FN(fully_connected_float_2_relaxed) \
- FN(fully_connected_float_4d_simple) \
- FN(fully_connected_float_4d_simple_relaxed) \
- FN(fully_connected_float_large_relaxed) \
- FN(fully_connected_float_large_weights_as_inputs_relaxed) \
- FN(fully_connected_float_relaxed) \
- FN(fully_connected_float_weights_as_inputs_relaxed) \
- FN(hashtable_lookup_float_relaxed) \
- FN(l2_normalization_2_relaxed) \
- FN(l2_normalization_large_relaxed) \
- FN(l2_normalization_relaxed) \
- FN(l2_pool_float_2_relaxed) \
- FN(l2_pool_float_large_relaxed) \
- FN(l2_pool_float_relaxed) \
- FN(local_response_norm_float_1_relaxed) \
- FN(local_response_norm_float_2_relaxed) \
- FN(local_response_norm_float_3_relaxed) \
- FN(local_response_norm_float_4_relaxed) \
- FN(logistic_float_1_relaxed) \
- FN(logistic_float_2_relaxed) \
- FN(lsh_projection_2_relaxed) \
- FN(lsh_projection_relaxed) \
- FN(lsh_projection_weights_as_inputs_relaxed) \
- FN(lstm2_relaxed) \
- FN(lstm2_state2_relaxed) \
- FN(lstm2_state_relaxed) \
- FN(lstm3_relaxed) \
- FN(lstm3_state2_relaxed) \
- FN(lstm3_state3_relaxed) \
- FN(lstm3_state_relaxed) \
- FN(lstm_relaxed) \
- FN(lstm_state2_relaxed) \
- FN(lstm_state_relaxed) \
- FN(max_pool_float_1_relaxed) \
- FN(max_pool_float_2_relaxed) \
- FN(max_pool_float_3_relaxed) \
- FN(max_pool_float_4_relaxed) \
- FN(mean) \
- FN(mean_float_1) \
- FN(mean_float_1_relaxed) \
- FN(mean_float_2) \
- FN(mean_float_2_relaxed) \
- FN(mean_quant8_1) \
- FN(mean_quant8_2) \
- FN(mean_relaxed) \
- FN(mobilenet_224_gender_basic_fixed_relaxed) \
- FN(mul_relaxed) \
- FN(mul_relu_relaxed) \
- FN(pad) \
- FN(pad_float_1) \
- FN(pad_float_1_relaxed) \
- FN(pad_relaxed) \
- FN(relu1_float_1_relaxed) \
- FN(relu1_float_2_relaxed) \
- FN(relu6_float_1_relaxed) \
- FN(relu6_float_2_relaxed) \
- FN(relu_float_1_relaxed) \
- FN(relu_float_2_relaxed) \
- FN(reshape_relaxed) \
- FN(reshape_weights_as_inputs_relaxed) \
- FN(resize_bilinear_2_relaxed) \
- FN(resize_bilinear_relaxed) \
- FN(rnn_relaxed) \
- FN(rnn_state_relaxed) \
- FN(softmax_float_1_relaxed) \
- FN(softmax_float_2_relaxed) \
- FN(space_to_batch) \
- FN(space_to_batch_float_1) \
- FN(space_to_batch_float_1_relaxed) \
- FN(space_to_batch_float_2) \
- FN(space_to_batch_float_2_relaxed) \
- FN(space_to_batch_float_3) \
- FN(space_to_batch_float_3_relaxed) \
- FN(space_to_batch_quant8_1) \
- FN(space_to_batch_quant8_2) \
- FN(space_to_batch_quant8_3) \
- FN(space_to_batch_relaxed) \
- FN(space_to_depth_float_1_relaxed) \
- FN(space_to_depth_float_2_relaxed) \
- FN(space_to_depth_float_3_relaxed) \
- FN(squeeze) \
- FN(squeeze_float_1) \
- FN(squeeze_float_1_relaxed) \
- FN(squeeze_quant8_1) \
- FN(squeeze_relaxed) \
- FN(strided_slice) \
- FN(strided_slice_float_1) \
- FN(strided_slice_float_10) \
- FN(strided_slice_float_10_relaxed) \
- FN(strided_slice_float_11) \
- FN(strided_slice_float_11_relaxed) \
- FN(strided_slice_float_1_relaxed) \
- FN(strided_slice_float_2) \
- FN(strided_slice_float_2_relaxed) \
- FN(strided_slice_float_3) \
- FN(strided_slice_float_3_relaxed) \
- FN(strided_slice_float_4) \
- FN(strided_slice_float_4_relaxed) \
- FN(strided_slice_float_5) \
- FN(strided_slice_float_5_relaxed) \
- FN(strided_slice_float_6) \
- FN(strided_slice_float_6_relaxed) \
- FN(strided_slice_float_7) \
- FN(strided_slice_float_7_relaxed) \
- FN(strided_slice_float_8) \
- FN(strided_slice_float_8_relaxed) \
- FN(strided_slice_float_9) \
- FN(strided_slice_float_9_relaxed) \
- FN(strided_slice_qaunt8_10) \
- FN(strided_slice_qaunt8_11) \
- FN(strided_slice_quant8_1) \
- FN(strided_slice_quant8_2) \
- FN(strided_slice_quant8_3) \
- FN(strided_slice_quant8_4) \
- FN(strided_slice_quant8_5) \
- FN(strided_slice_quant8_6) \
- FN(strided_slice_quant8_7) \
- FN(strided_slice_quant8_8) \
- FN(strided_slice_quant8_9) \
- FN(strided_slice_relaxed) \
- FN(sub) \
- FN(sub_broadcast_float) \
- FN(sub_broadcast_float_relaxed) \
- FN(sub_relaxed) \
- FN(svdf2_relaxed) \
- FN(svdf_relaxed) \
- FN(svdf_state_relaxed) \
- FN(tanh_relaxed) \
- FN(transpose) \
- FN(transpose_float_1) \
- FN(transpose_float_1_relaxed) \
- FN(transpose_quant8_1) \
- FN(transpose_relaxed)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.1/vts/functional/ModelsV1_0.h b/neuralnetworks/1.1/vts/functional/ModelsV1_0.h
deleted file mode 100644
index 52c0346..0000000
--- a/neuralnetworks/1.1/vts/functional/ModelsV1_0.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_V1_0_H
-#define VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_V1_0_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) \
- FN(add_broadcast_quant8) \
- FN(add) \
- FN(add_quant8) \
- FN(avg_pool_float_1) \
- FN(avg_pool_float_2) \
- FN(avg_pool_float_3) \
- FN(avg_pool_float_4) \
- FN(avg_pool_float_5) \
- FN(avg_pool_quant8_1) \
- FN(avg_pool_quant8_2) \
- FN(avg_pool_quant8_3) \
- FN(avg_pool_quant8_4) \
- FN(avg_pool_quant8_5) \
- FN(concat_float_1) \
- FN(concat_float_2) \
- FN(concat_float_3) \
- FN(concat_quant8_1) \
- FN(concat_quant8_2) \
- FN(concat_quant8_3) \
- FN(conv_1_h3_w2_SAME) \
- FN(conv_1_h3_w2_VALID) \
- FN(conv_3_h3_w2_SAME) \
- FN(conv_3_h3_w2_VALID) \
- FN(conv_float_2) \
- FN(conv_float_channels) \
- FN(conv_float_channels_weights_as_inputs) \
- FN(conv_float_large) \
- FN(conv_float_large_weights_as_inputs) \
- FN(conv_float) \
- FN(conv_float_weights_as_inputs) \
- FN(conv_quant8_2) \
- FN(conv_quant8_channels) \
- FN(conv_quant8_channels_weights_as_inputs) \
- FN(conv_quant8_large) \
- FN(conv_quant8_large_weights_as_inputs) \
- FN(conv_quant8) \
- FN(conv_quant8_overflow) \
- FN(conv_quant8_overflow_weights_as_inputs) \
- FN(conv_quant8_weights_as_inputs) \
- FN(depth_to_space_float_1) \
- FN(depth_to_space_float_2) \
- FN(depth_to_space_float_3) \
- FN(depth_to_space_quant8_1) \
- FN(depth_to_space_quant8_2) \
- FN(depthwise_conv2d_float_2) \
- FN(depthwise_conv2d_float_large_2) \
- FN(depthwise_conv2d_float_large_2_weights_as_inputs) \
- FN(depthwise_conv2d_float_large) \
- FN(depthwise_conv2d_float_large_weights_as_inputs) \
- FN(depthwise_conv2d_float) \
- FN(depthwise_conv2d_float_weights_as_inputs) \
- FN(depthwise_conv2d_quant8_2) \
- FN(depthwise_conv2d_quant8_large) \
- FN(depthwise_conv2d_quant8_large_weights_as_inputs) \
- FN(depthwise_conv2d_quant8) \
- FN(depthwise_conv2d_quant8_weights_as_inputs) \
- FN(depthwise_conv) \
- FN(dequantize) \
- FN(embedding_lookup) \
- FN(floor) \
- FN(fully_connected_float_2) \
- FN(fully_connected_float_large) \
- FN(fully_connected_float_large_weights_as_inputs) \
- FN(fully_connected_float) \
- FN(fully_connected_float_weights_as_inputs) \
- FN(fully_connected_quant8_2) \
- FN(fully_connected_quant8_large) \
- FN(fully_connected_quant8_large_weights_as_inputs) \
- FN(fully_connected_quant8) \
- FN(fully_connected_quant8_weights_as_inputs) \
- FN(hashtable_lookup_float) \
- FN(hashtable_lookup_quant8) \
- FN(l2_normalization_2) \
- FN(l2_normalization_large) \
- FN(l2_normalization) \
- FN(l2_pool_float_2) \
- FN(l2_pool_float_large) \
- FN(l2_pool_float) \
- FN(local_response_norm_float_1) \
- FN(local_response_norm_float_2) \
- FN(local_response_norm_float_3) \
- FN(local_response_norm_float_4) \
- FN(logistic_float_1) \
- FN(logistic_float_2) \
- FN(logistic_quant8_1) \
- FN(logistic_quant8_2) \
- FN(lsh_projection_2) \
- FN(lsh_projection) \
- FN(lsh_projection_weights_as_inputs) \
- FN(lstm2) \
- FN(lstm2_state2) \
- FN(lstm2_state) \
- FN(lstm3) \
- FN(lstm3_state2) \
- FN(lstm3_state3) \
- FN(lstm3_state) \
- FN(lstm) \
- FN(lstm_state2) \
- FN(lstm_state) \
- FN(max_pool_float_1) \
- FN(max_pool_float_2) \
- FN(max_pool_float_3) \
- FN(max_pool_float_4) \
- FN(max_pool_quant8_1) \
- FN(max_pool_quant8_2) \
- FN(max_pool_quant8_3) \
- FN(max_pool_quant8_4) \
- FN(mobilenet_224_gender_basic_fixed) \
- FN(mobilenet_quantized) \
- FN(mul_broadcast_quant8) \
- FN(mul) \
- FN(mul_quant8) \
- FN(mul_relu) \
- FN(relu1_float_1) \
- FN(relu1_float_2) \
- FN(relu1_quant8_1) \
- FN(relu1_quant8_2) \
- FN(relu6_float_1) \
- FN(relu6_float_2) \
- FN(relu6_quant8_1) \
- FN(relu6_quant8_2) \
- FN(relu_float_1) \
- FN(relu_float_2) \
- FN(relu_quant8_1) \
- FN(relu_quant8_2) \
- FN(reshape) \
- FN(reshape_quant8) \
- FN(reshape_quant8_weights_as_inputs) \
- FN(reshape_weights_as_inputs) \
- FN(resize_bilinear_2) \
- FN(resize_bilinear) \
- FN(rnn) \
- FN(rnn_state) \
- FN(softmax_float_1) \
- FN(softmax_float_2) \
- FN(softmax_quant8_1) \
- FN(softmax_quant8_2) \
- FN(space_to_depth_float_1) \
- FN(space_to_depth_float_2) \
- FN(space_to_depth_float_3) \
- FN(space_to_depth_quant8_1) \
- FN(space_to_depth_quant8_2) \
- FN(svdf2) \
- FN(svdf) \
- FN(svdf_state) \
- FN(tanh)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_V1_0_H
diff --git a/neuralnetworks/1.1/vts/functional/ValidationTests.cpp b/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
deleted file mode 100644
index 1c35ba8..0000000
--- a/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "Models.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/ValidationTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/ValidationTestsV1_0.cpp
deleted file mode 100644
index 7e2af05..0000000
--- a/neuralnetworks/1.1/vts/functional/ValidationTestsV1_0.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "ModelsV1_0.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 4a1e7a8..fe9b312 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -33,20 +33,30 @@
/**
* 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,
};
/**
+ * The range of values in the OperandType enum.
+ *
+ * THE MAX VALUES MUST BE UPDATED WHEN ADDING NEW TYPES to the OperandType enum.
+ */
+enum OperandTypeRange : uint32_t {
+ OPERAND_FUNDAMENTAL_MIN = 0,
+ OPERAND_FUNDAMENTAL_MAX = 8,
+ OPERAND_OEM_MIN = 10000,
+ OPERAND_OEM_MAX = 10001,
+};
+
+/**
* Operation types.
*
* The type of an operation in a model.
@@ -103,6 +113,20 @@
UNIDIRECTIONAL_SEQUENCE_LSTM = 85,
UNIDIRECTIONAL_SEQUENCE_RNN = 86,
ROTATED_BBOX_TRANSFORM = 87,
+ ABS = 88,
+ ROI_POOLING = 89,
+};
+
+/**
+ * The range of values in the OperationType enum.
+ *
+ * THE MAX VALUES MUST BE UPDATED WHEN ADDING NEW TYPES to the OperationType enum.
+ */
+enum OperationTypeRange : uint32_t {
+ OPERATION_FUNDAMENTAL_MIN = 0,
+ OPERATION_FUNDAMENTAL_MAX = 87,
+ OPERATION_OEM_MIN = 10000,
+ OPERATION_OEM_MAX = 10000,
};
/**
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 087c12f..085d5db 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -20,7 +20,6 @@
defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
srcs: [
"GeneratedTestsV1_0.cpp",
- "ValidationTestsV1_0.cpp",
]
}
@@ -30,7 +29,6 @@
defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
srcs: [
"GeneratedTestsV1_1.cpp",
- "ValidationTestsV1_1.cpp",
],
}
@@ -41,6 +39,5 @@
srcs: [
"BasicTests.cpp",
"GeneratedTests.cpp",
- "ValidationTests.cpp",
],
}
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
index 0608139..79d5a60 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_2_vts_tests.cpp"
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
index 8d685d1..42e22b0 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
index 8dbb586..aab5cb6 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
@@ -45,6 +45,8 @@
using ::android::nn::allocateSharedMemory;
using ::test_helper::MixedTypedExample;
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_1_vts_tests.cpp"
diff --git a/neuralnetworks/1.2/vts/functional/Models.h b/neuralnetworks/1.2/vts/functional/Models.h
deleted file mode 100644
index 2426ad0..0000000
--- a/neuralnetworks/1.2/vts/functional/Models.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
-#define VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) FN(random_multinomial)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.2/vts/functional/ModelsV1_0.h b/neuralnetworks/1.2/vts/functional/ModelsV1_0.h
deleted file mode 100644
index e81e64b..0000000
--- a/neuralnetworks/1.2/vts/functional/ModelsV1_0.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_V1_0_H
-#define VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_V1_0_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) \
- FN(add_broadcast_quant8) \
- FN(add) \
- FN(add_quant8) \
- FN(avg_pool_float_1) \
- FN(avg_pool_float_2) \
- FN(avg_pool_float_3) \
- FN(avg_pool_float_4) \
- FN(avg_pool_float_5) \
- FN(avg_pool_quant8_1) \
- FN(avg_pool_quant8_2) \
- FN(avg_pool_quant8_3) \
- FN(avg_pool_quant8_4) \
- FN(avg_pool_quant8_5) \
- FN(concat_float_1) \
- FN(concat_float_2) \
- FN(concat_float_3) \
- FN(concat_quant8_1) \
- FN(concat_quant8_2) \
- FN(concat_quant8_3) \
- FN(conv_1_h3_w2_SAME) \
- FN(conv_1_h3_w2_VALID) \
- FN(conv_3_h3_w2_SAME) \
- FN(conv_3_h3_w2_VALID) \
- FN(conv_float_2) \
- FN(conv_float_channels) \
- FN(conv_float_channels_weights_as_inputs) \
- FN(conv_float_large) \
- FN(conv_float_large_weights_as_inputs) \
- FN(conv_float) \
- FN(conv_float_weights_as_inputs) \
- FN(conv_quant8_2) \
- FN(conv_quant8_channels) \
- FN(conv_quant8_channels_weights_as_inputs) \
- FN(conv_quant8_large) \
- FN(conv_quant8_large_weights_as_inputs) \
- FN(conv_quant8) \
- FN(conv_quant8_overflow) \
- FN(conv_quant8_overflow_weights_as_inputs) \
- FN(conv_quant8_weights_as_inputs) \
- FN(depth_to_space_float_1) \
- FN(depth_to_space_float_2) \
- FN(depth_to_space_float_3) \
- FN(depth_to_space_quant8_1) \
- FN(depth_to_space_quant8_2) \
- FN(depthwise_conv2d_float_2) \
- FN(depthwise_conv2d_float_large_2) \
- FN(depthwise_conv2d_float_large_2_weights_as_inputs) \
- FN(depthwise_conv2d_float_large) \
- FN(depthwise_conv2d_float_large_weights_as_inputs) \
- FN(depthwise_conv2d_float) \
- FN(depthwise_conv2d_float_weights_as_inputs) \
- FN(depthwise_conv2d_quant8_2) \
- FN(depthwise_conv2d_quant8_large) \
- FN(depthwise_conv2d_quant8_large_weights_as_inputs) \
- FN(depthwise_conv2d_quant8) \
- FN(depthwise_conv2d_quant8_weights_as_inputs) \
- FN(depthwise_conv) \
- FN(dequantize) \
- FN(embedding_lookup) \
- FN(floor) \
- FN(fully_connected_float_2) \
- FN(fully_connected_float_large) \
- FN(fully_connected_float_large_weights_as_inputs) \
- FN(fully_connected_float) \
- FN(fully_connected_float_weights_as_inputs) \
- FN(fully_connected_quant8_2) \
- FN(fully_connected_quant8_large) \
- FN(fully_connected_quant8_large_weights_as_inputs) \
- FN(fully_connected_quant8) \
- FN(fully_connected_quant8_weights_as_inputs) \
- FN(hashtable_lookup_float) \
- FN(hashtable_lookup_quant8) \
- FN(l2_normalization_2) \
- FN(l2_normalization_large) \
- FN(l2_normalization) \
- FN(l2_pool_float_2) \
- FN(l2_pool_float_large) \
- FN(l2_pool_float) \
- FN(local_response_norm_float_1) \
- FN(local_response_norm_float_2) \
- FN(local_response_norm_float_3) \
- FN(local_response_norm_float_4) \
- FN(logistic_float_1) \
- FN(logistic_float_2) \
- FN(logistic_quant8_1) \
- FN(logistic_quant8_2) \
- FN(lsh_projection_2) \
- FN(lsh_projection) \
- FN(lsh_projection_weights_as_inputs) \
- FN(lstm2) \
- FN(lstm2_state2) \
- FN(lstm2_state) \
- FN(lstm3) \
- FN(lstm3_state2) \
- FN(lstm3_state3) \
- FN(lstm3_state) \
- FN(lstm) \
- FN(lstm_state2) \
- FN(lstm_state) \
- FN(max_pool_float_1) \
- FN(max_pool_float_2) \
- FN(max_pool_float_3) \
- FN(max_pool_float_4) \
- FN(max_pool_quant8_1) \
- FN(max_pool_quant8_2) \
- FN(max_pool_quant8_3) \
- FN(max_pool_quant8_4) \
- FN(mobilenet_224_gender_basic_fixed) \
- FN(mobilenet_quantized) \
- FN(mul_broadcast_quant8) \
- FN(mul) \
- FN(mul_quant8) \
- FN(mul_relu) \
- FN(relu1_float_1) \
- FN(relu1_float_2) \
- FN(relu1_quant8_1) \
- FN(relu1_quant8_2) \
- FN(relu6_float_1) \
- FN(relu6_float_2) \
- FN(relu6_quant8_1) \
- FN(relu6_quant8_2) \
- FN(relu_float_1) \
- FN(relu_float_2) \
- FN(relu_quant8_1) \
- FN(relu_quant8_2) \
- FN(reshape) \
- FN(reshape_quant8) \
- FN(reshape_quant8_weights_as_inputs) \
- FN(reshape_weights_as_inputs) \
- FN(resize_bilinear_2) \
- FN(resize_bilinear) \
- FN(rnn) \
- FN(rnn_state) \
- FN(softmax_float_1) \
- FN(softmax_float_2) \
- FN(softmax_quant8_1) \
- FN(softmax_quant8_2) \
- FN(space_to_depth_float_1) \
- FN(space_to_depth_float_2) \
- FN(space_to_depth_float_3) \
- FN(space_to_depth_quant8_1) \
- FN(space_to_depth_quant8_2) \
- FN(svdf2) \
- FN(svdf) \
- FN(svdf_state) \
- FN(tanh)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_V1_0_H
diff --git a/neuralnetworks/1.2/vts/functional/ModelsV1_1.h b/neuralnetworks/1.2/vts/functional/ModelsV1_1.h
deleted file mode 100644
index eb68de4..0000000
--- a/neuralnetworks/1.2/vts/functional/ModelsV1_1.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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 VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
-#define VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "TestHarness.h"
-
-#include <android/hardware/neuralnetworks/1.2/types.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using MixedTypedExample = test_helper::MixedTypedExample;
-
-#define FOR_EACH_TEST_MODEL(FN) \
- FN(add_relaxed) \
- FN(avg_pool_float_1_relaxed) \
- FN(avg_pool_float_2_relaxed) \
- FN(avg_pool_float_3_relaxed) \
- FN(avg_pool_float_4_relaxed) \
- FN(avg_pool_float_5_relaxed) \
- FN(batch_to_space) \
- FN(batch_to_space_float_1) \
- FN(batch_to_space_float_1_relaxed) \
- FN(batch_to_space_quant8_1) \
- FN(batch_to_space_relaxed) \
- FN(concat_float_1_relaxed) \
- FN(concat_float_2_relaxed) \
- FN(concat_float_3_relaxed) \
- FN(conv_1_h3_w2_SAME_relaxed) \
- FN(conv_1_h3_w2_VALID_relaxed) \
- FN(conv_3_h3_w2_SAME_relaxed) \
- FN(conv_3_h3_w2_VALID_relaxed) \
- FN(conv_float_2_relaxed) \
- FN(conv_float_channels_relaxed) \
- FN(conv_float_channels_weights_as_inputs_relaxed) \
- FN(conv_float_large_relaxed) \
- FN(conv_float_large_weights_as_inputs_relaxed) \
- FN(conv_float_relaxed) \
- FN(conv_float_weights_as_inputs_relaxed) \
- FN(depth_to_space_float_1_relaxed) \
- FN(depth_to_space_float_2_relaxed) \
- FN(depth_to_space_float_3_relaxed) \
- FN(depthwise_conv2d_float_2_relaxed) \
- FN(depthwise_conv2d_float_large_2_relaxed) \
- FN(depthwise_conv2d_float_large_2_weights_as_inputs_relaxed) \
- FN(depthwise_conv2d_float_large_relaxed) \
- FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed) \
- FN(depthwise_conv2d_float_relaxed) \
- FN(depthwise_conv2d_float_weights_as_inputs_relaxed) \
- FN(depthwise_conv_relaxed) \
- FN(dequantize_relaxed) \
- FN(div) \
- FN(div_broadcast_float) \
- FN(div_broadcast_float_relaxed) \
- FN(div_relaxed) \
- FN(embedding_lookup_relaxed) \
- FN(floor_relaxed) \
- FN(fully_connected_float_2_relaxed) \
- FN(fully_connected_float_4d_simple) \
- FN(fully_connected_float_4d_simple_relaxed) \
- FN(fully_connected_float_large_relaxed) \
- FN(fully_connected_float_large_weights_as_inputs_relaxed) \
- FN(fully_connected_float_relaxed) \
- FN(fully_connected_float_weights_as_inputs_relaxed) \
- FN(hashtable_lookup_float_relaxed) \
- FN(l2_normalization_2_relaxed) \
- FN(l2_normalization_large_relaxed) \
- FN(l2_normalization_relaxed) \
- FN(l2_pool_float_2_relaxed) \
- FN(l2_pool_float_large_relaxed) \
- FN(l2_pool_float_relaxed) \
- FN(local_response_norm_float_1_relaxed) \
- FN(local_response_norm_float_2_relaxed) \
- FN(local_response_norm_float_3_relaxed) \
- FN(local_response_norm_float_4_relaxed) \
- FN(logistic_float_1_relaxed) \
- FN(logistic_float_2_relaxed) \
- FN(lsh_projection_2_relaxed) \
- FN(lsh_projection_relaxed) \
- FN(lsh_projection_weights_as_inputs_relaxed) \
- FN(lstm2_relaxed) \
- FN(lstm2_state2_relaxed) \
- FN(lstm2_state_relaxed) \
- FN(lstm3_relaxed) \
- FN(lstm3_state2_relaxed) \
- FN(lstm3_state3_relaxed) \
- FN(lstm3_state_relaxed) \
- FN(lstm_relaxed) \
- FN(lstm_state2_relaxed) \
- FN(lstm_state_relaxed) \
- FN(max_pool_float_1_relaxed) \
- FN(max_pool_float_2_relaxed) \
- FN(max_pool_float_3_relaxed) \
- FN(max_pool_float_4_relaxed) \
- FN(mean) \
- FN(mean_float_1) \
- FN(mean_float_1_relaxed) \
- FN(mean_float_2) \
- FN(mean_float_2_relaxed) \
- FN(mean_quant8_1) \
- FN(mean_quant8_2) \
- FN(mean_relaxed) \
- FN(mobilenet_224_gender_basic_fixed_relaxed) \
- FN(mul_relaxed) \
- FN(mul_relu_relaxed) \
- FN(pad) \
- FN(pad_float_1) \
- FN(pad_float_1_relaxed) \
- FN(pad_relaxed) \
- FN(relu1_float_1_relaxed) \
- FN(relu1_float_2_relaxed) \
- FN(relu6_float_1_relaxed) \
- FN(relu6_float_2_relaxed) \
- FN(relu_float_1_relaxed) \
- FN(relu_float_2_relaxed) \
- FN(reshape_relaxed) \
- FN(reshape_weights_as_inputs_relaxed) \
- FN(resize_bilinear_2_relaxed) \
- FN(resize_bilinear_relaxed) \
- FN(rnn_relaxed) \
- FN(rnn_state_relaxed) \
- FN(softmax_float_1_relaxed) \
- FN(softmax_float_2_relaxed) \
- FN(space_to_batch) \
- FN(space_to_batch_float_1) \
- FN(space_to_batch_float_1_relaxed) \
- FN(space_to_batch_float_2) \
- FN(space_to_batch_float_2_relaxed) \
- FN(space_to_batch_float_3) \
- FN(space_to_batch_float_3_relaxed) \
- FN(space_to_batch_quant8_1) \
- FN(space_to_batch_quant8_2) \
- FN(space_to_batch_quant8_3) \
- FN(space_to_batch_relaxed) \
- FN(space_to_depth_float_1_relaxed) \
- FN(space_to_depth_float_2_relaxed) \
- FN(space_to_depth_float_3_relaxed) \
- FN(squeeze) \
- FN(squeeze_float_1) \
- FN(squeeze_float_1_relaxed) \
- FN(squeeze_quant8_1) \
- FN(squeeze_relaxed) \
- FN(strided_slice) \
- FN(strided_slice_float_1) \
- FN(strided_slice_float_10) \
- FN(strided_slice_float_10_relaxed) \
- FN(strided_slice_float_11) \
- FN(strided_slice_float_11_relaxed) \
- FN(strided_slice_float_1_relaxed) \
- FN(strided_slice_float_2) \
- FN(strided_slice_float_2_relaxed) \
- FN(strided_slice_float_3) \
- FN(strided_slice_float_3_relaxed) \
- FN(strided_slice_float_4) \
- FN(strided_slice_float_4_relaxed) \
- FN(strided_slice_float_5) \
- FN(strided_slice_float_5_relaxed) \
- FN(strided_slice_float_6) \
- FN(strided_slice_float_6_relaxed) \
- FN(strided_slice_float_7) \
- FN(strided_slice_float_7_relaxed) \
- FN(strided_slice_float_8) \
- FN(strided_slice_float_8_relaxed) \
- FN(strided_slice_float_9) \
- FN(strided_slice_float_9_relaxed) \
- FN(strided_slice_qaunt8_10) \
- FN(strided_slice_qaunt8_11) \
- FN(strided_slice_quant8_1) \
- FN(strided_slice_quant8_2) \
- FN(strided_slice_quant8_3) \
- FN(strided_slice_quant8_4) \
- FN(strided_slice_quant8_5) \
- FN(strided_slice_quant8_6) \
- FN(strided_slice_quant8_7) \
- FN(strided_slice_quant8_8) \
- FN(strided_slice_quant8_9) \
- FN(strided_slice_relaxed) \
- FN(sub) \
- FN(sub_broadcast_float) \
- FN(sub_broadcast_float_relaxed) \
- FN(sub_relaxed) \
- FN(svdf2_relaxed) \
- FN(svdf_relaxed) \
- FN(svdf_state_relaxed) \
- FN(tanh_relaxed) \
- FN(transpose) \
- FN(transpose_float_1) \
- FN(transpose_float_1_relaxed) \
- FN(transpose_quant8_1) \
- FN(transpose_relaxed)
-
-#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
- namespace function { \
- extern std::vector<MixedTypedExample> examples; \
- Model createTestModel(); \
- }
-
-FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
-
-#undef FORWARD_DECLARE_GENERATED_OBJECTS
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_V1_1_H
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index c1c6e55..c4f1b5e 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -128,16 +128,16 @@
///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
-static const int32_t invalidOperandTypes[] = {
- static_cast<int32_t>(OperandType::FLOAT32) - 1, // lower bound fundamental
- static_cast<int32_t>(OperandType::TENSOR_QUANT16_ASYMM) + 1, // upper bound fundamental
- static_cast<int32_t>(OperandType::OEM) - 1, // lower bound OEM
- static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1, // upper bound OEM
+static const uint32_t invalidOperandTypes[] = {
+ static_cast<uint32_t>(OperandTypeRange::OPERAND_FUNDAMENTAL_MIN) - 1,
+ static_cast<uint32_t>(OperandTypeRange::OPERAND_FUNDAMENTAL_MAX) + 1,
+ static_cast<uint32_t>(OperandTypeRange::OPERAND_OEM_MIN) - 1,
+ static_cast<uint32_t>(OperandTypeRange::OPERAND_OEM_MAX) + 1,
};
static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
for (size_t operand = 0; operand < model.operands.size(); ++operand) {
- for (int32_t invalidOperandType : invalidOperandTypes) {
+ for (uint32_t invalidOperandType : invalidOperandTypes) {
const std::string message = "mutateOperandTypeTest: operand " +
std::to_string(operand) + " set to value " +
std::to_string(invalidOperandType);
@@ -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;
@@ -224,8 +224,9 @@
case OperandType::TENSOR_INT32:
return {1};
case OperandType::TENSOR_QUANT8_ASYMM:
- case OperandType::TENSOR_QUANT16_ASYMM:
return {-1, 256};
+ case OperandType::TENSOR_QUANT16_SYMM:
+ return {-32769, -1, 1, 32768};
default:
return {};
}
@@ -278,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;
@@ -291,15 +292,33 @@
*operand = newOperand;
}
-static bool mutateOperationOperandTypeSkip(size_t operand, const Model& model) {
- // LSH_PROJECTION's second argument is allowed to have any type. This is the
- // only operation that currently has a type that can be anything independent
- // from any other type. Changing the operand type to any other type will
- // result in a valid model for LSH_PROJECTION. If this is the case, skip the
- // test.
+static bool mutateOperationOperandTypeSkip(size_t operand, OperandType type, const Model& model) {
+ // Do not test OEM types
+ if (type == model.operands[operand].type || type == OperandType::OEM ||
+ type == OperandType::TENSOR_OEM_BYTE) {
+ return true;
+ }
for (const Operation& operation : model.operations) {
- if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
- return true;
+ // Skip mutateOperationOperandTypeTest for the following operations.
+ // - LSH_PROJECTION's second argument is allowed to have any type.
+ // - ARGMIN and ARGMAX's first argument can be any of TENSOR_(FLOAT32|INT32|QUANT8_ASYMM).
+ // - CAST's argument can be any of TENSOR_(FLOAT32|INT32|QUANT8_ASYMM).
+ switch (operation.type) {
+ case OperationType::LSH_PROJECTION: {
+ if (operand == operation.inputs[1]) {
+ return true;
+ }
+ } break;
+ case OperationType::CAST:
+ case OperationType::ARGMAX:
+ case OperationType::ARGMIN: {
+ if (type == OperandType::TENSOR_FLOAT32 || type == OperandType::TENSOR_INT32 ||
+ type == OperandType::TENSOR_QUANT8_ASYMM) {
+ return true;
+ }
+ } break;
+ default:
+ break;
}
}
return false;
@@ -307,14 +326,8 @@
static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const Model& model) {
for (size_t operand = 0; operand < model.operands.size(); ++operand) {
- if (mutateOperationOperandTypeSkip(operand, model)) {
- continue;
- }
for (OperandType invalidOperandType : hidl_enum_range<OperandType>{}) {
- // Do not test OEM types
- if (invalidOperandType == model.operands[operand].type ||
- invalidOperandType == OperandType::OEM ||
- invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+ if (mutateOperationOperandTypeSkip(operand, invalidOperandType, model)) {
continue;
}
const std::string message = "mutateOperationOperandTypeTest: operand " +
@@ -329,16 +342,16 @@
///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
-static const int32_t invalidOperationTypes[] = {
- static_cast<int32_t>(OperationType::ADD) - 1, // lower bound fundamental
- static_cast<int32_t>(OperationType::TRANSPOSE) + 1, // upper bound fundamental
- static_cast<int32_t>(OperationType::OEM_OPERATION) - 1, // lower bound OEM
- static_cast<int32_t>(OperationType::OEM_OPERATION) + 1, // upper bound OEM
+static const uint32_t invalidOperationTypes[] = {
+ static_cast<uint32_t>(OperationTypeRange::OPERATION_FUNDAMENTAL_MIN) - 1,
+ static_cast<uint32_t>(OperationTypeRange::OPERATION_FUNDAMENTAL_MAX) + 1,
+ static_cast<uint32_t>(OperationTypeRange::OPERATION_OEM_MIN) - 1,
+ static_cast<uint32_t>(OperationTypeRange::OPERATION_OEM_MAX) + 1,
};
static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
- for (int32_t invalidOperationType : invalidOperationTypes) {
+ for (uint32_t invalidOperationType : invalidOperationTypes) {
const std::string message = "mutateOperationTypeTest: operation " +
std::to_string(operation) + " set to value " +
std::to_string(invalidOperationType);
@@ -406,8 +419,26 @@
removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
}
+static bool removeOperandSkip(size_t operand, const Model& model) {
+ for (const Operation& operation : model.operations) {
+ // Skip removeOperandTest for the following operations.
+ // - SPLIT's outputs are not checked during prepareModel.
+ if (operation.type == OperationType::SPLIT) {
+ for (const size_t outOprand : operation.outputs) {
+ if (operand == outOprand) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
static void removeOperandTest(const sp<IDevice>& device, const Model& model) {
for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+ if (removeOperandSkip(operand, model)) {
+ continue;
+ }
const std::string message = "removeOperandTest: operand " + std::to_string(operand);
validate(device, message, model,
[operand](Model* model) { removeOperand(model, operand); });
@@ -433,15 +464,76 @@
///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+static bool removeOperationInputSkip(const Operation& op, size_t input) {
+ // Skip removeOperationInputTest for the following operations.
+ // - CONCATENATION has at least 2 inputs, with the last element being INT32.
+ // - CONV_2D, DEPTHWISE_CONV_2D, MAX_POOL_2D, AVERAGE_POOL_2D, L2_POOL_2D, RESIZE_BILINEAR,
+ // SPACE_TO_DEPTH, SPACE_TO_DEPTH, SPACE_TO_BATCH_ND, BATCH_TO_SPACE_ND can have an optional
+ // layout parameter.
+ // - L2_NORMALIZATION, LOCAL_RESPONSE_NORMALIZATION, SOFTMAX can have an optional axis
+ // parameter.
+ switch (op.type) {
+ case OperationType::CONCATENATION: {
+ if (op.inputs.size() > 2 && input != op.inputs.size() - 1) {
+ return true;
+ }
+ } break;
+ case OperationType::DEPTHWISE_CONV_2D: {
+ if ((op.inputs.size() == 12 && input == 11) || (op.inputs.size() == 9 && input == 8)) {
+ return true;
+ }
+ } break;
+ case OperationType::CONV_2D:
+ case OperationType::AVERAGE_POOL_2D:
+ case OperationType::MAX_POOL_2D:
+ case OperationType::L2_POOL_2D: {
+ if ((op.inputs.size() == 11 && input == 10) || (op.inputs.size() == 8 && input == 7)) {
+ return true;
+ }
+ } break;
+ case OperationType::RESIZE_BILINEAR: {
+ if (op.inputs.size() == 4 && input == 3) {
+ return true;
+ }
+ } break;
+ case OperationType::SPACE_TO_DEPTH:
+ case OperationType::DEPTH_TO_SPACE:
+ case OperationType::BATCH_TO_SPACE_ND: {
+ if (op.inputs.size() == 3 && input == 2) {
+ return true;
+ }
+ } break;
+ case OperationType::SPACE_TO_BATCH_ND: {
+ if (op.inputs.size() == 4 && input == 3) {
+ return true;
+ }
+ } break;
+ case OperationType::L2_NORMALIZATION: {
+ if (op.inputs.size() == 2 && input == 1) {
+ return true;
+ }
+ } break;
+ case OperationType::LOCAL_RESPONSE_NORMALIZATION: {
+ if (op.inputs.size() == 6 && input == 5) {
+ return true;
+ }
+ } break;
+ case OperationType::SOFTMAX: {
+ if (op.inputs.size() == 3 && input == 2) {
+ return true;
+ }
+ } break;
+ default:
+ break;
+ }
+ return false;
+}
+
static void removeOperationInputTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
const Operation& op = model.operations[operation];
- // CONCATENATION has at least 2 inputs, with the last element being
- // INT32. Skip this test if removing one of CONCATENATION's
- // inputs still produces a valid model.
- if (op.type == OperationType::CONCATENATION && op.inputs.size() > 2 &&
- input != op.inputs.size() - 1) {
+ if (removeOperationInputSkip(op, input)) {
continue;
}
const std::string message = "removeOperationInputTest: operation " +
@@ -479,12 +571,13 @@
///////////////////////// ADD OPERATION INPUT /////////////////////////
-static bool addOperationInputSkip(const Operation& operation) {
+static bool addOperationInputSkip(const Operation& op) {
// Skip addOperationInputTest for the following operations.
- // L2_NORMALIZATION, LOCAL_RESPONSE_NORMALIZATION, SOFTMAX can have an optional axis parameter.
- if (operation.type == OperationType::L2_NORMALIZATION ||
- operation.type == OperationType::LOCAL_RESPONSE_NORMALIZATION ||
- operation.type == OperationType::SOFTMAX) {
+ // - L2_NORMALIZATION, LOCAL_RESPONSE_NORMALIZATION, SOFTMAX can have an optional INT32 axis
+ // parameter.
+ if ((op.type == OperationType::L2_NORMALIZATION && op.inputs.size() == 1) ||
+ (op.type == OperationType::LOCAL_RESPONSE_NORMALIZATION && op.inputs.size() == 5) ||
+ (op.type == OperationType::SOFTMAX && op.inputs.size() == 2)) {
return true;
}
return false;
diff --git a/neuralnetworks/1.2/vts/functional/ValidationTests.cpp b/neuralnetworks/1.2/vts/functional/ValidationTests.cpp
deleted file mode 100644
index 3bdc5cd..0000000
--- a/neuralnetworks/1.2/vts/functional/ValidationTests.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "Models.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/ValidationTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/ValidationTestsV1_0.cpp
deleted file mode 100644
index c54ed43..0000000
--- a/neuralnetworks/1.2/vts/functional/ValidationTestsV1_0.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "ModelsV1_0.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/ValidationTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/ValidationTestsV1_1.cpp
deleted file mode 100644
index 95932d5..0000000
--- a/neuralnetworks/1.2/vts/functional/ValidationTestsV1_1.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 "neuralnetworks_hidl_hal_test"
-
-#include "ModelsV1_1.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// generate validation tests
-#define VTS_CURRENT_TEST_CASE(TestName) \
- TEST_F(ValidationTest, TestName) { \
- const Model model = TestName::createTestModel(); \
- const std::vector<Request> requests = createRequests(TestName::examples); \
- validateModel(model); \
- validateRequests(model, requests); \
- }
-
-FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
-
-#undef VTS_CURRENT_TEST_CASE
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
new file mode 100644
index 0000000..04270c1
--- /dev/null
+++ b/power/stats/1.0/default/Android.bp
@@ -0,0 +1,34 @@
+// 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
+
+cc_library_shared {
+ name: "android.hardware.power.stats@1.0-service",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.power.stats@1.0-service.rc"],
+ srcs: ["service.cpp", "PowerStats.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ "android.hardware.power.stats@1.0",
+ ],
+ vendor: true,
+}
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
new file mode 100644
index 0000000..810c575
--- /dev/null
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+#include "PowerStats.h"
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <exception>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+#define MAX_FILE_PATH_LEN 128
+#define MAX_DEVICE_NAME_LEN 64
+#define MAX_QUEUE_SIZE 8192
+
+constexpr char kIioDirRoot[] = "/sys/bus/iio/devices/";
+constexpr char kDeviceName[] = "pm_device_name";
+constexpr char kDeviceType[] = "iio:device";
+constexpr uint32_t MAX_SAMPLING_RATE = 10;
+constexpr uint64_t WRITE_TIMEOUT_NS = 1000000000;
+
+void PowerStats::findIioPowerMonitorNodes() {
+ struct dirent* ent;
+ int fd;
+ char devName[MAX_DEVICE_NAME_LEN];
+ char filePath[MAX_FILE_PATH_LEN];
+ DIR* iioDir = opendir(kIioDirRoot);
+ if (!iioDir) {
+ ALOGE("Error opening directory: %s", kIioDirRoot);
+ return;
+ }
+ while (ent = readdir(iioDir), ent) {
+ if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0 &&
+ strlen(ent->d_name) > strlen(kDeviceType) &&
+ strncmp(ent->d_name, kDeviceType, strlen(kDeviceType)) == 0) {
+ snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", ent->d_name, "name");
+ fd = openat(dirfd(iioDir), filePath, O_RDONLY);
+ if (fd < 0) {
+ ALOGW("Failed to open directory: %s", filePath);
+ continue;
+ }
+ if (read(fd, devName, MAX_DEVICE_NAME_LEN) < 0) {
+ ALOGW("Failed to read device name from file: %s(%d)", filePath, fd);
+ close(fd);
+ continue;
+ }
+
+ if (strncmp(devName, kDeviceName, strlen(kDeviceName)) == 0) {
+ snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", kIioDirRoot, ent->d_name);
+ mPm.devicePaths.push_back(filePath);
+ }
+ close(fd);
+ }
+ }
+ closedir(iioDir);
+ return;
+}
+
+size_t PowerStats::parsePowerRails() {
+ std::string data;
+ std::string railFileName;
+ std::string spsFileName;
+ uint32_t index = 0;
+ uint32_t samplingRate;
+ for (const auto& path : mPm.devicePaths) {
+ railFileName = path + "/enabled_rails";
+ spsFileName = path + "/sampling_rate";
+ if (!android::base::ReadFileToString(spsFileName, &data)) {
+ ALOGW("Error reading file: %s", spsFileName.c_str());
+ continue;
+ }
+ samplingRate = strtoul(data.c_str(), NULL, 10);
+ if (!samplingRate || samplingRate == ULONG_MAX) {
+ ALOGE("Error parsing: %s", spsFileName.c_str());
+ break;
+ }
+ if (!android::base::ReadFileToString(railFileName, &data)) {
+ ALOGW("Error reading file: %s", railFileName.c_str());
+ continue;
+ }
+ std::istringstream railNames(data);
+ std::string line;
+ while (std::getline(railNames, line)) {
+ std::vector<std::string> words = android::base::Split(line, ":");
+ if (words.size() == 2) {
+ mPm.railsInfo.emplace(words[0], RailData{.devicePath = path,
+ .index = index,
+ .subsysName = words[1],
+ .samplingRate = samplingRate});
+ index++;
+ } else {
+ ALOGW("Unexpected format in file: %s", railFileName.c_str());
+ }
+ }
+ }
+ return index;
+}
+
+int PowerStats::parseIioEnergyNode(std::string devName) {
+ int ret = 0;
+ std::string data;
+ std::string fileName = devName + "/energy_value";
+ if (!android::base::ReadFileToString(fileName, &data)) {
+ ALOGE("Error reading file: %s", fileName.c_str());
+ return -1;
+ }
+
+ std::istringstream energyData(data);
+ std::string line;
+ uint64_t timestamp = 0;
+ bool timestampRead = false;
+ while (std::getline(energyData, line)) {
+ std::vector<std::string> words = android::base::Split(line, ",");
+ if (timestampRead == false) {
+ if (words.size() == 1) {
+ timestamp = strtoull(words[0].c_str(), NULL, 10);
+ if (timestamp == 0 || timestamp == ULLONG_MAX) {
+ ALOGW("Potentially wrong timestamp: %" PRIu64, timestamp);
+ }
+ timestampRead = true;
+ }
+ } else if (words.size() == 2) {
+ std::string railName = words[0];
+ if (mPm.railsInfo.count(railName) != 0) {
+ size_t index = mPm.railsInfo[railName].index;
+ mPm.reading[index].index = index;
+ mPm.reading[index].timestamp = timestamp;
+ mPm.reading[index].energy = strtoull(words[1].c_str(), NULL, 10);
+ if (mPm.reading[index].energy == ULLONG_MAX) {
+ ALOGW("Potentially wrong energy value: %" PRIu64, mPm.reading[index].energy);
+ }
+ }
+ } else {
+ ALOGW("Unexpected format in file: %s", fileName.c_str());
+ ret = -1;
+ break;
+ }
+ }
+ return ret;
+}
+
+Status PowerStats::parseIioEnergyNodes() {
+ Status ret = Status::SUCCESS;
+ if (mPm.hwEnabled == false) {
+ return Status::NOT_SUPPORTED;
+ }
+
+ for (const auto& devicePath : mPm.devicePaths) {
+ if (parseIioEnergyNode(devicePath) < 0) {
+ ALOGE("Error in parsing power stats");
+ ret = Status::FILESYSTEM_ERROR;
+ break;
+ }
+ }
+ return ret;
+}
+
+PowerStats::PowerStats() {
+ findIioPowerMonitorNodes();
+ size_t numRails = parsePowerRails();
+ if (mPm.devicePaths.empty() || numRails == 0) {
+ mPm.hwEnabled = false;
+ } else {
+ mPm.hwEnabled = true;
+ mPm.reading.resize(numRails);
+ }
+}
+
+Return<void> PowerStats::getRailInfo(getRailInfo_cb _hidl_cb) {
+ hidl_vec<RailInfo> rInfo;
+ Status ret = Status::SUCCESS;
+ size_t index;
+ std::lock_guard<std::mutex> _lock(mPm.mLock);
+ if (mPm.hwEnabled == false) {
+ _hidl_cb(rInfo, Status::NOT_SUPPORTED);
+ return Void();
+ }
+ rInfo.resize(mPm.railsInfo.size());
+ for (const auto& railData : mPm.railsInfo) {
+ index = railData.second.index;
+ rInfo[index].railName = railData.first;
+ rInfo[index].subsysName = railData.second.subsysName;
+ rInfo[index].index = index;
+ rInfo[index].samplingRate = railData.second.samplingRate;
+ }
+ _hidl_cb(rInfo, ret);
+ return Void();
+}
+
+Return<void> PowerStats::getEnergyData(const hidl_vec<uint32_t>& railIndices,
+ getEnergyData_cb _hidl_cb) {
+ hidl_vec<EnergyData> eVal;
+ std::lock_guard<std::mutex> _lock(mPm.mLock);
+ Status ret = parseIioEnergyNodes();
+
+ if (ret != Status::SUCCESS) {
+ ALOGE("Failed to getEnergyData");
+ _hidl_cb(eVal, ret);
+ return Void();
+ }
+
+ if (railIndices.size() == 0) {
+ eVal.resize(mPm.railsInfo.size());
+ memcpy(&eVal[0], &mPm.reading[0], mPm.reading.size() * sizeof(EnergyData));
+ } else {
+ eVal.resize(railIndices.size());
+ int i = 0;
+ for (const auto& railIndex : railIndices) {
+ if (railIndex >= mPm.reading.size()) {
+ ret = Status::INVALID_INPUT;
+ eVal.resize(0);
+ break;
+ }
+ memcpy(&eVal[i], &mPm.reading[railIndex], sizeof(EnergyData));
+ i++;
+ }
+ }
+ _hidl_cb(eVal, ret);
+ return Void();
+}
+
+Return<void> PowerStats::streamEnergyData(uint32_t timeMs, uint32_t samplingRate,
+ streamEnergyData_cb _hidl_cb) {
+ std::lock_guard<std::mutex> _lock(mPm.mLock);
+ if (mPm.fmqSynchronized != nullptr) {
+ _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES);
+ return Void();
+ }
+ uint32_t sps = std::min(samplingRate, MAX_SAMPLING_RATE);
+ uint32_t numSamples = timeMs * sps / 1000;
+ mPm.fmqSynchronized.reset(new (std::nothrow) MessageQueueSync(MAX_QUEUE_SIZE, true));
+ if (mPm.fmqSynchronized == nullptr || mPm.fmqSynchronized->isValid() == false) {
+ mPm.fmqSynchronized = nullptr;
+ _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES);
+ return Void();
+ }
+ std::thread pollThread = std::thread([this, sps, numSamples]() {
+ uint64_t sleepTimeUs = 1000000 / sps;
+ uint32_t currSamples = 0;
+ while (currSamples < numSamples) {
+ mPm.mLock.lock();
+ if (parseIioEnergyNodes() == Status::SUCCESS) {
+ mPm.fmqSynchronized->writeBlocking(&mPm.reading[0], mPm.reading.size(),
+ WRITE_TIMEOUT_NS);
+ mPm.mLock.unlock();
+ currSamples++;
+ if (usleep(sleepTimeUs) < 0) {
+ ALOGW("Sleep interrupted");
+ break;
+ }
+ } else {
+ mPm.mLock.unlock();
+ break;
+ }
+ }
+ mPm.mLock.lock();
+ mPm.fmqSynchronized = nullptr;
+ mPm.mLock.unlock();
+ return;
+ });
+ pollThread.detach();
+ _hidl_cb(*(mPm.fmqSynchronized)->getDesc(), numSamples, mPm.reading.size(), Status::SUCCESS);
+ return Void();
+}
+
+Return<void> PowerStats::getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) {
+ hidl_vec<PowerEntityInfo> eInfo;
+ _hidl_cb(eInfo, Status::NOT_SUPPORTED);
+ return Void();
+}
+
+Return<void> PowerStats::getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds,
+ getPowerEntityStateInfo_cb _hidl_cb) {
+ (void)powerEntityIds;
+ hidl_vec<PowerEntityStateSpace> powerEntityStateSpaces;
+ _hidl_cb(powerEntityStateSpaces, Status::NOT_SUPPORTED);
+ return Void();
+}
+
+Return<void> PowerStats::getPowerEntityStateResidencyData(
+ const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) {
+ (void)powerEntityIds;
+ hidl_vec<PowerEntityStateResidencyResult> results;
+ _hidl_cb(results, Status::NOT_SUPPORTED);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace stats
+} // namespace power
+} // namespace hardware
+} // namespace android
diff --git a/power/stats/1.0/default/PowerStats.h b/power/stats/1.0/default/PowerStats.h
new file mode 100644
index 0000000..fb2c6a8
--- /dev/null
+++ b/power/stats/1.0/default/PowerStats.h
@@ -0,0 +1,93 @@
+/*
+ * 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_POWERSTATS_V1_0_POWERSTATS_H
+#define ANDROID_HARDWARE_POWERSTATS_V1_0_POWERSTATS_H
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::power::stats::V1_0::EnergyData;
+using ::android::hardware::power::stats::V1_0::PowerEntityInfo;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateInfo;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateResidencyData;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateSpace;
+using ::android::hardware::power::stats::V1_0::PowerEntityType;
+using ::android::hardware::power::stats::V1_0::RailInfo;
+using ::android::hardware::power::stats::V1_0::Status;
+
+typedef MessageQueue<EnergyData, kSynchronizedReadWrite> MessageQueueSync;
+struct RailData {
+ std::string devicePath;
+ uint32_t index;
+ std::string subsysName;
+ uint32_t samplingRate;
+};
+
+struct OnDeviceMmt {
+ std::mutex mLock;
+ bool hwEnabled;
+ std::vector<std::string> devicePaths;
+ std::map<std::string, RailData> railsInfo;
+ std::vector<EnergyData> reading;
+ std::unique_ptr<MessageQueueSync> fmqSynchronized;
+};
+
+struct PowerStats : public IPowerStats {
+ PowerStats();
+ // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow.
+ Return<void> getRailInfo(getRailInfo_cb _hidl_cb) override;
+ Return<void> getEnergyData(const hidl_vec<uint32_t>& railIndices,
+ getEnergyData_cb _hidl_cb) override;
+ Return<void> streamEnergyData(uint32_t timeMs, uint32_t samplingRate,
+ streamEnergyData_cb _hidl_cb) override;
+ Return<void> getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) override;
+ Return<void> getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds,
+ getPowerEntityStateInfo_cb _hidl_cb) override;
+ Return<void> getPowerEntityStateResidencyData(
+ const hidl_vec<uint32_t>& powerEntityIds,
+ getPowerEntityStateResidencyData_cb _hidl_cb) override;
+
+ private:
+ OnDeviceMmt mPm;
+ void findIioPowerMonitorNodes();
+ size_t parsePowerRails();
+ int parseIioEnergyNode(std::string devName);
+ Status parseIioEnergyNodes();
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace stats
+} // namespace power
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_POWERSTATS_V1_0_POWERSTATS_H
diff --git a/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
new file mode 100644
index 0000000..d7e546b
--- /dev/null
+++ b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service
+ class hal
+ user system
+ group system
diff --git a/power/stats/1.0/default/service.cpp b/power/stats/1.0/default/service.cpp
new file mode 100644
index 0000000..80649f5
--- /dev/null
+++ b/power/stats/1.0/default/service.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "android.hardware.power.stats@1.0-service"
+
+#include <android/log.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "PowerStats.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhwbinder:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::implementation::PowerStats;
+
+int main(int /* argc */, char** /* argv */) {
+ ALOGI("power.stats service 1.0 is starting.");
+
+ android::sp<IPowerStats> service = new PowerStats();
+ if (service == nullptr) {
+ ALOGE("Can not create an instance of power.stats HAL Iface, exiting.");
+ return 1;
+ }
+
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+ status_t status = service->registerAsService();
+ if (status != OK) {
+ ALOGE("Could not register service for power.stats HAL Iface (%d), exiting.", status);
+ return 1;
+ }
+
+ ALOGI("power.stats service is ready");
+ joinRpcThreadpool();
+
+ // In normal operation, we don't expect the thread pool to exit
+ ALOGE("power.stats service is shutting down");
+ return 1;
+}
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index b6610e0..7012f6b 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -21,12 +21,17 @@
],
types: [
"AccessNetwork",
+ "CellConfigLte",
+ "CellInfo",
+ "CellInfoLte",
+ "CardStatus",
"DataProfileInfo",
"DataRegStateResult",
"EmergencyNumber",
"EmergencyNumberSource",
"EmergencyServiceCategory",
"LteVopsInfo",
+ "NetworkScanResult",
],
gen_java: true,
}
diff --git a/radio/1.3/IRadioIndication.hal b/radio/1.3/IRadioIndication.hal
index 509eef8..e7f26ac 100644
--- a/radio/1.3/IRadioIndication.hal
+++ b/radio/1.3/IRadioIndication.hal
@@ -49,4 +49,17 @@
*/
oneway currentEmergencyNumberList(RadioIndicationType type,
vec<EmergencyNumber> emergencyNumberList);
+
+ /**
+ * Request all of the current cell information known to the radio.
+ *
+ * @param type Type of radio indication
+ * @param records Current cell information
+ */
+ oneway cellInfoList_1_3(RadioIndicationType type, vec<CellInfo> records);
+
+ /**
+ * Incremental network scan results
+ */
+ oneway networkScanResult_1_3(RadioIndicationType type, NetworkScanResult result);
};
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index 10e7d63..fecd951 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -50,6 +50,17 @@
/**
* @param info Response info struct containing response type, serial no. and error
+ * @param cellInfo List of current cell information known to radio
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway getCellInfoListResponse_1_3(RadioResponseInfo info, vec<CellInfo> cellInfo);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
* @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
* types.hal
*
@@ -61,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 8b0891c..d3a6f78 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -18,11 +18,22 @@
import @1.0::ApnAuthType;
import @1.0::ApnTypes;
+import @1.0::CellInfoType;
import @1.0::DataProfileId;
import @1.0::DataProfileInfoType;
import @1.0::RadioAccessFamily;
+import @1.0::RadioError;
import @1.0::RegState;
+import @1.0::TimeStampType;
+import @1.1::ScanStatus;
import @1.2::AccessNetwork;
+import @1.2::CellInfo;
+import @1.2::CellInfoCdma;
+import @1.2::CellInfoGsm;
+import @1.2::CellInfoLte;
+import @1.2::CellInfoTdscdma;
+import @1.2::CellInfoWcdma;
+import @1.2::CardStatus;
import @1.2::CellIdentity;
import @1.2::DataRegStateResult;
@@ -168,6 +179,78 @@
LteVopsInfo lteVopsInfo; // LTE network capability
} vopsInfo;
+
+ /**
+ * True if use of dual connectivity with NR is restricted.
+ * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+ */
+ bool isDcNrRestricted;
+
+ /**
+ * True if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is present in
+ * plmn-IdentityList at position N.
+ * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+ * 3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+ */
+ bool isNrAvailable;
+};
+
+/** Contains the configuration of the LTE cell tower. */
+struct CellConfigLte {
+ /**
+ * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+ *
+ * True if the plmn-InfoList-r15 is present in SIB2 and at least one bit in this list is true,
+ * otherwise this value should be false.
+ *
+ * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+ */
+ bool isEndcAvailable;
+};
+
+/** Inherits from @1.2::CellInfoLte, in order to add the LTE configuration. */
+struct CellInfoLte {
+ @1.2::CellInfoLte base;
+ CellConfigLte cellConfig;
+};
+
+/** Overwritten from @1.2::CellInfo in order to update the CellInfoLte to 1.3 version. */
+struct CellInfo {
+ /** Cell type for selecting from union CellInfo. */
+ CellInfoType cellInfoType;
+
+ /**
+ * True if the phone is registered to a mobile network that provides service on this cell and
+ * this cell is being used or would be used for network signaling.
+ */
+ bool isRegistered;
+
+ /** CellInfo details, cellInfoType can tell which cell info should be used. */
+ safe_union Info {
+ CellInfoGsm gsm;
+ CellInfoCdma cdma;
+ CellInfoWcdma wcdma;
+ CellInfoTdscdma tdscdma;
+ CellInfoLte lte;
+ } info;
+};
+
+/** Overwritten from @1.2::NetworkScanResult in order to update the CellInfo to 1.3 version. */
+struct NetworkScanResult {
+ /**
+ * The status of the scan.
+ */
+ ScanStatus status;
+
+ /**
+ * The error code of the incremental result.
+ */
+ RadioError error;
+
+ /**
+ * List of network information as CellInfo.
+ */
+ vec<CellInfo> networkInfos;
};
/**
@@ -243,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/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
new file mode 100644
index 0000000..8dc0f27
--- /dev/null
+++ b/radio/config/1.1/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.radio.config@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IRadioConfigIndication.hal",
+ "IRadioConfigResponse.hal",
+ ],
+ interfaces: [
+ "android.hardware.radio@1.0",
+ "android.hardware.radio.config@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "SimSlotStatus",
+ ],
+ gen_java: true,
+}
diff --git a/radio/config/1.1/IRadioConfigIndication.hal b/radio/config/1.1/IRadioConfigIndication.hal
new file mode 100644
index 0000000..53eaa4d
--- /dev/null
+++ b/radio/config/1.1/IRadioConfigIndication.hal
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package android.hardware.radio.config@1.1;
+
+import @1.0::IRadioConfigIndication;
+import android.hardware.radio@1.0::RadioIndicationType;
+
+/**
+ * Interface declaring unsolicited radio config indications.
+ */
+interface IRadioConfigIndication extends @1.0::IRadioConfigIndication {
+
+ /**
+ * Indicates SIM slot status change.
+ *
+ * This indication must be sent by the modem whenever there is any slot status change, even the
+ * slot is inactive. For example, this indication must be triggered if a SIM card is inserted
+ * into an inactive slot.
+ *
+ * @param type Type of radio indication
+ * @param slotStatus new slot status info with size equals to the number of physical slots on
+ * the device
+ */
+ oneway simSlotsStatusChanged_1_1(RadioIndicationType type, vec<SimSlotStatus> slotStatus);
+};
diff --git a/radio/config/1.1/IRadioConfigResponse.hal b/radio/config/1.1/IRadioConfigResponse.hal
new file mode 100644
index 0000000..6f543ab
--- /dev/null
+++ b/radio/config/1.1/IRadioConfigResponse.hal
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.radio.config@1.1;
+
+import android.hardware.radio@1.0::RadioResponseInfo;
+import @1.0::IRadioConfigResponse;
+import @1.1::SimSlotStatus;
+
+/**
+ * Interface declaring response functions to solicited radio config requests.
+ */
+interface IRadioConfigResponse extends @1.0::IRadioConfigResponse {
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
+ * equal to the number of physical slots on the device
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:NO_MEMORY
+ * RadioError:INTERNAL_ERR
+ * RadioError:MODEM_ERR
+ */
+ oneway getSimSlotsStatusResponse_1_1(RadioResponseInfo info, vec<SimSlotStatus> slotStatus);
+};
diff --git a/radio/config/1.1/types.hal b/radio/config/1.1/types.hal
new file mode 100644
index 0000000..0c9d11e
--- /dev/null
+++ b/radio/config/1.1/types.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hardware.radio.config@1.1;
+
+import android.hardware.radio@1.0::CardState;
+import @1.0::SimSlotStatus;
+
+struct SimSlotStatus {
+ @1.0::SimSlotStatus 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 d3e3f7e..168b402 100644
--- a/sensors/2.0/default/Sensor.cpp
+++ b/sensors/2.0/default/Sensor.cpp
@@ -29,14 +29,20 @@
using ::android::hardware::sensors::V1_0::SensorStatus;
Sensor::Sensor(ISensorsEventCallback* callback)
- : mIsEnabled(false), mSamplingPeriodNs(0), mLastSampleTimeNs(0), mCallback(callback) {
+ : mIsEnabled(false),
+ mSamplingPeriodNs(0),
+ mLastSampleTimeNs(0),
+ mCallback(callback),
+ mMode(OperationMode::NORMAL) {
mRunThread = std::thread(startThread, this);
}
Sensor::~Sensor() {
+ std::unique_lock<std::mutex> lock(mRunMutex);
mStopThread = true;
mIsEnabled = false;
mWaitCV.notify_all();
+ lock.release();
mRunThread.join();
}
@@ -60,6 +66,7 @@
void Sensor::activate(bool enable) {
if (mIsEnabled != enable) {
+ std::unique_lock<std::mutex> lock(mRunMutex);
mIsEnabled = enable;
mWaitCV.notify_all();
}
@@ -79,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;
}
@@ -89,13 +96,14 @@
}
void Sensor::run() {
- std::mutex runMutex;
- std::unique_lock<std::mutex> runLock(runMutex);
+ std::unique_lock<std::mutex> runLock(mRunMutex);
constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000;
while (!mStopThread) {
- if (!mIsEnabled) {
- mWaitCV.wait(runLock, [&] { return mIsEnabled || mStopThread; });
+ if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) {
+ mWaitCV.wait(runLock, [&] {
+ return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread);
+ });
} else {
timespec curTime;
clock_gettime(CLOCK_REALTIME, &curTime);
@@ -105,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));
@@ -113,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;
@@ -127,6 +139,33 @@
return events;
}
+void Sensor::setOperationMode(OperationMode mode) {
+ if (mMode != mode) {
+ std::unique_lock<std::mutex> lock(mRunMutex);
+ mMode = mode;
+ mWaitCV.notify_all();
+ }
+}
+
+bool Sensor::supportsDataInjection() const {
+ return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION);
+}
+
+Result Sensor::injectEvent(const Event& event) {
+ Result result = Result::OK;
+ if (event.sensorType == SensorType::ADDITIONAL_INFO) {
+ // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation
+ // environment data into the device.
+ } else if (!supportsDataInjection()) {
+ result = Result::INVALID_OPERATION;
+ } else if (mMode == OperationMode::DATA_INJECTION) {
+ mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor());
+ } else {
+ result = Result::BAD_VALUE;
+ }
+ return result;
+}
+
AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
mSensorInfo.sensorHandle = sensorHandle;
mSensorInfo.name = "Accel Sensor";
@@ -142,7 +181,8 @@
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
- mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
+ mSensorInfo.flags =
+ static_cast<uint32_t>(SensorFlagBits::WAKE_UP | SensorFlagBits::DATA_INJECTION);
};
} // namespace implementation
diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h
index 75d9aab..3ab2299 100644
--- a/sensors/2.0/default/Sensor.h
+++ b/sensors/2.0/default/Sensor.h
@@ -21,10 +21,12 @@
#include <condition_variable>
#include <memory>
+#include <mutex>
#include <thread>
#include <vector>
using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V1_0::SensorType;
@@ -38,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 {
@@ -51,11 +53,17 @@
void activate(bool enable);
Result flush();
+ void setOperationMode(OperationMode mode);
+ bool supportsDataInjection() const;
+ Result injectEvent(const Event& event);
+
protected:
void run();
virtual std::vector<Event> readEvents();
static void startThread(Sensor* sensor);
+ bool isWakeUpSensor();
+
bool mIsEnabled;
int64_t mSamplingPeriodNs;
int64_t mLastSampleTimeNs;
@@ -63,9 +71,12 @@
std::atomic_bool mStopThread;
std::condition_variable mWaitCV;
+ std::mutex mRunMutex;
std::thread mRunThread;
ISensorsEventCallback* mCallback;
+
+ OperationMode mMode;
};
class AccelSensor : public Sensor {
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index cceb7d5..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.
@@ -54,9 +64,11 @@
return Void();
}
-Return<Result> Sensors::setOperationMode(OperationMode /* mode */) {
- // TODO implement
- return Result{};
+Return<Result> Sensors::setOperationMode(OperationMode mode) {
+ for (auto sensor : mSensors) {
+ sensor.second->setOperationMode(mode);
+ }
+ return Result::OK;
}
Return<Result> Sensors::activate(int32_t sensorHandle, bool enabled) {
@@ -99,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;
}
@@ -120,14 +136,18 @@
return Result::BAD_VALUE;
}
-Return<Result> Sensors::injectSensorData(const Event& /* event */) {
- // TODO implement
- return Result{};
+Return<Result> Sensors::injectSensorData(const Event& event) {
+ auto sensor = mSensors.find(event.sensorHandle);
+ if (sensor != mSensors.end()) {
+ return sensor->second->injectEvent(event);
+ }
+
+ return Result::BAD_VALUE;
}
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>();
}
@@ -141,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/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal
index fcb5087..a26896a 100644
--- a/soundtrigger/2.2/ISoundTriggerHw.hal
+++ b/soundtrigger/2.2/ISoundTriggerHw.hal
@@ -16,25 +16,27 @@
package android.hardware.soundtrigger@2.2;
-import @2.0::ISoundTriggerHwCallback.RecognitionEvent;
import @2.0::SoundModelHandle;
import @2.1::ISoundTriggerHw;
/**
- * SoundTrigger HAL interface. Used for hardware recognition of hotwords.
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords
+ * and other sounds.
*/
interface ISoundTriggerHw extends @2.1::ISoundTriggerHw {
/**
* Get the state of a given model.
- * The model state is returned as a RecognitionEvent.
- * @param modelHandle The handle of the sound model to use for recognition
+ * The model state is returned asynchronously as a RecognitionEvent via
+ * the callback that was registered in StartRecognition().
+ * @param modelHandle The handle of the sound model whose state is being
+ * queried.
* @return retval Operation completion status: 0 in case of success,
* -ENOSYS in case of invalid model handle,
* -ENOMEM in case of memory allocation failure,
- * -ENODEV in case of initialization error.
- * @return state RecognitionEvent in case of success
+ * -ENODEV in case of initialization error,
+ * -EINVAL in case where a recognition event is already
+ * being processed.
*/
- getModelState(SoundModelHandle modelHandle)
- generates (int32_t retval, @2.0::ISoundTriggerHwCallback.RecognitionEvent state);
+ getModelState(SoundModelHandle modelHandle) generates (int32_t retval);
};
diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp
index ffdf9fb..9d930ac 100644
--- a/soundtrigger/2.2/default/SoundTriggerHw.cpp
+++ b/soundtrigger/2.2/default/SoundTriggerHw.cpp
@@ -690,45 +690,26 @@
// Begin V2_2 implementation
-Return<void> SoundTriggerHw::getModelState(int32_t modelHandle, getModelState_cb hidl_cb) {
- int ret = 0;
- V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
- struct sound_trigger_recognition_event* halEvent = NULL;
+Return<int32_t> SoundTriggerHw::getModelState(int32_t modelHandle) {
sp<SoundModelClient> client;
if (mHwDevice == NULL) {
- ret = -ENODEV;
- goto exit;
+ return -ENODEV;
}
{
AutoMutex lock(mLock);
client = mClients.valueFor(modelHandle);
if (client == 0) {
- ret = -ENOSYS;
- goto exit;
+ return -ENOSYS;
}
}
if (mHwDevice->get_model_state == NULL) {
ALOGE("Failed to get model state from device, no such method");
- ret = -ENODEV;
- goto exit;
+ return -ENODEV;
}
- // Get the state from the device (as a recognition event)
- halEvent = mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
- if (halEvent == NULL) {
- ALOGE("Failed to get model state from device");
- ret = -ENODEV;
- goto exit;
- }
-
- convertRecognitionEventFromHal(&event, halEvent);
-
-exit:
- hidl_cb(ret, event);
- free(halEvent);
- return Void();
+ return mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h
index 876b990..6676318 100644
--- a/soundtrigger/2.2/default/SoundTriggerHw.h
+++ b/soundtrigger/2.2/default/SoundTriggerHw.h
@@ -82,7 +82,7 @@
int32_t cookie) override;
// Methods from V2_2::ISoundTriggerHw follow.
- Return<void> getModelState(int32_t modelHandle, getModelState_cb _hidl_cb) override;
+ Return<int32_t> getModelState(int32_t modelHandle) override;
SoundTriggerHw();
diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
index a473c37..0f37816 100644
--- a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
+++ b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
@@ -74,21 +74,14 @@
* Test ISoundTriggerHw::getModelState() method
*
* Verifies that:
- * - the implementation returns -EINVAL with invalid model handle
+ * - the implementation returns -ENOSYS with invalid model handle
*
*/
TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) {
- int ret = android::OK;
- ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
SoundModelHandle handle = 0;
- Return<void> hidlReturn =
- mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) {
- ret = retval;
- event = res;
- });
-
+ Return<int32_t> hidlReturn = mSoundTriggerHal->getModelState(handle);
EXPECT_TRUE(hidlReturn.isOk());
- EXPECT_EQ(-ENOSYS, ret);
+ EXPECT_EQ(-ENOSYS, hidlReturn);
}
int main(int argc, char** argv) {
diff --git a/tests/safeunion/cpp/1.0/.hidl_for_test b/tests/safeunion/cpp/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/.hidl_for_test
diff --git a/tests/safeunion/cpp/1.0/Android.bp b/tests/safeunion/cpp/1.0/Android.bp
new file mode 100644
index 0000000..1111719
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.tests.safeunion.cpp@1.0",
+ root: "android.hardware",
+ srcs: [
+ "ICppSafeUnion.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/tests/safeunion/cpp/1.0/ICppSafeUnion.hal b/tests/safeunion/cpp/1.0/ICppSafeUnion.hal
new file mode 100644
index 0000000..cc1a91e
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/ICppSafeUnion.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tests.safeunion.cpp@1.0;
+
+/**
+ * Safe union for cpp-only types.
+ */
+interface ICppSafeUnion {
+ safe_union PointerFmqSafeUnion {
+ interface iface;
+ fmq_sync<uint8_t> fmqSync;
+ fmq_unsync<uint8_t> fmqUnsync;
+ };
+ safe_union FmqSafeUnion {
+ fmq_sync<uint8_t> fmqSync;
+ fmq_unsync<uint8_t> fmqUnsync;
+ };
+
+ repeatPointerFmqSafeUnion(PointerFmqSafeUnion fmq) generates (PointerFmqSafeUnion fmq);
+ repeatFmqSafeUnion(FmqSafeUnion fmq) generates (FmqSafeUnion fmq);
+};
diff --git a/tests/safeunion/cpp/1.0/default/Android.bp b/tests/safeunion/cpp/1.0/default/Android.bp
new file mode 100644
index 0000000..210a639
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/default/Android.bp
@@ -0,0 +1,22 @@
+cc_library {
+ name: "android.hardware.tests.safeunion.cpp@1.0-impl",
+ relative_install_path: "hw",
+ srcs: [
+ "CppSafeUnion.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ // These are static libs only for testing purposes and portability. Shared
+ // libs should be used on device.
+ static_libs: [
+ "android.hardware.tests.safeunion.cpp@1.0",
+ ],
+}
diff --git a/tests/safeunion/cpp/1.0/default/CppSafeUnion.cpp b/tests/safeunion/cpp/1.0/default/CppSafeUnion.cpp
new file mode 100644
index 0000000..dcbd9d7
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/default/CppSafeUnion.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#include "CppSafeUnion.h"
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace safeunion {
+namespace cpp {
+namespace V1_0 {
+namespace implementation {
+
+Return<void> CppSafeUnion::repeatPointerFmqSafeUnion(const ICppSafeUnion::PointerFmqSafeUnion& fmq,
+ repeatPointerFmqSafeUnion_cb _hidl_cb) {
+ _hidl_cb(fmq);
+ return Void();
+}
+
+Return<void> CppSafeUnion::repeatFmqSafeUnion(const ICppSafeUnion::FmqSafeUnion& fmq,
+ repeatFmqSafeUnion_cb _hidl_cb) {
+ _hidl_cb(fmq);
+ return Void();
+}
+
+ICppSafeUnion* HIDL_FETCH_ICppSafeUnion(const char* /* name */) {
+ return new CppSafeUnion();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cpp
+} // namespace safeunion
+} // namespace tests
+} // namespace hardware
+} // namespace android
diff --git a/tests/safeunion/cpp/1.0/default/CppSafeUnion.h b/tests/safeunion/cpp/1.0/default/CppSafeUnion.h
new file mode 100644
index 0000000..a128273
--- /dev/null
+++ b/tests/safeunion/cpp/1.0/default/CppSafeUnion.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/tests/safeunion/cpp/1.0/ICppSafeUnion.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace safeunion {
+namespace cpp {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct CppSafeUnion : public ICppSafeUnion {
+ Return<void> repeatPointerFmqSafeUnion(const ICppSafeUnion::PointerFmqSafeUnion& fmq,
+ repeatPointerFmqSafeUnion_cb _hidl_cb) override;
+ Return<void> repeatFmqSafeUnion(const ICppSafeUnion::FmqSafeUnion& fmq,
+ repeatFmqSafeUnion_cb _hidl_cb) override;
+};
+
+extern "C" ICppSafeUnion* HIDL_FETCH_ICppSafeUnion(const char* name);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cpp
+} // namespace safeunion
+} // namespace tests
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 5e87c1c..163a870 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -9,6 +9,7 @@
srcs: [
"types.hal",
"IWifi.hal",
+ "IWifiChip.hal",
"IWifiStaIface.hal",
],
interfaces: [
diff --git a/wifi/1.3/IWifiChip.hal b/wifi/1.3/IWifiChip.hal
new file mode 100644
index 0000000..74d527d
--- /dev/null
+++ b/wifi/1.3/IWifiChip.hal
@@ -0,0 +1,69 @@
+/*
+ * 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@1.3;
+
+import @1.0::WifiStatus;
+import @1.2::IWifiChip;
+
+/**
+ * Interface that represents a chip that must be configured as a single unit.
+ */
+interface IWifiChip extends @1.2::IWifiChip {
+
+ /**
+ * Capabilities exposed by this chip.
+ */
+ enum ChipCapabilityMask : @1.2::IWifiChip.ChipCapabilityMask {
+ /**
+ * Set Latency Mode.
+ */
+ SET_LATENCY_MODE = 1 << 12
+ };
+
+ /**
+ * Get the capabilities supported by this chip.
+ *
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ * @return capabilities Bitset of |ChipCapabilityMask| values.
+ */
+ getCapabilities_1_3()
+ generates (WifiStatus status, bitfield<ChipCapabilityMask> capabilities);
+
+ /**
+ * This enum represents the different latency modes that can be set through
+ * setLatencyMode()
+ */
+ enum LatencyMode : uint32_t {
+ NORMAL = 0,
+ LOW = 1
+ };
+
+ /**
+ * API to set the wifi latency mode
+ *
+ * Latency mode determines whether or not to optimize for reducing wifi
+ * latency as a tradeoff with other wifi functionality such as scanning,
+ * roaming, etc. This optimization is suitable for some applications such
+ * as gaming and virtual reality applications.
+ */
+ setLatencyMode(LatencyMode mode) generates (WifiStatus status);
+};
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);
};