Merge "Revert "Update cas@1.0 hal to cas@1.1""
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 3494682..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 4
-UseTab: Never
-IndentWidth: 4
-ContinuationIndentWidth: 8
diff --git a/.clang-format b/.clang-format
new file mode 120000
index 0000000..ddcf5a2
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..bdb17cd
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <math.h>
+
+// pull in all the <= 4.0 tests
+#include "4.0/AudioPrimaryHidlHalTest.cpp"
+
+TEST_P(InputStreamTest, SetMicrophoneDirection) {
+ doc::test("Make sure setMicrophoneDirection correctly handles valid & invalid arguments");
+
+ // MicrophoneDirection dir = MicrophoneDirection::FRONT;
+ for (MicrophoneDirection dir : android::hardware::hidl_enum_range<MicrophoneDirection>()) {
+ ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneDirection(dir));
+ }
+
+ // Bogus values
+ for (auto dir : {42, -1, 4}) {
+ ASSERT_RESULT(invalidArgsOrNotSupported,
+ stream->setMicrophoneDirection(MicrophoneDirection(dir)));
+ }
+}
+
+TEST_P(InputStreamTest, SetMicrophoneFieldDimension) {
+ doc::test("Make sure setMicrophoneFieldDimension correctly handles valid & invalid arguments");
+
+ // Valid zoom values -1.0 -> 1.0
+ float incr = 0.1f;
+ for (float val = -1.0f; val <= 1.0; val += incr) {
+ ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneFieldDimension(val));
+ }
+
+ // Bogus values
+ for (float val = 1.0f + incr; val <= 10.0f; val += incr) {
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(val));
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-val));
+ }
+ // Some extremes
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(NAN));
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-NAN));
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(INFINITY));
+ ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-INFINITY));
+}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 6498289..f434e42 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -73,8 +73,7 @@
name: "VtsHalAudioV5_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
srcs: [
- // for now the tests are the same as V4
- "4.0/AudioPrimaryHidlHalTest.cpp",
+ "5.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
"android.hardware.audio@5.0",
diff --git a/audio/effect/5.0/types.hal b/audio/effect/5.0/types.hal
index 84e1108..4b6c196 100644
--- a/audio/effect/5.0/types.hal
+++ b/audio/effect/5.0/types.hal
@@ -53,6 +53,7 @@
* | Volume | 6..8 | 0 none
* | management | | 1 implements volume control
* | | | 2 requires volume indication
+ * | | | 3 monitors requested volume
* | | | 4 reserved
* +----------------+--------+--------------------------------------------------
* | Device | 9..11 | 0 none
@@ -136,6 +137,7 @@
VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT,
VOLUME_CTRL = 1 << VOLUME_SHIFT,
VOLUME_IND = 2 << VOLUME_SHIFT,
+ VOLUME_MONITOR = 3 << VOLUME_SHIFT,
VOLUME_NONE = 0 << VOLUME_SHIFT,
// Device indication
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 7614cad..08cdffa 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -198,6 +198,15 @@
{.config =
{
+ .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {SEAT_1_LEFT}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
@@ -321,6 +330,8 @@
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
.areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ .minSampleRate = 1.0f,
+ .maxSampleRate = 2.0f,
},
.initialValue = {.floatValues = {100.0f}}}, // units in meters
@@ -328,6 +339,8 @@
{.prop = toInt(VehicleProperty::TIRE_PRESSURE),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+ .minSampleRate = 1.0f,
+ .maxSampleRate = 2.0f,
.areaConfigs =
{VehicleAreaConfig{
.areaId = WHEEL_FRONT_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index a488d67..89e809b 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -281,9 +281,62 @@
TOO_SIMILAR = 15,
/**
+ * The magnitude of the pan angle of the user’s face with respect to the sensor’s
+ * capture plane is too high.
+ *
+ * The pan angle is defined as the angle swept out by the user’s face turning
+ * their neck left and right. The pan angle would be zero if the user faced the
+ * camera directly.
+ *
+ * The user should be informed to look more directly at the camera.
+ */
+ PAN_TOO_EXTREME = 16,
+
+ /**
+ * The magnitude of the tilt angle of the user’s face with respect to the sensor’s
+ * capture plane is too high.
+ *
+ * The tilt angle is defined as the angle swept out by the user’s face looking up
+ * and down. The pan angle would be zero if the user faced the camera directly.
+ *
+ * The user should be informed to look more directly at the camera.
+ */
+ TILT_TOO_EXTREME = 17,
+
+ /**
+ * The magnitude of the roll angle of the user’s face with respect to the sensor’s
+ * capture plane is too high.
+ *
+ * The roll angle is defined as the angle swept out by the user’s face tilting their head
+ * towards their shoulders to the left and right. The pan angle would be zero if the user
+ * faced the camera directly.
+ *
+ * The user should be informed to look more directly at the camera.
+ */
+ ROLL_TOO_EXTREME = 18,
+
+ /**
+ * The user’s face has been obscured by some object.
+ *
+ * The user should be informed to remove any objects from the line of sight from
+ * the sensor to the user’s face.
+ */
+ FACE_OBSCURED = 19,
+
+ /**
+ * This message represents the earliest message sent at the beginning of the authentication
+ * pipeline. It is expected to be used to measure latency. For example, in a camera-based
+ * authentication system it's expected to be sent prior to camera initialization. Note this
+ * should be sent whenever authentication is restarted (see IBiometricsFace#userActivity).
+ * The framework will measure latency based on the time between the last START message and the
+ * onAuthenticated callback.
+ */
+ START = 20,
+
+ /**
* Used to enable a vendor-specific acquisition message.
*/
- VENDOR = 16
+ VENDOR = 21
};
/**
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index fd785df..f2d7a47 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -44,13 +44,15 @@
static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
HandleImporter CameraDeviceSession::sHandleImporter;
+buffer_handle_t CameraDeviceSession::sEmptyBuffer = nullptr;
+
const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
CameraDeviceSession::CameraDeviceSession(
camera3_device_t* device,
const camera_metadata_t* deviceInfo,
const sp<ICameraDeviceCallback>& callback) :
- camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
+ camera3_callback_ops({&sProcessCaptureResult, &sNotify, nullptr, nullptr}),
mDevice(device),
mDeviceVersion(device->common.version),
mFreeBufEarly(shouldFreeBufEarly()),
@@ -246,10 +248,50 @@
}
}
+Status CameraDeviceSession::importBuffer(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;
+ }
+ }
+
+ Mutex::Autolock _l(mInflightLock);
+ CirculatingBuffers& cbs = mCirculatingBuffers[streamId];
+ if (cbs.count(bufId) == 0) {
+ // 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 CameraDeviceSession::importRequest(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
hidl_vec<int>& allFences) {
+ return importRequestImpl(request, allBufPtrs, allFences);
+}
+
+Status CameraDeviceSession::importRequestImpl(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences,
+ bool allowEmptyBuf) {
bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
request.inputBuffer.bufferId != 0);
size_t numOutputBufs = request.outputBuffers.size();
@@ -277,25 +319,15 @@
}
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;
- }
+ Status st = importBuffer(
+ streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i],
+ // Disallow empty buf for input stream, otherwise follow
+ // the allowEmptyBuf argument.
+ (hasInputBuf && i == numOutputBufs) ? false : 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
@@ -1271,18 +1303,26 @@
ATRACE_END();
// free all imported buffers
+ Mutex::Autolock _l(mInflightLock);
for(auto& pair : mCirculatingBuffers) {
CirculatingBuffers& buffers = pair.second;
for (auto& p2 : buffers) {
sHandleImporter.freeBuffer(p2.second);
}
+ buffers.clear();
}
+ mCirculatingBuffers.clear();
mClosed = true;
}
return Void();
}
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t&, int) {
+ // No need to fill in bufferId by default
+ return BUFFER_ID_NO_BUFFER;
+}
+
status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result,
const camera3_capture_result *hal_result) {
uint32_t frameNumber = hal_result->frame_number;
@@ -1396,6 +1436,14 @@
result.outputBuffers[i].streamId =
static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
result.outputBuffers[i].buffer = nullptr;
+ if (hal_result->output_buffers[i].buffer != nullptr) {
+ result.outputBuffers[i].bufferId = getCapResultBufferId(
+ *(hal_result->output_buffers[i].buffer),
+ result.outputBuffers[i].streamId);
+ } else {
+ result.outputBuffers[i].bufferId = 0;
+ }
+
result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
// skip acquire fence since it's of no use to camera service
if (hal_result->output_buffers[i].release_fence != -1) {
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index bcee259..a96c245 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -161,6 +161,7 @@
std::map<uint32_t, bool> mInflightRawBoostPresent;
::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
+ static const uint64_t BUFFER_ID_NO_BUFFER = 0;
// buffers currently ciculating between HAL and camera service
// key: bufferId sent via HIDL interface
// value: imported buffer_handle_t
@@ -171,6 +172,7 @@
std::map<int, CirculatingBuffers> mCirculatingBuffers;
static HandleImporter sHandleImporter;
+ static buffer_handle_t sEmptyBuffer;
bool mInitFail;
bool mFirstRequest = false;
@@ -301,11 +303,23 @@
Status initStatus() const;
// Validate and import request's input buffer and acquire fence
- Status importRequest(
+ virtual Status importRequest(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
hidl_vec<int>& allFences);
+ Status importRequestImpl(
+ 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);
+
static void cleanupInflightFences(
hidl_vec<int>& allFences, size_t numFences);
@@ -332,6 +346,11 @@
static callbacks_process_capture_result_t sProcessCaptureResult;
static callbacks_notify_t sNotify;
+ // By default camera service uses frameNumber/streamId pair to retrieve the buffer that
+ // was sent to HAL. Override this implementation if HAL is using buffers from buffer management
+ // APIs to send output buffer.
+ virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId);
+
status_t constructCaptureResult(CaptureResult& result,
const camera3_capture_result *hal_result);
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index f2e031c..e52577c 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -87,6 +87,14 @@
Return<void> CameraDeviceSession::configureStreams_3_4(
const StreamConfiguration& requestedConfiguration,
ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
+ configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
+ return Void();
+}
+
+void CameraDeviceSession::configureStreams_3_4_Impl(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+ uint32_t streamConfigCounter) {
Status status = initStatus();
HalStreamConfiguration outStreams;
@@ -97,7 +105,7 @@
ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
__FUNCTION__);
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
}
}
@@ -109,7 +117,7 @@
ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
__FUNCTION__, mInflightBuffers.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (!mInflightAETriggerOverrides.empty()) {
@@ -117,7 +125,7 @@
" trigger overrides!", __FUNCTION__,
mInflightAETriggerOverrides.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (!mInflightRawBoostPresent.empty()) {
@@ -125,12 +133,12 @@
" boost overrides!", __FUNCTION__,
mInflightRawBoostPresent.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (status != Status::OK) {
_hidl_cb(status, outStreams);
- return Void();
+ return;
}
const camera_metadata_t *paramBuffer = nullptr;
@@ -139,11 +147,12 @@
}
camera3_stream_configuration_t stream_list{};
+ stream_list.stream_configuration_counter = streamConfigCounter;
hidl_vec<camera3_stream_t*> streams;
stream_list.session_parameters = paramBuffer;
if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
ATRACE_BEGIN("camera3->configure_streams");
@@ -168,7 +177,7 @@
}
_hidl_cb(status, outStreams);
- return Void();
+ return;
}
bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index fdc8a5a..00500b1 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -87,6 +87,12 @@
void postProcessConfigurationFailureLocked_3_4(
const StreamConfiguration& requestedConfiguration);
+ void configureStreams_3_4_Impl(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+ // Optional argument for ICameraDeviceSession@3.5 impl
+ uint32_t streamConfigCounter = 0);
+
Return<void> processCaptureRequest_3_4(
const hidl_vec<V3_4::CaptureRequest>& requests,
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 963893a..0770f04 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -15,8 +15,10 @@
*/
#define LOG_TAG "CamDevSession@3.5-impl"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <android/log.h>
+#include <vector>
#include <utils/Trace.h>
#include "CameraDeviceSession.h"
@@ -33,13 +35,26 @@
const sp<V3_2::ICameraDeviceCallback>& callback) :
V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
- mHasCallback_3_5 = false;
+ mCallback_3_5 = nullptr;
auto castResult = ICameraDeviceCallback::castFrom(callback);
if (castResult.isOk()) {
sp<ICameraDeviceCallback> callback3_5 = castResult;
if (callback3_5 != nullptr) {
- mHasCallback_3_5 = true;
+ mCallback_3_5 = callback3_5;
+ }
+ }
+
+ if (mCallback_3_5 != nullptr) {
+ camera_metadata_entry bufMgrVersion = mDeviceInfo.find(
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+ if (bufMgrVersion.count > 0) {
+ mSupportBufMgr = (bufMgrVersion.data.u8[0] ==
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+ if (mSupportBufMgr) {
+ request_stream_buffers = sRequestStreamBuffers;
+ return_stream_buffers = sReturnStreamBuffers;
+ }
}
}
}
@@ -50,14 +65,297 @@
Return<void> CameraDeviceSession::configureStreams_3_5(
const StreamConfiguration& requestedConfiguration,
ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) {
- return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+ configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
+ requestedConfiguration.streamConfigCounter);
+ return Void();
}
Return<void> CameraDeviceSession::signalStreamFlush(
- const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+ const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) {
+ std::vector<camera3_stream_t*> streams(streamIds.size());
+ {
+ Mutex::Autolock _l(mInflightLock);
+ for (size_t i = 0; i < streamIds.size(); i++) {
+ int32_t id = streamIds[i];
+ if (mStreamMap.count(id) == 0) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, id);
+ return Void();
+ }
+ streams[i] = &mStreamMap[id];
+ }
+ }
+ if (mDevice->ops->signal_stream_flush != nullptr) {
+ mDevice->ops->signal_stream_flush(mDevice,
+ streamConfigCounter, streams.size(), streams.data());
+ }
return Void();
}
+Status CameraDeviceSession::importRequest(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) {
+ if (mSupportBufMgr) {
+ return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
+ }
+ return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
+}
+
+void CameraDeviceSession::pushBufferId(
+ const buffer_handle_t& buf, uint64_t bufferId, int streamId) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+ // emplace will return existing entry if there is one.
+ auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{});
+ BufferIdMap& bIdMap = pair.first->second;
+ bIdMap[buf] = bufferId;
+}
+
+uint64_t CameraDeviceSession::popBufferId(
+ const buffer_handle_t& buf, int streamId) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+ auto streamIt = mBufferIdMaps.find(streamId);
+ if (streamIt == mBufferIdMaps.end()) {
+ return BUFFER_ID_NO_BUFFER;
+ }
+ BufferIdMap& bIdMap = streamIt->second;
+ auto it = bIdMap.find(buf);
+ if (it == bIdMap.end()) {
+ return BUFFER_ID_NO_BUFFER;
+ }
+ uint64_t bufId = it->second;
+ bIdMap.erase(it);
+ if (bIdMap.empty()) {
+ mBufferIdMaps.erase(streamIt);
+ }
+ return bufId;
+}
+
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) {
+ if (mSupportBufMgr) {
+ return popBufferId(buf, streamId);
+ }
+ return BUFFER_ID_NO_BUFFER;
+}
+
+Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) {
+ Mutex::Autolock _l(mInflightLock);
+ if (mStreamMap.count(streamId) == 0) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId);
+ return nullptr;
+ }
+ return &mStreamMap[streamId];
+}
+
+void CameraDeviceSession::cleanupInflightBufferFences(
+ std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs) {
+ hidl_vec<int> hFences = fences;
+ cleanupInflightFences(hFences, fences.size());
+ for (auto& p : bufs) {
+ popBufferId(p.first, p.second);
+ }
+}
+
+camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers(
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+ ATRACE_CALL();
+ *num_returned_buf_reqs = 0;
+ hidl_vec<BufferRequest> hBufReqs(num_buffer_reqs);
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ hBufReqs[i].streamId =
+ static_cast<Camera3Stream*>(buffer_reqs[i].stream)->mId;
+ hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested;
+ }
+
+ ATRACE_BEGIN("HIDL requestStreamBuffers");
+ BufferRequestStatus status;
+ hidl_vec<StreamBufferRet> bufRets;
+ auto err = mCallback_3_5->requestStreamBuffers(hBufReqs,
+ [&status, &bufRets]
+ (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
+ status = s;
+ bufRets = std::move(rets);
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ ATRACE_END();
+
+ if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
+ if (bufRets.size() != num_buffer_reqs) {
+ ALOGE("%s: expect %d buffer requests returned, only got %zu",
+ __FUNCTION__, num_buffer_reqs, bufRets.size());
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ // maybe we can query all streams in one call to avoid frequent locking device here?
+ Camera3Stream* stream = getStreamPointer(bufRets[i].streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ returned_buf_reqs[i].stream = stream;
+ }
+
+ std::vector<int> importedFences;
+ std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ int streamId = bufRets[i].streamId;
+ switch (bufRets[i].val.getDiscriminator()) {
+ case StreamBuffersVal::hidl_discriminator::error:
+ returned_buf_reqs[i].num_output_buffers = 0;
+ switch (bufRets[i].val.error()) {
+ case StreamBufferRequestError::NO_BUFFER_AVAILABLE:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE;
+ break;
+ case StreamBufferRequestError::MAX_BUFFER_EXCEEDED:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED;
+ break;
+ case StreamBufferRequestError::STREAM_DISCONNECTED:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED;
+ break;
+ case StreamBufferRequestError::UNKNOWN_ERROR:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR;
+ break;
+ default:
+ ALOGE("%s: Unknown StreamBufferRequestError %d",
+ __FUNCTION__, bufRets[i].val.error());
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ break;
+ case StreamBuffersVal::hidl_discriminator::buffers: {
+ const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers();
+ camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers;
+ for (size_t b = 0; b < hBufs.size(); b++) {
+ const StreamBuffer& hBuf = hBufs[b];
+ camera3_stream_buffer_t& outBuf = outBufs[b];
+ // maybe add importBuffers API to avoid frequent locking device?
+ Status s = importBuffer(streamId,
+ hBuf.bufferId, hBuf.buffer.getNativeHandle(),
+ /*out*/&(outBuf.buffer),
+ /*allowEmptyBuf*/false);
+ if (s != Status::OK) {
+ ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!",
+ __FUNCTION__, streamId, hBuf.bufferId);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ // Buffer import should never fail - restart HAL since something is very
+ // wrong.
+ assert(false);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+
+ pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId);
+ importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId));
+
+ if (!sHandleImporter.importFence(
+ hBuf.acquireFence,
+ outBuf.acquire_fence)) {
+ ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid",
+ __FUNCTION__, streamId, hBuf.bufferId);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ importedFences.push_back(outBuf.acquire_fence);
+ outBuf.stream = returned_buf_reqs[i].stream;
+ outBuf.status = CAMERA3_BUFFER_STATUS_OK;
+ outBuf.release_fence = -1;
+ }
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK;
+ } break;
+ default:
+ ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ }
+
+ *num_returned_buf_reqs = num_buffer_reqs;
+
+ return (status == BufferRequestStatus::OK) ?
+ CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
+ }
+
+ switch (status) {
+ case BufferRequestStatus::FAILED_CONFIGURING:
+ return CAMERA3_BUF_REQ_FAILED_CONFIGURING;
+ case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS:
+ return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+ case BufferRequestStatus::FAILED_UNKNOWN:
+ default:
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+}
+
+void CameraDeviceSession::returnStreamBuffers(
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers) {
+ ATRACE_CALL();
+ hidl_vec<StreamBuffer> hBufs(num_buffers);
+
+ for (size_t i = 0; i < num_buffers; i++) {
+ hBufs[i].streamId =
+ static_cast<Camera3Stream*>(buffers[i]->stream)->mId;
+ hBufs[i].buffer = nullptr; // use bufferId
+ hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId);
+ if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) {
+ ALOGE("%s: unknown buffer is returned to stream %d",
+ __FUNCTION__, hBufs[i].streamId);
+ }
+ // ERROR since the buffer is not for application to consume
+ hBufs[i].status = BufferStatus::ERROR;
+ // skip acquire fence since it's of no use to camera service
+ if (buffers[i]->release_fence != -1) {
+ native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+ handle->data[0] = buffers[i]->release_fence;
+ hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+ }
+ }
+
+ mCallback_3_5->returnStreamBuffers(hBufs);
+ return;
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers(
+ const struct camera3_callback_ops *cb,
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr ||
+ returned_buf_reqs == nullptr) {
+ ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p",
+ __FUNCTION__, num_buffer_reqs, buffer_reqs,
+ num_returned_buf_reqs, returned_buf_reqs);
+ return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+ }
+
+ return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs,
+ num_returned_buf_reqs, returned_buf_reqs);
+}
+
+void CameraDeviceSession::sReturnStreamBuffers(
+ const struct camera3_callback_ops *cb,
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ d->returnStreamBuffers(num_buffers, buffers);
+}
+
} // namespace implementation
} // namespace V3_5
} // namespace device
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
index ec34769..4f7284c 100644
--- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -21,6 +21,7 @@
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
#include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+#include <unordered_map>
namespace android {
namespace hardware {
@@ -30,11 +31,14 @@
namespace implementation {
using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
using ::android::hardware::camera::device::V3_5::StreamConfiguration;
using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
using ::android::hardware::Return;
@@ -44,6 +48,25 @@
using ::android::sp;
using ::android::Mutex;
+
+/**
+ * Function pointer types with C calling convention to
+ * use for HAL callback functions.
+ */
+extern "C" {
+ typedef camera3_buffer_request_status_t (callbacks_request_stream_buffer_t)(
+ const struct camera3_callback_ops *,
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+ typedef void (callbacks_return_stream_buffer_t)(
+ const struct camera3_callback_ops *,
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers);
+}
+
struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
CameraDeviceSession(camera3_device_t*,
@@ -62,12 +85,85 @@
ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
Return<void> signalStreamFlush(
- const hidl_vec<int32_t>& requests,
+ const hidl_vec<int32_t>& streamIds,
uint32_t streamConfigCounter);
+ virtual Status importRequest(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) override;
- // Whether this camera device session is created with version 3.5 callback.
- bool mHasCallback_3_5;
+ /**
+ * Static callback forwarding methods from HAL to instance
+ */
+ static callbacks_request_stream_buffer_t sRequestStreamBuffers;
+ static callbacks_return_stream_buffer_t sReturnStreamBuffers;
+
+ camera3_buffer_request_status_t requestStreamBuffers(
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+ void returnStreamBuffers(
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers);
+
+ struct BufferHasher {
+ size_t operator()(const buffer_handle_t& buf) const {
+ if (buf == nullptr)
+ return 0;
+
+ size_t result = 1;
+ result = 31 * result + buf->numFds;
+ for (int i = 0; i < buf->numFds; i++) {
+ result = 31 * result + buf->data[i];
+ }
+ return result;
+ }
+ };
+
+ struct BufferComparator {
+ bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+ if (buf1->numFds == buf2->numFds) {
+ for (int i = 0; i < buf1->numFds; i++) {
+ if (buf1->data[i] != buf2->data[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ Camera3Stream* getStreamPointer(int32_t streamId);
+
+ // Register buffer to mBufferIdMaps so we can find corresponding bufferId
+ // when the buffer is returned to camera service
+ void pushBufferId(const buffer_handle_t& buf, uint64_t bufferId, int streamId);
+
+ // Method to pop buffer's bufferId from mBufferIdMaps
+ // BUFFER_ID_NO_BUFFER is returned if no matching buffer is found
+ uint64_t popBufferId(const buffer_handle_t& buf, int streamId);
+
+ // Method to cleanup imported buffer/fences if requestStreamBuffers fails half way
+ void cleanupInflightBufferFences(
+ std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs);
+
+ // Overrides the default constructCaptureResult behavior for buffer management APIs
+ virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId) override;
+
+ std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
+ typedef std::unordered_map<const buffer_handle_t, uint64_t,
+ BufferHasher, BufferComparator> BufferIdMap;
+ // stream ID -> per stream buffer ID map for buffers coming from requestStreamBuffers API
+ // Entries are created during requestStreamBuffers when a stream first request a buffer, and
+ // deleted in returnStreamBuffers/processCaptureResult* when all buffers are returned
+ std::unordered_map<int, BufferIdMap> mBufferIdMaps;
+
+ sp<ICameraDeviceCallback> mCallback_3_5;
+ bool mSupportBufMgr;
private:
diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal
index 28c56c8..9bbc90d 100644
--- a/camera/metadata/3.4/types.hal
+++ b/camera/metadata/3.4/types.hal
@@ -73,6 +73,28 @@
*/
ANDROID_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_DEPTH_END,
+ /** android.depth.availableDynamicDepthStreamConfigurations [static, enum[], ndk_public]
+ *
+ * <p>The available dynamic depth dataspace stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).</p>
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+
+ /** android.depth.availableDynamicDepthMinFrameDurations [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for dynamic depth output streams.</p>
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
+
+ /** android.depth.availableDynamicDepthStallDurations [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination for dynamic depth streams.</p>
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
+
ANDROID_DEPTH_END_3_4,
/** android.logicalMultiCamera.activePhysicalId [dynamic, byte, public]
@@ -136,3 +158,11 @@
enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t {
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5,
};
+
+/** android.depth.availableDynamicDepthStreamConfigurations enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations : uint32_t {
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT,
+};
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 488b9af..e02cc7e 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -41,11 +41,8 @@
const char *kExternalProviderName = "external/0";
// "device@<version>/legacy/<id>"
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
-const char *kHAL3_2 = "3.2";
-const char *kHAL3_3 = "3.3";
const char *kHAL3_4 = "3.4";
const char *kHAL3_5 = "3.5";
-const char *kHAL1_0 = "1.0";
const int kMaxCameraDeviceNameLen = 128;
const int kMaxCameraIdLen = 16;
@@ -143,7 +140,6 @@
int new_status) {
CameraProvider* cp = const_cast<CameraProvider*>(
static_cast<const CameraProvider*>(callbacks));
- bool found = false;
if (cp == nullptr) {
ALOGE("%s: callback ops is null", __FUNCTION__);
@@ -155,17 +151,23 @@
snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
std::string cameraIdStr(cameraId);
cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status;
- if (cp->mCallbacks != nullptr) {
- CameraDeviceStatus status = (CameraDeviceStatus) new_status;
- for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
- if (cameraIdStr.compare(deviceNamePair.first) == 0) {
- cp->mCallbacks->cameraDeviceStatusChange(
- deviceNamePair.second, status);
- found = true;
- }
- }
- switch (status) {
+ if (cp->mCallbacks == nullptr) {
+ // For camera connected before mCallbacks is set, the corresponding
+ // addDeviceNames() would be called later in setCallbacks().
+ return;
+ }
+
+ bool found = false;
+ CameraDeviceStatus status = (CameraDeviceStatus)new_status;
+ for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
+ if (cameraIdStr.compare(deviceNamePair.first) == 0) {
+ cp->mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+ found = true;
+ }
+ }
+
+ switch (status) {
case CameraDeviceStatus::PRESENT:
case CameraDeviceStatus::ENUMERATING:
if (!found) {
@@ -176,7 +178,6 @@
if (found) {
cp->removeDeviceNames(camera_id);
}
- }
}
}
@@ -222,22 +223,6 @@
return cameraId;
}
-int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) {
- std::string deviceVersion;
- bool match = matchDeviceName(deviceName, &deviceVersion, nullptr);
- if (!match) {
- return -1;
- }
- if (deviceVersion == kHAL3_3) {
- return CAMERA_DEVICE_API_VERSION_3_3;
- } else if (deviceVersion == kHAL3_2) {
- return CAMERA_DEVICE_API_VERSION_3_2;
- } else if (deviceVersion == kHAL1_0) {
- return CAMERA_DEVICE_API_VERSION_1_0;
- }
- return 0;
-}
-
std::string CameraProvider::getHidlDeviceName(
std::string cameraId, int deviceVersion) {
// Maybe consider create a version check method and SortedVec to speed up?
@@ -245,9 +230,16 @@
deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 &&
deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 &&
deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 &&
- deviceVersion != CAMERA_DEVICE_API_VERSION_3_5) {
+ deviceVersion != CAMERA_DEVICE_API_VERSION_3_5 &&
+ deviceVersion != CAMERA_DEVICE_API_VERSION_3_6) {
return hidl_string("");
}
+
+ // Supported combinations:
+ // CAMERA_DEVICE_API_VERSION_1_0 -> ICameraDevice@1.0
+ // CAMERA_DEVICE_API_VERSION_3_[2-4] -> ICameraDevice@[3.2|3.3]
+ // CAMERA_DEVICE_API_VERSION_3_5 + CAMERA_MODULE_API_VERSION_2_4 -> ICameraDevice@3.4
+ // CAMERA_DEVICE_API_VERSION_3_[5-6] + CAMERA_MODULE_API_VERSION_2_5 -> ICameraDevice@3.5
bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0;
int versionMajor = isV1 ? 1 : 3;
int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
@@ -257,6 +249,8 @@
} else {
versionMinor = 4;
}
+ } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) {
+ versionMinor = 5;
}
char deviceName[kMaxCameraDeviceNameLen];
snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
@@ -356,7 +350,8 @@
// device_version undefined in CAMERA_MODULE_API_VERSION_1_0,
// All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible
- if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
+ uint16_t moduleVersion = mModule->getModuleApiVersion();
+ if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) {
// Verify the device version is in the supported range
switch (info.device_version) {
case CAMERA_DEVICE_API_VERSION_1_0:
@@ -366,6 +361,20 @@
case CAMERA_DEVICE_API_VERSION_3_5:
// in support
break;
+ case CAMERA_DEVICE_API_VERSION_3_6:
+ /**
+ * ICameraDevice@3.5 contains APIs from both
+ * CAMERA_DEVICE_API_VERSION_3_6 and CAMERA_MODULE_API_VERSION_2_5
+ * so we require HALs to uprev both for simplified supported combinations.
+ * HAL can still opt in individual new APIs indepedently.
+ */
+ if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) {
+ ALOGE("%s: Device %d has unsupported version combination:"
+ "HAL version %x and module version %x",
+ __FUNCTION__, id, info.device_version, moduleVersion);
+ return NO_INIT;
+ }
+ break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
@@ -439,8 +448,22 @@
// Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
Return<Status> CameraProvider::setCallback(const sp<ICameraProviderCallback>& callback) {
+ if (callback == nullptr) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
Mutex::Autolock _l(mCbLock);
mCallbacks = callback;
+
+ // Add and report all presenting external cameras.
+ for (auto const& statusPair : mCameraStatusMap) {
+ int id = std::stoi(statusPair.first);
+ auto status = static_cast<CameraDeviceStatus>(statusPair.second);
+ if (id >= mNumberOfLegacyCameras && status != CameraDeviceStatus::NOT_PRESENT) {
+ addDeviceNames(id, status, true);
+ }
+ }
+
return Status::OK;
}
@@ -452,6 +475,11 @@
Return<void> CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
std::vector<hidl_string> deviceNameList;
for (auto const& deviceNamePair : mCameraDeviceNames) {
+ if (std::stoi(deviceNamePair.first) >= mNumberOfLegacyCameras) {
+ // External camera devices must be reported through the device status change callback,
+ // not in this list.
+ continue;
+ }
if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) {
deviceNameList.push_back(deviceNamePair.second);
}
@@ -552,10 +580,11 @@
return Void();
}
- // ICameraDevice 3.4 or upper
sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl;
+
+ // ICameraDevice 3.4 or upper
if (deviceVersion >= kHAL3_4) {
- ALOGV("Constructing v3.4 camera device");
+ ALOGV("Constructing v3.4+ camera device");
if (deviceVersion == kHAL3_4) {
deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 0f0959f..10e9b0d 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -98,7 +98,6 @@
// extract legacy camera ID/device version from a HIDL device name
static std::string getLegacyCameraId(const hidl_string& deviceName);
- static int getCameraDeviceVersion(const hidl_string& deviceName);
// convert conventional HAL status to HIDL Status
static Status getHidlStatus(int);
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 1556c08..211240a 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -5521,6 +5521,24 @@
ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION "
<< " per API contract should never be set by Hal!";
}
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, &entry);
+ if ((0 == retcode) || (entry.count > 0)) {
+ ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS"
+ << " per API contract should never be set by Hal!";
+ }
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS, &entry);
+ if ((0 == retcode) || (entry.count > 0)) {
+ ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS"
+ << " per API contract should never be set by Hal!";
+ }
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS, &entry);
+ if ((0 == retcode) || (entry.count > 0)) {
+ ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS"
+ << " per API contract should never be set by Hal!";
+ }
}
void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars,
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6be6930..425e376 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -17,8 +17,9 @@
LOCAL_PATH := $(call my-dir)
BUILD_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
+my_empty_manifest := $(LOCAL_PATH)/manifest.empty.xml
-# Framework Compatibility Matrix (common to all FCM versions)
+# System Compatibility Matrix (common to all FCM versions)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/clear_vars.mk
@@ -26,6 +27,7 @@
LOCAL_MODULE_STEM := compatibility_matrix.device.xml
# define LOCAL_MODULE_CLASS for local-generated-sources-dir.
LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
ifndef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
LOCAL_SRC_FILES := compatibility_matrix.empty.xml
@@ -37,10 +39,9 @@
# Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
# by checking it against an empty manifest. But the empty manifest needs to contain
# BOARD_SEPOLICY_VERS to be compatible with DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
-my_manifest_src_file := $(LOCAL_PATH)/manifest.empty.xml
my_gen_check_manifest := $(local-generated-sources-dir)/manifest.check.xml
-$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_manifest_src_file)
-$(my_gen_check_manifest): $(my_manifest_src_file) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_empty_manifest)
+$(my_gen_check_manifest): $(my_empty_manifest) $(HOST_OUT_EXECUTABLES)/assemble_vintf
BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
VINTF_IGNORE_TARGET_FCM_VERSION=true \
$(HOST_OUT_EXECUTABLES)/assemble_vintf -i $(PRIVATE_SRC_FILE) -o $@
@@ -49,7 +50,6 @@
LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_gen_check_manifest)"
my_gen_check_manifest :=
-my_manifest_src_file :=
endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
@@ -61,18 +61,57 @@
include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+# Product Compatibility Matrix
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := product_compatibility_matrix.xml
+
+ifndef DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+my_framework_matrix_deps :=
+include $(BUILD_PHONY_PACKAGE)
+else # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+
+LOCAL_MODULE_STEM := compatibility_matrix.xml
+LOCAL_PRODUCT_MODULE := true
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
+
+# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specify an absolute path
+LOCAL_GENERATED_SOURCES := $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)
+
+# Enforce that DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE does not specify required HALs
+# by checking it against an empty manifest.
+LOCAL_GEN_FILE_DEPENDENCIES += $(my_empty_manifest)
+LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_empty_manifest)"
+
+my_framework_matrix_deps := $(LOCAL_MODULE)
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+endif # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+
my_system_matrix_deps := \
framework_compatibility_matrix.legacy.xml \
framework_compatibility_matrix.1.xml \
framework_compatibility_matrix.2.xml \
framework_compatibility_matrix.3.xml \
framework_compatibility_matrix.current.xml \
- framework_compatibility_matrix.device.xml
+ framework_compatibility_matrix.device.xml \
-# Phony target that installs all framework compatibility matrix files
+my_framework_matrix_deps += \
+ $(my_system_matrix_deps)
+
+# Phony target that installs all system compatibility matrix files
+include $(CLEAR_VARS)
+LOCAL_MODULE := system_compatibility_matrix.xml
+LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+include $(BUILD_PHONY_PACKAGE)
+
+# Phony target that installs all framework compatibility matrix files (system + product)
include $(CLEAR_VARS)
LOCAL_MODULE := framework_compatibility_matrix.xml
-LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+LOCAL_REQUIRED_MODULES := $(my_framework_matrix_deps)
include $(BUILD_PHONY_PACKAGE)
# Final Framework Compatibility Matrix for OTA
@@ -80,7 +119,7 @@
include $(LOCAL_PATH)/clear_vars.mk
LOCAL_MODULE := verified_assembled_system_matrix.xml
LOCAL_MODULE_PATH := $(PRODUCT_OUT)
-LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+LOCAL_REQUIRED_MODULES := $(my_framework_matrix_deps)
LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
LOCAL_ADD_VBMETA_VERSION_OVERRIDE := true
@@ -97,4 +136,6 @@
BUILT_SYSTEM_MATRIX := $(LOCAL_BUILT_MODULE)
my_system_matrix_deps :=
+my_framework_matrix_deps :=
+my_empty_manifest :=
BUILD_FRAMEWORK_COMPATIBILITY_MATRIX :=
diff --git a/compatibility_matrices/CleanSpec.mk b/compatibility_matrices/CleanSpec.mk
new file mode 100644
index 0000000..9b150ed
--- /dev/null
+++ b/compatibility_matrices/CleanSpec.mk
@@ -0,0 +1,47 @@
+# Copyright 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.device.xml)
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
index bafc84b..d22e510 100644
--- a/compatibility_matrices/compatibility_matrix.mk
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -17,7 +17,8 @@
##### Input Variables:
# LOCAL_MODULE: required. Module name for the build system.
# LOCAL_MODULE_CLASS: optional. Default is ETC.
-# LOCAL_MODULE_PATH: optional. Path of output file. Default is $(TARGET_OUT)/etc/vintf.
+# LOCAL_MODULE_PATH / LOCAL_MODULE_RELATIVE_PATH: required. (Relative) path of output file.
+# If not defined, LOCAL_MODULE_RELATIVE_PATH will be "vintf".
# LOCAL_MODULE_STEM: optional. Name of output file. Default is $(LOCAL_MODULE).
# LOCAL_SRC_FILES: required. Local source files provided to assemble_vintf
# (command line argument -i).
@@ -48,7 +49,9 @@
endif
ifndef LOCAL_MODULE_PATH
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+ifndef LOCAL_MODULE_RELATIVE_PATH
+$(error Either LOCAL_MODULE_PATH or LOCAL_MODULE_RELATIVE_PATH must be defined.)
+endif
endif
GEN := $(local-generated-sources-dir)/$(LOCAL_MODULE_STEM)
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
index 7e5f706..431b3fc 100644
--- a/configstore/1.2/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -15,7 +15,7 @@
*/
package android.hardware.configstore@1.2;
-import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::PixelFormat;
import android.hardware.graphics.common@1.2::Dataspace;
import @1.1::ISurfaceFlingerConfigs;
import @1.0::OptionalBool;
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
index d38b402..714442b 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -27,8 +27,8 @@
namespace V1_2 {
namespace implementation {
-using ::android::hardware::graphics::common::V1_1::PixelFormat;
using ::android::hardware::graphics::common::V1_2::Dataspace;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
// ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
Return<void> SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) {
diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
index 881b591..d7f4dcf 100644
--- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
+++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
@@ -31,10 +31,10 @@
using ::android::hardware::configstore::V1_0::OptionalBool;
using ::android::hardware::configstore::V1_0::OptionalInt64;
using ::android::hardware::configstore::V1_0::OptionalUInt64;
-using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
using ::android::hardware::configstore::V1_2::DisplayPrimaries;
-using ::android::hardware::graphics::common::V1_1::PixelFormat;
+using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
using ::android::hardware::graphics::common::V1_2::Dataspace;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
diff --git a/current.txt b/current.txt
index 3b87306..478cbc5 100644
--- a/current.txt
+++ b/current.txt
@@ -399,8 +399,9 @@
417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
-271187e261b30c01a33011aea257c07a2d2f05b72943ebee89e973e997849973 android.hardware.radio@1.0::types
+ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types
1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
+cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types
e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types
3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
diff --git a/gnss/measurement_corrections/1.0/types.hal b/gnss/measurement_corrections/1.0/types.hal
index 5f20734..edf26bf 100644
--- a/gnss/measurement_corrections/1.0/types.hal
+++ b/gnss/measurement_corrections/1.0/types.hal
@@ -79,18 +79,35 @@
* toaGpsNanosecondsOfWeek
*/
struct MeasurementCorrections {
- /** Represents latitude in degrees. */
+ /** Represents latitude in degrees at which the corrections are computed.. */
double latitudeDegrees;
- /** Represents longitude in degrees. */
+ /** Represents longitude in degrees at which the corrections are computed.. */
double longitudeDegrees;
/**
- * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
*/
double altitudeMeters;
- /** Time Of Applicability, GPS time of week */
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontalPositionUncertaintyMeters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double verticalPositionUncertaintyMeters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
uint64_t toaGpsNanosecondsOfWeek;
/**
diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
index 6eee71f..a2a881a 100644
--- a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
+++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
@@ -1,5 +1,6 @@
service vendor.gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service
class hal animation
+ interface android.hardware.graphics.allocator@2.0::IAllocator default
user system
group graphics drmrpc
capabilities SYS_NICE
diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal
index 392a12e..3da6176 100644
--- a/graphics/common/1.2/types.hal
+++ b/graphics/common/1.2/types.hal
@@ -25,7 +25,8 @@
/**
* Hdr
*/
-@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_")
+@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_",
+ export_parent="false")
enum Hdr : @1.0::Hdr {
HDR10_PLUS = 4,
};
@@ -41,6 +42,13 @@
* Use full range, sRGB transfer and BT2020 standard
*/
DISPLAY_BT2020 = STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL,
+
+ /**
+ * ISO 16684-1:2011(E)
+ *
+ * Embedded depth metadata following the dynamic depth specification.
+ */
+ DYNAMIC_DEPTH = 0x1002,
};
enum ColorMode : @1.1::ColorMode {
@@ -96,3 +104,18 @@
*/
typedef int32_t[4] Rect;
+/**
+ * Pixel formats for graphics buffers.
+ */
+@export(name="android_pixel_format_v1_2_t", value_prefix="HAL_PIXEL_FORMAT_",
+ export_parent="false")
+enum PixelFormat : @1.1::PixelFormat {
+ /**
+ * 24-bit format that has 8-bit H, S, and V components, in that order,
+ * from the lowest memory address to the highest memory address.
+ *
+ * The component values are unsigned normalized to the range [0, 1], whose
+ * interpretation is defined by the dataspace.
+ */
+ HSV_888 = 0x37,
+};
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index cf78dea..a3b7792 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -17,7 +17,7 @@
package android.hardware.graphics.composer@2.3;
import android.hardware.graphics.common@1.1::RenderIntent;
-import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::PixelFormat;
import android.hardware.graphics.common@1.2::ColorMode;
import android.hardware.graphics.common@1.2::Dataspace;
import android.hardware.graphics.common@1.2::Hdr;
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
index edc203e..a272e72 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -123,7 +123,7 @@
Return<void> getDisplayedContentSamplingAttributes(
uint64_t display,
IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override {
- common::V1_1::PixelFormat format;
+ PixelFormat format;
common::V1_2::Dataspace dataspace;
hidl_bitfield<IComposerClient::FormatColorComponent> componentMask;
Error error =
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
index 882621f..a0812ad 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -25,11 +25,11 @@
namespace V2_3 {
namespace hal {
-using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
using V2_1::Display;
using V2_1::Error;
using V2_1::Layer;
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 9fb6d4b..41e333a 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -34,11 +34,11 @@
namespace detail {
-using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
using V2_1::Display;
using V2_1::Error;
@@ -91,14 +91,16 @@
Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
PixelFormat format, Dataspace dataspace) override {
- return getClientTargetSupport_2_2(display, width, height, format,
+ return getClientTargetSupport_2_2(display, width, height,
+ static_cast<common::V1_1::PixelFormat>(format),
static_cast<common::V1_1::Dataspace>(dataspace));
}
Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
Dataspace* outDataspace) override {
return getReadbackBufferAttributes(
- display, outFormat, reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
+ display, reinterpret_cast<common::V1_1::PixelFormat*>(outFormat),
+ reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
}
Error getDisplayIdentificationData(Display display, uint8_t* outPort,
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index 7add322..ad4ef0b 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -32,11 +32,11 @@
namespace V2_3 {
namespace vts {
-using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
using V2_1::Display;
using V2_1::Error;
using V2_3::IComposer;
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index dca7406..de74e28 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -36,10 +36,10 @@
namespace {
using common::V1_0::BufferUsage;
-using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
+using common::V1_2::PixelFormat;
using mapper::V2_0::IMapper;
using mapper::V2_0::vts::Gralloc;
@@ -492,9 +492,6 @@
}
TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) {
- using common::V1_1::PixelFormat;
- using common::V1_2::Dataspace;
-
int constexpr invalid = -1;
auto format = static_cast<PixelFormat>(invalid);
auto dataspace = static_cast<Dataspace>(invalid);
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
index c3c6fc6..6815a51 100644
--- a/input/classifier/1.0/Android.bp
+++ b/input/classifier/1.0/Android.bp
@@ -7,29 +7,12 @@
enabled: true,
},
srcs: [
- "types.hal",
"IInputClassifier.hal",
],
interfaces: [
+ "android.hardware.input.common@1.0",
"android.hidl.base@1.0",
],
- types: [
- "Action",
- "Axis",
- "Button",
- "Classification",
- "EdgeFlag",
- "Flag",
- "Meta",
- "MotionEvent",
- "PointerCoords",
- "PointerProperties",
- "PolicyFlag",
- "Source",
- "SourceClass",
- "ToolType",
- "VideoFrame",
- ],
gen_java: true,
}
diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal
index edc1138..7397fea 100644
--- a/input/classifier/1.0/IInputClassifier.hal
+++ b/input/classifier/1.0/IInputClassifier.hal
@@ -16,6 +16,9 @@
package android.hardware.input.classifier@1.0;
+import android.hardware.input.common@1.0::Classification;
+import android.hardware.input.common@1.0::MotionEvent;
+
interface IInputClassifier {
/**
@@ -23,4 +26,16 @@
*/
classify(MotionEvent event) generates (Classification classification);
+ /**
+ * Called by the framework to reset the HAL internal state. The reset may be called
+ * to prevent an inconsistent stream of events to be sent to the HAL.
+ */
+ reset();
+
+ /**
+ * Called by the framework to reset the HAL internal state for a specific device.
+ * The reset may be called once device reset is received by the framework.
+ */
+ resetDevice(int32_t deviceId);
+
};
diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp
index c463361..a78bbc5 100644
--- a/input/classifier/1.0/default/InputClassifier.cpp
+++ b/input/classifier/1.0/default/InputClassifier.cpp
@@ -21,7 +21,7 @@
#include <log/log.h>
#include <utils/Timers.h>
-using namespace android::hardware::input::classifier::V1_0;
+using namespace android::hardware::input::common::V1_0;
namespace android {
namespace hardware {
@@ -57,6 +57,18 @@
return Classification::NONE;
}
+Return<void> InputClassifier::reset() {
+ // We don't have any internal state in this example implementation,
+ // so no work needed here.
+ return Void();
+}
+
+Return<void> InputClassifier::resetDevice(int32_t /*deviceId*/) {
+ // We don't have any internal per-device state in this example implementation,
+ // so no work needed here.
+ return Void();
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace classifier
diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h
index 0858ecb..eef370e 100644
--- a/input/classifier/1.0/default/InputClassifier.h
+++ b/input/classifier/1.0/default/InputClassifier.h
@@ -31,8 +31,12 @@
struct InputClassifier : public IInputClassifier {
// Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
- Return<Classification> classify(
- const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override;
+
+ Return<android::hardware::input::common::V1_0::Classification> classify(
+ const android::hardware::input::common::V1_0::MotionEvent& event) override;
+
+ Return<void> reset() override;
+ Return<void> resetDevice(int32_t deviceId) override;
};
} // namespace implementation
diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp
new file mode 100644
index 0000000..68a77f1
--- /dev/null
+++ b/input/common/1.0/Android.bp
@@ -0,0 +1,34 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.input.common@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Action",
+ "Axis",
+ "Button",
+ "Classification",
+ "EdgeFlag",
+ "Flag",
+ "Meta",
+ "MotionEvent",
+ "PointerCoords",
+ "PointerProperties",
+ "PolicyFlag",
+ "Source",
+ "SourceClass",
+ "ToolType",
+ "VideoFrame",
+ ],
+ gen_java: true,
+}
+
diff --git a/input/classifier/1.0/types.hal b/input/common/1.0/types.hal
similarity index 99%
rename from input/classifier/1.0/types.hal
rename to input/common/1.0/types.hal
index 244ecd9..1a07f3b 100644
--- a/input/classifier/1.0/types.hal
+++ b/input/common/1.0/types.hal
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.input.classifier@1.0;
+package android.hardware.input.common@1.0;
/**
@@ -435,12 +435,12 @@
};
enum SourceClass: uint8_t {
- NONE = 1 << 0,
- BUTTON = 1 << 1,
- POINTER = 1 << 2,
- NAVIGATION = 1 << 3,
- POSITION = 1 << 4,
- JOYSTICK = 1 << 5,
+ NONE = 0 << 0,
+ BUTTON = 1 << 0,
+ POINTER = 1 << 1,
+ NAVIGATION = 1 << 2,
+ POSITION = 1 << 3,
+ JOYSTICK = 1 << 4,
};
/**
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index c37c22b..56c78b2 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -13,6 +13,7 @@
"IComponentListener.hal",
"IComponentStore.hal",
"IConfigurable.hal",
+ "IInputSink.hal",
"IInputSurface.hal",
"IInputSurfaceConnection.hal",
],
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
index deb9255..7fd551f 100644
--- a/media/c2/1.0/IComponent.hal
+++ b/media/c2/1.0/IComponent.hal
@@ -22,13 +22,19 @@
import IConfigurable;
import IComponentInterface;
import IComponentListener;
+import IInputSurface;
+import IInputSurfaceConnection;
/**
- * 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 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 IComponent extends IComponentInterface {
+interface IComponent {
// METHODS AVAILABLE WHEN RUNNING
// =========================================================================
@@ -38,44 +44,42 @@
*
* This method must be supported in running (including tripped) states.
*
- * This method must return within 1ms
+ * It is acceptable for this method to return `OK` and return an error value
+ * using the IComponentListener::onWorkDone() callback.
*
- * 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.
+ * @param workBundle `WorkBundle` object containing a list of `Work` objects
+ * 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(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).
+ * - `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.
*/
queue(WorkBundle workBundle) generates (Status status);
/**
- * Discards and abandons any pending work for the component.
+ * Discards and abandons any pending `Work` items for the component.
*
* This method must be supported in running (including tripped) states.
*
- * This method must return within 5ms.
+ * `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.
*
- * 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.
+ * `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.
*
* @return status Status of the call, which may be
- * - 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.
+ * - `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.
*/
flush(
) generates (
@@ -87,42 +91,39 @@
* Drains the component, and optionally downstream components. This is a
* signalling method; as such it does not wait for any work completion.
*
- * 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.
+ * 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.
*
* This method must be supported in running (including tripped) states.
*
- * This method must return within 1ms.
- *
- * Work that is completed must be returned via the onWorkDone() callback.
+ * `Work` that is completed must be returned via
+ * IComponentListener::onWorkDone().
*
* @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 flush could not be completed within the time limit.
- * (unexpected)
- * - CORRUPTED - Some unknown error prevented flushing from completion.
- * (unexpected)
+ * - `OK` - The drain request has been successfully recorded.
+ * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `CORRUPTED` - Some unknown error occurred.
*/
drain(bool withEos) generates (Status status);
/**
* Starts using a surface for output.
*
- * @param blockPoolId The id of the BlockPool to be associated with the
- * output surface.
- * @param surface A surface to use for codec output.
+ * This method must not block.
+ *
+ * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+ * output surface.
+ * @param surface Output surface.
* @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 component could not be connected within the time
- * limit. (unexpected)
- * - CORRUPTED - Some unknown error prevented connecting the component.
- * (unexpected)
+ * - `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.
*/
setOutputSurface(
uint64_t blockPoolId,
@@ -132,65 +133,101 @@
);
/**
- * Starts using a persistent OMX input surface for a component.
+ * Starts using an input surface.
*
* The component must be in running state.
*
- * @param producer Producer component of an OMX persistent input surface.
- * @param source Source component of an OMX persistent input surface.
+ * @param inputSurface Input surface to connect to.
* @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 - 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)
+ * - `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.
*/
connectToOmxInputSurface(
IGraphicBufferProducer producer,
IGraphicBufferSource source
- ) generates (Status status);
+ ) generates (
+ Status status,
+ IInputSurfaceConnection connection
+ );
/**
* 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 - 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)
+ * - `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.
*/
disconnectFromInputSurface() generates (Status Status);
/**
- * Creates a local block pool backed by the given allocator and returns its
- * identifier.
+ * Creates a local `C2BlockPool` backed by the given allocator and returns
+ * its id.
*
- * This call must return within 100 msec.
+ * 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.
*
- * @param allocatorId The Codec 2.0 allocator ID
+ * 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`.
* @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 - 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.
+ * - `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.
*/
createBlockPool(uint32_t allocatorId) generates (
Status status,
@@ -201,17 +238,13 @@
/**
* Destroys a local block pool previously created by createBlockPool().
*
- * This call must return within 100 msec.
- *
- * @param blockPoolId The block pool id previously returned by
+ * @param blockPoolId Id of a `C2BlockPool` that was 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 pool could not be destroyedwithin the time limit.
- * (unexpected)
- * - CORRUPTED - Some unknown error prevented destruction of the pool.
- * (unexpected)
+ * - `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.
*/
destroyBlockPool(uint64_t blockPoolId) generates (Status status);
@@ -223,28 +256,24 @@
*
* 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 component could not be started within the time limit.
- * (unexpected)
- * - CORRUPTED - Some unknown error prevented starting the component.
- * (unexpected)
+ * - `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.
*/
start() generates (Status status);
@@ -255,22 +284,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 component could not be stopped within the time limit.
- * (unexpected)
- * - CORRUPTED - Some unknown error prevented starting the component.
- * (unexpected)
+ * - `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.
*/
stop() generates (Status status);
@@ -284,25 +313,24 @@
*
* This method must return withing 500ms.
*
- * After this call returns all work must have been abandoned, all references
- * must have been released.
+ * 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.
*
- * 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.
+ * 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 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 component could not be reset within the time limit.
- * (unexpected)
- * - CORRUPTED - Some unknown error prevented resetting the component.
- * (unexpected)
+ * - `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.
*/
reset() generates (Status status);
@@ -311,19 +339,27 @@
*
* This method must be supported in stopped state.
*
- * This method must return withing 500ms. Upon return all references must
- * be abandoned.
+ * This method destroys the component. Upon return, if @p status is `OK` or
+ * `DUPLICATE`, all resources must have been released.
*
* @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 component could not be released within the time
- * limit. (unexpected)
- * - CORRUPTED - Some unknown error prevented releasing the component.
- * (unexpected)
+ * - `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.
*/
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 d4b30b1..a007d02 100644
--- a/media/c2/1.0/IComponentInterface.hal
+++ b/media/c2/1.0/IComponentInterface.hal
@@ -19,21 +19,20 @@
import IConfigurable;
/**
- * Component interface object. This object contains all of the configuration of
+ * Component interface object. This object contains all of the configurations of
* a potential or actual component. It can be created and used independently of
- * 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.
+ * 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().
*/
-interface IComponentInterface extends IConfigurable {
- /*
- * There are no additional methods to IConfigurable interface.
+interface IComponentInterface {
+ /**
+ * Returns the @ref IConfigurable instance associated to this component
+ * interface.
*
- * 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.
+ * @return configurable `IConfigurable` instance. This must not be null.
*/
+ getConfigurable() generates (IConfigurable configurable);
};
diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal
index eb71ecb..70d5fb2 100644
--- a/media/c2/1.0/IComponentListener.hal
+++ b/media/c2/1.0/IComponentListener.hal
@@ -17,54 +17,112 @@
package android.hardware.media.c2@1.0;
/**
- * This callback interface is used for handling notifications from IComponent.
+ * Callback interface for handling notifications from @ref IComponent.
*/
interface IComponentListener {
/**
- * Notify the listener that some works have been completed.
+ * 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.
*/
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 is unknown.
- * @param errorCode Additional error code. The framework may not recognize
- * this.
+ * @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.
*/
oneway onError(Status status, uint32_t errorCode);
/**
- * Information about rendering of a frame.
+ * Information about rendering of a frame to a `Surface`.
*/
struct RenderedFrame {
/**
- * Id of the buffer queue containing the rendered buffer.
+ * Id of the `BufferQueue` containing the rendered buffer.
+ *
+ * This value must have been obtained by an earlier call to
+ * IGraphicBufferProducer::getUniqueId().
*/
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 of the rendering (consistent with timestamps in
- * the associated BufferQueue).
+ * Timestamp the rendering happened.
+ *
+ * The reference point for the timestamp is determined by the
+ * `BufferQueue` that performed the rendering.
*/
int64_t timestampNs;
};
/**
- * Notify the listener that frames are rendered.
+ * Notify the listener that frames have been rendered.
*
- * @param renderedFrames List of information about renderings of frames.
+ * @param renderedFrames List of @ref RenderedFrame objects.
*/
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 4bfa170..2aa6a70 100644
--- a/media/c2/1.0/IComponentStore.hal
+++ b/media/c2/1.0/IComponentStore.hal
@@ -23,27 +23,33 @@
import IConfigurable;
import IInputSurface;
-interface IComponentStore extends IConfigurable {
+/**
+ * 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 {
/**
* Creates a component by name.
*
- * This method must return within 100ms.
- *
- * @param name Name of the component to create. This should match one of the
+ * @param name Name of the component to create. This must 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.
+ * @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 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`.
+ * - `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`.
+ *
+ * @sa IComponentListener.
*/
createComponent(
string name,
@@ -57,19 +63,15 @@
/**
* 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 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`.
+ * - `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`.
*/
createInterface(
string name
@@ -83,57 +85,49 @@
*/
struct ComponentTraits {
/**
- * Name of the component.
+ * 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().
*/
string name;
enum Domain : uint32_t {
- AUDIO,
+ OTHER = 0,
VIDEO,
- OTHER = 0xffffffff,
+ AUDIO,
+ IMAGE,
};
/**
- * Component domain. The framework may not recognize `OTHER`.
+ * Component domain.
*/
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. The framework may not recognize `OTHER`.
+ * Component kind.
*/
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;
/**
- * Media type.
+ * MIME type.
*/
string mediaType;
/**
* Aliases for component name for backward compatibility.
*
- * \note Multiple components can have the same alias (but not the same
+ * Multiple components can have the same alias (but not the same
* component name) as long as their media types differ.
*/
vec<string> aliases;
@@ -142,36 +136,51 @@
/**
* Returns the list of components supported by this component store.
*
- * This method must return within 500ms.
- *
- * @return traits List of component traits for all components supported by this store in no
- * particular order.
+ * @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).
*/
- listComponents() generates (vec<ComponentTraits> traits);
+ listComponents() generates (
+ Status status,
+ vec<ComponentTraits> traits
+ );
/**
* Creates a persistent input surface that can be used as an input surface
* for any IComponent instance
*
- * This method must return within 100ms.
- *
- * @return surface A persistent input surface
+ * @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.
*/
- createInputSurface() generates (IInputSurface surface);
+ createInputSurface() generates (
+ Status status,
+ IInputSurface surface
+ );
/**
- * Returns a list of StructDescriptor object for a set of requested
- * structures that this store is aware of.
+ * Returns a list of `StructDescriptor` objects for a set of requested
+ * C2Param structure indices 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 struct indices to return des
+ * @param indices Indices of C2Param structures to describe.
* @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.
- * @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.
+ * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `CORRUPTED` - Some unknown error occurred.
+ * @return structs List of `StructDescriptor` objects.
*/
getStructDescriptors(
vec<ParamIndex> indices
@@ -181,33 +190,35 @@
);
/**
- * 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.
+ * Copies 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.
- * - CORRUPTED - The copy cannot be done. (unexpected)
+ * - `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.
*/
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 cd4dd10..31dc4d3 100644
--- a/media/c2/1.0/IConfigurable.hal
+++ b/media/c2/1.0/IConfigurable.hal
@@ -17,43 +17,78 @@
package android.hardware.media.c2@1.0;
/**
- * Generic configuration interface used by all configurable Codec 2.0
- * components.
+ * Generic configuration interface presented by all configurable Codec2 objects.
*
- * This interface must be supported in all states of the inheriting
- * object, and must not change the state of the inheriting object.
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
*/
interface IConfigurable {
/**
- * Returns the name of this object. This must match the name that was
- * supplied during the creation of the object.
+ * Returns the id of the object. This must be unique among all objects of
+ * the same type hosted by the same store.
*
- * @return name Name of this 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.
*/
getName() generates (string name);
/**
- * 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.
+ * Queries a set of parameters from the object.
*
- * \note Parameter values do not depend on the order of query.
+ * 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.
*
- * This method must return within 1ms if \p mayBlock is DONT_BLOCK, and
- * within 5ms otherwise.
+ * If @p mayBlock is false, this method must not block. All parameter
+ * queries that require blocking must be skipped.
*
- * @param indices List of param indices for params to be queried.
+ * 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 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.
- * - CORRUPTED - Some unknown error prevented the querying of the
- * parameters. (unexpected)
- * @return params List of params queried corresponding to \p indices.
+ * - `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.
*/
query(
vec<ParamIndex> indices,
@@ -64,31 +99,60 @@
);
/**
- * 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.
+ * Sets a set of parameters for the object.
*
- * \note Parameter tuning DOES depend on the order of the tuning parameters.
- * E.g. some parameter update may allow some subsequent parameter update.
+ * 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.
*
- * This method must return within 1ms if \p mayBlock is false, and within
- * 5ms otherwise.
+ * 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.
*
* @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.
- * - 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.
+ * - `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.
*/
config(
Params inParams,
@@ -103,22 +167,19 @@
// =========================================================================
/**
- * Returns a selected range of the set of supported parameters.
+ * Returns a list of supported parameters within a selected range of C2Param
+ * structure indices.
*
- * 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
+ * @param start The first index of the selected range.
+ * @param count The length of the selected range.
* @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 Vector containing the selected range of supported
- * parameters.
+ * - `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.
*/
querySupportedParams(
uint32_t start,
@@ -131,23 +192,42 @@
/**
* Retrieves the supported values for the queried fields.
*
- * 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.
+ * The object must process all fields queried even if some queries fail.
*
- * This method must return within 1ms if \p mayBlock is false, and within
- * 5ms otherwise.
+ * 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.
*
- * @param inFields Vector of field queries.
+ * \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 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.
- * - 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.
+ * - `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.
*/
querySupportedValues(
vec<FieldSupportedValuesQuery> inFields,
diff --git a/media/c2/1.0/IInputSink.hal b/media/c2/1.0/IInputSink.hal
new file mode 100644
index 0000000..809c27a
--- /dev/null
+++ b/media/c2/1.0/IInputSink.hal
@@ -0,0 +1,55 @@
+/*
+ * 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.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+
+import IConfigurable;
+
+/**
+ * An `IInputSink` is a receiver of work items.
+ *
+ * An @ref IComponent instance can present itself as an `IInputSink` via a thin
+ * wrapper.
+ *
+ * @sa IInputSurface, IComponent.
+ */
+interface IInputSink {
+ /**
+ * Feeds work to the sink.
+ *
+ * @param workBundle `WorkBundle` object containing a list of `Work` objects
+ * 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` - Tunneling has not been set up for this sink, 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.
+ */
+ queue(WorkBundle workBundle) generates (Status status);
+
+ /**
+ * Returns the @ref IConfigurable instance associated to this sink.
+ *
+ * @return configurable `IConfigurable` instance. This must not be null.
+ */
+ getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
index c083a21..d11ce15 100644
--- a/media/c2/1.0/IInputSurface.hal
+++ b/media/c2/1.0/IInputSurface.hal
@@ -19,43 +19,57 @@
import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
import IConfigurable;
-import IComponent;
+import IInputSink;
import IInputSurfaceConnection;
/**
- * Input surface that can be configured for the IComponent.
+ * 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().
*/
-interface IInputSurface extends IGraphicBufferProducer {
+interface IInputSurface {
+ /**
+ * Returns the producer interface into the internal buffer queue.
+ *
+ * @return producer `IGraphicBufferProducer` instance. This must not be
+ * null.
+ */
+ getGraphicBufferProducer() generates (IGraphicBufferProducer producer);
/**
- * Connects this input surface to a component.
+ * Returns the @ref IConfigurable instance associated to this input surface.
*
- * 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.
+ * @return configurable `IConfigurable` instance. This must not be null.
*/
- connectToComponent(
- IComponent component
+ getConfigurable() generates (IConfigurable configurable);
+
+ /**
+ * Connects the input surface to an input sink.
+ *
+ * This function is generally called from inside the implementation of
+ * IComponent::connectToInputSurface(), where @p sink is a thin wrapper of
+ * the component that consumes buffers from this surface.
+ *
+ * @param sink Input sink. See `IInputSink` for more information.
+ * @return status Status of the call, which may be
+ * - `OK` - Configuration successful.
+ * - `BAD_VALUE` - @p sink is invalid.
+ * - `CORRUPTED` - Some unknown error occurred.
+ * @return connection `IInputSurfaceConnection` object. This must not be
+ * null if @p status is `OK`.
+ */
+ connect(
+ IInputSink sink
) 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 500091d..035b115 100644
--- a/media/c2/1.0/IInputSurfaceConnection.hal
+++ b/media/c2/1.0/IInputSurfaceConnection.hal
@@ -16,20 +16,33 @@
package android.hardware.media.c2@1.0;
-interface IInputSurfaceConnection {
+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 {
/**
- * Disconnects this input surface from the component.
- *
- * This call must return within 100 ms.
+ * Destroys the connection between an input surface and a component.
*
* @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)
+ * - `OK` - The disconnection succeeded.
+ * - `BAD_STATE` - The component is not in running state.
+ * - `NOT_FOUND` - The surface is not connected to a component.
+ * - `CORRUPTED` - Some unknown error occurred.
*/
disconnect() generates (Status status);
+ /**
+ * Returns the @ref IConfigurable instance associated to this connection.
+ *
+ * This can be used to customize the connection.
+ *
+ * @return configurable `IConfigurable` instance. This must not be null.
+ */
+ getConfigurable() generates (IConfigurable configurable);
};
diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal
index 252d781..ec422b1 100644
--- a/media/c2/1.0/types.hal
+++ b/media/c2/1.0/types.hal
@@ -18,220 +18,278 @@
import android.hardware.media.bufferpool@2.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,
};
/**
- * Codec 2.0 parameter index
+ * C2Param structure index.
+ *
+ * This is a number that is unique for each C2Param structure type.
+ *
+ * @sa Codec 2.0 standard.
*/
typedef uint32_t ParamIndex;
/**
- * Codec 2.0 parameter structure
+ * Flattened representation of C2Param objects.
*
- * The description of a Params is provided by supplying a ParamIndex to
- * IComponentStore::getStructDescriptors().
+ * 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.
*/
typedef vec<uint8_t> Params;
/**
- * Struct uniquely specifying a field in an arbitrary parameter structure.
+ * 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 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;
};
/**
- * Struct representing a location of a field in a parameter with a given index.
+ * Reference to a field in a C2Param structure.
*/
struct ParamField {
- /** Index of the parameter */
+ /** Index of the C2Param structure. */
ParamIndex index;
- /** Field identifier */
+ /** Identifier of the field inside the C2Param structure. */
FieldId fieldId;
};
/**
- * Struct describing basic properties of a parameter with a given index.
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
*/
struct ParamDescriptor {
- /** Parameter index */
+ /**
+ * Index of the C2Param structure being described.
+ */
ParamIndex index;
enum Attrib : uint32_t {
/**
- * Parameter is required to be specified.
+ * The parameter is required to be specified.
*/
REQUIRED = 1u << 0,
/**
- * Parameter retains its value.
+ * The parameter retains its value.
*/
PERSISTENT = 1u << 1,
/**
- * Parameter is strict.
+ * The parameter is strict.
*/
STRICT = 1u << 2,
/**
- * Parameter is publicly read-only.
+ * The parameter is publicly read-only.
*/
READ_ONLY = 1u << 3,
/**
- * Parameter must not be visible to clients.
+ * The parameter must not be visible to clients.
*/
HIDDEN = 1u << 4,
/**
- * Parameter must not be used by framework (other than testing).
+ * The parameter must not be used by framework (other than testing).
*/
INTERNAL = 1u << 5,
/**
- * Parameter is publicly constant (hence read-only).
+ * The parameter is publicly constant (hence read-only).
*/
CONST = 1u << 6,
};
- /** Parameter attributes */
bitfield<Attrib> attrib;
- /** Parameter name */
+ /**
+ * Name of the structure. This must be unique for each structure.
+ */
string name;
- /** index of other parameters that this parameter depends on */
+ /**
+ * Indices of other C2Param structures that this C2Param structure depends
+ * on.
+ */
vec<ParamIndex> dependencies;
};
-// Generic way to describe supported numeric values for Codec 2.0 interfaces.
+// Generic way to describe supported numeric values for Codec2 interfaces.
/**
- * An untyped value that can fit on 64 bits - the type of which is communicated
- * via a separate channel (FieldType).
+ * An untyped value that can fit in 64 bits, the type of which is communicated
+ * via a separate channel (@ref FieldSupportedValues.type).
*/
typedef uint64_t PrimitiveValue;
/*
- * Generic supported values for a field.
+ * Description of supported values for a field.
*
- * 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.
+ * This can be a continuous range or a discrete set of values.
*/
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,
- /** Numeric range that can be continuous or discrete */
+ EMPTY = 0,
+ /** Numeric range, described in a #Range structure */
RANGE,
/** List of values */
VALUES,
/** List of flags that can be OR-ed */
FLAGS,
- /** Other representations */
- OTHER = 0xffffffff,
};
/**
- * Type of the supported values. The framework may not recognize `OTHER`.
+ * Type of the supported values.
*/
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.
- */
/**
- * If #type = RANGE, #range will specify the range of possible values.
+ * When #type is #Type.RANGE, #range shall specify the range of possible
+ * values.
*
- * The intended type of members of #range will be clear in the context where
- * FieldSupportedValues is used.
+ * The intended type of members of #range shall be clear in the context
+ * where `FieldSupportedValues` is used.
*/
Range range;
/**
- * If #type is `VALUES` or `FLAGS`, #value will list supported values.
+ * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported
+ * values/flags.
*
- * The intended type of components of #value will be clear in the context
- * where FieldSupportedValues is used.
+ * The intended type of components of #value shall be clear in the context
+ * where `FieldSupportedValues` is used.
*/
vec<PrimitiveValue> values;
};
/**
- * Supported values for a specific field.
+ * Supported values for a 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 {
- /** the field or parameter */
+ /**
+ * Reference to a field or a C2Param structure.
+ */
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
@@ -241,18 +299,18 @@
};
/**
- * Field descriptor.
+ * Description of a field inside a C2Param structure.
*/
struct FieldDescriptor {
- /** Field id */
+ /** Location of the field in the C2Param structure */
FieldId fieldId;
/**
- * Possible types of a field.
+ * Possible types of the field.
*/
enum Type : uint32_t {
- NO_INIT,
+ NO_INIT = 0,
INT32,
UINT32,
CNTR32,
@@ -261,186 +319,227 @@
CNTR64,
FLOAT,
/**
- * Fixed-size string (POD)
+ * Fixed-size string (POD).
*/
STRING = 0x100,
/**
- * blobs have no sub-elements and can be thought of as byte arrays.
- * However, bytes cannot be individually addressed by clients.
+ * A blob has no sub-elements and can be thought of as an array of
+ * bytes. However, bytes cannot be individually addressed by clients.
*/
BLOB,
/**
- * Structs. Marked with this flag in addition to their coreIndex.
+ * The field is a structure that may contain other fields.
*/
- STRUCT_FLAG = 0x20000,
+ STRUCT = 0x20000,
};
/**
* Type of the field.
*/
bitfield<Type> type;
- /** 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.
+ /**
+ * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+ * otherwise, #structIndex is not used.
*/
+ ParamIndex structIndex;
- /** Name of the field */
+ /**
+ * 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.
+ */
string name;
- /** Named value type */
+
+ /**
+ * Named value type. This is used for defining an enum value for a numeric
+ * 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;
};
- /** Named values for the field */
+ /**
+ * List of enum values. This is not used when #type is not one of the
+ * numeric types.
+ */
vec<NamedValue> namedValues;
};
/**
- * Struct descriptor.
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
*/
struct StructDescriptor {
- /** Struct type */
+ /**
+ * Index of the structure.
+ */
ParamIndex type;
- /** Field descriptors for each field */
+ /**
+ * List of fields in the structure.
+ *
+ * Fields are ordered by their offsets. A field that is a structure is
+ * ordered before its members.
+ */
vec<FieldDescriptor> fields;
};
/**
- * Information describing the reason a parameter settings may fail, or
- * may be overriden.
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
*/
struct SettingResult {
- /** Failure code (of Codec 2.0 SettingResult failure type) */
+ /** Failure code */
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 in conflict with an/other setting(s). */
+ /** 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).
+ */
CONFLICT,
/**
- * Parameter is out of range due to other settings. (This failure mode
- * can only be used for strict parameters.)
+ * Parameter field is out of range due to other settings. (This failure
+ * mode can only be used for strict calculated 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 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.
+ * 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.
*/
- OTHER = 0xffffffff,
+ INFO_CONFLICT,
};
- /**
- * 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. 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)
+ * 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).
*/
ParamFieldValues field;
/**
- * Conflicting parameters or fields with
- * (optional) suggested values for any conflicting fields to avoid the conflict.
+ * 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.
*/
vec<ParamFieldValues> conflicts;
};
/**
- * 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.
+ * 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.
*/
struct WorkOrdinal {
/**
- * Timestamp in microseconds - can wrap around.
+ * Timestamp in microseconds.
*/
uint64_t timestampUs;
/**
- * Frame index - can wrap around.
+ * Frame index.
*/
uint64_t frameIndex;
/**
- * Component specific frame ordinal - can wrap around.
+ * Component specific frame ordinal.
*/
uint64_t customOrdinal;
};
/**
- * 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.
+ * 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.
*/
-struct BaseBlock {
- enum Type : int32_t {
- NATIVE,
- POOLED,
- };
+safe_union BaseBlock {
/**
- * There are two types of blocks: NATIVE and POOLED.
- */
- Type type;
-
- /**
- * A "NATIVE" block is represented by a native handle.
+ * #nativeBlock is the opaque representation of a buffer.
*/
handle nativeBlock;
-
- /*
- * A "POOLED" block is represented by `BufferStatusMessage`.
+ /**
+ * #pooledBlock is a reference to a buffer handled by a BufferPool.
*/
BufferStatusMessage pooledBlock;
};
/**
- * 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`.
+ * 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`.
*/
struct Block {
/**
- * Identity of the BaseBlock within a WorkBundle. This is an index into the
- * `baseBlocks` array of a `WorkBundle` object.
+ * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+ * #WorkBundle.baseBlocks.
*/
uint32_t index;
/**
- * Metadata associated with the block.
+ * Metadata associated with this `Block`.
*/
Params meta;
/**
- * Fence for synchronizing block access.
+ * Fence for synchronizing `Block` access.
*/
handle fence;
};
/**
- * Type of buffers processed by a component.
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
*/
struct Buffer {
/**
@@ -454,23 +553,37 @@
};
/**
- * An extension of Buffer that also contains an index.
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
*/
struct InfoBuffer {
+ /**
+ * A C2Param structure index.
+ */
ParamIndex index;
+ /**
+ * Associated @ref Buffer object.
+ */
Buffer buffer;
};
/**
- * 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.
+ * 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.
*/
struct FrameData {
enum Flags : uint32_t {
/**
- * For input frames: no output frame will be generated when processing
+ * For input frames: no output frame shall 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.
*/
@@ -482,92 +595,178 @@
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.
+ * Frame flags, as described in #Flags.
*/
bitfield<Flags> flags;
/**
- * Ordinal of the frame.
+ * @ref WorkOrdinal of the frame.
*/
WorkOrdinal ordinal;
/**
- * Frame buffers.
+ * List of frame buffers.
*/
vec<Buffer> buffers;
/**
- * Params determining a configuration update.
+ * List of configuration updates.
*/
Params configUpdate;
/**
- * Info buffers.
+ * List of info buffers.
*/
vec<InfoBuffer> infoBuffers;
};
/**
- * Struct for
+ * 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 Worklet {
/**
- * List of Params describing tunings.
+ * Component id. (Input)
+ *
+ * This is used only when tunneling is enabled.
+ *
+ * When used, this must match the return value from IConfigurable::getId().
*/
- vec<Params> tunings;
+ uint32_t componentId;
/**
- * List of failures.
+ * List of C2Param objects describing tunings to be applied before
+ * processing this `Worklet`. (Input)
+ */
+ Params tunings;
+
+ /**
+ * List of failures. (Output)
*/
vec<SettingResult> failures;
/**
- * Output frame data.
+ * Output frame data. (Output)
*/
FrameData output;
-
- /* Note: Component id is not necessary as tunneling is not supported. */
};
/**
- * This structure holds information about a single work item. It must be passed
- * by the client to the component.
+ * 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.
*/
struct Work {
/**
- * FrameData for the input. Indices of Blocks inside #input refer to
- * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+ * Additional work chain info not part of this work.
+ */
+ Params chainInfo;
+
+ /**
+ * @ref FrameData for the input.
*/
FrameData input;
+
/**
- * Worklet. Indices of Blocks inside `worklet.output` refer to
- * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+ * 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 worklet;
+ vec<Worklet> worklets;
+
/**
- * Whether the worklet was processed or not.
+ * 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`.
*/
- bool workletProcessed;
+ 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.
+ */
Status result;
};
/**
- * This structure holds a list of Work objects and a list of BaseBlocks.
+ * 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.
*/
struct WorkBundle {
/**
@@ -581,27 +780,48 @@
};
/**
- * This structure describes a query for supported values of a field. This is
- * used as input to IConfigurable::queryFieldSupportedValues().
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
*/
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,
};
-
- ParamField field;
+ /**
+ * Type of the query. See #Type for more information.
+ */
Type type;
};
/**
* This structure is used to hold the result from
- * IConfigurable::queryFieldSupportedValues().
+ * IConfigurable::querySupportedValues().
*/
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 2920cec..52d6328 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -23,6 +23,7 @@
defaults: ["VtsHalTargetTestDefaults"],
export_include_dirs: ["."],
shared_libs: [
+ "libfmq",
"libnativewindow",
],
static_libs: [
@@ -51,6 +52,7 @@
"VtsHalNeuralnetworks.cpp",
],
shared_libs: [
+ "libfmq",
"libnativewindow",
],
static_libs: [
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 65c425e..2e13854 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+#include "GeneratedTestHarness.h"
#include "Callbacks.h"
+#include "ExecutionBurstController.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -109,14 +111,24 @@
}
return result;
}
-enum class Synchronously { NO, YES };
+static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+ const sp<V1_0::IPreparedModel>&) {
+ ADD_FAILURE() << "asking for burst execution at V1_0";
+ return nullptr;
+}
+static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+ const sp<V1_2::IPreparedModel>& preparedModel) {
+ return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+}
+enum class Executor { ASYNC, SYNC, BURST };
+enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
const float kDefaultAtol = 1e-5f;
const float kDefaultRtol = 1e-5f;
template <typename T_IPreparedModel>
void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
const std::vector<MixedTypedExample>& examples,
bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
- Synchronously sync, MeasureTiming measure, bool testDynamicOutputShape) {
+ Executor executor, MeasureTiming measure, OutputType outputType) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
@@ -164,8 +176,20 @@
// Go through all outputs, initialize RequestArgument descriptors
resize_accordingly(golden, test);
- for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
+ bool sizeLargerThanOne = true;
+ for_all(golden, [&outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
+ int index, auto, auto s) {
if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+ if (index == 0) {
+ // On OutputType::INSUFFICIENT, set the output operand with index 0 with
+ // buffer size one byte less than needed.
+ if (outputType == OutputType::INSUFFICIENT) {
+ if (s > 1)
+ s -= 1;
+ else
+ sizeLargerThanOne = false;
+ }
+ }
RequestArgument arg = {
.location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
.dimensions = {},
@@ -173,6 +197,9 @@
outputs_info[index] = arg;
outputSize += s;
});
+ // If output0 does not have size larger than one byte,
+ // we can not provide an insufficient buffer
+ if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
// Compute offset for outputs 1 and so on
{
size_t offset = 0;
@@ -209,46 +236,73 @@
inputMemory->commit();
outputMemory->commit();
+ const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
+
ErrorStatus executionStatus;
hidl_vec<OutputShape> outputShapes;
Timing timing;
- if (sync == Synchronously::NO) {
- SCOPED_TRACE("asynchronous");
+ switch (executor) {
+ case Executor::ASYNC: {
+ SCOPED_TRACE("asynchronous");
- // launch execution
- sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
- Return<ErrorStatus> executionLaunchStatus = ExecutePreparedModel(
- preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
- measure, executionCallback);
- ASSERT_TRUE(executionLaunchStatus.isOk());
- EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+ // launch execution
+ sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+ ASSERT_NE(nullptr, executionCallback.get());
+ Return<ErrorStatus> executionLaunchStatus =
+ ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+ ASSERT_TRUE(executionLaunchStatus.isOk());
+ EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
- // retrieve execution status
- executionCallback->wait();
- executionStatus = executionCallback->getStatus();
- outputShapes = executionCallback->getOutputShapes();
- timing = executionCallback->getTiming();
- } else {
- SCOPED_TRACE("synchronous");
+ // retrieve execution status
+ executionCallback->wait();
+ executionStatus = executionCallback->getStatus();
+ outputShapes = executionCallback->getOutputShapes();
+ timing = executionCallback->getTiming();
- // execute
- Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
- preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
- measure, &outputShapes, &timing);
- ASSERT_TRUE(executionReturnStatus.isOk());
- executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+ break;
+ }
+ case Executor::SYNC: {
+ SCOPED_TRACE("synchronous");
+
+ // execute
+ Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+ preparedModel, request, measure, &outputShapes, &timing);
+ ASSERT_TRUE(executionReturnStatus.isOk());
+ executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+
+ break;
+ }
+ case Executor::BURST: {
+ SCOPED_TRACE("burst");
+
+ // create burst
+ const std::unique_ptr<::android::nn::ExecutionBurstController> controller =
+ CreateBurst(preparedModel);
+ ASSERT_NE(nullptr, controller.get());
+
+ // create memory keys
+ std::vector<intptr_t> keys(request.pools.size());
+ for (size_t i = 0; i < keys.size(); ++i) {
+ keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+ }
+
+ // execute burst
+ std::tie(executionStatus, outputShapes, timing) =
+ controller->compute(request, measure, keys);
+
+ break;
+ }
}
- if (testDynamicOutputShape && executionStatus != ErrorStatus::NONE) {
+ if (outputType != OutputType::FULLY_SPECIFIED &&
+ executionStatus == ErrorStatus::GENERAL_FAILURE) {
LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
"execute model that it does not support.";
std::cout << "[ ] Early termination of test because vendor service cannot "
"execute model that it does not support."
<< std::endl;
- return;
+ GTEST_SKIP();
}
- ASSERT_EQ(ErrorStatus::NONE, executionStatus);
if (measure == MeasureTiming::NO) {
EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
@@ -258,9 +312,28 @@
}
}
+ switch (outputType) {
+ case OutputType::FULLY_SPECIFIED:
+ // If the model output operands are fully specified, outputShapes must be either
+ // either empty, or have the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_TRUE(outputShapes.size() == 0 ||
+ outputShapes.size() == test.operandDimensions.size());
+ break;
+ case OutputType::UNSPECIFIED:
+ // If the model output operands are not fully specified, outputShapes must have
+ // the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+ break;
+ case OutputType::INSUFFICIENT:
+ ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+ ASSERT_FALSE(outputShapes[0].isSufficient);
+ return;
+ }
// Go through all outputs, overwrite output dimensions with returned output shapes
- if (testDynamicOutputShape) {
- ASSERT_NE(outputShapes.size(), 0);
+ if (outputShapes.size() > 0) {
for_each<uint32_t>(test.operandDimensions,
[&outputShapes](int idx, std::vector<uint32_t>& dim) {
dim = outputShapes[idx].dimensions;
@@ -286,10 +359,55 @@
template <typename T_IPreparedModel>
void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, Synchronously sync, MeasureTiming measure,
- bool testDynamicOutputShape) {
+ bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
+ OutputType outputType) {
EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
- kDefaultRtol, sync, measure, testDynamicOutputShape);
+ kDefaultRtol, executor, measure, outputType);
+}
+
+void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+ std::function<bool(int)> is_ignored,
+ const std::vector<MixedTypedExample>& examples,
+ bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
+ if (testDynamicOutputShape) {
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
+ } else {
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+ Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+ }
}
static void getPreparedModel(sp<PreparedModelCallback> callback,
@@ -338,15 +456,15 @@
std::cout << "[ ] Early termination of test because vendor service cannot "
"prepare model that it does not support."
<< std::endl;
- return;
+ GTEST_SKIP();
}
EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
ASSERT_NE(nullptr, preparedModel.get());
float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
EvaluatePreparedModel(preparedModel, is_ignored, examples,
- /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Synchronously::NO,
- MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+ /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC,
+ MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
}
void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
@@ -386,22 +504,18 @@
std::cout << "[ ] Early termination of test because vendor service cannot "
"prepare model that it does not support."
<< std::endl;
- return;
+ GTEST_SKIP();
}
EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
ASSERT_NE(nullptr, preparedModel.get());
EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Synchronously::NO,
- MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+ model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC,
+ MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
}
-// TODO: Reduce code duplication.
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
- bool testDynamicOutputShape) {
- V1_2::Model model = create_model();
-
+void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
+ sp<V1_2::IPreparedModel>* preparedModel) {
// see if service can handle model
bool fullySupportsModel = false;
Return<void> supportedCall = device->getSupportedOperations_1_2(
@@ -424,34 +538,31 @@
// retrieve prepared model
preparedModelCallback->wait();
ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
- sp<V1_2::IPreparedModel> preparedModel;
- getPreparedModel(preparedModelCallback, &preparedModel);
+ getPreparedModel(preparedModelCallback, preparedModel);
// early termination if vendor service cannot fully prepare model
if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
- ASSERT_EQ(nullptr, preparedModel.get());
+ ASSERT_EQ(nullptr, preparedModel->get());
LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
"prepare model that it does not support.";
std::cout << "[ ] Early termination of test because vendor service cannot "
"prepare model that it does not support."
<< std::endl;
- return;
+ GTEST_SKIP();
}
EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
- ASSERT_NE(nullptr, preparedModel.get());
+ ASSERT_NE(nullptr, preparedModel->get());
+}
+// TODO: Reduce code duplication.
+void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+ bool testDynamicOutputShape) {
+ V1_2::Model model = create_model();
+ sp<V1_2::IPreparedModel> preparedModel = nullptr;
+ PrepareModel(device, model, &preparedModel);
EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, Synchronously::NO,
- MeasureTiming::NO, testDynamicOutputShape);
- EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, Synchronously::YES,
- MeasureTiming::NO, testDynamicOutputShape);
- EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, Synchronously::NO,
- MeasureTiming::YES, testDynamicOutputShape);
- EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, Synchronously::YES,
- MeasureTiming::YES, testDynamicOutputShape);
+ model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
}
} // namespace generated_tests
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..c7d2399
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+#define VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::test_helper::MixedTypedExample;
+
+void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
+ sp<V1_2::IPreparedModel>* preparedModel);
+
+void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+ std::function<bool(int)> is_ignored,
+ const std::vector<MixedTypedExample>& examples,
+ bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
+
+void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+
+void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+
+void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+ bool testDynamicOutputShape = false);
+
+} // namespace generated_tests
+
+} // namespace neuralnetworks
+} // namespace hardware
+} // namespace android
+
+#endif // VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index 55e5861..d1c7de3 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,13 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_0::IDevice>&, std::function<V1_0::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-} // namespace generated_tests
-
namespace V1_0 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
index d98ea04..4db1276 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,13 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-} // namespace generated_tests
-
namespace V1_1 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
index 1df3218..e67ef8e 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,13 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-} // namespace generated_tests
-
namespace V1_1 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index 6c3b483..b9fa388 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -76,6 +76,21 @@
getType() generates (ErrorStatus status, DeviceType type);
/**
+ * Gets information about extensions supported by the driver implementation.
+ *
+ * All extension operations and operands must be fully supported for the
+ * extension to appear in the list of supported extensions.
+ *
+ * @return status Error status of the call, must be:
+ * - NONE if successful
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * @return extensions A list of supported extensions.
+ */
+ getSupportedExtensions()
+ generates (ErrorStatus status, vec<Extension> extensions);
+
+ /**
* Gets the supported operations in a model.
*
* getSupportedOperations indicates which operations of a model are fully
@@ -98,6 +113,25 @@
generates (ErrorStatus status, vec<bool> supportedOperations);
/**
+ * Gets whether the driver supports compilation caching.
+ *
+ * isCachingSupported indicates whether the driver supports compilation caching.
+ * Even if so, the driver may still choose not to cache certain compiled models.
+ *
+ * If the device reports the caching is not supported, the user may avoid calling
+ * IDevice::prepareModelFromCache and IPreparedModel::saveToCache.
+ *
+ * @return status Error status of the call, must be:
+ * - NONE if successful
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * @return supported A boolean indicating whether the driver supports compilation
+ * caching. Even on returning true, the driver may still choose
+ * not to cache certain compiled models.
+ */
+ isCachingSupported() generates (ErrorStatus status, bool supported);
+
+ /**
* Creates a prepared model for execution.
*
* prepareModel is used to make any necessary transformations or alternative
@@ -153,4 +187,84 @@
prepareModel_1_2(Model model, ExecutionPreference preference,
IPreparedModelCallback callback)
generates (ErrorStatus status);
+
+ /**
+ * Creates a prepared model from cache files for execution.
+ *
+ * prepareModelFromCache is used to retrieve a prepared model directly from
+ * cache files to avoid slow model compilation time. There are exactly two
+ * cache file descriptors provided to the driver: modelCache and dataCache.
+ *
+ * The dataCache is for caching constant data, possibly including preprocessed
+ * and transformed tensor buffers. Any modification to the dataCache should
+ * have no worse effect than generating bad output values at execution time.
+ *
+ * The modelCache is for caching security-sensitive data such as compiled
+ * executable machine code in the device's native binary format. A modification
+ * to the modelCache may affect the driver's execution behavior, and a malicious
+ * client could make use of this to execute beyond the granted permission. Thus,
+ * the driver must always check whether the modelCache is corrupted before preparing
+ * the model from cache.
+ *
+ * The two file descriptors may be closed by the client once the asynchronous
+ * preparation has finished. The driver has to copy all the data it needs.
+ *
+ * The model is prepared asynchronously with respect to the caller. The
+ * prepareModelFromCache function must verify the inputs to the
+ * prepareModelFromCache function are correct, and that the security-sensitive
+ * cache has not been modified since it was last written by the driver.
+ * If there is an error, or if compilation caching is not supported, or if the
+ * security-sensitive cache has been modified, prepareModelFromCache must
+ * immediately invoke the callback with the appropriate ErrorStatus value and
+ * nullptr for the IPreparedModel, then return with the same ErrorStatus. If
+ * the inputs to the prepareModelFromCache function are valid, the security-sensitive
+ * cache is not modified, and there is no error, prepareModelFromCache must launch an
+ * asynchronous task to prepare the model in the background, and immediately return
+ * from prepareModelFromCache with ErrorStatus::NONE. If the asynchronous task
+ * fails to launch, prepareModelFromCache must immediately invoke the callback
+ * with ErrorStatus::GENERAL_FAILURE and nullptr for the IPreparedModel, then
+ * return with ErrorStatus::GENERAL_FAILURE.
+ *
+ * When the asynchronous task has finished preparing the model, it must
+ * immediately invoke the callback function provided as an input to
+ * prepareModelFromCache. If the model was prepared successfully, the
+ * callback object must be invoked with an error status of ErrorStatus::NONE
+ * and the produced IPreparedModel object. If an error occurred preparing
+ * the model, the callback object must be invoked with the appropriate
+ * ErrorStatus value and nullptr for the IPreparedModel.
+ *
+ * The only information that may be unknown to the model at this stage is
+ * the shape of the tensors, which may only be known at execution time. As
+ * such, some driver services may return partially prepared models, where
+ * the prepared model may only be finished when it is paired with a set of
+ * inputs to the model. Note that the same prepared model object may be
+ * used with different shapes of inputs on different (possibly concurrent)
+ * executions.
+ *
+ * @param modelCache A handle holding exactly one cache file descriptor for the
+ * security-sensitive cache.
+ * @param dataCache A handle holding exactly one cache file descriptor for the
+ * constants' cache.
+ * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
+ * identifying the prepared model. It is the same token provided when saving
+ * the cache files with IPreparedModel::saveToCache. Tokens should be chosen
+ * to have a low rate of collision for a particular application. The driver
+ * cannot detect a collision; a collision will result in a failed execution
+ * or in a successful execution that produces incorrect output values.
+ * @param callback A callback object used to return the error status of
+ * preparing the model for execution and the prepared model if
+ * successful, nullptr otherwise. The callback object's notify function
+ * must be called exactly once, even if the model could not be prepared.
+ * @return status Error status of launching a task which prepares the model
+ * in the background; must be:
+ * - NONE if preparation task is successfully launched
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if caching is not supported or if there is an
+ * unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid
+ */
+ prepareModelFromCache(handle modelCache, handle dataCache,
+ uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
+ IPreparedModelCallback callback)
+ generates (ErrorStatus status);
};
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 5d2d80f..757d5f1 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -157,4 +157,62 @@
fmq_sync<FmqRequestDatum> requestChannel,
fmq_sync<FmqResultDatum> resultChannel)
generates (ErrorStatus status, IBurstContext context);
+
+ /*
+ * Saves the prepared model to cache files.
+ *
+ * saveToCache is used to save a prepared model to cache files for faster
+ * model compilation time when the same model preparation is requested in
+ * the future. There are exactly two cache file descriptors provided to the
+ * driver: modelCache and dataCache.
+ *
+ * The dataCache is for caching constant data, possibly including preprocessed
+ * and transformed tensor buffers. Any modification to the dataCache should
+ * have no worse effect than generating bad output values at execution time.
+ *
+ * The modelCache is for caching security-sensitive data such as compiled
+ * executable machine code in the device's native binary format. A modification
+ * to the modelCache may affect the driver's execution behavior, and a malicious
+ * client could make use of this to execute beyond the granted permission. Thus,
+ * the driver must always check whether the modelCache is corrupted before preparing
+ * the model from cache.
+ *
+ * The two file descriptors must point to two zero-length files with offset
+ * positioned at the beginning of the file. The file descriptors may be closed
+ * by the client once the method has returned.
+ *
+ * If the driver decides not to save the prepared model without looking at the
+ * input arguments to the saveToCache function, saveToCache must return with
+ * ErrorStatus::GENERAL_FAILURE. Otherwise, the saveToCache function must verify
+ * the input arguments to the saveToCache function are valid, and return with
+ * ErrorStatus::INVALID_ARGUMENT if not. If the inputs are valid but the driver
+ * could not save the prepared model, saveToCache must return with the appropriate
+ * ErrorStatus. Otherwise, it must write the cache files and return
+ * ErrorStatus::NONE. Unless saveToCache returns ErrorStatus::NONE, the contents
+ * of the cache files are undefined.
+ *
+ * @param modelCache A handle holding exactly one cache file descriptor for the
+ * security-sensitive cache.
+ * @param dataCache A handle holding exactly one cache file descriptor for the
+ * constants' cache.
+ * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
+ * identifying the prepared model. The same token will be provided
+ * when retrieving the prepared model from cache files with
+ * IDevice::prepareModelFromCache. Tokens should be chosen to have
+ * a low rate of collision for a particular application. The driver
+ * cannot detect a collision; a collision will result in a failed
+ * execution or in a successful execution that produces incorrect
+ * output values.
+ * @return status Error status of saveToCache, must be:
+ * - NONE if saveToCache is performed successfully
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if the driver could not save the
+ * prepared model or if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid,
+ * unless the driver decides not to save the prepared model
+ * without looking at the input arguments
+ */
+ saveToCache(handle modelCache, handle dataCache,
+ uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token)
+ generates (ErrorStatus status);
};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index bd8354f..2e48ba0 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -25,6 +25,13 @@
import android.hidl.safe_union@1.0::Monostate;
+enum Constant : uint32_t {
+ /**
+ * The byte size of the cache token.
+ */
+ BYTE_SIZE_OF_CACHE_TOKEN = 32,
+};
+
enum OperandType : @1.0::OperandType {
/**
* An 8 bit boolean scalar value.
@@ -40,7 +47,7 @@
* used to convert the 16 bit number to a real value in the following way:
* realValue = integerValue * scale.
*
- * scale is a 32 bit floating point with value greater then zero.
+ * scale is a 32 bit floating point with value greater than zero.
*/
TENSOR_QUANT16_SYMM = 7,
/** A tensor of IEEE 754 16 bit floating point values. */
@@ -66,10 +73,11 @@
* These fields are located inside Operand's extraParams union, inside the
* SymmPerChannelQuantParams struct.
*
- * An Operand of this type must use 'channelQuant' field of its extraParams
- * union.
+ * An Operand of this type must use the 'channelQuant' variant of its
+ * extraParams field.
*
- * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
+ * The channel dimension of this tensor must be known, i.e.
+ * dimensions[channelDim] must be non-zero.
*
* The formula for real values:
* realValue[..., C, ...] =
@@ -89,11 +97,21 @@
* real_value = (integer_value - zeroPoint) * scale.
*/
TENSOR_QUANT16_ASYMM = 12,
+ /**
+ * A tensor of 8 bit signed integers that represent real numbers.
+ *
+ * Attached to this tensor is a number representing real value scale that is
+ * used to convert the 8 bit number to a real value in the following way:
+ * realValue = integerValue * scale.
+ *
+ * scale is a 32 bit floating point with value greater than zero.
+ */
+ TENSOR_QUANT8_SYMM = 13,
/* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF
- * OperandTypeRange::OPERAND_FUNDAMENTAL_MAX.
+ * OperandTypeRange::FUNDAMENTAL_MAX.
*/
/* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF
- * OperandTypeRange::OPERAND_OEM_MAX.
+ * OperandTypeRange::OEM_MAX.
*/
};
@@ -101,10 +119,12 @@
* The range of operand values in the OperandType enum.
*/
enum OperandTypeRange : uint32_t {
- OPERAND_FUNDAMENTAL_MIN = 0,
- OPERAND_FUNDAMENTAL_MAX = 12,
- OPERAND_OEM_MIN = 10000,
- OPERAND_OEM_MAX = 10001,
+ BASE_MIN = 0,
+ FUNDAMENTAL_MIN = 0,
+ FUNDAMENTAL_MAX = 13,
+ OEM_MIN = 10000,
+ OEM_MAX = 10001,
+ BASE_MAX = 0xFFFF,
};
/**
@@ -171,10 +191,10 @@
UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
UNIDIRECTIONAL_SEQUENCE_RNN = 93,
/* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
- * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX.
+ * OperationTypeRange::FUNDAMENTAL_MAX.
*/
/* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF
- * OperationTypeRange::OPERATION_OEM_MAX.
+ * OperationTypeRange::OEM_MAX.
*/
};
@@ -182,10 +202,12 @@
* The range of values in the OperationType enum.
*/
enum OperationTypeRange : uint32_t {
- OPERATION_FUNDAMENTAL_MIN = 0,
- OPERATION_FUNDAMENTAL_MAX = 93,
- OPERATION_OEM_MIN = 10000,
- OPERATION_OEM_MAX = 10000,
+ BASE_MIN = 0,
+ FUNDAMENTAL_MIN = 0,
+ FUNDAMENTAL_MAX = 93,
+ OEM_MIN = 10000,
+ OEM_MAX = 10000,
+ BASE_MAX = 0xFFFF,
};
/**
@@ -214,6 +236,10 @@
struct Operation {
/**
* The operation type.
+ *
+ * Besides the values listed in {@link OperationType}, any value above
+ * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
+ * as an extension type according to {@link Model::extensionNameToPrefix}.
*/
OperationType type;
@@ -240,21 +266,16 @@
uint32_t channelDim;
};
-// TODO(slavash): Operand Extension support
-// /**
-// * Parameters for an unknown (as of 1.2) operand extension. This is
-// * a vendor-specific extension or a platform extension (backport of
-// * functionality from newer NNAPI interface).
-// */
-// struct OperandParamsUnknown {
-// };
-
/**
* Describes one operand of the model's graph.
*/
struct Operand {
/**
- * Data type of the operand.
+ * The data type.
+ *
+ * Besides the values listed in {@link OperandType}, any value above
+ * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
+ * as an extension type according to {@link Model::extensionNameToPrefix}.
*/
OperandType type;
@@ -344,25 +365,28 @@
DataLocation location;
/**
- * Union of extra parameters, used by some types of Operands that need additional
- * information for the complete definition of an Operand.
+ * Additional parameters specific to a particular operand type.
*/
safe_union ExtraParams {
/**
- * Placeholder for operand with no extra parameters.
+ * No additional parameters.
*/
Monostate none;
/**
- * Used with TENSOR_QUANT8_SYMM_PER_CHANNEL operand type.
+ * Symmetric per-channel quantization parameters.
+ *
+ * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
*/
SymmPerChannelQuantParams channelQuant;
- // TODO(slavash): Operand Extension support
- // /**
- // * Used with Extension operand type.
- // */
- // OperandParamsUnknown unknown;
+ /**
+ * Extension operand parameters.
+ *
+ * The framework treats this as an opaque data blob.
+ * The format is up to individual extensions.
+ */
+ vec<uint8_t> extension;
} extraParams;
};
@@ -425,6 +449,63 @@
* range and precision of the IEEE 754 32-bit floating-point format.
*/
bool relaxComputationFloat32toFloat16;
+
+ /**
+ * The mapping between extension names and prefixes of operand and
+ * operation type values.
+ *
+ * An operand or operation whose numeric type value is above
+ * {@link OperandTypeRange::BASE_MAX} or
+ * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
+ * as an extension operand. The low
+ * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
+ * correspond to the value within the extension and the high
+ * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+ * the "prefix", which maps uniquely to the extension name.
+ *
+ * For example, if a model contains an operation whose value is
+ * 0xAAAABBBB and extensionNameToPrefix contains an entry with
+ * prefix=0xAAAA and name="vendor.test.test_extension", then
+ * the operation should be interpreted as the operation 0xBBBB
+ * of the extension named vendor.test.test_extension.
+ *
+ * This is a one-to-one correspondence. That is, there must be at most one
+ * prefix corresponding to each extension name and at most one extension
+ * name corresponding to each prefix.
+ */
+ vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+
+ /**
+ * A correspondence between an extension name and a prefix of operand and
+ * operation type values.
+ */
+ struct ExtensionNameAndPrefix {
+ /**
+ * The extension name.
+ *
+ * See {@link Extension::name}.
+ */
+ string name;
+
+ /**
+ * The unique extension identifier within the model.
+ *
+ * See {@link Model::extensionNameToPrefix}.
+ */
+ uint16_t prefix;
+ };
+
+ /**
+ * Numeric values of extension operand and operation types have the
+ * following structure:
+ * - 16 high bits represent the "prefix", which corresponds uniquely to the
+ * extension name.
+ * - 16 low bits represent the type ID within the extension.
+ */
+ enum ExtensionTypeEncoding : uint8_t {
+ HIGH_BITS_PREFIX = 16,
+ LOW_BITS_TYPE = 16,
+ };
};
/**
@@ -678,3 +759,43 @@
*/
Timing executionTiming;
};
+
+/**
+ * Information about an extension.
+ */
+struct Extension {
+ /**
+ * The extension name.
+ *
+ * The name must start with the reverse domain name of the vendor.
+ * Example: com.google.test_extension
+ */
+ string name;
+
+ /**
+ * Information about an extension operand type.
+ */
+ struct OperandTypeInformation {
+ /**
+ * The extension operand type.
+ */
+ uint16_t type;
+
+ /**
+ * Indicates whether the extension operand type represents a tensor or
+ * a scalar.
+ */
+ bool isTensor;
+
+ /**
+ * The byte size of the operand (if scalar) or of a single element (if
+ * tensor).
+ */
+ uint32_t byteSize;
+ };
+
+ /**
+ * Information about operand types defined by the extension.
+ */
+ vec<OperandTypeInformation> operandTypes;
+};
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 0cb9e16..510a0d5 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -46,6 +46,7 @@
defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
srcs: [
"BasicTests.cpp",
+ "CompilationCachingTests.cpp",
"GeneratedTests.cpp",
],
cflags: [
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 8c3ad15..2b88edd 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -55,6 +55,29 @@
});
EXPECT_TRUE(ret.isOk());
}
+
+// device supported extensions test
+TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
+ Return<void> ret = device->getSupportedExtensions(
+ [](ErrorStatus status, const hidl_vec<Extension>& extensions) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ for (auto& extension : extensions) {
+ std::string extensionName = extension.name;
+ EXPECT_FALSE(extensionName.empty());
+ EXPECT_NE(extensionName.find("."), std::string::npos)
+ << "Extension name must start with the reverse domain name of the "
+ "vendor";
+ }
+ });
+ EXPECT_TRUE(ret.isOk());
+}
+
+// isCachingSupported test
+TEST_F(NeuralnetworksHidlTest, IsCachingSupported) {
+ Return<void> ret = device->isCachingSupported(
+ [](ErrorStatus status, bool) { EXPECT_EQ(ErrorStatus::NONE, status); });
+ EXPECT_TRUE(ret.isOk());
+}
} // namespace functional
} // namespace vts
} // namespace V1_2
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
new file mode 100644
index 0000000..454aa1f
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <cstdio>
+#include <cstdlib>
+#include <random>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
+using ::test_helper::MixedTypedExample;
+
+namespace {
+
+// In frameworks/ml/nn/runtime/tests/generated/, creates a hidl model of mobilenet.
+#include "examples/mobilenet_224_gender_basic_fixed.example.cpp"
+#include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp"
+
+// Prevent the compiler from complaining about an otherwise unused function.
+[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
+[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
+
+enum class AccessMode { READ_ONLY, WRITE_ONLY };
+
+void createCacheHandle(const std::vector<std::string>& files, AccessMode mode,
+ hidl_handle* handle) {
+ std::vector<int> fds;
+ for (const auto& file : files) {
+ int fd;
+ if (mode == AccessMode::READ_ONLY) {
+ fd = open(file.c_str(), O_RDONLY);
+ } else if (mode == AccessMode::WRITE_ONLY) {
+ fd = open(file.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ } else {
+ FAIL();
+ }
+ ASSERT_GE(fd, 0);
+ fds.push_back(fd);
+ }
+ native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0);
+ ASSERT_NE(cacheNativeHandle, nullptr);
+ for (uint32_t i = 0; i < fds.size(); i++) {
+ cacheNativeHandle->data[i] = fds[i];
+ }
+ handle->setTo(cacheNativeHandle, /*shouldOwn=*/true);
+}
+
+} // namespace
+
+// Tag for the compilation caching tests.
+class CompilationCachingTest : public NeuralnetworksHidlTest {
+ protected:
+ void SetUp() override {
+ NeuralnetworksHidlTest::SetUp();
+
+ // Create cache directory.
+ char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
+ char* cacheDir = mkdtemp(cacheDirTemp);
+ ASSERT_NE(cacheDir, nullptr);
+ mCache1 = cacheDir + mCache1;
+ mCache2 = cacheDir + mCache2;
+ mCache3 = cacheDir + mCache3;
+
+ // Check if caching is supported.
+ bool isCachingSupported;
+ Return<void> ret = device->isCachingSupported(
+ [&isCachingSupported](ErrorStatus status, bool supported) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ isCachingSupported = supported;
+ });
+ EXPECT_TRUE(ret.isOk());
+ if (isCachingSupported) {
+ mIsCachingSupported = true;
+ } else {
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service does not "
+ "support compilation caching.";
+ std::cout << "[ ] Early termination of test because vendor service does not "
+ "support compilation caching."
+ << std::endl;
+ mIsCachingSupported = false;
+ }
+
+ // Create empty cache files.
+ hidl_handle handle;
+ createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle);
+ }
+
+ void saveModelToCache(sp<IPreparedModel> preparedModel, const hidl_handle& cache1,
+ const hidl_handle& cache2, ErrorStatus* status) {
+ // Save IPreparedModel to cache.
+ hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
+ Return<ErrorStatus> saveToCacheStatus =
+ preparedModel->saveToCache(cache1, cache2, cacheToken);
+ ASSERT_TRUE(saveToCacheStatus.isOk());
+ *status = static_cast<ErrorStatus>(saveToCacheStatus);
+ }
+
+ bool checkEarlyTermination(ErrorStatus status) {
+ if (status == ErrorStatus::GENERAL_FAILURE) {
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "save the prepared model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "save the prepared model that it does not support."
+ << std::endl;
+ return true;
+ }
+ return false;
+ }
+
+ void prepareModelFromCache(const hidl_handle& cache1, const hidl_handle& cache2,
+ sp<IPreparedModel>* preparedModel, ErrorStatus* status) {
+ // Launch prepare model from cache.
+ sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+ ASSERT_NE(nullptr, preparedModelCallback.get());
+ hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
+ Return<ErrorStatus> prepareLaunchStatus =
+ device->prepareModelFromCache(cache1, cache2, cacheToken, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk());
+ if (static_cast<ErrorStatus>(prepareLaunchStatus) != ErrorStatus::NONE) {
+ *preparedModel = nullptr;
+ *status = static_cast<ErrorStatus>(prepareLaunchStatus);
+ return;
+ }
+
+ // Retrieve prepared model.
+ preparedModelCallback->wait();
+ *status = preparedModelCallback->getStatus();
+ *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+ .withDefault(nullptr);
+ }
+
+ std::string mCache1 = "/cache1";
+ std::string mCache2 = "/cache2";
+ std::string mCache3 = "/cache3";
+ uint8_t mToken[static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {};
+ bool mIsCachingSupported;
+};
+
+TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (!mIsCachingSupported) {
+ EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ } else {
+ if (checkEarlyTermination(status)) return;
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+ }
+
+ // Retrieve preparedModel from cache.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ if (!mIsCachingSupported) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ return;
+ } else {
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ ASSERT_NE(preparedModel, nullptr);
+ }
+ }
+
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+}
+
+TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (!mIsCachingSupported) {
+ EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ } else {
+ if (checkEarlyTermination(status)) return;
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+ }
+
+ // Retrieve preparedModel from cache.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ uint8_t dummyByte = 0;
+ // Advance offset by one byte.
+ ASSERT_GE(read(cache1.getNativeHandle()->data[0], &dummyByte, 1), 0);
+ ASSERT_GE(read(cache2.getNativeHandle()->data[0], &dummyByte, 1), 0);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ if (!mIsCachingSupported) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ return;
+ } else {
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ ASSERT_NE(preparedModel, nullptr);
+ }
+ }
+
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // cache1 with invalid NumFd.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1, mCache3}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ }
+
+ // cache2 with invalid NumFd.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2, mCache3}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ }
+}
+
+TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+ }
+
+ // cache1 with invalid NumFd.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1, mCache3}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+ }
+
+ // cache2 with invalid NumFd.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2, mCache3}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+ }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // cache1 with invalid access mode.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+
+ // cache2 with invalid access mode.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+}
+
+TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+ }
+
+ // cache1 with invalid access mode.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // cache2 with invalid access mode.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidOffset) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // cache1 with invalid file descriptor offset.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ uint8_t dummyByte = 0;
+ // Advance offset by one byte.
+ ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+
+ // cache2 with invalid file descriptor offset.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ uint8_t dummyByte = 0;
+ // Advance offset by one byte.
+ ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidFileSize) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // cache1 with invalid file size.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ uint8_t dummyByte = 0;
+ // Write one byte and seek back to the beginning.
+ ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
+ ASSERT_EQ(lseek(cache1.getNativeHandle()->data[0], 0, SEEK_SET), 0);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+
+ // cache2 with invalid file size.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ uint8_t dummyByte = 0;
+ // Write one byte and seek back to the beginning.
+ ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
+ ASSERT_EQ(lseek(cache2.getNativeHandle()->data[0], 0, SEEK_SET), 0);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+}
+
+class CompilationCachingSecurityTest : public CompilationCachingTest,
+ public ::testing::WithParamInterface<uint32_t> {
+ protected:
+ void SetUp() {
+ CompilationCachingTest::SetUp();
+ generator.seed(kSeed);
+ }
+
+ // Get a random integer within a closed range [lower, upper].
+ template <typename T>
+ T getRandomInt(T lower, T upper) {
+ std::uniform_int_distribution<T> dis(lower, upper);
+ return dis(generator);
+ }
+
+ const uint32_t kSeed = GetParam();
+ std::mt19937 generator;
+};
+
+TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) {
+ if (!mIsCachingSupported) return;
+
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (checkEarlyTermination(status)) return;
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+
+ // Randomly flip one single bit of the cache entry.
+ FILE* pFile = fopen(mCache1.c_str(), "r+");
+ ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0);
+ long int fileSize = ftell(pFile);
+ ASSERT_GT(fileSize, 0);
+ ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0);
+ int readByte = fgetc(pFile);
+ ASSERT_NE(readByte, EOF);
+ ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0);
+ ASSERT_NE(fputc(static_cast<uint8_t>(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF);
+ fclose(pFile);
+
+ // Retrieve preparedModel from cache, expect failure.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
+TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) {
+ if (!mIsCachingSupported) return;
+
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (checkEarlyTermination(status)) return;
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+
+ // Randomly append bytes to the cache entry.
+ FILE* pFile = fopen(mCache1.c_str(), "a");
+ uint32_t appendLength = getRandomInt(1, 256);
+ for (uint32_t i = 0; i < appendLength; i++) {
+ ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+ }
+ fclose(pFile);
+
+ // Retrieve preparedModel from cache, expect failure.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
+TEST_P(CompilationCachingSecurityTest, WrongToken) {
+ if (!mIsCachingSupported) return;
+
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+ sp<IPreparedModel> preparedModel = nullptr;
+ generated_tests::PrepareModel(device, testModel, &preparedModel);
+ // Terminate early if the driver cannot prepare the model.
+ if (preparedModel == nullptr) return;
+
+ // Save the compilation to cache.
+ {
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+ saveModelToCache(preparedModel, cache1, cache2, &status);
+ if (checkEarlyTermination(status)) return;
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ }
+
+ // Randomly flip one single bit in mToken.
+ uint32_t ind = getRandomInt(0u, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN) - 1);
+ mToken[ind] ^= (1U << getRandomInt(0, 7));
+
+ // Retrieve the preparedModel from cache, expect failure.
+ {
+ preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_handle cache1, cache2;
+ createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+ createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
+ ::testing::Range(0U, 10U));
+
+} // namespace functional
+} // namespace vts
+} // namespace V1_2
+} // namespace neuralnetworks
+} // namespace hardware
+} // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
index 4bc891f..2c3287a 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,14 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&,
- bool testDynamicOutputShape = false);
-} // namespace generated_tests
-
namespace V1_2 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
index 956926a..990cab9 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,14 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&,
- bool testDynamicOutputShape = false);
-} // namespace generated_tests
-
namespace V1_2 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
index 425690f..fa6d54d 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -29,14 +30,6 @@
namespace android {
namespace hardware {
namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExample>&,
- bool testDynamicOutputShape = false);
-} // namespace generated_tests
-
namespace V1_2 {
namespace vts {
namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index f3e528e..a0f11eb 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -128,10 +128,10 @@
///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
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_cast<uint32_t>(OperandTypeRange::FUNDAMENTAL_MIN) - 1,
+ static_cast<uint32_t>(OperandTypeRange::FUNDAMENTAL_MAX) + 1,
+ static_cast<uint32_t>(OperandTypeRange::OEM_MIN) - 1,
+ static_cast<uint32_t>(OperandTypeRange::OEM_MAX) + 1,
};
static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
@@ -161,6 +161,7 @@
case OperandType::TENSOR_FLOAT32:
case OperandType::TENSOR_INT32:
case OperandType::TENSOR_QUANT8_ASYMM:
+ case OperandType::TENSOR_QUANT8_SYMM:
case OperandType::TENSOR_QUANT16_ASYMM:
case OperandType::TENSOR_QUANT16_SYMM:
case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
@@ -199,6 +200,7 @@
return 1.0f;
case OperandType::TENSOR_INT32:
return -1.0f;
+ case OperandType::TENSOR_QUANT8_SYMM:
case OperandType::TENSOR_QUANT8_ASYMM:
case OperandType::TENSOR_QUANT16_ASYMM:
case OperandType::TENSOR_QUANT16_SYMM:
@@ -235,6 +237,8 @@
return {1};
case OperandType::TENSOR_QUANT8_ASYMM:
return {-1, 256};
+ case OperandType::TENSOR_QUANT8_SYMM:
+ return {-129, -1, 1, 128};
case OperandType::TENSOR_QUANT16_ASYMM:
return {-1, 65536};
case OperandType::TENSOR_QUANT16_SYMM:
@@ -292,6 +296,7 @@
newOperand.zeroPoint = 0;
break;
case OperandType::TENSOR_QUANT8_ASYMM:
+ case OperandType::TENSOR_QUANT8_SYMM:
case OperandType::TENSOR_QUANT16_ASYMM:
case OperandType::TENSOR_QUANT16_SYMM:
newOperand.dimensions =
@@ -392,10 +397,10 @@
///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
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_cast<uint32_t>(OperationTypeRange::FUNDAMENTAL_MIN) - 1,
+ static_cast<uint32_t>(OperationTypeRange::FUNDAMENTAL_MAX) + 1,
+ static_cast<uint32_t>(OperationTypeRange::OEM_MIN) - 1,
+ static_cast<uint32_t>(OperationTypeRange::OEM_MAX) + 1,
};
static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index 00a7c3e..d411da4 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -19,6 +19,7 @@
#include "VtsHalNeuralnetworks.h"
#include "Callbacks.h"
+#include "ExecutionBurstController.h"
#include "TestHarness.h"
#include "Utils.h"
@@ -112,6 +113,7 @@
};
MeasureTiming measure = (hash & 1) ? MeasureTiming::YES : MeasureTiming::NO;
+ // asynchronous
{
SCOPED_TRACE(message + " [execute_1_2]");
@@ -131,6 +133,7 @@
ASSERT_TRUE(badTiming(timing));
}
+ // synchronous
{
SCOPED_TRACE(message + " [executeSynchronously]");
@@ -144,6 +147,43 @@
});
ASSERT_TRUE(executeStatus.isOk());
}
+
+ // burst
+ {
+ SCOPED_TRACE(message + " [burst]");
+
+ // create burst
+ std::unique_ptr<::android::nn::ExecutionBurstController> burst =
+ ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+ ASSERT_NE(nullptr, burst.get());
+
+ // create memory keys
+ std::vector<intptr_t> keys(request.pools.size());
+ for (size_t i = 0; i < keys.size(); ++i) {
+ keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+ }
+
+ // execute and verify
+ ErrorStatus error;
+ std::vector<OutputShape> outputShapes;
+ Timing timing;
+ std::tie(error, outputShapes, timing) = burst->compute(request, measure, keys);
+ EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+ EXPECT_EQ(outputShapes.size(), 0);
+ EXPECT_TRUE(badTiming(timing));
+
+ // additional burst testing
+ if (request.pools.size() > 0) {
+ // valid free
+ burst->freeMemory(keys.front());
+
+ // negative test: invalid free of unknown (blank) memory
+ burst->freeMemory(intptr_t{});
+
+ // negative test: double free of memory
+ burst->freeMemory(keys.front());
+ }
+ }
}
// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
index b57466d..7a09639 100644
--- a/power/stats/1.0/default/Android.bp
+++ b/power/stats/1.0/default/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
cc_binary {
- name: "android.hardware.power.stats@1.0-service",
+ name: "android.hardware.power.stats@1.0-service.mock",
relative_install_path: "hw",
init_rc: ["android.hardware.power.stats@1.0-service.rc"],
srcs: ["service.cpp", "PowerStats.cpp"],
@@ -31,4 +31,5 @@
"android.hardware.power.stats@1.0",
],
vendor: true,
+ vintf_fragments: ["android.hardware.power.stats@1.0-service-mock.xml"],
}
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
index 350aa62..78766f2 100644
--- a/power/stats/1.0/default/PowerStats.cpp
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "android.hardware.power.stats@1.0-service-mock"
+
#include "PowerStats.h"
#include <android-base/file.h>
#include <android-base/logging.h>
diff --git a/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml b/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml
new file mode 100644
index 0000000..dc52f66
--- /dev/null
+++ b/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.power.stats</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IPowerStats</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
\ No newline at end of file
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
index d7e546b..9377fc2 100644
--- 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
@@ -1,4 +1,5 @@
-service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service
+service vendor.power.stats-hal-1-0-mock /vendor/bin/hw/android.hardware.power.stats@1.0-service.mock
+ interface android.hardware.power.stats@1.0::IPowerStats default
class hal
user system
group system
diff --git a/power/stats/1.0/default/service.cpp b/power/stats/1.0/default/service.cpp
index a516536..8eb53e8 100644
--- a/power/stats/1.0/default/service.cpp
+++ b/power/stats/1.0/default/service.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.power.stats@1.0-service"
+#define LOG_TAG "android.hardware.power.stats@1.0-service-mock"
#include <android/log.h>
#include <hidl/HidlTransportSupport.h>
@@ -82,7 +82,7 @@
};
int main(int /* argc */, char** /* argv */) {
- ALOGI("power.stats service 1.0 is starting.");
+ ALOGI("power.stats service 1.0 mock is starting.");
PowerStats* service = new PowerStats();
if (service == nullptr) {
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index 17718e0..8393cf5 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -1230,85 +1230,108 @@
struct GsmSignalStrength {
uint32_t signalStrength; // Valid values are (0-61, 99) as defined in
- // TS 27.007 8.69
- uint32_t bitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ // TS 27.007 8.69; INT_MAX means invalid/unreported.
+ uint32_t bitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5;
+ // INT_MAX means invalid/unreported.
int32_t timingAdvance; // Timing Advance in bit periods. 1 bit period = 48/13 us.
- // INT_MAX denotes invalid value
+ // INT_MAX means invalid/unreported.
};
struct WcdmaSignalStrength{
int32_t signalStrength; // Valid values are (0-31, 99) as defined in
- // TS 27.007 8.5
- int32_t bitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ // TS 27.007 8.5; INT_MAX means unreported.
+ int32_t bitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5;
+ // INT_MAX means invalid/unreported.
};
struct CdmaSignalStrength {
uint32_t dbm; // This value is the actual RSSI
// value multiplied by -1. Example: If the
// actual RSSI is -75, then this response value will
- // be 75.
+ // be 75. INT_MAX means invalid/unreported.
uint32_t ecio; // This value is the actual
// Ec/Io multiplied by -10. Example: If the
// actual Ec/Io is -12.5 dB, then this response value
- // will be 125.
+ // will be 125. INT_MAX means invalid/unreported.
};
struct EvdoSignalStrength {
uint32_t dbm; // This value is the actual
// RSSI value multiplied by -1.
// Example: If the actual RSSI is -75,
- // then this response value will be 75.
+ // then this response value will be 75; INT_MAX means
+ // invalid/unreported.
uint32_t ecio; // This value is the actual
// Ec/Io multiplied by -10. Example: If the
// actual Ec/Io is -12.5 dB, then this response value
- // will be 125.
+ // will be 125; INT_MAX means invalid/unreported.
uint32_t signalNoiseRatio; // Valid values are 0-8. 8 is the highest signal to
- // noise ratio.
+ // noise ratio; INT_MAX means invalid/unreported.
};
struct LteSignalStrength {
uint32_t signalStrength; // Valid values are (0-31, 99) as defined in
- // TS 27.007 8.5
+ // TS 27.007 8.5; INT_MAX means invalid/unreported.
uint32_t rsrp; // The current Reference Signal Receive Power in dBm
// multipled by -1.
- // Range: 44 to 140 dBm
- // INT_MAX: 0x7FFFFFFF denotes invalid value.
+ // Range: 44 to 140 dBm;
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP TS 36.133 9.1.4
uint32_t rsrq; // The current Reference Signal Receive Quality in dB
// multiplied by -1.
- // Range: 20 to 3 dB.
- // INT_MAX: 0x7FFFFFFF denotes invalid value.
+ // Range: 20 to 3 dB;
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP TS 36.133 9.1.7
int32_t rssnr; // The current reference signal signal-to-noise ratio in
// 0.1 dB units.
// Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
- // INT_MAX : 0x7FFFFFFF denotes invalid value.
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP TS 36.101 8.1.1
uint32_t cqi; // The current Channel Quality Indicator.
// Range: 0 to 15.
- // INT_MAX : 0x7FFFFFFF denotes invalid value.
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP TS 36.101 9.2, 9.3, A.4
uint32_t timingAdvance; // timing advance in micro seconds for a one way trip
// from cell to device.
// Approximate distance is calculated using
// 300m/us * timingAdvance.
// Range: 0 to 1282 inclusive.
- // INT_MAX : 0x7FFFFFFF denotes unknown value.
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP 36.213 section 4.2.3
};
struct TdScdmaSignalStrength {
uint32_t rscp; // The Received Signal Code Power in dBm multiplied by -1.
// Range : 25 to 120
- // INT_MAX: 0x7FFFFFFF denotes invalid value.
+ // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
// Reference: 3GPP TS 25.123, section 9.1.1.1
};
struct SignalStrength {
+ /**
+ * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
GsmSignalStrength gw;
+ /**
+ * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
CdmaSignalStrength cdma;
+ /**
+ * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
EvdoSignalStrength evdo;
+ /**
+ * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
LteSignalStrength lte;
+ /**
+ * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+ * otherwise all fields should be set to INT_MAX to mark them as invalid.
+ */
TdScdmaSignalStrength tdScdma;
};
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 4715fac..2dceeb1 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -427,11 +427,13 @@
/**
* CPICH RSCP as defined in TS 25.215 5.1.1
* Valid values are (0-96, 255) as defined in TS 27.007 8.69
+ * INT_MAX denotes that the value is invalid/unreported.
*/
uint32_t rscp;
/**
* Ec/No value as defined in TS 25.215 5.1.5
* Valid values are (0-49, 255) as defined in TS 27.007 8.69
+ * INT_MAX denotes that the value is invalid/unreported.
*/
uint32_t ecno;
@@ -441,26 +443,53 @@
/**
* UTRA carrier RSSI as defined in TS 25.225 5.1.4
* Valid values are (0-31, 99) as defined in TS 27.007 8.5
+ * INT_MAX denotes that the value is invalid/unreported.
*/
uint32_t signalStrength;
/**
* Transport Channel BER as defined in TS 25.225 5.2.5
* Valid values are (0-7, 99) as defined in TS 27.007 8.5
+ * INT_MAX denotes that the value is invalid/unreported.
*/
uint32_t bitErrorRate;
/**
* P-CCPCH RSCP as defined in TS 25.225 5.1.1
* Valid values are (0-96, 255) as defined in TS 27.007 8.69
+ * INT_MAX denotes that the value is invalid/unreported.
*/
uint32_t rscp;
};
struct SignalStrength {
+ /**
+ * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
GsmSignalStrength gsm;
+ /**
+ * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
CdmaSignalStrength cdma;
+ /**
+ * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
EvdoSignalStrength evdo;
+ /**
+ * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
LteSignalStrength lte;
+ /**
+ * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+ * otherwise all fields should be set to INT_MAX to mark them as invalid.
+ */
TdScdmaSignalStrength tdScdma;
+ /**
+ * If WCDMA measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
WcdmaSignalStrength wcdma;
};
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
new file mode 100644
index 0000000..fd69f36
--- /dev/null
+++ b/radio/1.4/vts/OWNERS
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+shuoq@google.com
+sasindran@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
new file mode 100644
index 0000000..2d0e089
--- /dev/null
+++ b/radio/1.4/vts/functional/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalRadioV1_4TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "radio_hidl_hal_api.cpp",
+ "radio_hidl_hal_test.cpp",
+ "radio_response.cpp",
+ "radio_indication.cpp",
+ "VtsHalRadioV1_4TargetTest.cpp",
+ ],
+ static_libs: [
+ "RadioVtsTestUtilBase",
+ "android.hardware.radio@1.4",
+ "android.hardware.radio@1.3",
+ "android.hardware.radio@1.2",
+ "android.hardware.radio@1.1",
+ "android.hardware.radio@1.0",
+ ],
+ header_libs: ["radio.util.header@1.0"],
+ test_suites: ["general-tests"]
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
new file mode 100644
index 0000000..d6330e6
--- /dev/null
+++ b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_4.h>
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ RadioHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
new file mode 100644
index 0000000..6b1f85e
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -0,0 +1,19 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_4.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
new file mode 100644
index 0000000..4d80696
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_4.h>
+
+void RadioHidlTest_v1_4::SetUp() {
+ radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
+ ::android::hardware::radio::V1_4::IRadio>(
+ RadioHidlEnvironment::Instance()
+ ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
+ hidl_string(RADIO_SERVICE_NAME)));
+ if (radio_v1_4 == NULL) {
+ sleep(60);
+ radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
+ ::android::hardware::radio::V1_4::IRadio>(
+ RadioHidlEnvironment::Instance()
+ ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
+ hidl_string(RADIO_SERVICE_NAME)));
+ }
+ ASSERT_NE(nullptr, radio_v1_4.get());
+
+ radioRsp_v1_4 = new (std::nothrow) RadioResponse_v1_4(*this);
+ ASSERT_NE(nullptr, radioRsp_v1_4.get());
+
+ count_ = 0;
+
+ radioInd_v1_4 = new (std::nothrow) RadioIndication_v1_4(*this);
+ ASSERT_NE(nullptr, radioInd_v1_4.get());
+
+ radio_v1_4->setResponseFunctions(radioRsp_v1_4, radioInd_v1_4);
+
+ updateSimCardStatus();
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+ /* Enforce Vts Testing with Sim Status Present only. */
+ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioHidlTest_v1_4::notify(int receivedSerial) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ if (serial == receivedSerial) {
+ count_++;
+ cv_.notify_one();
+ }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioHidlTest_v1_4::wait() {
+ std::unique_lock<std::mutex> lock(mtx_);
+
+ std::cv_status status = std::cv_status::no_timeout;
+ auto now = std::chrono::system_clock::now();
+ while (count_ == 0) {
+ status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) {
+ return status;
+ }
+ }
+ count_--;
+ return status;
+}
+
+void RadioHidlTest_v1_4::updateSimCardStatus() {
+ serial = GetRandomSerialNumber();
+ radio_v1_4->getIccCardStatus(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
new file mode 100644
index 0000000..f290d5d
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -0,0 +1,733 @@
+/*
+ * 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 <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/1.4/IRadio.h>
+#include <android/hardware/radio/1.4/IRadioIndication.h>
+#include <android/hardware/radio/1.4/IRadioResponse.h>
+#include <android/hardware/radio/1.4/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::V1_4;
+using namespace ::android::hardware::radio::V1_3;
+using namespace ::android::hardware::radio::V1_2;
+using namespace ::android::hardware::radio::V1_1;
+using namespace ::android::hardware::radio::V1_0;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioHidlTest_v1_4;
+extern ::android::hardware::radio::V1_4::CardStatus cardStatus;
+
+/* Callback class for radio respons v1_4 */
+class RadioResponse_v1_4 : public ::android::hardware::radio::V1_4::IRadioResponse {
+ protected:
+ RadioHidlTest_v1_4& parent_v1_4;
+
+ public:
+ hidl_vec<RadioBandMode> radioBandModes;
+
+ RadioResponseInfo rspInfo;
+
+ // Modem
+ bool isModemEnabled;
+ bool enableModemResponseToggle;
+
+ // Data
+ ::android::hardware::radio::V1_4::DataRegStateResult dataRegResp;
+
+ RadioResponse_v1_4(RadioHidlTest_v1_4& parent_v1_4);
+ virtual ~RadioResponse_v1_4() = default;
+
+ Return<void> getIccCardStatusResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::CardStatus& cardStatus);
+
+ Return<void> supplyIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPukForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> changeIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyNetworkDepersonalizationResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> getCurrentCallsResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& calls);
+
+ Return<void> dialResponse(const RadioResponseInfo& info);
+
+ Return<void> getIMSIForAppResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& imsi);
+
+ Return<void> hangupConnectionResponse(const RadioResponseInfo& info);
+
+ Return<void> hangupWaitingOrBackgroundResponse(const RadioResponseInfo& info);
+
+ Return<void> hangupForegroundResumeBackgroundResponse(const RadioResponseInfo& info);
+
+ Return<void> switchWaitingOrHoldingAndActiveResponse(const RadioResponseInfo& info);
+
+ Return<void> conferenceResponse(const RadioResponseInfo& info);
+
+ Return<void> rejectCallResponse(const RadioResponseInfo& info);
+
+ Return<void> getLastCallFailCauseResponse(const RadioResponseInfo& info,
+ const LastCallFailCauseInfo& failCauseInfo);
+
+ Return<void> getSignalStrengthResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::SignalStrength& sigStrength);
+
+ Return<void> getVoiceRegistrationStateResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::VoiceRegStateResult& voiceRegResponse);
+
+ Return<void> getDataRegistrationStateResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::DataRegStateResult& dataRegResponse);
+
+ Return<void> getOperatorResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& longName,
+ const ::android::hardware::hidl_string& shortName,
+ const ::android::hardware::hidl_string& numeric);
+
+ Return<void> setRadioPowerResponse(const RadioResponseInfo& info);
+
+ Return<void> sendDtmfResponse(const RadioResponseInfo& info);
+
+ Return<void> sendSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+ Return<void> sendSMSExpectMoreResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+ Return<void> setupDataCallResponse(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::SetupDataCallResult& dcResponse);
+
+ Return<void> iccIOForAppResponse(const RadioResponseInfo& info, const IccIoResult& iccIo);
+
+ Return<void> sendUssdResponse(const RadioResponseInfo& info);
+
+ Return<void> cancelPendingUssdResponse(const RadioResponseInfo& info);
+
+ Return<void> getClirResponse(const RadioResponseInfo& info, int32_t n, int32_t m);
+
+ Return<void> setClirResponse(const RadioResponseInfo& info);
+
+ Return<void> getCallForwardStatusResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<CallForwardInfo>& call_forwardInfos);
+
+ Return<void> setCallForwardResponse(const RadioResponseInfo& info);
+
+ Return<void> getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+ int32_t serviceClass);
+
+ Return<void> setCallWaitingResponse(const RadioResponseInfo& info);
+
+ Return<void> acknowledgeLastIncomingGsmSmsResponse(const RadioResponseInfo& info);
+
+ Return<void> acceptCallResponse(const RadioResponseInfo& info);
+
+ Return<void> deactivateDataCallResponse(const RadioResponseInfo& info);
+
+ Return<void> getFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t response);
+
+ Return<void> setFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t retry);
+
+ Return<void> setBarringPasswordResponse(const RadioResponseInfo& info);
+
+ Return<void> getNetworkSelectionModeResponse(const RadioResponseInfo& info, bool manual);
+
+ Return<void> setNetworkSelectionModeAutomaticResponse(const RadioResponseInfo& info);
+
+ Return<void> setNetworkSelectionModeManualResponse(const RadioResponseInfo& info);
+
+ Return<void> getAvailableNetworksResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<OperatorInfo>& networkInfos);
+
+ Return<void> startDtmfResponse(const RadioResponseInfo& info);
+
+ Return<void> stopDtmfResponse(const RadioResponseInfo& info);
+
+ Return<void> getBasebandVersionResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& version);
+
+ Return<void> separateConnectionResponse(const RadioResponseInfo& info);
+
+ Return<void> setMuteResponse(const RadioResponseInfo& info);
+
+ Return<void> getMuteResponse(const RadioResponseInfo& info, bool enable);
+
+ Return<void> getClipResponse(const RadioResponseInfo& info, ClipStatus status);
+
+ Return<void> getDataCallListResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_0::SetupDataCallResult>& dcResponse);
+
+ Return<void> sendOemRilRequestRawResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<uint8_t>& data);
+
+ Return<void> sendOemRilRequestStringsResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
+
+ Return<void> setSuppServiceNotificationsResponse(const RadioResponseInfo& info);
+
+ Return<void> writeSmsToSimResponse(const RadioResponseInfo& info, int32_t index);
+
+ Return<void> deleteSmsOnSimResponse(const RadioResponseInfo& info);
+
+ Return<void> setBandModeResponse(const RadioResponseInfo& info);
+
+ Return<void> getAvailableBandModesResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<RadioBandMode>& bandModes);
+
+ Return<void> sendEnvelopeResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& commandResponse);
+
+ Return<void> sendTerminalResponseToSimResponse(const RadioResponseInfo& info);
+
+ Return<void> handleStkCallSetupRequestFromSimResponse(const RadioResponseInfo& info);
+
+ Return<void> explicitCallTransferResponse(const RadioResponseInfo& info);
+
+ Return<void> setPreferredNetworkTypeResponse(const RadioResponseInfo& info);
+
+ Return<void> getPreferredNetworkTypeResponse(const RadioResponseInfo& info,
+ PreferredNetworkType nwType);
+
+ Return<void> getNeighboringCidsResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<NeighboringCell>& cells);
+
+ Return<void> setLocationUpdatesResponse(const RadioResponseInfo& info);
+
+ Return<void> setCdmaSubscriptionSourceResponse(const RadioResponseInfo& info);
+
+ Return<void> setCdmaRoamingPreferenceResponse(const RadioResponseInfo& info);
+
+ Return<void> getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+ CdmaRoamingType type);
+
+ Return<void> setTTYModeResponse(const RadioResponseInfo& info);
+
+ Return<void> getTTYModeResponse(const RadioResponseInfo& info, TtyMode mode);
+
+ Return<void> setPreferredVoicePrivacyResponse(const RadioResponseInfo& info);
+
+ Return<void> getPreferredVoicePrivacyResponse(const RadioResponseInfo& info, bool enable);
+
+ Return<void> sendCDMAFeatureCodeResponse(const RadioResponseInfo& info);
+
+ Return<void> sendBurstDtmfResponse(const RadioResponseInfo& info);
+
+ Return<void> sendCdmaSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+ Return<void> acknowledgeLastIncomingCdmaSmsResponse(const RadioResponseInfo& info);
+
+ Return<void> getGsmBroadcastConfigResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& configs);
+
+ Return<void> setGsmBroadcastConfigResponse(const RadioResponseInfo& info);
+
+ Return<void> setGsmBroadcastActivationResponse(const RadioResponseInfo& info);
+
+ Return<void> getCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& configs);
+
+ Return<void> setCdmaBroadcastConfigResponse(const RadioResponseInfo& info);
+
+ Return<void> setCdmaBroadcastActivationResponse(const RadioResponseInfo& info);
+
+ Return<void> getCDMASubscriptionResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& mdn,
+ const ::android::hardware::hidl_string& hSid,
+ const ::android::hardware::hidl_string& hNid,
+ const ::android::hardware::hidl_string& min,
+ const ::android::hardware::hidl_string& prl);
+
+ Return<void> writeSmsToRuimResponse(const RadioResponseInfo& info, uint32_t index);
+
+ Return<void> deleteSmsOnRuimResponse(const RadioResponseInfo& info);
+
+ Return<void> getDeviceIdentityResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& imei,
+ const ::android::hardware::hidl_string& imeisv,
+ const ::android::hardware::hidl_string& esn,
+ const ::android::hardware::hidl_string& meid);
+
+ Return<void> exitEmergencyCallbackModeResponse(const RadioResponseInfo& info);
+
+ Return<void> getSmscAddressResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& smsc);
+
+ Return<void> setSmscAddressResponse(const RadioResponseInfo& info);
+
+ Return<void> reportSmsMemoryStatusResponse(const RadioResponseInfo& info);
+
+ Return<void> reportStkServiceIsRunningResponse(const RadioResponseInfo& info);
+
+ Return<void> getCdmaSubscriptionSourceResponse(const RadioResponseInfo& info,
+ CdmaSubscriptionSource source);
+
+ Return<void> requestIsimAuthenticationResponse(
+ const RadioResponseInfo& info, const ::android::hardware::hidl_string& response);
+
+ Return<void> acknowledgeIncomingGsmSmsWithPduResponse(const RadioResponseInfo& info);
+
+ Return<void> sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+ const IccIoResult& iccIo);
+
+ Return<void> getVoiceRadioTechnologyResponse(
+ const RadioResponseInfo& info, ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+ Return<void> getCellInfoListResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+ cellInfo);
+
+ Return<void> setCellInfoListRateResponse(const RadioResponseInfo& info);
+
+ Return<void> setInitialAttachApnResponse(const RadioResponseInfo& info);
+
+ Return<void> getImsRegistrationStateResponse(const RadioResponseInfo& info, bool isRegistered,
+ RadioTechnologyFamily ratFamily);
+
+ Return<void> sendImsSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+ Return<void> iccTransmitApduBasicChannelResponse(const RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> iccOpenLogicalChannelResponse(
+ const RadioResponseInfo& info, int32_t channelId,
+ const ::android::hardware::hidl_vec<int8_t>& selectResponse);
+
+ Return<void> iccCloseLogicalChannelResponse(const RadioResponseInfo& info);
+
+ Return<void> iccTransmitApduLogicalChannelResponse(const RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> nvReadItemResponse(const RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& result);
+
+ Return<void> nvWriteItemResponse(const RadioResponseInfo& info);
+
+ Return<void> nvWriteCdmaPrlResponse(const RadioResponseInfo& info);
+
+ Return<void> nvResetConfigResponse(const RadioResponseInfo& info);
+
+ Return<void> setUiccSubscriptionResponse(const RadioResponseInfo& info);
+
+ Return<void> setDataAllowedResponse(const RadioResponseInfo& info);
+
+ Return<void> getHardwareConfigResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<HardwareConfig>& config);
+
+ Return<void> requestIccSimAuthenticationResponse(const RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> setDataProfileResponse(const RadioResponseInfo& info);
+
+ Return<void> requestShutdownResponse(const RadioResponseInfo& info);
+
+ Return<void> getRadioCapabilityResponse(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> setRadioCapabilityResponse(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> startLceServiceResponse(const RadioResponseInfo& info,
+ const LceStatusInfo& statusInfo);
+
+ Return<void> stopLceServiceResponse(const RadioResponseInfo& info,
+ const LceStatusInfo& statusInfo);
+
+ Return<void> pullLceDataResponse(const RadioResponseInfo& info, const LceDataInfo& lceInfo);
+
+ Return<void> getModemActivityInfoResponse(const RadioResponseInfo& info,
+ const ActivityStatsInfo& activityInfo);
+
+ Return<void> setAllowedCarriersResponse(const RadioResponseInfo& info, int32_t numAllowed);
+
+ Return<void> getAllowedCarriersResponse(const RadioResponseInfo& info, bool allAllowed,
+ const CarrierRestrictions& carriers);
+
+ Return<void> sendDeviceStateResponse(const RadioResponseInfo& info);
+
+ Return<void> setIndicationFilterResponse(const RadioResponseInfo& info);
+
+ Return<void> setSimCardPowerResponse(const RadioResponseInfo& info);
+
+ Return<void> acknowledgeRequest(int32_t serial);
+
+ /* 1.1 Api */
+ Return<void> setCarrierInfoForImsiEncryptionResponse(const RadioResponseInfo& info);
+
+ Return<void> setSimCardPowerResponse_1_1(const RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse(const RadioResponseInfo& info);
+
+ Return<void> stopNetworkScanResponse(const RadioResponseInfo& info);
+
+ Return<void> startKeepaliveResponse(const RadioResponseInfo& info,
+ const KeepaliveStatus& status);
+
+ Return<void> stopKeepaliveResponse(const RadioResponseInfo& info);
+
+ /* 1.2 Api */
+ Return<void> setSignalStrengthReportingCriteriaResponse(const RadioResponseInfo& info);
+
+ Return<void> setLinkCapacityReportingCriteriaResponse(const RadioResponseInfo& info);
+
+ Return<void> getIccCardStatusResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::CardStatus& card_status);
+
+ Return<void> getCurrentCallsResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls);
+
+ Return<void> getSignalStrengthResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::SignalStrength& sig_strength);
+
+ Return<void> getCellInfoListResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+ cellInfo);
+
+ Return<void> getVoiceRegistrationStateResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse);
+
+ Return<void> getDataRegistrationStateResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::DataRegStateResult& dataRegResponse);
+
+ /* 1.3 Api */
+ Return<void> setSystemSelectionChannelsResponse(const RadioResponseInfo& info);
+
+ Return<void> enableModemResponse(const RadioResponseInfo& info);
+
+ Return<void> getModemStackStatusResponse(const RadioResponseInfo& info, const bool enabled);
+
+ /* 1.4 Api */
+ Return<void> emergencyDialResponse(const RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse_1_4(const RadioResponseInfo& info);
+
+ Return<void> getCellInfoListResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+ cellInfo);
+
+ Return<void> getDataRegistrationStateResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse);
+
+ Return<void> getIccCardStatusResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::CardStatus& card_status);
+
+ Return<void> getPreferredNetworkTypeBitmapResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_bitfield<
+ ::android::hardware::radio::V1_4::RadioAccessFamily>
+ networkTypeBitmap);
+
+ Return<void> setPreferredNetworkTypeBitmapResponse(const RadioResponseInfo& info);
+
+ Return<void> getDataCallListResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::SetupDataCallResult>& dcResponse);
+
+ Return<void> setupDataCallResponse_1_4(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_4::SetupDataCallResult& dcResponse);
+
+ Return<void> setAllowedCarriersResponse_1_4(const RadioResponseInfo& info);
+
+ Return<void> getAllowedCarriersResponse_1_4(const RadioResponseInfo& info,
+ const CarrierRestrictionsWithPriority& carriers,
+ SimLockMultiSimPolicy multiSimPolicy);
+};
+
+/* Callback class for radio indication */
+class RadioIndication_v1_4 : public ::android::hardware::radio::V1_4::IRadioIndication {
+ protected:
+ RadioHidlTest_v1_4& parent_v1_4;
+
+ public:
+ RadioIndication_v1_4(RadioHidlTest_v1_4& parent_v1_4);
+ virtual ~RadioIndication_v1_4() = default;
+
+ /* 1.4 Api */
+ Return<void> currentEmergencyNumberList(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<EmergencyNumber>& emergencyNumberList);
+
+ Return<void> cellInfoList_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+ records);
+
+ Return<void> networkScanResult_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_4::NetworkScanResult& result);
+
+ Return<void> currentPhysicalChannelConfigs_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::PhysicalChannelConfig>& configs);
+
+ Return<void> dataCallListChanged_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_4::SetupDataCallResult>& dcList);
+
+ /* 1.2 Api */
+ Return<void> networkScanResult_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::NetworkScanResult& result);
+
+ Return<void> cellInfoList_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+ records);
+
+ Return<void> currentLinkCapacityEstimate(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::LinkCapacityEstimate& lce);
+
+ Return<void> currentPhysicalChannelConfigs(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::PhysicalChannelConfig>& configs);
+
+ Return<void> currentSignalStrength_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::SignalStrength& signalStrength);
+
+ /* 1.1 Api */
+ Return<void> carrierInfoForImsiEncryption(RadioIndicationType info);
+
+ Return<void> networkScanResult(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_1::NetworkScanResult& result);
+
+ Return<void> keepaliveStatus(RadioIndicationType type, const KeepaliveStatus& status);
+
+ /* 1.0 Api */
+ Return<void> radioStateChanged(RadioIndicationType type, RadioState radioState);
+
+ Return<void> callStateChanged(RadioIndicationType type);
+
+ Return<void> networkStateChanged(RadioIndicationType type);
+
+ Return<void> newSms(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+ Return<void> newSmsStatusReport(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+ Return<void> newSmsOnSim(RadioIndicationType type, int32_t recordNumber);
+
+ Return<void> onUssd(RadioIndicationType type, UssdModeType modeType,
+ const ::android::hardware::hidl_string& msg);
+
+ Return<void> nitzTimeReceived(RadioIndicationType type,
+ const ::android::hardware::hidl_string& nitzTime,
+ uint64_t receivedTime);
+
+ Return<void> currentSignalStrength(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_0::SignalStrength& signalStrength);
+
+ Return<void> dataCallListChanged(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_0::SetupDataCallResult>& dcList);
+
+ Return<void> suppSvcNotify(RadioIndicationType type, const SuppSvcNotification& suppSvc);
+
+ Return<void> stkSessionEnd(RadioIndicationType type);
+
+ Return<void> stkProactiveCommand(RadioIndicationType type,
+ const ::android::hardware::hidl_string& cmd);
+
+ Return<void> stkEventNotify(RadioIndicationType type,
+ const ::android::hardware::hidl_string& cmd);
+
+ Return<void> stkCallSetup(RadioIndicationType type, int64_t timeout);
+
+ Return<void> simSmsStorageFull(RadioIndicationType type);
+
+ Return<void> simRefresh(RadioIndicationType type, const SimRefreshResult& refreshResult);
+
+ Return<void> callRing(RadioIndicationType type, bool isGsm, const CdmaSignalInfoRecord& record);
+
+ Return<void> simStatusChanged(RadioIndicationType type);
+
+ Return<void> cdmaNewSms(RadioIndicationType type, const CdmaSmsMessage& msg);
+
+ Return<void> newBroadcastSms(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& data);
+
+ Return<void> cdmaRuimSmsStorageFull(RadioIndicationType type);
+
+ Return<void> restrictedStateChanged(RadioIndicationType type, PhoneRestrictedState state);
+
+ Return<void> enterEmergencyCallbackMode(RadioIndicationType type);
+
+ Return<void> cdmaCallWaiting(RadioIndicationType type,
+ const CdmaCallWaiting& callWaitingRecord);
+
+ Return<void> cdmaOtaProvisionStatus(RadioIndicationType type, CdmaOtaProvisionStatus status);
+
+ Return<void> cdmaInfoRec(RadioIndicationType type, const CdmaInformationRecords& records);
+
+ Return<void> indicateRingbackTone(RadioIndicationType type, bool start);
+
+ Return<void> resendIncallMute(RadioIndicationType type);
+
+ Return<void> cdmaSubscriptionSourceChanged(RadioIndicationType type,
+ CdmaSubscriptionSource cdmaSource);
+
+ Return<void> cdmaPrlChanged(RadioIndicationType type, int32_t version);
+
+ Return<void> exitEmergencyCallbackMode(RadioIndicationType type);
+
+ Return<void> rilConnected(RadioIndicationType type);
+
+ Return<void> voiceRadioTechChanged(RadioIndicationType type,
+ ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+ Return<void> cellInfoList(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+ records);
+
+ Return<void> imsNetworkStateChanged(RadioIndicationType type);
+
+ Return<void> subscriptionStatusChanged(RadioIndicationType type, bool activate);
+
+ Return<void> srvccStateNotify(RadioIndicationType type, SrvccState state);
+
+ Return<void> hardwareConfigChanged(
+ RadioIndicationType type, const ::android::hardware::hidl_vec<HardwareConfig>& configs);
+
+ Return<void> radioCapabilityIndication(
+ RadioIndicationType type, const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> onSupplementaryServiceIndication(RadioIndicationType type,
+ const StkCcUnsolSsResult& ss);
+
+ Return<void> stkCallControlAlphaNotify(RadioIndicationType type,
+ const ::android::hardware::hidl_string& alpha);
+
+ Return<void> lceData(RadioIndicationType type, const LceDataInfo& lce);
+
+ Return<void> pcoData(RadioIndicationType type, const PcoDataInfo& pco);
+
+ Return<void> modemReset(RadioIndicationType type,
+ const ::android::hardware::hidl_string& reason);
+};
+
+// Test environment for Radio HIDL HAL.
+class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static RadioHidlEnvironment* Instance() {
+ static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
+ return instance;
+ }
+ virtual void registerTestServices() override {
+ registerTestService<::android::hardware::radio::V1_4::IRadio>();
+ }
+
+ private:
+ RadioHidlEnvironment() {}
+};
+
+// The main test class for Radio HIDL.
+class RadioHidlTest_v1_4 : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ std::mutex mtx_;
+ std::condition_variable cv_;
+ int count_;
+
+ /* Serial number for radio request */
+ int serial;
+
+ /* Update Sim Card Status */
+ void updateSimCardStatus();
+
+ public:
+ virtual void SetUp() override;
+
+ /* Used as a mechanism to inform the test about data/event callback */
+ void notify(int receivedSerial);
+
+ /* Test code calls this function to wait for response */
+ std::cv_status wait();
+
+ /* radio service handle */
+ sp<::android::hardware::radio::V1_4::IRadio> radio_v1_4;
+
+ /* radio response handle */
+ sp<RadioResponse_v1_4> radioRsp_v1_4;
+
+ /* radio indication handle */
+ sp<RadioIndication_v1_4> radioInd_v1_4;
+};
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_indication.cpp b/radio/1.4/vts/functional/radio_indication.cpp
new file mode 100644
index 0000000..f08b361
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_indication.cpp
@@ -0,0 +1,324 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_4.h>
+
+RadioIndication_v1_4::RadioIndication_v1_4(RadioHidlTest_v1_4& parent) : parent_v1_4(parent) {}
+
+/* 1.4 Apis */
+Return<void> RadioIndication_v1_4::currentPhysicalChannelConfigs_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::PhysicalChannelConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkScanResult_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_4::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentEmergencyNumberList(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<EmergencyNumber>& /*emergencyNumberList*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::dataCallListChanged_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_4::SetupDataCallResult>&
+ /*dcList*/) {
+ return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioIndication_v1_4::networkScanResult_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentLinkCapacityEstimate(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::LinkCapacityEstimate& /*lce*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentPhysicalChannelConfigs(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::PhysicalChannelConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentSignalStrength_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::SignalStrength& /*signalStrength*/) {
+ return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioIndication_v1_4::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkScanResult(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_1::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::keepaliveStatus(RadioIndicationType /*type*/,
+ const KeepaliveStatus& /*status*/) {
+ return Void();
+}
+
+/* 1.0 Apis */
+Return<void> RadioIndication_v1_4::radioStateChanged(RadioIndicationType /*type*/,
+ RadioState /*radioState*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::callStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSms(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSmsStatusReport(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSmsOnSim(RadioIndicationType /*type*/,
+ int32_t /*recordNumber*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::onUssd(RadioIndicationType /*type*/, UssdModeType /*modeType*/,
+ const ::android::hardware::hidl_string& /*msg*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::nitzTimeReceived(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*nitzTime*/,
+ uint64_t /*receivedTime*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentSignalStrength(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_0::SignalStrength& /*signalStrength*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::dataCallListChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+ /*dcList*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::suppSvcNotify(RadioIndicationType /*type*/,
+ const SuppSvcNotification& /*suppSvc*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkSessionEnd(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkProactiveCommand(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*cmd*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkEventNotify(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_string& /*cmd*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkCallSetup(RadioIndicationType /*type*/, int64_t /*timeout*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::simSmsStorageFull(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::simRefresh(RadioIndicationType /*type*/,
+ const SimRefreshResult& /*refreshResult*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+ const CdmaSignalInfoRecord& /*record*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::simStatusChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaNewSms(RadioIndicationType /*type*/,
+ const CdmaSmsMessage& /*msg*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::newBroadcastSms(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::restrictedStateChanged(RadioIndicationType /*type*/,
+ PhoneRestrictedState /*state*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaCallWaiting(RadioIndicationType /*type*/,
+ const CdmaCallWaiting& /*callWaitingRecord*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+ CdmaOtaProvisionStatus /*status*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaInfoRec(RadioIndicationType /*type*/,
+ const CdmaInformationRecords& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::indicateRingbackTone(RadioIndicationType /*type*/,
+ bool /*start*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::resendIncallMute(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaSubscriptionSourceChanged(
+ RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaPrlChanged(RadioIndicationType /*type*/,
+ int32_t /*version*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::rilConnected(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::voiceRadioTechChanged(
+ RadioIndicationType /*type*/, ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_0::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::subscriptionStatusChanged(RadioIndicationType /*type*/,
+ bool /*activate*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::srvccStateNotify(RadioIndicationType /*type*/,
+ SrvccState /*state*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::hardwareConfigChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<HardwareConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::radioCapabilityIndication(
+ RadioIndicationType /*type*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::onSupplementaryServiceIndication(
+ RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkCallControlAlphaNotify(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*alpha*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::lceData(RadioIndicationType /*type*/,
+ const LceDataInfo& /*lce*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::pcoData(RadioIndicationType /*type*/,
+ const PcoDataInfo& /*pco*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_4::modemReset(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_string& /*reason*/) {
+ return Void();
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
new file mode 100644
index 0000000..2ae5f7c
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -0,0 +1,867 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_4.h>
+
+::android::hardware::radio::V1_4::CardStatus cardStatus;
+
+RadioResponse_v1_4::RadioResponse_v1_4(RadioHidlTest_v1_4& parent) : parent_v1_4(parent) {}
+
+/* 1.0 Apis */
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::CardStatus& /*card_status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPukForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPuk2ForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::changeIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::changeIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyNetworkDepersonalizationResponse(
+ const RadioResponseInfo& /*info*/, int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCurrentCallsResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& /*calls*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::dialResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIMSIForAppResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imsi*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupWaitingOrBackgroundResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupForegroundResumeBackgroundResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::switchWaitingOrHoldingAndActiveResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::conferenceResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::rejectCallResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getLastCallFailCauseResponse(
+ const RadioResponseInfo& /*info*/, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSignalStrengthResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::SignalStrength& /*sig_strength*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRegistrationStateResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::VoiceRegStateResult& /*voiceRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::DataRegStateResult& /*dataRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getOperatorResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*longName*/,
+ const ::android::hardware::hidl_string& /*shortName*/,
+ const ::android::hardware::hidl_string& /*numeric*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setRadioPowerResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendDtmfResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendSmsResponse(const RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendSMSExpectMoreResponse(const RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setupDataCallResponse(
+ const RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::SetupDataCallResult& /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccIOForAppResponse(const RadioResponseInfo& /*info*/,
+ const IccIoResult& /*iccIo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendUssdResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::cancelPendingUssdResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getClirResponse(const RadioResponseInfo& /*info*/, int32_t /*n*/,
+ int32_t /*m*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setClirResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCallForwardStatusResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<CallForwardInfo>&
+ /*callForwardInfos*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCallForwardResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCallWaitingResponse(const RadioResponseInfo& /*info*/,
+ bool /*enable*/, int32_t /*serviceClass*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCallWaitingResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeLastIncomingGsmSmsResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::acceptCallResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::deactivateDataCallResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*response*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*retry*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setBarringPasswordResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getNetworkSelectionModeResponse(const RadioResponseInfo& /*info*/,
+ bool /*manual*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setNetworkSelectionModeAutomaticResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setNetworkSelectionModeManualResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAvailableNetworksResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<OperatorInfo>& /*networkInfos*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::startDtmfResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopDtmfResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getBasebandVersionResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*version*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::separateConnectionResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setMuteResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getMuteResponse(const RadioResponseInfo& /*info*/,
+ bool /*enable*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getClipResponse(const RadioResponseInfo& /*info*/,
+ ClipStatus /*status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataCallListResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+ /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendOemRilRequestRawResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendOemRilRequestStringsResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSuppServiceNotificationsResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::writeSmsToSimResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*index*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::deleteSmsOnSimResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setBandModeResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAvailableBandModesResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<RadioBandMode>& bandModes) {
+ rspInfo = info;
+ radioBandModes = bandModes;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendEnvelopeResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*commandResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendTerminalResponseToSimResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::handleStkCallSetupRequestFromSimResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::explicitCallTransferResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredNetworkTypeResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredNetworkTypeResponse(const RadioResponseInfo& /*info*/,
+ PreferredNetworkType /*nw_type*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getNeighboringCidsResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<NeighboringCell>& /*cells*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setLocationUpdatesResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaRoamingPreferenceResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaRoamingPreferenceResponse(const RadioResponseInfo& /*info*/,
+ CdmaRoamingType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setTTYModeResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getTTYModeResponse(const RadioResponseInfo& /*info*/,
+ TtyMode /*mode*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredVoicePrivacyResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredVoicePrivacyResponse(const RadioResponseInfo& /*info*/,
+ bool /*enable*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendCDMAFeatureCodeResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendBurstDtmfResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendCdmaSmsResponse(const RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeLastIncomingCdmaSmsResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getGsmBroadcastConfigResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setGsmBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setGsmBroadcastActivationResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaBroadcastActivationResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCDMASubscriptionResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*mdn*/,
+ const ::android::hardware::hidl_string& /*hSid*/,
+ const ::android::hardware::hidl_string& /*hNid*/,
+ const ::android::hardware::hidl_string& /*min*/,
+ const ::android::hardware::hidl_string& /*prl*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::writeSmsToRuimResponse(const RadioResponseInfo& /*info*/,
+ uint32_t /*index*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::deleteSmsOnRuimResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDeviceIdentityResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imei*/,
+ const ::android::hardware::hidl_string& /*imeisv*/,
+ const ::android::hardware::hidl_string& /*esn*/,
+ const ::android::hardware::hidl_string& /*meid*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::exitEmergencyCallbackModeResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSmscAddressResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*smsc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSmscAddressResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::reportSmsMemoryStatusResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::reportStkServiceIsRunningResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& /*info*/, CdmaSubscriptionSource /*source*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestIsimAuthenticationResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*response*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeIncomingGsmSmsWithPduResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendEnvelopeWithStatusResponse(const RadioResponseInfo& /*info*/,
+ const IccIoResult& /*iccIo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRadioTechnologyResponse(
+ const RadioResponseInfo& /*info*/,
+ ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_0::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCellInfoListRateResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setInitialAttachApnResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getImsRegistrationStateResponse(
+ const RadioResponseInfo& /*info*/, bool /*isRegistered*/,
+ RadioTechnologyFamily /*ratFamily*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendImsSmsResponse(const RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccTransmitApduBasicChannelResponse(
+ const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccOpenLogicalChannelResponse(
+ const RadioResponseInfo& /*info*/, int32_t /*channelId*/,
+ const ::android::hardware::hidl_vec<int8_t>& /*selectResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccCloseLogicalChannelResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccTransmitApduLogicalChannelResponse(
+ const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvReadItemResponse(
+ const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvWriteItemResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvWriteCdmaPrlResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvResetConfigResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setUiccSubscriptionResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setDataAllowedResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getHardwareConfigResponse(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<HardwareConfig>& /*config*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestIccSimAuthenticationResponse(
+ const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setDataProfileResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestShutdownResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getRadioCapabilityResponse(
+ const RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setRadioCapabilityResponse(
+ const RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::startLceServiceResponse(const RadioResponseInfo& /*info*/,
+ const LceStatusInfo& /*statusInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopLceServiceResponse(const RadioResponseInfo& /*info*/,
+ const LceStatusInfo& /*statusInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::pullLceDataResponse(const RadioResponseInfo& /*info*/,
+ const LceDataInfo& /*lceInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getModemActivityInfoResponse(
+ const RadioResponseInfo& /*info*/, const ActivityStatsInfo& /*activityInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setAllowedCarriersResponse(const RadioResponseInfo& /*info*/,
+ int32_t /*numAllowed*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAllowedCarriersResponse(
+ const RadioResponseInfo& /*info*/, bool /*allAllowed*/,
+ const CarrierRestrictions& /*carriers*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendDeviceStateResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setIndicationFilterResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSimCardPowerResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeRequest(int32_t /*serial*/) {
+ return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioResponse_v1_4::setCarrierInfoForImsiEncryptionResponse(
+ const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSimCardPowerResponse_1_1(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::startNetworkScanResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopNetworkScanResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::startKeepaliveResponse(const RadioResponseInfo& /*info*/,
+ const KeepaliveStatus& /*status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopKeepaliveResponse(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioResponse_v1_4::setSignalStrengthReportingCriteriaResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setLinkCapacityReportingCriteriaResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse_1_2(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::CardStatus& /*card_status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCurrentCallsResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& /*calls*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSignalStrengthResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::SignalStrength& /*sig_strength*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse_1_2(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRegistrationStateResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse_1_2(
+ const RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::DataRegStateResult& /*dataRegResponse*/) {
+ return Void();
+}
+
+/* 1.3 Apis */
+Return<void> RadioResponse_v1_4::setSystemSelectionChannelsResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::enableModemResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ enableModemResponseToggle = !enableModemResponseToggle;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getModemStackStatusResponse(const RadioResponseInfo& info,
+ const bool enabled) {
+ rspInfo = info;
+ isModemEnabled = enabled;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioResponse_v1_4::emergencyDialResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::startNetworkScanResponse_1_4(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse) {
+ rspInfo = info;
+ dataRegResp = dataRegResponse;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::CellInfo>& /*cellInfo*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::CardStatus& card_status) {
+ rspInfo = info;
+ cardStatus = card_status;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredNetworkTypeBitmapResponse(
+ const RadioResponseInfo& info, const ::android::hardware::hidl_bitfield<
+ ::android::hardware::radio::V1_4::RadioAccessFamily>
+ /*networkTypeBitmap*/) {
+ rspInfo = info;
+ // TODO: may need a new member for bitfield networkTypeBitmap.
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredNetworkTypeBitmapResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataCallListResponse_1_4(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::SetupDataCallResult>&
+ /*dcResponse*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setupDataCallResponse_1_4(
+ const RadioResponseInfo& info,
+ const android::hardware::radio::V1_4::SetupDataCallResult& /*dcResponse*/) {
+ rspInfo = info;
+ parent_v1_4.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::setAllowedCarriersResponse_1_4(const RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAllowedCarriersResponse_1_4(
+ const RadioResponseInfo& /*info*/, const CarrierRestrictionsWithPriority& /*carriers*/,
+ SimLockMultiSimPolicy /*multiSimPolicy*/) {
+ return Void();
+}
\ No newline at end of file
diff --git a/secure_element/1.1/Android.bp b/secure_element/1.1/Android.bp
new file mode 100644
index 0000000..e16bc3d
--- /dev/null
+++ b/secure_element/1.1/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.secure_element@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "ISecureElement.hal",
+ "ISecureElementHalCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.secure_element@1.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
+
diff --git a/secure_element/1.1/ISecureElement.hal b/secure_element/1.1/ISecureElement.hal
new file mode 100644
index 0000000..2f68fc7
--- /dev/null
+++ b/secure_element/1.1/ISecureElement.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.secure_element@1.1;
+
+import @1.1::ISecureElementHalCallback;
+import @1.0::ISecureElement;
+
+interface ISecureElement extends @1.0::ISecureElement {
+ /**
+ * Initializes the Secure Element. This may include updating the applet
+ * and/or vendor-specific initialization.
+ *
+ * HAL service must send onStateChange() with connected equal to true
+ * after all the initialization has been successfully completed.
+ * Clients must wait for a onStateChange(true) before opening channels.
+ *
+ * @param clientCallback callback used to sent status of the SE back to the
+ * client
+ */
+ init_1_1(ISecureElementHalCallback clientCallback);
+};
diff --git a/secure_element/1.1/ISecureElementHalCallback.hal b/secure_element/1.1/ISecureElementHalCallback.hal
new file mode 100644
index 0000000..090db5f
--- /dev/null
+++ b/secure_element/1.1/ISecureElementHalCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.secure_element@1.1;
+
+import @1.0::ISecureElementHalCallback;
+
+interface ISecureElementHalCallback extends @1.0::ISecureElementHalCallback {
+ /*
+ * Used to inform the client about changes in the state of the Secure
+ * Element.
+ *
+ * @param connected indicates the current state of the SE
+ * @param reason provides additional data why there was a change in state
+ * ex. initialization error, SE removed etc
+ * This is used only for debugging purpose to understand
+ * in-field issues.
+ */
+ onStateChange_1_1(bool connected, string debugReason);
+};
diff --git a/secure_element/1.1/vts/functional/Android.bp b/secure_element/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..51410bd
--- /dev/null
+++ b/secure_element/1.1/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+ name: "VtsHalSecureElementV1_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalSecureElementV1_1TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.secure_element@1.0",
+ "android.hardware.secure_element@1.1",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
new file mode 100644
index 0000000..f8765ca
--- /dev/null
+++ b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#define LOG_TAG "secure_element_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/secure_element/1.0/types.h>
+#include <android/hardware/secure_element/1.1/ISecureElement.h>
+#include <android/hardware/secure_element/1.1/ISecureElementHalCallback.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::secure_element::V1_1::ISecureElement;
+using ::android::hardware::secure_element::V1_1::ISecureElementHalCallback;
+using ::testing::VtsHalHidlTargetTestEnvBase;
+
+constexpr char kCallbackNameOnStateChange[] = "onStateChange";
+
+class SecureElementCallbackArgs {
+ public:
+ bool state_;
+ hidl_string reason_;
+};
+
+class SecureElementHalCallback
+ : public ::testing::VtsHalHidlTargetCallbackBase<SecureElementCallbackArgs>,
+ public ISecureElementHalCallback {
+ public:
+ virtual ~SecureElementHalCallback() = default;
+
+ Return<void> onStateChange_1_1(bool state, const hidl_string& reason) override {
+ SecureElementCallbackArgs args;
+ args.state_ = state;
+ args.reason_ = reason;
+ NotifyFromCallback(kCallbackNameOnStateChange, args);
+ return Void();
+ };
+
+ Return<void> onStateChange(__attribute__((unused)) bool state) override { return Void(); }
+};
+
+class SecureElementHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static SecureElementHidlEnvironment* Instance() {
+ static SecureElementHidlEnvironment* instance = new SecureElementHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<ISecureElement>(); }
+
+ private:
+ SecureElementHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SecureElementHidlEnvironment);
+};
+
+class SecureElementHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ std::string serviceName =
+ SecureElementHidlEnvironment::Instance()->getServiceName<ISecureElement>("eSE1");
+ LOG(INFO) << "get service with name:" << serviceName;
+ ASSERT_FALSE(serviceName.empty());
+ se_ = ::testing::VtsHalHidlTargetTestBase::getService<ISecureElement>(serviceName);
+ ASSERT_NE(se_, nullptr);
+
+ se_cb_ = new SecureElementHalCallback();
+ ASSERT_NE(se_cb_, nullptr);
+ se_->init_1_1(se_cb_);
+ auto res = se_cb_->WaitForCallback(kCallbackNameOnStateChange);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_TRUE(res.args->state_);
+ EXPECT_NE(res.args->reason_, "");
+ }
+
+ sp<ISecureElement> se_;
+ sp<SecureElementHalCallback> se_cb_;
+};
+
+/*
+ * isCardPresent:
+ * Expects the card to be present
+ */
+TEST_F(SecureElementHidlTest, isCardPresent) {
+ EXPECT_TRUE(se_->isCardPresent());
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(SecureElementHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ SecureElementHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ return status;
+}
diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp
index 168b402..c09173f 100644
--- a/sensors/2.0/default/Sensor.cpp
+++ b/sensors/2.0/default/Sensor.cpp
@@ -18,6 +18,8 @@
#include <utils/SystemClock.h>
+#include <cmath>
+
namespace android {
namespace hardware {
namespace sensors {
@@ -28,6 +30,8 @@
using ::android::hardware::sensors::V1_0::SensorFlagBits;
using ::android::hardware::sensors::V1_0::SensorStatus;
+static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000;
+
Sensor::Sensor(ISensorsEventCallback* callback)
: mIsEnabled(false),
mSamplingPeriodNs(0),
@@ -83,7 +87,7 @@
// to the Event FMQ prior to writing the flush complete event.
Event ev;
ev.sensorHandle = mSensorInfo.sensorHandle;
- ev.sensorType = SensorType::ADDITIONAL_INFO;
+ ev.sensorType = SensorType::META_DATA;
ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
std::vector<Event> evs{ev};
mCallback->postEvents(evs, isWakeUpSensor());
@@ -131,9 +135,9 @@
event.sensorHandle = mSensorInfo.sensorHandle;
event.sensorType = mSensorInfo.type;
event.timestamp = ::android::elapsedRealtimeNano();
- event.u.vec3.x = 1;
- event.u.vec3.y = 2;
- event.u.vec3.z = 3;
+ event.u.vec3.x = 0;
+ event.u.vec3.y = 0;
+ event.u.vec3.z = 0;
event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
events.push_back(event);
return events;
@@ -166,6 +170,31 @@
return result;
}
+OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback)
+ : Sensor(callback), mPreviousEventSet(false) {}
+
+void OnChangeSensor::activate(bool enable) {
+ Sensor::activate(enable);
+ if (!enable) {
+ mPreviousEventSet = false;
+ }
+}
+
+std::vector<Event> OnChangeSensor::readEvents() {
+ std::vector<Event> events = Sensor::readEvents();
+ std::vector<Event> outputEvents;
+
+ for (auto iter = events.begin(); iter != events.end(); ++iter) {
+ Event ev = *iter;
+ if (ev.u.vec3 != mPreviousEvent.u.vec3 || !mPreviousEventSet) {
+ outputEvents.push_back(ev);
+ mPreviousEvent = ev;
+ mPreviousEventSet = true;
+ }
+ }
+ return outputEvents;
+}
+
AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
mSensorInfo.sensorHandle = sensorHandle;
mSensorInfo.name = "Accel Sensor";
@@ -177,14 +206,166 @@
mSensorInfo.resolution = 1.52e-5;
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 20 * 1000; // microseconds
- mSensorInfo.maxDelay = 1000 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION);
+};
+
+PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Pressure Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::PRESSURE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1100.0f; // hPa
+ mSensorInfo.resolution = 0.005f; // hPa
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelay = 100 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Magnetic Field Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::MAGNETIC_FIELD;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1300.0f;
+ mSensorInfo.resolution = 0.01f;
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelay = 20 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Light Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::LIGHT;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 43000.0f;
+ mSensorInfo.resolution = 10.0f;
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelay = 200 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+};
+
+ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Proximity Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::PROXIMITY;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 5.0f;
+ mSensorInfo.resolution = 1.0f;
+ mSensorInfo.power = 0.012f; // mA
+ mSensorInfo.minDelay = 200 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
mSensorInfo.flags =
- static_cast<uint32_t>(SensorFlagBits::WAKE_UP | SensorFlagBits::DATA_INJECTION);
+ static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE | SensorFlagBits::WAKE_UP);
};
+GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Gyro Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::GYROSCOPE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f;
+ mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f);
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelay = 2.5f * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Ambient Temp Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 80.0f;
+ mSensorInfo.resolution = 0.01f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelay = 40 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+};
+
+DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Device Temp Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::TEMPERATURE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 80.0f;
+ mSensorInfo.resolution = 0.01f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelay = 40 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+}
+
+RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
+ ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Relative Humidity Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::RELATIVE_HUMIDITY;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 100.0f;
+ mSensorInfo.resolution = 0.1f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelay = 40 * 1000; // microseconds
+ mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace sensors
diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h
index 3ab2299..61900fa 100644
--- a/sensors/2.0/default/Sensor.h
+++ b/sensors/2.0/default/Sensor.h
@@ -50,7 +50,7 @@
const SensorInfo& getSensorInfo() const;
void batch(int32_t samplingPeriodNs);
- void activate(bool enable);
+ virtual void activate(bool enable);
Result flush();
void setOperationMode(OperationMode mode);
@@ -79,11 +79,65 @@
OperationMode mMode;
};
+class OnChangeSensor : public Sensor {
+ public:
+ OnChangeSensor(ISensorsEventCallback* callback);
+
+ virtual void activate(bool enable) override;
+
+ protected:
+ virtual std::vector<Event> readEvents() override;
+
+ protected:
+ Event mPreviousEvent;
+ bool mPreviousEventSet;
+};
+
class AccelSensor : public Sensor {
public:
AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
+class GyroSensor : public Sensor {
+ public:
+ GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class AmbientTempSensor : public OnChangeSensor {
+ public:
+ AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class DeviceTempSensor : public OnChangeSensor {
+ public:
+ DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class PressureSensor : public Sensor {
+ public:
+ PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class MagnetometerSensor : public Sensor {
+ public:
+ MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class LightSensor : public OnChangeSensor {
+ public:
+ LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class ProximitySensor : public OnChangeSensor {
+ public:
+ ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class RelativeHumiditySensor : public OnChangeSensor {
+ public:
+ RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
} // namespace implementation
} // namespace V2_0
} // namespace sensors
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index 15fe86f..23dd26b 100644
--- a/sensors/2.0/default/Sensors.cpp
+++ b/sensors/2.0/default/Sensors.cpp
@@ -37,13 +37,20 @@
Sensors::Sensors()
: mEventQueueFlag(nullptr),
+ mNextHandle(1),
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;
+ AddSensor<AccelSensor>();
+ AddSensor<GyroSensor>();
+ AddSensor<AmbientTempSensor>();
+ AddSensor<DeviceTempSensor>();
+ AddSensor<PressureSensor>();
+ AddSensor<MagnetometerSensor>();
+ AddSensor<LightSensor>();
+ AddSensor<ProximitySensor>();
+ AddSensor<RelativeHumiditySensor>();
}
Sensors::~Sensors() {
diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h
index eba3f97..d06dd78 100644
--- a/sensors/2.0/default/Sensors.h
+++ b/sensors/2.0/default/Sensors.h
@@ -87,6 +87,16 @@
private:
/**
+ * Add a new sensor
+ */
+ template <class SensorType>
+ void AddSensor() {
+ std::shared_ptr<SensorType> sensor =
+ std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
+ mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
+ }
+
+ /**
* Utility function to delete the Event Flag
*/
void deleteEventFlag();
@@ -132,6 +142,11 @@
std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
/**
+ * The next available sensor handle
+ */
+ int32_t mNextHandle;
+
+ /**
* Lock to protect writes to the FMQs
*/
std::mutex mWriteLock;
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 4a1f8f1..39053fe 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -51,7 +51,7 @@
}
void onEvent(const ::android::hardware::sensors::V1_0::Event& event) override {
- if (event.sensorType == SensorType::ADDITIONAL_INFO &&
+ if (event.sensorType == SensorType::META_DATA &&
event.u.meta.what == MetaDataEventType::META_DATA_FLUSH_COMPLETE) {
std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
mFlushMap[event.sensorHandle]++;
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index c0af30b..e5762f2 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -29,17 +29,23 @@
using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::sp;
+extern WifiHidlEnvironment* gEnv;
+
/**
* Fixture to use for all AP Iface HIDL interface tests.
*/
class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
+ if (!gEnv->isSoftApOn) return;
wifi_ap_iface_ = getWifiApIface();
ASSERT_NE(nullptr, wifi_ap_iface_.get());
}
- virtual void TearDown() override { stopWifi(); }
+ virtual void TearDown() override {
+ if (!gEnv->isSoftApOn) return;
+ stopWifi();
+ }
protected:
sp<IWifiApIface> wifi_ap_iface_;
@@ -51,6 +57,7 @@
* successfully created.
*/
TEST(WifiApIfaceHidlTestNoFixture, Create) {
+ if (!gEnv->isSoftApOn) return;
EXPECT_NE(nullptr, getWifiApIface().get());
stopWifi();
}
@@ -60,6 +67,7 @@
* Ensures that the correct interface type is returned for AP interface.
*/
TEST_F(WifiApIfaceHidlTest, GetType) {
+ if (!gEnv->isSoftApOn) return;
const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
EXPECT_EQ(IfaceType::AP, status_and_type.second);
@@ -71,6 +79,7 @@
* status code.
*/
TEST_F(WifiApIfaceHidlTest, SetCountryCode) {
+ if (!gEnv->isSoftApOn) return;
const android::hardware::hidl_array<int8_t, 2> kCountryCode{
std::array<int8_t, 2>{{0x55, 0x53}}};
EXPECT_EQ(WifiStatusCode::SUCCESS,
@@ -82,6 +91,7 @@
* Ensures that we can retrieve valid frequencies for 2.4 GHz band.
*/
TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
+ if (!gEnv->isSoftApOn) return;
const auto& status_and_freqs = HIDL_INVOKE(
wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index 3555c2e..72cafd1 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -365,6 +365,7 @@
* succeeds. The 2nd iface creation should be rejected.
*/
TEST_F(WifiChipHidlTest, CreateApIface) {
+ if (!gEnv->isSoftApOn) return;
configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> iface;
@@ -381,6 +382,7 @@
* iface name is returned via the list.
*/
TEST_F(WifiChipHidlTest, GetApIfaceNames) {
+ if (!gEnv->isSoftApOn) return;
configureChipForIfaceType(IfaceType::AP, true);
const auto& status_and_iface_names1 =
@@ -413,6 +415,7 @@
* doesn't retrieve an iface object.
*/
TEST_F(WifiChipHidlTest, GetApIface) {
+ if (!gEnv->isSoftApOn) return;
configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> ap_iface;
@@ -439,6 +442,7 @@
* doesn't remove the iface.
*/
TEST_F(WifiChipHidlTest, RemoveApIface) {
+ if (!gEnv->isSoftApOn) return;
configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> ap_iface;
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index 2b1c8ec..d430ce0 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -58,26 +58,33 @@
public:
// Whether NaN feature is supported on the device.
bool isNanOn = false;
+ // Whether SoftAp feature is supported on the device.
+ bool isSoftApOn = false;
void usage(char* me, char* arg) {
fprintf(stderr,
"unrecognized option: %s\n\n"
"usage: %s <gtest options> <test options>\n\n"
"test options are:\n\n"
- "-N, --nan_on: Whether NAN feature is supported\n",
+ "-N, --nan_on: Whether NAN feature is supported\n"
+ "-S, --softap_on: Whether SOFTAP feature is supported\n",
arg, me);
}
int initFromOptions(int argc, char** argv) {
static struct option options[] = {{"nan_on", no_argument, 0, 'N'},
+ {"softap_on", no_argument, 0, 'S'},
{0, 0, 0, 0}};
int c;
- while ((c = getopt_long(argc, argv, "N", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "NS", options, NULL)) >= 0) {
switch (c) {
case 'N':
isNanOn = true;
break;
+ case 'S':
+ isSoftApOn = true;
+ break;
default:
usage(argv[0], argv[optind]);
return 2;
diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
index d1af655..439a624 100644
--- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
@@ -34,6 +34,14 @@
using ::android::hardware::wifi::hostapd::V1_1::IHostapd;
using ::android::hardware::wifi::hostapd::V1_1::IHostapdCallback;
+namespace {
+constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
+ '2', '3', '4', '5'};
+constexpr char kNwPassphrase[] = "test12345";
+constexpr int kIfaceChannel = 6;
+constexpr int kIfaceInvalidChannel = 567;
+} // namespace
+
class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
@@ -45,6 +53,99 @@
virtual void TearDown() override { stopHostapd(); }
protected:
+ std::string getPrimaryWlanIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ property_get("wifi.interface", buffer.data(), "wlan0");
+ return buffer.data();
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcs() {
+ ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+ iface_params;
+ IHostapd::IfaceParams iface_params_1_1;
+
+ iface_params.ifaceName = getPrimaryWlanIfaceName();
+ iface_params.hwModeParams.enable80211N = true;
+ iface_params.hwModeParams.enable80211AC = false;
+ iface_params.channelParams.enableAcs = true;
+ iface_params.channelParams.acsShouldExcludeDfs = true;
+ iface_params.channelParams.channel = 0;
+ iface_params.channelParams.band = IHostapd::Band::BAND_ANY;
+ iface_params_1_1.V1_0 = iface_params;
+ return iface_params_1_1;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcsAndChannelRange() {
+ IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithAcs();
+ IHostapd::ChannelParams channelParams;
+ IHostapd::AcsChannelRange acsChannelRange;
+ acsChannelRange.start = 1;
+ acsChannelRange.end = 11;
+ std::vector<IHostapd::AcsChannelRange> vec_acsChannelRange;
+ vec_acsChannelRange.push_back(acsChannelRange);
+ channelParams.acsChannelRanges = vec_acsChannelRange;
+ iface_params_1_1.channelParams = channelParams;
+ return iface_params_1_1;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidChannelRange() {
+ IHostapd::IfaceParams iface_params_1_1 =
+ getIfaceParamsWithAcsAndChannelRange();
+ iface_params_1_1.channelParams.acsChannelRanges[0].start = 222;
+ iface_params_1_1.channelParams.acsChannelRanges[0].end = 999;
+ return iface_params_1_1;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+ ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+ iface_params;
+ IHostapd::IfaceParams iface_params_1_1;
+
+ iface_params.ifaceName = getPrimaryWlanIfaceName();
+ iface_params.hwModeParams.enable80211N = true;
+ iface_params.hwModeParams.enable80211AC = false;
+ iface_params.channelParams.enableAcs = false;
+ iface_params.channelParams.acsShouldExcludeDfs = false;
+ iface_params.channelParams.channel = kIfaceChannel;
+ iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
+ iface_params_1_1.V1_0 = iface_params;
+ return iface_params_1_1;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
+ IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithoutAcs();
+ iface_params_1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
+ return iface_params_1_1;
+ }
+
+ IHostapd::NetworkParams getPskNwParams() {
+ IHostapd::NetworkParams nw_params;
+ nw_params.ssid =
+ std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+ nw_params.isHidden = false;
+ nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+ nw_params.pskPassphrase = kNwPassphrase;
+ return nw_params;
+ }
+
+ IHostapd::NetworkParams getInvalidPskNwParams() {
+ IHostapd::NetworkParams nw_params;
+ nw_params.ssid =
+ std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+ nw_params.isHidden = false;
+ nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+ return nw_params;
+ }
+
+ IHostapd::NetworkParams getOpenNwParams() {
+ IHostapd::NetworkParams nw_params;
+ nw_params.ssid =
+ std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+ nw_params.isHidden = false;
+ nw_params.encryptionType = IHostapd::EncryptionType::NONE;
+ return nw_params;
+ }
+
// IHostapd object used for all tests in this fixture.
sp<IHostapd> hostapd_;
};
@@ -65,3 +166,113 @@
EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
});
}
+
+/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config, ACS enabled & channel Range.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndChannelRange) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithAcsAndChannelRange(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel range.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidChannelRange) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithAcsAndInvalidChannelRange(),
+ getPskNwParams());
+ EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithAcs(), getOpenNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithoutAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithoutAcs(), getOpenNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+ status =
+ HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithoutAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+ status =
+ HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+ getIfaceParamsWithInvalidChannel(), getPskNwParams());
+ EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_1, getIfaceParamsWithoutAcs(),
+ getInvalidPskNwParams());
+ EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}