Merge "Updating CDDL schemas to match the finalized spec." into sc-dev
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
index 7f1d4d1..8adec84 100644
--- a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
+++ b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
@@ -18,6 +18,7 @@
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <utils/Log.h>
+#include <unordered_set>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
@@ -184,20 +185,34 @@
TEST_P(VehicleHalHidlTest, setProp) {
ALOGD("VehicleHalHidlTest::setProp");
hidl_vec<VehiclePropConfig> propConfigs;
+ // skip hvac related properties
+ std::unordered_set<int32_t> hvacProps = {(int)VehicleProperty::HVAC_DEFROSTER,
+ (int)VehicleProperty::HVAC_AC_ON,
+ (int)VehicleProperty::HVAC_MAX_AC_ON,
+ (int)VehicleProperty::HVAC_MAX_DEFROST_ON,
+ (int)VehicleProperty::HVAC_RECIRC_ON,
+ (int)VehicleProperty::HVAC_DUAL_ON,
+ (int)VehicleProperty::HVAC_AUTO_ON,
+ (int)VehicleProperty::HVAC_POWER_ON,
+ (int)VehicleProperty::HVAC_AUTO_RECIRC_ON,
+ (int)VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON};
mVehicle->getAllPropConfigs(
[&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
for (const VehiclePropConfig& cfg : propConfigs) {
// test on boolean and writable property
- if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop)) {
+ if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop) &&
+ !hvacProps.count(cfg.prop)) {
invokeGet(cfg.prop, 0);
int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
VehiclePropValue propToSet = mActualValue;
propToSet.value.int32Values[0] = setValue;
- ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet));
+ ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet))
+ << "Invalid status code for setting property: " << cfg.prop;
// check set success
invokeGet(cfg.prop, 0);
ASSERT_EQ(StatusCode::OK, mActualStatusCode);
- ASSERT_EQ(setValue, mActualValue.value.int32Values[0]);
+ ASSERT_EQ(setValue, mActualValue.value.int32Values[0])
+ << "Failed to set value for property: " << cfg.prop;
}
}
}
@@ -241,6 +256,7 @@
ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VehicleHalHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VehicleHalHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index ada6f73..47a7813 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -32,21 +32,8 @@
constexpr int kSensorId = 0;
constexpr int kUserId = 0;
-enum class MethodName {
- kOnError,
- kOnSessionClosed,
-};
-
-struct Invocation {
- MethodName methodName;
- Error error;
- int32_t vendorCode;
-};
-
class SessionCallback : public BnSessionCallback {
public:
- explicit SessionCallback(Invocation* inv) : mInv(inv) {}
-
ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
return ndk::ScopedAStatus::ok();
}
@@ -64,11 +51,11 @@
}
ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override {
- *mInv = {};
- mInv->methodName = MethodName::kOnError;
- mInv->error = error;
- mInv->vendorCode = vendorCode;
-
+ auto lock = std::lock_guard<std::mutex>{mMutex};
+ mError = error;
+ mVendorCode = vendorCode;
+ mOnErrorInvoked = true;
+ mCv.notify_one();
return ndk::ScopedAStatus::ok();
}
@@ -121,14 +108,18 @@
}
ndk::ScopedAStatus onSessionClosed() override {
- *mInv = {};
- mInv->methodName = MethodName::kOnSessionClosed;
-
+ auto lock = std::lock_guard<std::mutex>{mMutex};
+ mOnSessionClosedInvoked = true;
+ mCv.notify_one();
return ndk::ScopedAStatus::ok();
}
- private:
- Invocation* mInv;
+ std::mutex mMutex;
+ std::condition_variable mCv;
+ Error mError = Error::UNKNOWN;
+ int32_t mVendorCode = 0;
+ bool mOnErrorInvoked = false;
+ bool mOnSessionClosedInvoked = false;
};
class Face : public testing::TestWithParam<std::string> {
@@ -140,12 +131,11 @@
}
std::shared_ptr<IFace> mHal;
- Invocation mInv;
};
TEST_P(Face, AuthenticateTest) {
// Prepare the callback.
- auto cb = ndk::SharedRefBase::make<SessionCallback>(&mInv);
+ auto cb = ndk::SharedRefBase::make<SessionCallback>();
// Create a session
std::shared_ptr<ISession> session;
@@ -155,15 +145,18 @@
std::shared_ptr<common::ICancellationSignal> cancellationSignal;
ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).isOk());
+ auto lock = std::unique_lock<std::mutex>(cb->mMutex);
+ cb->mCv.wait(lock, [&cb] { return cb->mOnErrorInvoked; });
// Get the results
- EXPECT_EQ(mInv.methodName, MethodName::kOnError);
- EXPECT_EQ(mInv.error, Error::UNABLE_TO_PROCESS);
- EXPECT_EQ(mInv.vendorCode, 0);
+ EXPECT_EQ(cb->mError, Error::UNABLE_TO_PROCESS);
+ EXPECT_EQ(cb->mVendorCode, 0);
+ lock.unlock();
// Close the session
ASSERT_TRUE(session->close().isOk());
- EXPECT_EQ(mInv.methodName, MethodName::kOnSessionClosed);
+ lock.lock();
+ cb->mCv.wait(lock, [&cb] { return cb->mOnSessionClosedInvoked; });
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
@@ -180,4 +173,3 @@
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
-
diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
index 8443336..b2417bd 100644
--- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
@@ -73,24 +73,29 @@
constexpr int NUM_TASKS = 10000;
WorkerThread worker(NUM_TASKS);
+ std::mutex mut;
+ std::condition_variable cv;
+ bool finished = false;
std::vector<int> results;
+
for (int i = 0; i < NUM_TASKS; ++i) {
- worker.schedule(Callable::from([&results, i] {
+ worker.schedule(Callable::from([&mut, &results, i] {
// Delay tasks differently to provoke races.
std::this_thread::sleep_for(std::chrono::nanoseconds(100 - i % 100));
- // Unguarded write to results to provoke races.
+ auto lock = std::lock_guard(mut);
results.push_back(i);
}));
}
- std::promise<void> promise;
- auto future = promise.get_future();
-
// Schedule a special task to signal when all of the tasks are finished.
- worker.schedule(
- Callable::from([promise = std::move(promise)]() mutable { promise.set_value(); }));
- future.wait();
+ worker.schedule(Callable::from([&mut, &cv, &finished] {
+ auto lock = std::lock_guard(mut);
+ finished = true;
+ cv.notify_one();
+ }));
+ auto lock = std::unique_lock(mut);
+ cv.wait(lock, [&finished] { return finished; });
ASSERT_EQ(results.size(), NUM_TASKS);
EXPECT_TRUE(std::is_sorted(results.begin(), results.end()));
}
diff --git a/camera/metadata/3.5/types.hal b/camera/metadata/3.5/types.hal
index 99d6115..d32bc91 100644
--- a/camera/metadata/3.5/types.hal
+++ b/camera/metadata/3.5/types.hal
@@ -73,7 +73,7 @@
ANDROID_CONTROL_END_3_5,
- /** android.scaler.availableRotateAndCropModes [static, byte[], hidden]
+ /** android.scaler.availableRotateAndCropModes [static, byte[], public]
*
* <p>List of rotate-and-crop modes for ANDROID_SCALER_ROTATE_AND_CROP that are supported by this camera device.</p>
*
@@ -81,7 +81,7 @@
*/
ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_SCALER_END_3_4,
- /** android.scaler.rotateAndCrop [dynamic, enum, hidden]
+ /** android.scaler.rotateAndCrop [dynamic, enum, public]
*
* <p>Whether a rotation-and-crop operation is applied to processed
* outputs from the camera.</p>
diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal
index 97cac7c..185687c 100644
--- a/camera/metadata/3.6/types.hal
+++ b/camera/metadata/3.6/types.hal
@@ -348,6 +348,14 @@
ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE,
};
+/** android.sensor.testPatternMode enumeration values added since v3.2
+ * @see ANDROID_SENSOR_TEST_PATTERN_MODE
+ */
+enum CameraMetadataEnumAndroidSensorTestPatternMode :
+ @3.2::CameraMetadataEnumAndroidSensorTestPatternMode {
+ ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK,
+};
+
/** android.sensor.pixelMode enumeration values
* @see ANDROID_SENSOR_PIXEL_MODE
*/
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 0ec9fe3..41a08f9 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -42,6 +42,7 @@
#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraDevice.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera/metadata/3.4/types.h>
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
@@ -767,6 +768,9 @@
sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/,
sp<device::V3_6::ICameraDeviceSession> *session3_6 /*out*/,
sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
+ void castInjectionSession(
+ const sp<ICameraDeviceSession>& session,
+ sp<device::V3_7::ICameraInjectionSession>* injectionSession3_7 /*out*/);
void castDevice(const sp<device::V3_2::ICameraDevice>& device, int32_t deviceVersion,
sp<device::V3_5::ICameraDevice>* device3_5 /*out*/,
sp<device::V3_7::ICameraDevice>* device3_7 /*out*/);
@@ -5880,6 +5884,301 @@
notifyDeviceState(provider::V2_5::DeviceState::NORMAL);
}
+// Verify that all supported stream formats and sizes can be configured
+// successfully for injection camera.
+TEST_P(CameraHidlTest, configureInjectionStreamsAvailableOutputs) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ std::vector<AvailableStream> outputStreams;
+
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) {
+ continue;
+ }
+
+ camera_metadata_t* staticMetaBuffer;
+ Return<void> ret;
+ Status s;
+ sp<ICameraDeviceSession> session;
+ sp<device::V3_7::ICameraInjectionSession> injectionSession3_7;
+ openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
+ castInjectionSession(session, &injectionSession3_7);
+ if (injectionSession3_7 == nullptr) {
+ ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__,
+ mProviderType.c_str());
+ continue;
+ }
+
+ ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+ hidlChars.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(staticMetaBuffer)),
+ get_camera_metadata_size(staticMetaBuffer));
+
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ uint32_t jpegBufferSize = 0;
+ ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
+ ASSERT_NE(0u, jpegBufferSize);
+
+ int32_t streamId = 0;
+ uint32_t streamConfigCounter = 0;
+ for (auto& it : outputStreams) {
+ V3_2::Stream stream3_2;
+ V3_2::DataspaceFlags dataspaceFlag = getDataspace(static_cast<PixelFormat>(it.format));
+ stream3_2 = {streamId,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(it.width),
+ static_cast<uint32_t>(it.height),
+ static_cast<PixelFormat>(it.format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ dataspaceFlag,
+ StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
+ ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
+ ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+ ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+ createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2,
+ &config3_4, &config3_5, &config3_7, jpegBufferSize);
+
+ config3_7.streamConfigCounter = streamConfigCounter++;
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ ASSERT_EQ(Status::OK, s);
+ streamId++;
+ }
+
+ free_camera_metadata(staticMetaBuffer);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+}
+
+// Check for correct handling of invalid/incorrect configuration parameters for injection camera.
+TEST_P(CameraHidlTest, configureInjectionStreamsInvalidOutputs) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ std::vector<AvailableStream> outputStreams;
+
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) {
+ continue;
+ }
+
+ camera_metadata_t* staticMetaBuffer;
+ Return<void> ret;
+ Status s;
+ sp<ICameraDeviceSession> session;
+ sp<device::V3_7::ICameraInjectionSession> injectionSession3_7;
+ openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
+ castInjectionSession(session, &injectionSession3_7);
+ if (injectionSession3_7 == nullptr) {
+ ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__,
+ mProviderType.c_str());
+ continue;
+ }
+
+ ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+ hidlChars.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(staticMetaBuffer)),
+ get_camera_metadata_size(staticMetaBuffer));
+
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ uint32_t jpegBufferSize = 0;
+ ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize));
+ ASSERT_NE(0u, jpegBufferSize);
+
+ int32_t streamId = 0;
+ V3_2::Stream stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(0),
+ static_cast<uint32_t>(0),
+ static_cast<PixelFormat>(outputStreams[0].format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ 0,
+ StreamRotation::ROTATION_0};
+ uint32_t streamConfigCounter = 0;
+ ::android::hardware::hidl_vec<V3_2::Stream> streams = {stream3_2};
+ ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
+ ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+ ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+ createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2,
+ &config3_4, &config3_5, &config3_7, jpegBufferSize);
+
+ config3_7.streamConfigCounter = streamConfigCounter++;
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s));
+
+ stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(UINT32_MAX),
+ static_cast<uint32_t>(UINT32_MAX),
+ static_cast<PixelFormat>(outputStreams[0].format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ 0,
+ StreamRotation::ROTATION_0};
+ streams[0] = stream3_2;
+ createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2,
+ &config3_4, &config3_5, &config3_7, jpegBufferSize);
+ config3_7.streamConfigCounter = streamConfigCounter++;
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+
+ for (auto& it : outputStreams) {
+ stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(it.width),
+ static_cast<uint32_t>(it.height),
+ static_cast<PixelFormat>(UINT32_MAX),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ 0,
+ StreamRotation::ROTATION_0};
+ streams[0] = stream3_2;
+ createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2,
+ &config3_4, &config3_5, &config3_7, jpegBufferSize);
+ config3_7.streamConfigCounter = streamConfigCounter++;
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+
+ stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(it.width),
+ static_cast<uint32_t>(it.height),
+ static_cast<PixelFormat>(it.format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ 0,
+ static_cast<StreamRotation>(UINT32_MAX)};
+ streams[0] = stream3_2;
+ createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2,
+ &config3_4, &config3_5, &config3_7, jpegBufferSize);
+ config3_7.streamConfigCounter = streamConfigCounter++;
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ }
+
+ free_camera_metadata(staticMetaBuffer);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+}
+
+// Check whether session parameters are supported for injection camera. If Hal support for them
+// exist, then try to configure a preview stream using them.
+TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ std::vector<AvailableStream> outputPreviewStreams;
+ AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+ static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) {
+ continue;
+ }
+
+ camera_metadata_t* staticMetaBuffer;
+ Return<void> ret;
+ Status s;
+ sp<ICameraDeviceSession> session;
+ sp<device::V3_7::ICameraInjectionSession> injectionSession3_7;
+ openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
+ castInjectionSession(session, &injectionSession3_7);
+ if (injectionSession3_7 == nullptr) {
+ ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__,
+ mProviderType.c_str());
+ continue;
+ }
+
+ ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+ hidlChars.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(staticMetaBuffer)),
+ get_camera_metadata_size(staticMetaBuffer));
+
+ std::unordered_set<int32_t> availableSessionKeys;
+ auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
+ &availableSessionKeys);
+ ASSERT_TRUE(Status::OK == rc);
+ if (availableSessionKeys.empty()) {
+ free_camera_metadata(staticMetaBuffer);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ continue;
+ }
+
+ android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
+ android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams,
+ modifiedSessionParams;
+ constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW,
+ &previewRequestSettings, &sessionParams);
+ if (sessionParams.isEmpty()) {
+ free_camera_metadata(staticMetaBuffer);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ continue;
+ }
+
+ outputPreviewStreams.clear();
+
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams,
+ &previewThreshold));
+ ASSERT_NE(0u, outputPreviewStreams.size());
+
+ V3_4::Stream previewStream;
+ previewStream.v3_2 = {0,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(outputPreviewStreams[0].width),
+ static_cast<uint32_t>(outputPreviewStreams[0].height),
+ static_cast<PixelFormat>(outputPreviewStreams[0].format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ 0,
+ StreamRotation::ROTATION_0};
+ previewStream.bufferSize = 0;
+ ::android::hardware::hidl_vec<V3_4::Stream> streams = {previewStream};
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config;
+ ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+ ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
+ config.streams = streams;
+ config.operationMode = StreamConfigurationMode::NORMAL_MODE;
+ modifiedSessionParams = sessionParams;
+ auto sessionParamsBuffer = sessionParams.release();
+ config.sessionParams.setToExternal(reinterpret_cast<uint8_t*>(sessionParamsBuffer),
+ get_camera_metadata_size(sessionParamsBuffer));
+ config3_5.v3_4 = config;
+ config3_5.streamConfigCounter = 0;
+ config3_7.streams = {{previewStream, -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}};
+ config3_7.operationMode = config.operationMode;
+ config3_7.sessionParams.setToExternal(reinterpret_cast<uint8_t*>(sessionParamsBuffer),
+ get_camera_metadata_size(sessionParamsBuffer));
+ config3_7.streamConfigCounter = 0;
+ config3_7.multiResolutionInputImage = false;
+
+ s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars);
+ sessionParams.acquire(sessionParamsBuffer);
+ ASSERT_EQ(Status::OK, s);
+
+ free_camera_metadata(staticMetaBuffer);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+}
+
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -7253,6 +7552,22 @@
}
}
+// Cast camera device session to injection session
+void CameraHidlTest::castInjectionSession(
+ const sp<ICameraDeviceSession>& session,
+ sp<device::V3_7::ICameraInjectionSession>* injectionSession3_7 /*out*/) {
+ ASSERT_NE(nullptr, injectionSession3_7);
+
+ sp<device::V3_7::ICameraDeviceSession> session3_7;
+ auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session);
+ ASSERT_TRUE(castResult.isOk());
+ session3_7 = castResult;
+
+ auto castInjectionResult = device::V3_7::ICameraInjectionSession::castFrom(session3_7);
+ ASSERT_TRUE(castInjectionResult.isOk());
+ *injectionSession3_7 = castInjectionResult;
+}
+
void CameraHidlTest::verifyStreamCombination(
sp<device::V3_7::ICameraDevice> cameraDevice3_7,
const ::android::hardware::camera::device::V3_7::StreamConfiguration& config3_7,
diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml
index 01cd1f6..aee2c51 100644
--- a/compatibility_matrices/compatibility_matrix.6.xml
+++ b/compatibility_matrices/compatibility_matrix.6.xml
@@ -508,6 +508,7 @@
<interface>
<name>ISharedSecret</name>
<instance>default</instance>
+ <instance>strongbox</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 3b84b6e..8b6e841 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -508,6 +508,7 @@
<interface>
<name>ISharedSecret</name>
<instance>default</instance>
+ <instance>strongbox</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
diff --git a/current.txt b/current.txt
index 3102972..8230852 100644
--- a/current.txt
+++ b/current.txt
@@ -4,6 +4,7 @@
# Test HALs
717c17cd380bb48710dff601d1a03351d4ebc28028353d5d60489248f506523c android.hardware.tests.lazy@1.0::ILazy
+67222a2ed4071b6c232e671ce0f4be4f85c1c6fb017ec2355396adaae1fe26be android.hardware.tests.lazy@1.1::ILazy
# HALs released in Android O
@@ -767,6 +768,7 @@
98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
# ABI preserving changes to HALs during Android S
+159a0069336035852e9eca6354b86b7990680d1b239f23ef2f631b01807c4cb9 android.hardware.camera.metadata@3.5::types
e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub
c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback
bda492ec4021d13869de72bd6f8c15c5837b78d6136b8d538efec5320573a5ec android.hardware.gnss@1.0::IGnssMeasurementCallback
@@ -825,6 +827,9 @@
b4cbc1f2d38787f2ad069a8e4d10c0896287531a2596f0de0283e390b0ecf05d android.hardware.audio.effect@7.0::IVirtualizerEffect
2b5681e1ea6a2db0dc1e84edb96d3de2f7daf306046543e7956be76dcb8f20fb android.hardware.audio.effect@7.0::IVisualizerEffect
fa1e2d78e66fd662de93cb479ffd55947fe54f51cb53915814b3d3e3036c86a5 android.hardware.audio.effect@7.0::types
+e3865e74cb1a6e6afd38c7aa84115cb109ce47b972132de5242bc3838d2771f6 android.hardware.automotive.vehicle@2.0::types
+b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
+7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
b525e91d886379c13588f4975bb04d625d46e1f41b4453792c4b2db1e7ff4340 android.hardware.biometrics.fingerprint@2.3::IBiometricsFingerprint
4baf8e0eca4aa896cc9ceb7bb676aaf4fa21372ef8b49eed68eced1221c3dc0d android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvider
d417a9212c8f96e3a06a2f221c8c5756c765355b2b81de2b2a65d4c9eee85401 android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory
@@ -834,7 +839,7 @@
3be6faa3d11ad9c7ec01a1a0a009cf11cb65d701d109dab37613ce9cfb3cdd60 android.hardware.camera.device@3.7::ICameraDeviceSession
3740ec773b2eb8fa6bd8c6e879eedb56c4e4306b88f1c20fa51103d791d871b1 android.hardware.camera.device@3.7::ICameraInjectionSession
21f023685571daf46148097d98b89cea353f07e3ed83b2ed5685b23bd136c3ee android.hardware.camera.device@3.7::types
-f655c93132d223369ff6ddc621cb721f82dde6cc85ab9df2cbde6cb24cf2c885 android.hardware.camera.metadata@3.6::types
+e932e7ef95210142e1fd3a4504e1d19bdb1acc988450f1ced543f3401f67855a android.hardware.camera.metadata@3.6::types
98ff825a7d37e5ab983502d13cec1f2e5a9cac9b674b6ff1a52bcf540f4e315e android.hardware.camera.provider@2.7::ICameraProvider
51fd14005859b16be55872660c34f5d423c77a2abcc5d4bdd5a537c40f32516b android.hardware.camera.provider@2.7::types
3500d3c4e2d49eeed2f3239330a166beb2db2d5071b84d9c738b048c2d54a3d9 android.hardware.contexthub@1.2::IContexthub
diff --git a/gnss/aidl/default/GnssHidlHal.cpp b/gnss/aidl/default/GnssHidlHal.cpp
index 263715c..10b0106 100644
--- a/gnss/aidl/default/GnssHidlHal.cpp
+++ b/gnss/aidl/default/GnssHidlHal.cpp
@@ -43,7 +43,6 @@
hidl_vec<GnssSvInfo> GnssHidlHal::filterBlocklistedSatellitesV2_1(
hidl_vec<GnssSvInfo> gnssSvInfoList) {
- ALOGD("GnssHidlHal::filterBlocklistSatellitesV2_1");
if (mGnssConfigurationAidl == nullptr) {
ALOGE("Handle to AIDL GnssConfiguration is not available.");
return gnssSvInfoList;
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index a66bfc1..fcc1f98 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -75,19 +75,20 @@
void GnssMeasurementInterface::stop() {
ALOGD("stop");
mIsActive = false;
- if (mThread.joinable()) {
- mThread.join();
- }
}
void GnssMeasurementInterface::reportMeasurement(const GnssData& data) {
ALOGD("reportMeasurement()");
- std::unique_lock<std::mutex> lock(mMutex);
- if (sCallback == nullptr) {
- ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
- return;
+ std::shared_ptr<IGnssMeasurementCallback> callbackCopy;
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sCallback == nullptr) {
+ ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
+ return;
+ }
+ callbackCopy = sCallback;
}
- sCallback->gnssMeasurementCb(data);
+ callbackCopy->gnssMeasurementCb(data);
}
} // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 67ccf52..5964f81 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -29,6 +29,7 @@
using android::hardware::gnss::BlocklistedSource;
using android::hardware::gnss::ElapsedRealtime;
using android::hardware::gnss::GnssClock;
+using android::hardware::gnss::GnssData;
using android::hardware::gnss::GnssMeasurement;
using android::hardware::gnss::GnssPowerStats;
using android::hardware::gnss::IGnss;
@@ -65,18 +66,158 @@
ASSERT_FALSE(status.isOk());
}
+void CheckSatellitePvt(const SatellitePvt& satellitePvt) {
+ const double kMaxOrbitRadiusMeters = 43000000.0;
+ const double kMaxVelocityMps = 4000.0;
+ // The below values are determined using GPS ICD Table 20-1
+ const double kMinHardwareCodeBiasMeters = -17.869;
+ const double kMaxHardwareCodeBiasMeters = 17.729;
+ const double kMaxTimeCorrelationMeters = 3e6;
+ const double kMaxSatClkDriftMps = 1.117;
+
+ ASSERT_TRUE(satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO ||
+ satellitePvt.flags & SatellitePvt::HAS_IONO ||
+ satellitePvt.flags & SatellitePvt::HAS_TROPO);
+ if (satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) {
+ ALOGD("Found HAS_POSITION_VELOCITY_CLOCK_INFO");
+ ASSERT_TRUE(satellitePvt.satPosEcef.posXMeters >= -kMaxOrbitRadiusMeters &&
+ satellitePvt.satPosEcef.posXMeters <= kMaxOrbitRadiusMeters);
+ ASSERT_TRUE(satellitePvt.satPosEcef.posYMeters >= -kMaxOrbitRadiusMeters &&
+ satellitePvt.satPosEcef.posYMeters <= kMaxOrbitRadiusMeters);
+ ASSERT_TRUE(satellitePvt.satPosEcef.posZMeters >= -kMaxOrbitRadiusMeters &&
+ satellitePvt.satPosEcef.posZMeters <= kMaxOrbitRadiusMeters);
+ ASSERT_TRUE(satellitePvt.satPosEcef.ureMeters > 0);
+ ASSERT_TRUE(satellitePvt.satVelEcef.velXMps >= -kMaxVelocityMps &&
+ satellitePvt.satVelEcef.velXMps <= kMaxVelocityMps);
+ ASSERT_TRUE(satellitePvt.satVelEcef.velYMps >= -kMaxVelocityMps &&
+ satellitePvt.satVelEcef.velYMps <= kMaxVelocityMps);
+ ASSERT_TRUE(satellitePvt.satVelEcef.velZMps >= -kMaxVelocityMps &&
+ satellitePvt.satVelEcef.velZMps <= kMaxVelocityMps);
+ ASSERT_TRUE(satellitePvt.satVelEcef.ureRateMps > 0);
+ ASSERT_TRUE(
+ satellitePvt.satClockInfo.satHardwareCodeBiasMeters > kMinHardwareCodeBiasMeters &&
+ satellitePvt.satClockInfo.satHardwareCodeBiasMeters < kMaxHardwareCodeBiasMeters);
+ ASSERT_TRUE(satellitePvt.satClockInfo.satTimeCorrectionMeters >
+ -kMaxTimeCorrelationMeters &&
+ satellitePvt.satClockInfo.satTimeCorrectionMeters < kMaxTimeCorrelationMeters);
+ ASSERT_TRUE(satellitePvt.satClockInfo.satClkDriftMps > -kMaxSatClkDriftMps &&
+ satellitePvt.satClockInfo.satClkDriftMps < kMaxSatClkDriftMps);
+ }
+ if (satellitePvt.flags & SatellitePvt::HAS_IONO) {
+ ALOGD("Found HAS_IONO");
+ ASSERT_TRUE(satellitePvt.ionoDelayMeters > 0 && satellitePvt.ionoDelayMeters < 100);
+ }
+ if (satellitePvt.flags & SatellitePvt::HAS_TROPO) {
+ ALOGD("Found HAS_TROPO");
+ ASSERT_TRUE(satellitePvt.tropoDelayMeters > 0 && satellitePvt.tropoDelayMeters < 100);
+ }
+}
+
+void CheckGnssMeasurementClockFields(const GnssData& measurement) {
+ ASSERT_TRUE(measurement.elapsedRealtime.flags >= 0 &&
+ measurement.elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS |
+ ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS));
+ if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIMESTAMP_NS) {
+ ASSERT_TRUE(measurement.elapsedRealtime.timestampNs > 0);
+ }
+ if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
+ ASSERT_TRUE(measurement.elapsedRealtime.timeUncertaintyNs > 0);
+ }
+ ASSERT_TRUE(measurement.clock.gnssClockFlags >= 0 &&
+ measurement.clock.gnssClockFlags <=
+ (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY |
+ GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS |
+ GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
+ GnssClock::HAS_DRIFT_UNCERTAINTY));
+}
+
+void CheckGnssMeasurementFlags(const GnssMeasurement& measurement) {
+ ASSERT_TRUE(measurement.flags >= 0 &&
+ measurement.flags <=
+ (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY |
+ GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE |
+ GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY |
+ GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL |
+ GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY |
+ GnssMeasurement::HAS_SATELLITE_ISB |
+ GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY |
+ GnssMeasurement::HAS_SATELLITE_PVT |
+ GnssMeasurement::HAS_CORRELATION_VECTOR));
+}
+
/*
- * TestGnssMeasurementExtension:
+ * TestGnssMeasurementExtensionAndSatellitePvt:
* 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
- * 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies fields are valid.
+ * 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies mandatory fields are
+ * valid.
+ * 3. If SatellitePvt is supported, waits for a measurement with SatellitePvt, and verifies the
+ * fields are valid.
*/
-TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
+TEST_P(GnssHalTest, TestGnssMeasurementExtensionAndSatellitePvt) {
+ const bool kIsSatellitePvtSupported =
+ aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT;
+ ALOGD("SatellitePvt supported: %s", kIsSatellitePvtSupported ? "true" : "false");
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+ const int kNumMeasurementEvents = 75;
+
+ sp<IGnssMeasurementInterface> iGnssMeasurement;
+ auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+ auto callback = sp<GnssMeasurementCallbackAidl>::make();
+ status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
+ /* enableCorrVecOutputs */ false);
+ ASSERT_TRUE(status.isOk());
+
+ bool satellitePvtFound = false;
+ for (int i = 0; i < kNumMeasurementEvents; i++) {
+ if (i > 0 && (!kIsSatellitePvtSupported || satellitePvtFound)) {
+ break;
+ }
+ GnssData lastMeasurement;
+ ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
+ kFirstGnssMeasurementTimeoutSeconds));
+ EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+
+ // Validity check GnssData fields
+ CheckGnssMeasurementClockFields(lastMeasurement);
+
+ for (const auto& measurement : lastMeasurement.measurements) {
+ CheckGnssMeasurementFlags(measurement);
+ if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT &&
+ kIsSatellitePvtSupported == true) {
+ ALOGD("Found a measurement with SatellitePvt");
+ satellitePvtFound = true;
+ CheckSatellitePvt(measurement.satellitePvt);
+ }
+ }
+ }
+ if (kIsSatellitePvtSupported) {
+ ASSERT_TRUE(satellitePvtFound);
+ }
+
+ status = iGnssMeasurement->close();
+ ASSERT_TRUE(status.isOk());
+}
+
+/*
+ * TestCorrelationVector:
+ * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
+ * 2. Sets a GnssMeasurementCallback, waits for GnssMeasurements with CorrelationVector, and
+ * verifies fields are valid.
+ */
+TEST_P(GnssHalTest, TestCorrelationVector) {
const bool kIsCorrelationVectorSupported = aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_CORRELATION_VECTOR;
+ const int kNumMeasurementEvents = 75;
+ // Pass the test if CorrelationVector is not supported
+ if (!kIsCorrelationVectorSupported) {
+ return;
+ }
+
const int kFirstGnssMeasurementTimeoutSeconds = 10;
-
- bool has_capability_satpvt = false;
-
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
@@ -88,96 +229,39 @@
/* enableCorrVecOutputs */ kIsCorrelationVectorSupported);
ASSERT_TRUE(status.isOk());
- android::hardware::gnss::GnssData lastMeasurement;
- ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
- kFirstGnssMeasurementTimeoutSeconds));
- EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), 1);
- ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
-
- // Validity check GnssData fields
- ASSERT_TRUE(
- lastMeasurement.elapsedRealtime.flags >= 0 &&
- lastMeasurement.elapsedRealtime.flags <=
- (ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS));
- if (lastMeasurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIMESTAMP_NS) {
- ASSERT_TRUE(lastMeasurement.elapsedRealtime.timestampNs > 0);
- }
- if (lastMeasurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
- ASSERT_TRUE(lastMeasurement.elapsedRealtime.timeUncertaintyNs > 0);
- }
- ASSERT_TRUE(lastMeasurement.clock.gnssClockFlags >= 0 &&
- lastMeasurement.clock.gnssClockFlags <=
- (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY |
- GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS |
- GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
- GnssClock::HAS_DRIFT_UNCERTAINTY));
-
- if (aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT) {
- has_capability_satpvt = true;
- }
- for (const auto& measurement : lastMeasurement.measurements) {
- ASSERT_TRUE(
- measurement.flags >= 0 &&
- measurement.flags <=
- (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY |
- GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE |
- GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY |
- GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL |
- GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY |
- GnssMeasurement::HAS_SATELLITE_ISB |
- GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY |
- GnssMeasurement::HAS_SATELLITE_PVT |
- GnssMeasurement::HAS_CORRELATION_VECTOR));
-
- if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT &&
- has_capability_satpvt == true) {
- if (measurement.satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) {
- ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posXMeters >= -43000000 &&
- measurement.satellitePvt.satPosEcef.posXMeters <= 43000000);
- ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posYMeters >= -43000000 &&
- measurement.satellitePvt.satPosEcef.posYMeters <= 43000000);
- ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posZMeters >= -43000000 &&
- measurement.satellitePvt.satPosEcef.posZMeters <= 43000000);
- ASSERT_TRUE(measurement.satellitePvt.satPosEcef.ureMeters > 0);
- ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velXMps >= -4000 &&
- measurement.satellitePvt.satVelEcef.velXMps <= 4000);
- ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velYMps >= -4000 &&
- measurement.satellitePvt.satVelEcef.velYMps <= 4000);
- ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velZMps >= -4000 &&
- measurement.satellitePvt.satVelEcef.velZMps <= 4000);
- ASSERT_TRUE(measurement.satellitePvt.satVelEcef.ureRateMps > 0);
- ASSERT_TRUE(
- measurement.satellitePvt.satClockInfo.satHardwareCodeBiasMeters > -17.869 &&
- measurement.satellitePvt.satClockInfo.satHardwareCodeBiasMeters < 17.729);
- ASSERT_TRUE(measurement.satellitePvt.satClockInfo.satTimeCorrectionMeters > -3e6 &&
- measurement.satellitePvt.satClockInfo.satTimeCorrectionMeters < 3e6);
- ASSERT_TRUE(measurement.satellitePvt.satClockInfo.satClkDriftMps > -1.117 &&
- measurement.satellitePvt.satClockInfo.satClkDriftMps < 1.117);
- }
- if (measurement.satellitePvt.flags & SatellitePvt::HAS_IONO) {
- ASSERT_TRUE(measurement.satellitePvt.ionoDelayMeters > 0 &&
- measurement.satellitePvt.ionoDelayMeters < 100);
- }
- if (measurement.satellitePvt.flags & SatellitePvt::HAS_TROPO) {
- ASSERT_TRUE(measurement.satellitePvt.tropoDelayMeters > 0 &&
- measurement.satellitePvt.tropoDelayMeters < 100);
- }
+ bool correlationVectorFound = false;
+ for (int i = 0; i < kNumMeasurementEvents; i++) {
+ // Pass the test if at least one CorrelationVector has been found.
+ if (correlationVectorFound) {
+ break;
}
+ GnssData lastMeasurement;
+ ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
+ kFirstGnssMeasurementTimeoutSeconds));
+ EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
- if (kIsCorrelationVectorSupported &&
- measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) {
- ASSERT_TRUE(measurement.correlationVectors.size() > 0);
- for (const auto& correlationVector : measurement.correlationVectors) {
- ASSERT_GE(correlationVector.frequencyOffsetMps, 0);
- ASSERT_GT(correlationVector.samplingWidthM, 0);
- ASSERT_GE(correlationVector.samplingStartM, 0);
- ASSERT_TRUE(correlationVector.magnitude.size() > 0);
- for (const auto& magnitude : correlationVector.magnitude) {
- ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767);
+ // Validity check GnssData fields
+ CheckGnssMeasurementClockFields(lastMeasurement);
+
+ for (const auto& measurement : lastMeasurement.measurements) {
+ CheckGnssMeasurementFlags(measurement);
+ if (measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) {
+ correlationVectorFound = true;
+ ASSERT_TRUE(measurement.correlationVectors.size() > 0);
+ for (const auto& correlationVector : measurement.correlationVectors) {
+ ASSERT_GE(correlationVector.frequencyOffsetMps, 0);
+ ASSERT_GT(correlationVector.samplingWidthM, 0);
+ ASSERT_GE(correlationVector.samplingStartM, 0);
+ ASSERT_TRUE(correlationVector.magnitude.size() > 0);
+ for (const auto& magnitude : correlationVector.magnitude) {
+ ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767);
+ }
}
}
}
}
+ ASSERT_TRUE(correlationVectorFound);
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
@@ -227,27 +311,42 @@
EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 2);
+
auto powerStats2 = gnssPowerIndicationCallback->last_gnss_power_stats_;
- // Elapsed realtime must increase
- EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
+ if ((gnssPowerIndicationCallback->last_capabilities_ &
+ (int)GnssPowerIndicationCallback::CAPABILITY_TOTAL)) {
+ // Elapsed realtime must increase
+ EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
- // Total energy must increase
- EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
+ // Total energy must increase
+ EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
+ }
// At least oone of singleband and multiband acquisition energy must increase
bool singlebandAcqEnergyIncreased = powerStats2.singlebandAcquisitionModeEnergyMilliJoule >
powerStats1.singlebandAcquisitionModeEnergyMilliJoule;
bool multibandAcqEnergyIncreased = powerStats2.multibandAcquisitionModeEnergyMilliJoule >
powerStats1.multibandAcquisitionModeEnergyMilliJoule;
- EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
+
+ if ((gnssPowerIndicationCallback->last_capabilities_ &
+ (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION) ||
+ (gnssPowerIndicationCallback->last_capabilities_ &
+ (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION)) {
+ EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
+ }
// At least one of singleband and multiband tracking energy must increase
bool singlebandTrackingEnergyIncreased = powerStats2.singlebandTrackingModeEnergyMilliJoule >
powerStats1.singlebandTrackingModeEnergyMilliJoule;
bool multibandTrackingEnergyIncreased = powerStats2.multibandTrackingModeEnergyMilliJoule >
powerStats1.multibandTrackingModeEnergyMilliJoule;
- EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
+ if ((gnssPowerIndicationCallback->last_capabilities_ &
+ (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING) ||
+ (gnssPowerIndicationCallback->last_capabilities_ &
+ (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING)) {
+ EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
+ }
// Clean up
StopAndClearLocations();
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 4b6b7c8..55aaf12 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -308,6 +308,12 @@
writer->reset();
}
+NativeHandleWrapper::~NativeHandleWrapper() {
+ if (mHandle) {
+ mGralloc.freeBuffer(mHandle);
+ }
+}
+
Gralloc::Gralloc() {
[this] {
ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>("default", "default",
@@ -324,9 +330,10 @@
}();
}
-const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import,
- uint32_t* outStride) {
+const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+ PixelFormat format, uint64_t usage, bool import,
+ uint32_t* outStride) {
+ const native_handle_t* handle;
if (mGralloc4) {
IMapper4::BufferDescriptorInfo info{};
info.width = width;
@@ -334,7 +341,7 @@
info.layerCount = layerCount;
info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
info.usage = usage;
- return mGralloc4->allocate(info, import, outStride);
+ handle = mGralloc4->allocate(info, import, outStride);
} else if (mGralloc3) {
IMapper3::BufferDescriptorInfo info{};
info.width = width;
@@ -342,7 +349,7 @@
info.layerCount = layerCount;
info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
info.usage = usage;
- return mGralloc3->allocate(info, import, outStride);
+ handle = mGralloc3->allocate(info, import, outStride);
} else {
IMapper2::BufferDescriptorInfo info{};
info.width = width;
@@ -350,8 +357,9 @@
info.layerCount = layerCount;
info.format = format;
info.usage = usage;
- return mGralloc2->allocate(info, import, outStride);
+ handle = mGralloc2->allocate(info, import, outStride);
}
+ return NativeHandleWrapper(*this, handle);
}
void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 63aa713..2949823 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -136,13 +136,30 @@
int32_t height;
};
+class Gralloc;
+
+// RAII wrapper around native_handle_t*
+class NativeHandleWrapper {
+ public:
+ NativeHandleWrapper(Gralloc& gralloc, const native_handle_t* handle)
+ : mGralloc(gralloc), mHandle(handle) {}
+
+ ~NativeHandleWrapper();
+
+ const native_handle_t* get() { return mHandle; }
+
+ private:
+ Gralloc& mGralloc;
+ const native_handle_t* mHandle;
+};
+
class Gralloc {
public:
explicit Gralloc();
- const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import = true,
- uint32_t* outStride = nullptr);
+ const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+ PixelFormat format, uint64_t usage, bool import = true,
+ uint32_t* outStride = nullptr);
void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const AccessRegion& accessRegionRect, int acquireFence);
diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
index 0b42d2e..ea06752 100644
--- a/graphics/composer/2.1/vts/OWNERS
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -1,6 +1,6 @@
# Graphics team
+adyabr@google.com
lpy@google.com
-vhau@google.com
# VTS team
yim@google.com
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index f0250c0..4822678 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -666,7 +666,7 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- const native_handle_t* allocate() {
+ NativeHandleWrapper allocate() {
uint64_t usage =
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
BufferUsage::COMPOSER_OVERLAY);
@@ -727,11 +727,11 @@
display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
kBufferSlotCount, &format));
- const native_handle_t* handle;
- ASSERT_NO_FATAL_FAILURE(handle = allocate());
+ std::unique_ptr<NativeHandleWrapper> handle;
+ ASSERT_NO_FATAL_FAILURE(handle.reset(new NativeHandleWrapper(allocate())));
mWriter->selectDisplay(display);
- mWriter->setOutputBuffer(0, handle, -1);
+ mWriter->setOutputBuffer(0, handle->get(), -1);
execute();
}
@@ -783,7 +783,7 @@
mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE);
auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ ASSERT_NE(nullptr, handle.get());
IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
@@ -800,7 +800,7 @@
mWriter->setLayerZOrder(10);
mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
- mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerBuffer(0, handle.get(), -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
@@ -817,8 +817,8 @@
mWriter->selectLayer(layer);
auto handle2 = allocate();
- ASSERT_NE(nullptr, handle2);
- mWriter->setLayerBuffer(0, handle2, -1);
+ ASSERT_NE(nullptr, handle2.get());
+ mWriter->setLayerBuffer(0, handle2.get(), -1);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
mWriter->presentDisplay();
execute();
@@ -833,12 +833,12 @@
mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ ASSERT_NE(nullptr, handle.get());
IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerBuffer(0, handle.get(), -1);
mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
mWriter->setLayerDisplayFrame(displayFrame);
mWriter->setLayerPlaneAlpha(1);
@@ -871,7 +871,7 @@
*/
TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ ASSERT_NE(nullptr, handle.get());
Layer layer;
ASSERT_NO_FATAL_FAILURE(layer =
@@ -879,7 +879,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerBuffer(0, handle.get(), -1);
execute();
}
@@ -1003,7 +1003,7 @@
}
auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ ASSERT_NE(nullptr, handle.get());
Layer layer;
ASSERT_NO_FATAL_FAILURE(layer =
@@ -1011,7 +1011,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerSidebandStream(handle);
+ mWriter->setLayerSidebandStream(handle.get());
execute();
}
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index 19f5e8c..30596fc 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -208,22 +208,13 @@
mAccessRegion.height = height;
}
-ReadbackBuffer::~ReadbackBuffer() {
- if (mBufferHandle != nullptr) {
- mGralloc->freeBuffer(mBufferHandle);
- }
-}
-
void ReadbackBuffer::setReadbackBuffer() {
- if (mBufferHandle != nullptr) {
- mGralloc->freeBuffer(mBufferHandle);
- mBufferHandle = nullptr;
- }
- mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
- /*import*/ true, &mStride);
- ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
- mFormat, mUsage, mStride));
- ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
+ mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
+ mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+ /*import*/ true, &mStride)));
+ ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
+ mLayerCount, mFormat, mUsage, mStride));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
}
void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
@@ -231,11 +222,11 @@
int32_t fenceHandle;
ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
- void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle);
+ void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
mPixelFormat);
- int32_t unlockFence = mGralloc->unlock(mBufferHandle);
+ int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
if (unlockFence != -1) {
sync_wait(unlockFence, -1);
close(unlockFence);
@@ -281,23 +272,17 @@
setSourceCrop({0, 0, (float)width, (float)height});
}
-TestBufferLayer::~TestBufferLayer() {
- if (mBufferHandle != nullptr) {
- mGralloc->freeBuffer(mBufferHandle);
- }
-}
-
void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
TestLayer::write(writer);
writer->setLayerCompositionType(mComposition);
writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
- if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+ if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence);
}
LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
layerSettings.source.buffer.buffer = std::make_shared<renderengine::ExternalTexture>(
- new GraphicBuffer(mBufferHandle, GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
+ new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
static_cast<int32_t>(mFormat), 1, mUsage, mStride),
mRenderEngine.getInternalRenderEngine(),
renderengine::ExternalTexture::Usage::READABLE);
@@ -318,10 +303,10 @@
}
void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
- void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1);
+ void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1);
ASSERT_NO_FATAL_FAILURE(
ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
- mFillFence = mGralloc->unlock(mBufferHandle);
+ mFillFence = mGralloc->unlock(mBufferHandle->get());
if (mFillFence != -1) {
sync_wait(mFillFence, -1);
close(mFillFence);
@@ -329,16 +314,13 @@
}
void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
- if (mBufferHandle != nullptr) {
- mGralloc->freeBuffer(mBufferHandle);
- mBufferHandle = nullptr;
- }
- mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
- /*import*/ true, &mStride);
- ASSERT_NE(nullptr, mBufferHandle);
+ mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
+ mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+ /*import*/ true, &mStride)));
+ ASSERT_NE(nullptr, mBufferHandle->get());
ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
- ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
- mFormat, mUsage, mStride));
+ ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
+ mLayerCount, mFormat, mUsage, mStride));
}
void TestBufferLayer::setDataspace(Dataspace dataspace,
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 6bc2732..d3bba17 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -93,10 +93,12 @@
class Gralloc : public V2_1::vts::Gralloc {
public:
+ using NativeHandleWrapper = V2_1::vts::NativeHandleWrapper;
+
Gralloc();
- const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import = true,
- uint32_t* outStride = nullptr) {
+ const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+ PixelFormat format, uint64_t usage, bool import = true,
+ uint32_t* outStride = nullptr) {
return V2_1::vts::Gralloc::allocate(
width, height, layerCount,
static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format), usage,
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
index b24e3b6..58efde9 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -25,6 +25,8 @@
#include <mapper-vts/2.1/MapperVts.h>
#include <renderengine/RenderEngine.h>
+#include <memory>
+
namespace android {
namespace hardware {
namespace graphics {
@@ -116,8 +118,6 @@
PixelFormat format,
IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
- ~TestBufferLayer();
-
void write(const std::shared_ptr<CommandWriterBase>& writer) override;
LayerSettings toRenderEngineLayerSettings() override;
@@ -143,7 +143,7 @@
std::shared_ptr<Gralloc> mGralloc;
TestRenderEngine& mRenderEngine;
int32_t mFillFence;
- const native_handle_t* mBufferHandle = nullptr;
+ std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle;
};
class ReadbackHelper {
@@ -182,7 +182,6 @@
ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
PixelFormat pixelFormat, Dataspace dataspace);
- ~ReadbackBuffer();
void setReadbackBuffer();
@@ -196,7 +195,7 @@
uint64_t mUsage;
AccessRegion mAccessRegion;
uint32_t mStride;
- const native_handle_t* mBufferHandle = nullptr;
+ std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle = nullptr;
PixelFormat mPixelFormat;
Dataspace mDataspace;
Display mDisplay;
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 8d52173..7a1568b 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -39,15 +39,13 @@
namespace vts {
namespace {
-using android::GraphicBuffer;
using android::Rect;
-using android::hardware::hidl_handle;
using common::V1_1::BufferUsage;
using common::V1_1::Dataspace;
using common::V1_1::PixelFormat;
-using mapper::V2_1::IMapper;
using V2_1::Config;
using V2_1::Display;
+using V2_1::vts::NativeHandleWrapper;
using V2_1::vts::TestCommandReader;
using vts::Gralloc;
@@ -355,9 +353,9 @@
// This following buffer call should have no effect
uint64_t usage =
static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
- const native_handle_t* bufferHandle =
+ NativeHandleWrapper bufferHandle =
mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
- mWriter->setLayerBuffer(0, bufferHandle, -1);
+ mWriter->setLayerBuffer(0, bufferHandle.get(), -1);
// expected color for each pixel
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
@@ -465,24 +463,24 @@
// create client target buffer
uint32_t clientStride;
- const native_handle_t* clientBufferHandle =
+ NativeHandleWrapper clientBufferHandle =
mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount,
clientFormat, clientUsage, /*import*/ true, &clientStride);
- ASSERT_NE(nullptr, clientBufferHandle);
+ ASSERT_NE(nullptr, clientBufferHandle.get());
void* clientBufData =
- mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1);
+ mGralloc->lock(clientBufferHandle.get(), clientUsage, layer->mAccessRegion, -1);
ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight,
clientStride, clientBufData,
clientFormat, expectedColors));
- int clientFence = mGralloc->unlock(clientBufferHandle);
+ int clientFence = mGralloc->unlock(clientBufferHandle.get());
if (clientFence != -1) {
sync_wait(clientFence, -1);
close(clientFence);
}
- mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace,
+ mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
std::vector<IComposerClient::Rect>(1, damage));
layer->setToClientComposition(mWriter);
@@ -593,12 +591,12 @@
// create client target buffer
ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
uint32_t clientStride;
- const native_handle_t* clientBufferHandle =
+ NativeHandleWrapper clientBufferHandle =
mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount,
clientFormat, clientUsage, /*import*/ true, &clientStride);
- ASSERT_NE(nullptr, clientBufferHandle);
+ ASSERT_NE(nullptr, clientBufferHandle.get());
- void* clientBufData = mGralloc->lock(clientBufferHandle, clientUsage,
+ void* clientBufData = mGralloc->lock(clientBufferHandle.get(), clientUsage,
{0, 0, mDisplayWidth, mDisplayHeight}, -1);
std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
@@ -606,13 +604,13 @@
ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight,
clientStride, clientBufData,
clientFormat, clientColors));
- int clientFence = mGralloc->unlock(clientBufferHandle);
+ int clientFence = mGralloc->unlock(clientBufferHandle.get());
if (clientFence != -1) {
sync_wait(clientFence, -1);
close(clientFence);
}
- mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace,
+ mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
std::vector<IComposerClient::Rect>(1, clientFrame));
clientLayer->setToClientComposition(mWriter);
mWriter->validateDisplay();
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 31ec885..7e25a2e 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -36,13 +36,11 @@
namespace {
using common::V1_0::BufferUsage;
-using common::V1_0::ColorTransform;
-using common::V1_0::Transform;
using common::V1_1::ColorMode;
using common::V1_1::Dataspace;
using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
-using mapper::V2_0::IMapper;
+using V2_1::vts::NativeHandleWrapper;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
@@ -154,7 +152,7 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- const native_handle_t* allocate() {
+ NativeHandleWrapper allocate() {
uint64_t usage =
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
@@ -440,12 +438,12 @@
static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
std::unique_ptr<Gralloc> gralloc;
- const native_handle_t* buffer;
+ std::unique_ptr<NativeHandleWrapper> buffer;
ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
- ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
- mReadbackPixelFormat, usage));
+ ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
+ gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
- mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
+ mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->get(), -1);
}
/**
@@ -463,12 +461,13 @@
static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
std::unique_ptr<Gralloc> gralloc;
- const native_handle_t* buffer;
+ std::unique_ptr<NativeHandleWrapper> buffer;
ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
- ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
- mReadbackPixelFormat, usage));
+ ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
+ gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
- Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr);
+ Error error =
+ mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->get(), nullptr);
ASSERT_EQ(Error::BAD_DISPLAY, error);
}
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index 8b42654..54ba79d 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -38,12 +38,10 @@
namespace vts {
namespace {
-using common::V1_0::BufferUsage;
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 V2_2::vts::Gralloc;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
@@ -140,12 +138,6 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- const native_handle_t* allocate() {
- return mGralloc->allocate(
- 64, 64, 1, static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
- static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
- }
-
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
std::unique_ptr<CommandWriterBase> mWriter;
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 7d0a83b..5aceda7 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -52,8 +52,8 @@
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
using common::V1_2::PixelFormat;
-using mapper::V2_0::IMapper;
using V2_1::Layer;
+using V2_1::vts::NativeHandleWrapper;
using V2_2::Transform;
using V2_2::vts::Gralloc;
@@ -159,7 +159,7 @@
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- const native_handle_t* allocate(int32_t width, int32_t height) {
+ NativeHandleWrapper allocate(int32_t width, int32_t height) {
return mGralloc->allocate(
width, height, /*layerCount*/ 1,
static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
@@ -493,46 +493,53 @@
IComposerClient::FRect displayCrop = display.getCrop();
int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
- auto handle = allocate(displayWidth, displayHeight);
- ASSERT_NE(nullptr, handle);
-
Layer layer;
ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount));
- mWriter->selectLayer(layer);
- mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
- mWriter->setLayerDisplayFrame(display.getFrameRect());
- mWriter->setLayerPlaneAlpha(1);
- mWriter->setLayerSourceCrop(display.getCrop());
- mWriter->setLayerTransform(static_cast<Transform>(0));
- mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
- mWriter->setLayerZOrder(10);
- mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
- mWriter->setLayerBuffer(0, handle, -1);
- mWriter->setLayerDataspace(Dataspace::UNKNOWN);
- mWriter->validateDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
- mReader->mCompositionChanges.clear();
+ {
+ auto handle = allocate(displayWidth, displayHeight);
+ ASSERT_NE(nullptr, handle.get());
- mWriter->presentDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+ mWriter->setLayerDisplayFrame(display.getFrameRect());
+ mWriter->setLayerPlaneAlpha(1);
+ mWriter->setLayerSourceCrop(display.getCrop());
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerVisibleRegion(
+ std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+ mWriter->setLayerSurfaceDamage(
+ std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
+ mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
- mWriter->selectLayer(layer);
- auto handle2 = allocate(displayWidth, displayHeight);
- ASSERT_NE(nullptr, handle2);
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mReader->mCompositionChanges.clear();
- mWriter->setLayerBuffer(0, handle2, -1);
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
- mWriter->validateDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
- mReader->mCompositionChanges.clear();
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ }
- mWriter->presentDisplay();
- execute();
+ {
+ auto handle = allocate(displayWidth, displayHeight);
+ ASSERT_NE(nullptr, handle.get());
+
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mReader->mCompositionChanges.clear();
+
+ mWriter->presentDisplay();
+ execute();
+ }
ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer));
}
@@ -561,17 +568,28 @@
setActiveConfig(display, config1);
sendRefreshFrame(display, nullptr);
- int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
+ const auto vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
display.get(), config1,
IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
- int32_t vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
+ const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config1,
+ IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
+ const auto vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
display.get(), config2,
IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+ const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config2,
+ IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
if (vsyncPeriod1 == vsyncPeriod2) {
return; // continue
}
+ // We don't allow delayed change when changing config groups
+ if (params.delayForChange > 0 && configGroup1 != configGroup2) {
+ return; // continue
+ }
+
VsyncPeriodChangeTimeline timeline;
IComposerClient::VsyncPeriodChangeConstraints constraints = {
.desiredTimeNanos = systemTime() + params.delayForChange,
diff --git a/identity/TEST_MAPPING b/identity/TEST_MAPPING
index f35f4b7..85cf91f 100644
--- a/identity/TEST_MAPPING
+++ b/identity/TEST_MAPPING
@@ -8,6 +8,9 @@
},
{
"name": "android.hardware.identity-support-lib-test"
+ },
+ {
+ "name": "libeic_test"
}
]
}
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 7c68aee..28c4893 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -114,6 +114,43 @@
],
}
+cc_test {
+ name: "libeic_test",
+ srcs: [
+ "EicTests.cpp",
+ "FakeSecureHardwareProxy.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-g",
+ "-DEIC_DEBUG",
+ ],
+ local_include_dirs: [
+ "common",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcrypto",
+ "libkeymaster_messages",
+ ],
+ static_libs: [
+ "libbase",
+ "libcppbor_external",
+ "libcppcose_rkp",
+ "libutils",
+ "libsoft_attestation_cert",
+ "libkeymaster_portable",
+ "libsoft_attestation_cert",
+ "libpuresoftkeymasterdevice",
+ "android.hardware.identity-support-lib",
+ "android.hardware.identity-libeic-library",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+}
+
prebuilt_etc {
name: "android.hardware.identity_credential.xml",
sub_dir: "permissions",
diff --git a/identity/aidl/default/EicTests.cpp b/identity/aidl/default/EicTests.cpp
new file mode 100644
index 0000000..a28080d
--- /dev/null
+++ b/identity/aidl/default/EicTests.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021, 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 <gtest/gtest.h>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include "FakeSecureHardwareProxy.h"
+
+// Most of libeic is tested as part of VTS since there's almost a 1:1 mapping between
+// the HAL and libeic interfaces. This test suite is mainly for the few things which
+// doesn't map directly.
+//
+
+using std::optional;
+using std::string;
+using std::vector;
+
+using android::hardware::identity::AccessCheckResult;
+using android::hardware::identity::FakeSecureHardwarePresentationProxy;
+using android::hardware::identity::FakeSecureHardwareProvisioningProxy;
+
+TEST(EicTest, AccessControlIsEnforced) {
+ // First provision the credential...
+ //
+ FakeSecureHardwareProvisioningProxy provisioningProxy;
+ bool isTestCredential = false;
+ provisioningProxy.initialize(isTestCredential);
+ optional<vector<uint8_t>> credKey =
+ provisioningProxy.createCredentialKey({0x01, 0x02}, {0x03, 0x04});
+ ASSERT_TRUE(credKey.has_value());
+ string docType = "org.iso.18013.5.1.mDL";
+ ASSERT_TRUE(provisioningProxy.startPersonalization(0, {1}, docType, 125));
+
+ vector<int> acpIds = {};
+ string nameSpace = "org.iso.18013.5.1";
+ string name = "NonAccessibleElement";
+ vector<uint8_t> content = {0x63, 0x46, 0x6f, 0x6f}; // "Foo" tstr
+ ASSERT_TRUE(provisioningProxy.beginAddEntry(acpIds, nameSpace, name, content.size()));
+ optional<vector<uint8_t>> encContent =
+ provisioningProxy.addEntryValue(acpIds, nameSpace, name, content);
+ ASSERT_TRUE(encContent.has_value());
+ ASSERT_EQ(encContent->size(), content.size() + 28);
+
+ optional<vector<uint8_t>> signatureOfToBeSigned = provisioningProxy.finishAddingEntries();
+ ASSERT_TRUE(signatureOfToBeSigned.has_value());
+
+ optional<vector<uint8_t>> credData = provisioningProxy.finishGetCredentialData(docType);
+ ASSERT_TRUE(credData.has_value());
+ ASSERT_TRUE(provisioningProxy.shutdown());
+
+ // Then present data from it...
+ //
+ FakeSecureHardwarePresentationProxy presentationProxy;
+ ASSERT_TRUE(presentationProxy.initialize(isTestCredential, docType, credData.value()));
+ AccessCheckResult res =
+ presentationProxy.startRetrieveEntryValue(nameSpace, name, 1, content.size(), acpIds);
+ ASSERT_EQ(res, AccessCheckResult::kNoAccessControlProfiles);
+
+ // Ensure that we can't get the data out if startRetrieveEntryValue() returned
+ // something other than kOk... See b/190757775 for details.
+ //
+ optional<vector<uint8_t>> decContent =
+ presentationProxy.retrieveEntryValue(encContent.value(), nameSpace, name, acpIds);
+ ASSERT_FALSE(decContent.has_value());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 25f129b..200ee61 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -210,6 +210,15 @@
"numAccessControlProfileRemaining_ is not zero"));
}
+ // Ensure passed-in profile ids reference valid access control profiles
+ for (const int32_t id : accessControlProfileIds) {
+ if (accessControlProfileIds_.find(id) == accessControlProfileIds_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "An id in accessControlProfileIds references non-existing ACP"));
+ }
+ }
+
if (remainingEntryCounts_.size() == 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "No more namespaces to add to"));
diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c
index 9e033b3..3d13766 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -633,6 +633,8 @@
// We'll need to calc and store a digest of additionalData to check that it's the same
// additionalData being passed in for every eicPresentationRetrieveEntryValue() call...
+ //
+ ctx->accessCheckOk = false;
if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
nameSpace, name, additionalDataCbor,
additionalDataCborBufSize, &additionalDataCborSize,
@@ -680,6 +682,7 @@
if (result == EIC_ACCESS_CHECK_RESULT_OK) {
eicCborAppendString(&ctx->cbor, name);
+ ctx->accessCheckOk = true;
}
return result;
}
@@ -702,10 +705,15 @@
calculatedSha256)) {
return false;
}
+
if (eicCryptoMemCmp(calculatedSha256, ctx->additionalDataSha256, EIC_SHA256_DIGEST_SIZE) != 0) {
eicDebug("SHA-256 mismatch of additionalData");
return false;
}
+ if (!ctx->accessCheckOk) {
+ eicDebug("Attempting to retrieve a value for which access is not granted");
+ return false;
+ }
if (!eicOpsDecryptAes128Gcm(ctx->storageKey, encryptedContent, encryptedContentSize,
additionalDataCbor, additionalDataCborSize, content)) {
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index 7cad068..c888049 100644
--- a/identity/aidl/default/libeic/EicPresentation.h
+++ b/identity/aidl/default/libeic/EicPresentation.h
@@ -70,6 +70,10 @@
// Set to true initialized as a test credential.
bool testCredential;
+ // Set to true if the evaluation of access control checks in
+ // eicPresentationStartRetrieveEntryValue() resulted EIC_ACCESS_CHECK_RESULT_OK
+ bool accessCheckOk;
+
// These are bitmasks indicating which of the possible 32 access control profiles are
// authorized. They are built up by eicPresentationValidateAccessControlProfile().
//
diff --git a/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index d3addf4..7627c9c 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -102,7 +102,7 @@
ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
// Single entry - don't care about the returned encrypted data
- ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Some Data", 1).isOk());
+ ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
vector<uint8_t> encryptedData;
ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index fa0e293..c622193 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -102,7 +102,7 @@
ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
// Single entry - don't care about the returned encrypted data
- ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Some Data", 1).isOk());
+ ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
vector<uint8_t> encryptedData;
ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 4547624..7f4674d 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -644,7 +644,7 @@
// the VTS tests. Of course, this is a pretend-only game since hopefully no
// relying party is ever going to trust our batch key and those keys above
// it.
- ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
+ ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
keymaster_error_t error;
@@ -682,10 +682,9 @@
i2d_X509_NAME(subjectName.get(), &subjectPtr);
- uint64_t nowMilliSeconds = time(nullptr) * 1000;
::keymaster::AuthorizationSet auth_set(
::keymaster::AuthorizationSetBuilder()
- .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, nowMilliSeconds)
+ .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
.Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
.Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
challenge.size())
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index e170f4a..58945d3 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -26,7 +26,10 @@
cc_test {
name: "VtsHalInputClassifierV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"],
+ srcs: [
+ ":inputconstants_aidl",
+ "VtsHalInputClassifierV1_0TargetTest.cpp",
+ ],
header_libs: ["jni_headers"],
static_libs: [
"android.hardware.input.classifier@1.0",
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index bc294bd..342b3e2 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -71,6 +71,7 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_NULL* rollback_resistance;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@@ -78,56 +79,84 @@
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
- ASN1_NULL* trusted_user_presence_required;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
- TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL, TAG_ROLLBACK_RESISTANCE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
- TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
- TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
- TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
- TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
- TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER, TAG_VENDOR_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+ TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+ TAG_ROLLBACK_RESISTANCE.maskedTag()),
+
+ ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+ TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+ TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+ TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+ TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+ TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+ TAG_CREATION_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
+ TAG_VENDOR_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -259,6 +288,14 @@
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+ copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+ copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+ copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+ copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+ copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+ copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+ copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 9e37ed0..01c502c 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -96,6 +96,18 @@
return count > 0;
}
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ char value[PROPERTY_VALUE_MAX];
+ int len = property_get(prop, value, /* default = */ "");
+ if (len > 0) {
+ tags->Authorization(ttag, reinterpret_cast<const uint8_t*>(value),
+ static_cast<size_t>(len));
+ }
+}
+
constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
@@ -4409,6 +4421,95 @@
}
/*
+ * AttestationTest.EcAttestationID
+ *
+ * Verifies that attesting to EC keys with correct attestation ID fields works and generates the
+ * expected output.
+ */
+TEST_P(AttestationTest, EcAttestationID) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+ // Include one of the (valid) attestation ID tags.
+ builder.push_back(tag);
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ auto result = AttestKey(builder, &cert_chain);
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+ continue;
+ }
+
+ ASSERT_EQ(ErrorCode::OK, result);
+ EXPECT_GE(cert_chain.size(), 2U);
+
+ std::vector<KeyParameter> expected_hw_enforced = key_characteristics_.hardwareEnforced;
+ expected_hw_enforced.push_back(tag);
+
+ EXPECT_TRUE(verify_attestation_record(
+ "challenge", "foo", key_characteristics_.softwareEnforced,
+ hidl_vec<KeyParameter>(expected_hw_enforced), SecLevel(), cert_chain[0]));
+ }
+}
+
+/*
+ * AttestationTest.EcAttestationMismatchID
+ *
+ * Verifies that attesting to EC keys with incorrect attestation ID fields fails.
+ */
+TEST_P(AttestationTest, EcAttestationMismatchID) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+ // Collection of invalid attestation ID tags.
+ std::string invalid = "completely-invalid";
+ auto invalid_tags =
+ AuthorizationSetBuilder()
+ .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+ invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+ for (const KeyParameter& invalid_tag : invalid_tags) {
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+ // Include one of the invalid attestation ID tags.
+ builder.push_back(invalid_tag);
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ auto result = AttestKey(builder, &cert_chain);
+
+ EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result: " << static_cast<int32_t>(result);
+ }
+}
+
+/*
* AttestationTest.EcAttestationRequiresAttestationAppId
*
* Verifies that attesting to EC keys requires app ID
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 207a7e8..15230d5 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -79,6 +79,8 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_NULL* rollback_resistance;
+ ASN1_NULL* early_boot_only;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@@ -86,21 +88,27 @@
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
- ASN1_NULL* trusted_user_presence_required;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
- ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
ASN1_NULL* identity_credential_key;
} KM_AUTH_LIST;
@@ -116,6 +124,7 @@
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
@@ -138,12 +147,27 @@
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
@@ -279,6 +303,14 @@
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+ copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+ copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+ copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+ copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+ copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+ copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+ copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
index 40eb142..e8db56a 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -53,6 +53,14 @@
using V4_0::TAG_ASSOCIATED_DATA;
using V4_0::TAG_ATTESTATION_APPLICATION_ID;
using V4_0::TAG_ATTESTATION_CHALLENGE;
+using V4_0::TAG_ATTESTATION_ID_BRAND;
+using V4_0::TAG_ATTESTATION_ID_DEVICE;
+using V4_0::TAG_ATTESTATION_ID_IMEI;
+using V4_0::TAG_ATTESTATION_ID_MANUFACTURER;
+using V4_0::TAG_ATTESTATION_ID_MEID;
+using V4_0::TAG_ATTESTATION_ID_MODEL;
+using V4_0::TAG_ATTESTATION_ID_PRODUCT;
+using V4_0::TAG_ATTESTATION_ID_SERIAL;
using V4_0::TAG_AUTH_TIMEOUT;
using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
using V4_0::TAG_BLOCK_MODE;
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 0639da8..4a57f44 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "keymaster_hidl_hal_test"
#include <cutils/log.h>
+#include <vector>
#include "Keymaster4_1HidlTest.h"
@@ -26,6 +27,8 @@
#include <keymasterV4_1/attestation_record.h>
#include <keymasterV4_1/authorization_set.h>
+using android::hardware::keymaster::V4_0::test::add_tag_from_prop;
+
// Not to dump the attestation by default. Can enable by specify the parameter
// "--dump_attestations" on lunching VTS
static bool dumpAttestations = false;
@@ -172,10 +175,42 @@
attestation.software_enforced.Sort();
attestation.hardware_enforced.Sort();
- EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(attestation.software_enforced))
- << DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
- EXPECT_EQ(filter_tags(expected_hw_enforced), filter_tags(attestation.hardware_enforced))
- << DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
+ expected_sw_enforced = filter_tags(expected_sw_enforced);
+ expected_hw_enforced = filter_tags(expected_hw_enforced);
+ AuthorizationSet attestation_sw_enforced = filter_tags(attestation.software_enforced);
+ AuthorizationSet attestation_hw_enforced = filter_tags(attestation.hardware_enforced);
+
+ EXPECT_EQ(expected_sw_enforced, attestation_sw_enforced)
+ << DIFFERENCE(expected_sw_enforced, attestation_sw_enforced);
+ EXPECT_EQ(expected_hw_enforced, attestation_hw_enforced)
+ << DIFFERENCE(expected_hw_enforced, attestation_hw_enforced);
+}
+
+X509_Ptr parse_cert_blob(const std::vector<uint8_t>& blob) {
+ const uint8_t* p = blob.data();
+ return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
+}
+
+bool check_certificate_chain_signatures(const hidl_vec<hidl_vec<uint8_t>>& cert_chain) {
+ // TODO: Check that root is self-signed once b/187803288 is resolved.
+ for (size_t i = 0; i < cert_chain.size() - 1; ++i) {
+ X509_Ptr key_cert(parse_cert_blob(cert_chain[i]));
+ X509_Ptr signing_cert(parse_cert_blob(cert_chain[i + 1]));
+
+ if (!key_cert.get() || !signing_cert.get()) {
+ return false;
+ }
+
+ EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+ if (!signing_pubkey.get()) {
+ return false;
+ }
+
+ if (!X509_verify(key_cert.get(), signing_pubkey.get())) {
+ return false;
+ }
+ }
+ return true;
}
} // namespace
@@ -243,6 +278,7 @@
EXPECT_EQ(ErrorCode::OK, result);
EXPECT_EQ(2U, cert_chain.size());
+ EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
if (dumpAttestations) {
for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
}
@@ -289,6 +325,7 @@
EXPECT_EQ(ErrorCode::OK, result);
EXPECT_EQ(2U, cert_chain.size());
+ EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
if (dumpAttestations) {
for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
}
@@ -312,6 +349,106 @@
SecLevel());
}
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ HidlBuf challenge("challenge");
+ HidlBuf app_id("foo");
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+ builder.push_back(tag);
+ ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+ // It is optional for Strong box to support DeviceUniqueAttestation.
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+
+ ASSERT_EQ(ErrorCode::OK, result);
+ EXPECT_EQ(2U, cert_chain.size());
+ if (dumpAttestations) {
+ for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
+ }
+ auto [err, attestation] = parse_attestation_record(cert_chain[0]);
+ ASSERT_EQ(ErrorCode::OK, err);
+
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ hw_enforced.push_back(tag);
+ check_attestation_record(
+ attestation, challenge,
+ /* sw_enforced */
+ AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+ hw_enforced, SecLevel());
+ }
+}
+
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+ // Collection of invalid attestation ID tags.
+ std::string invalid = "completely-invalid";
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+ invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ HidlBuf challenge("challenge");
+ HidlBuf app_id("foo");
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+ builder.push_back(invalid_tag);
+ ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+ EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result: " << static_cast<int32_t>(result);
+ }
+}
+
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
} // namespace test
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
index f8c1fad..670ccfb 100644
--- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -18,6 +18,8 @@
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <android-base/properties.h>
+
#include <KeymasterHidlTest.h>
#include <keymasterV4_1/authorization_set.h>
@@ -159,3 +161,17 @@
android::hardware::PrintInstanceNameToString)
} // namespace android::hardware::keymaster::V4_1::test
+
+namespace android::hardware::keymaster::V4_0::test {
+
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+ if (!prop_value.empty()) {
+ tags->Authorization(ttag, prop_value.data(), prop_value.size());
+ }
+}
+
+} // namespace android::hardware::keymaster::V4_0::test
diff --git a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index e0b529f..94ce5c1 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -357,16 +357,40 @@
return false;
}
+ // If fallbackModel is not provided, call prepareModelFromCache.
+ // If fallbackModel is provided, and prepareModelFromCache returns GENERAL_FAILURE,
+ // then prepareModel(fallbackModel) will be called.
+ // This replicates the behaviour of the runtime when loading a model from cache.
+ // NNAPI Shim depends on this behaviour and may try to load the model from cache in
+ // prepareModel (shim needs model information when loading from cache).
void prepareModelFromCache(const std::vector<ndk::ScopedFileDescriptor>& modelCache,
const std::vector<ndk::ScopedFileDescriptor>& dataCache,
- std::shared_ptr<IPreparedModel>* preparedModel,
- ErrorStatus* status) {
+ std::shared_ptr<IPreparedModel>* preparedModel, ErrorStatus* status,
+ const Model* fallbackModel = nullptr) {
// Launch prepare model from cache.
std::shared_ptr<PreparedModelCallback> preparedModelCallback =
ndk::SharedRefBase::make<PreparedModelCallback>();
std::vector<uint8_t> cacheToken(std::begin(mToken), std::end(mToken));
- const auto prepareLaunchStatus = kDevice->prepareModelFromCache(
+ auto prepareLaunchStatus = kDevice->prepareModelFromCache(
kNoDeadline, modelCache, dataCache, cacheToken, preparedModelCallback);
+
+ // The shim does not support prepareModelFromCache() properly, but it
+ // will still attempt to create a model from cache when modelCache or
+ // dataCache is provided in prepareModel(). Instead of failing straight
+ // away, we try to utilize that other code path when fallbackModel is
+ // set. Note that we cannot verify whether the returned model was
+ // actually prepared from cache in that case.
+ if (!prepareLaunchStatus.isOk() &&
+ prepareLaunchStatus.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ static_cast<ErrorStatus>(prepareLaunchStatus.getServiceSpecificError()) ==
+ ErrorStatus::GENERAL_FAILURE &&
+ mIsCachingSupported && fallbackModel != nullptr) {
+ preparedModelCallback = ndk::SharedRefBase::make<PreparedModelCallback>();
+ prepareLaunchStatus = kDevice->prepareModel(
+ *fallbackModel, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority,
+ kNoDeadline, modelCache, dataCache, cacheToken, preparedModelCallback);
+ }
+
ASSERT_TRUE(prepareLaunchStatus.isOk() ||
prepareLaunchStatus.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< "prepareLaunchStatus: " << prepareLaunchStatus.getDescription();
@@ -382,6 +406,42 @@
*preparedModel = preparedModelCallback->getPreparedModel();
}
+ // Replicate behaviour of runtime when loading model from cache.
+ // Test if prepareModelFromCache behaves correctly when faced with bad
+ // arguments. If prepareModelFromCache is not supported (GENERAL_FAILURE),
+ // it attempts to call prepareModel with same arguments, which is expected either
+ // to not support the model (GENERAL_FAILURE) or return a valid model.
+ void verifyModelPreparationBehaviour(const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const Model* model, const TestModel& testModel) {
+ std::shared_ptr<IPreparedModel> preparedModel;
+ ErrorStatus status;
+
+ // Verify that prepareModelFromCache fails either due to bad
+ // arguments (INVALID_ARGUMENT) or GENERAL_FAILURE if not supported.
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+
+ // If caching is not supported, attempt calling prepareModel.
+ if (status == ErrorStatus::GENERAL_FAILURE) {
+ // Fallback with prepareModel should succeed regardless of cache files
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/model);
+ // Unless caching is not supported?
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ // But if it is, we should see a valid model.
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ ASSERT_NE(preparedModel, nullptr);
+ EvaluatePreparedModel(kDevice, preparedModel, testModel,
+ /*testKind=*/TestKind::GENERAL);
+ }
+ }
+ }
+
// Absolute path to the temporary cache directory.
std::string mCacheDir;
@@ -397,7 +457,7 @@
uint8_t mToken[static_cast<uint32_t>(IDevice::BYTE_SIZE_OF_CACHE_TOKEN)] = {};
uint32_t mNumModelCache;
uint32_t mNumDataCache;
- uint32_t mIsCachingSupported;
+ bool mIsCachingSupported;
const std::shared_ptr<IDevice> kDevice;
// The primary data type of the testModel.
@@ -438,7 +498,8 @@
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/&model);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
@@ -498,7 +559,8 @@
for (uint32_t i = 0; i < dataCache.size(); i++) {
ASSERT_GE(read(dataCache[i].get(), &placeholderByte, 1), 0);
}
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/&model);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
@@ -536,13 +598,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of model cache files smaller than mNumModelCache.
@@ -560,13 +616,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files greater than mNumDataCache.
@@ -583,13 +633,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files smaller than mNumDataCache.
@@ -607,13 +651,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -633,68 +671,48 @@
// Test with number of model cache files greater than mNumModelCache.
{
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
mModelCache.push_back({mTmpCache});
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.pop_back();
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of model cache files smaller than mNumModelCache.
if (mModelCache.size() > 0) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
auto tmp = mModelCache.back();
mModelCache.pop_back();
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.push_back(tmp);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files greater than mNumDataCache.
{
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
mDataCache.push_back({mTmpCache});
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.pop_back();
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files smaller than mNumDataCache.
if (mDataCache.size() > 0) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
auto tmp = mDataCache.back();
mDataCache.pop_back();
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.push_back(tmp);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -719,13 +737,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Go through each handle in data cache, test with invalid access mode.
@@ -741,13 +753,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -769,30 +775,23 @@
// Go through each handle in model cache, test with invalid access mode.
for (uint32_t i = 0; i < mNumModelCache; i++) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
modelCacheMode[i] = AccessMode::WRITE_ONLY;
createCacheFds(mModelCache, modelCacheMode, &modelCache);
createCacheFds(mDataCache, dataCacheMode, &dataCache);
modelCacheMode[i] = AccessMode::READ_WRITE;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Go through each handle in data cache, test with invalid access mode.
for (uint32_t i = 0; i < mNumDataCache; i++) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
dataCacheMode[i] = AccessMode::WRITE_ONLY;
createCacheFds(mModelCache, modelCacheMode, &modelCache);
createCacheFds(mDataCache, dataCacheMode, &dataCache);
dataCacheMode[i] = AccessMode::READ_WRITE;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -872,7 +871,8 @@
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
// The preparation may fail or succeed, but must not crash. If the preparation succeeds,
// the prepared model must be executed with the correct result and not crash.
@@ -933,7 +933,8 @@
// Spawn a thread to copy the cache content concurrently while preparing from cache.
std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
thread.join();
// The preparation may fail or succeed, but must not crash. If the preparation succeeds,
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 5bb088a..ffab66c 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -22,6 +22,7 @@
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <android/binder_status.h>
#include <unistd.h>
@@ -82,6 +83,11 @@
DurationWrapper(1000000000L, 4L),
};
+inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
+ return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
+ status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
+}
+
class PowerAidl : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -147,7 +153,7 @@
int64_t rate = -1;
auto status = power->getHintSessionPreferredRate(&rate);
if (!status.isOk()) {
- ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status));
return;
}
@@ -159,7 +165,7 @@
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
if (!status.isOk()) {
- ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status));
return;
}
ASSERT_NE(nullptr, session);
@@ -173,10 +179,9 @@
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
ASSERT_FALSE(status.isOk());
- if (EX_UNSUPPORTED_OPERATION == status.getExceptionCode()) {
+ if (isUnknownOrUnsupported(status)) {
return;
}
- // Test with empty tid list
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
}
@@ -184,7 +189,7 @@
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
if (!status.isOk()) {
- ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status));
return;
}
ASSERT_NE(nullptr, session);
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index de18279..a6eb2d8 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -19,6 +19,82 @@
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
/*
+ * Test IRadio.setAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ allowedNetworkTypesBitmap{};
+ allowedNetworkTypesBitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+ radio_v1_6->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
+ }
+}
+
+/*
+ * Test IRadio.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ allowedNetworkTypesBitmap{};
+ allowedNetworkTypesBitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+ radio_v1_6->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+ sleep(3); // wait for modem
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getAllowedNetworkTypesBitmap(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
+ }
+ }
+}
+
+/*
* Test IRadio.setupDataCall_1_6() for the response returned.
*/
TEST_P(RadioHidlTest_v1_6, setupDataCall_1_6) {
@@ -865,7 +941,11 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
- EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
if(pbCapacity.maxAdnRecords > 0
&& pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index b1e679b..e1b9f56 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -1172,10 +1172,13 @@
}
Return<void> RadioResponse_v1_6::getAllowedNetworkTypesBitmapResponse(
- const ::android::hardware::radio::V1_6::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const ::android::hardware::hidl_bitfield<
::android::hardware::radio::V1_4::RadioAccessFamily>
- /*networkTypeBitmap*/) {
+ networkTypeBitmap) {
+ rspInfo = info;
+ networkTypeBitmapResponse = networkTypeBitmap;
+ parent_v1_6.notify(info.serial);
return Void();
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index f93dbba..fd6bf65 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -159,18 +159,17 @@
* purpose [1] EXPLICIT SET OF INTEGER OPTIONAL,
* algorithm [2] EXPLICIT INTEGER OPTIONAL,
* keySize [3] EXPLICIT INTEGER OPTIONAL,
- * blockMode [4] EXPLICIT SET OF INTEGER OPTIONAL,
* digest [5] EXPLICIT SET OF INTEGER OPTIONAL,
* padding [6] EXPLICIT SET OF INTEGER OPTIONAL,
- * callerNonce [7] EXPLICIT NULL OPTIONAL,
- * minMacLength [8] EXPLICIT INTEGER OPTIONAL,
* ecCurve [10] EXPLICIT INTEGER OPTIONAL,
* rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL,
+ * mgfDigest [203] EXPLICIT SET OF INTEGER OPTIONAL,
* rollbackResistance [303] EXPLICIT NULL OPTIONAL,
+ * earlyBootOnly [305] EXPLICIT NULL OPTIONAL,
* activeDateTime [400] EXPLICIT INTEGER OPTIONAL,
* originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL,
* usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL,
- * userSecureId [502] EXPLICIT INTEGER OPTIONAL,
+ * usageCountLimit [405] EXPLICIT INTEGER OPTIONAL,
* noAuthRequired [503] EXPLICIT NULL OPTIONAL,
* userAuthType [504] EXPLICIT INTEGER OPTIONAL,
* authTimeout [505] EXPLICIT INTEGER OPTIONAL,
@@ -194,6 +193,7 @@
* attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL,
* vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL,
* bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL,
+ * deviceUniqueAttestation [720] EXPLICIT NULL OPTIONAL,
* }
*/
Certificate[] certificateChain;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 4ff4574..58e02b3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -831,14 +831,24 @@
/**
* DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attested key generation/import
* operations. It indicates that attestation using a device-unique key is requested, rather
- * than a batch key. When a device-unique key is used, only the attestation certificate is
- * returned; no additional chained certificates are provided. It's up to the caller to
- * recognize the device-unique signing key. Only SecurityLevel::STRONGBOX IKeyMintDevices may
- * support device-unique attestations. SecurityLevel::TRUSTED_ENVIRONMENT IKeyMintDevices must
- * return ErrorCode::INVALID_ARGUMENT if they receive DEVICE_UNIQUE_ATTESTATION.
+ * than a batch key. When a device-unique key is used, the returned chain should contain two
+ * certificates:
+ * * The attestation certificate, containing the attestation extension, as described in
+ KeyCreationResult.aidl.
+ * * A self-signed root certificate, signed by the device-unique key.
+ * No additional chained certificates are provided. Only SecurityLevel::STRONGBOX
+ * IKeyMintDevices may support device-unique attestations. SecurityLevel::TRUSTED_ENVIRONMENT
+ * IKeyMintDevices must return ErrorCode::INVALID_ARGUMENT if they receive
+ * DEVICE_UNIQUE_ATTESTATION.
* SecurityLevel::STRONGBOX IKeyMintDevices need not support DEVICE_UNIQUE_ATTESTATION, and
* return ErrorCode::CANNOT_ATTEST_IDS if they do not support it.
*
+ * The caller needs to obtain the device-unique keys out-of-band and compare them against the
+ * key used to sign the self-signed root certificate.
+ * To ease this process, the IKeyMintDevice implementation should include, both in the subject
+ * and issuer fields of the self-signed root, the unique identifier of the device. Using the
+ * unique identifier will make it straightforward for the caller to link a device to its key.
+ *
* IKeyMintDevice implementations that support device-unique attestation MUST add the
* DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
*/
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index b8699e9..a312723 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -141,11 +141,18 @@
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ // The returned key characteristics will include CREATION_DATETIME (checked below)
+ // in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
+ // call below, to match what getKeyCharacteristics() returns (which doesn't include
+ // any SecurityLevel::KEYSTORE characteristics).
+ CheckCharacteristics(attested_key_blob, attested_key_characteristics);
+
CheckedDeleteKey(&attested_key_blob);
CheckedDeleteKey(&attest_key.keyBlob);
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
// The client-specified CREATION_DATETIME should be in sw_enforced.
// Its presence will also trigger verify_attestation_record() to check that it
// is in the attestation extension with a matching value.
@@ -549,7 +556,7 @@
.EcdsaSigningKey(curve)
.AttestKey()
.SetDefaultValidity(),
- {} /* attestation siging key */, &attest_key.keyBlob,
+ {} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
ASSERT_GT(attest_key_cert_chain.size(), 0);
@@ -633,7 +640,7 @@
ErrorCode::OK,
GenerateKey(
AuthorizationSetBuilder().EcdsaSigningKey(EcCurve::P_256).SetDefaultValidity(),
- {} /* attestation siging key */, &non_attest_key.keyBlob,
+ {} /* attestation signing key */, &non_attest_key.keyBlob,
&non_attest_key_characteristics, &non_attest_key_cert_chain));
ASSERT_GT(non_attest_key_cert_chain.size(), 0);
@@ -655,6 +662,124 @@
&attested_key_cert_chain));
}
+TEST_P(AttestKeyTest, EcdsaAttestationID) {
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ ASSERT_GT(attest_key_cert_chain.size(), 0);
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+ // Use attestation key to sign an ECDSA key, but include an attestation ID field.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ builder.push_back(tag);
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+ continue;
+ }
+
+ ASSERT_EQ(result, ErrorCode::OK);
+
+ CheckedDeleteKey(&attested_key_blob);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
+ // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+ // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+ // attestation extension should contain them, so make sure the extra tag is added.
+ hw_enforced.push_back(tag);
+
+ EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
+ SecLevel(),
+ attested_key_cert_chain[0].encodedCertificate));
+ }
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
+TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ ASSERT_GT(attest_key_cert_chain.size(), 0);
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Collection of invalid attestation ID tags.
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+
+ // Use attestation key to sign an ECDSA key, but include an invalid
+ // attestation ID field.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ builder.push_back(invalid_tag);
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+
+ ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result = " << result;
+ }
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index b0f056a..a3ed3ad 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -29,7 +29,7 @@
protected:
void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob,
const vector<KeyCharacteristics>& key_characteristics,
- const AuthorizationSet& hw_enforced, int key_size) {
+ const AuthorizationSet& hw_enforced) {
ASSERT_GT(cert_chain_.size(), 0);
if (KeyMintAidlTestBase::dump_Attestations) {
@@ -40,10 +40,11 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) << "Key size missing";
-
+ // The device-unique attestation chain should contain exactly two certificates:
+ // * The leaf with the attestation extension.
+ // * A self-signed root, signed using the device-unique key.
+ ASSERT_EQ(cert_chain_.size(), 2);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
- ASSERT_GT(cert_chain_.size(), 0);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
@@ -133,17 +134,32 @@
ASSERT_EQ(ErrorCode::OK, result);
- AuthorizationSet hw_enforced = AuthorizationSetBuilder()
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::SHA_2_256)
- .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
- .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
- .Authorization(TAG_OS_VERSION, os_version())
- .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
- CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
+
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
}
/*
@@ -157,11 +173,10 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- int key_size = 256;
auto result = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.AttestationChallenge("challenge")
@@ -173,17 +188,137 @@
if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
ASSERT_EQ(ErrorCode::OK, result);
- AuthorizationSet hw_enforced = AuthorizationSetBuilder()
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_EC_CURVE, EcCurve::P_256)
- .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
- .Authorization(TAG_OS_VERSION, os_version())
- .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
- CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationID
+ *
+ * Verifies that device unique attestation can include IDs that do match the
+ * local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ builder.push_back(tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+ // It is optional for Strong box to support DeviceUniqueAttestation.
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+ ASSERT_EQ(ErrorCode::OK, result);
+
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ // Expect the specified tag to be present in the attestation extension.
+ hw_enforced.push_back(tag);
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+ }
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationMismatchID
+ *
+ * Verifies that device unique attestation rejects attempts to attest to IDs that
+ * don't match the local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ // Collection of invalid attestation ID tags.
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ // Add the tag that doesn't match the local device's real ID.
+ builder.push_back(invalid_tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+ ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG);
+ }
}
INSTANTIATE_KEYMINT_AIDL_TEST(DeviceUniqueAttestationTest);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index a9a67bc..44b8274 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -142,6 +142,15 @@
return filtered;
}
+// Remove any SecurityLevel::KEYSTORE entries from a list of key characteristics.
+void strip_keystore_tags(vector<KeyCharacteristics>* characteristics) {
+ characteristics->erase(std::remove_if(characteristics->begin(), characteristics->end(),
+ [](const auto& entry) {
+ return entry.securityLevel == SecurityLevel::KEYSTORE;
+ }),
+ characteristics->end());
+}
+
string x509NameToStr(X509_NAME* name) {
char* s = X509_NAME_oneline(name, nullptr, 0);
string retval(s);
@@ -320,6 +329,65 @@
return GetReturnErrorCode(result);
}
+ErrorCode KeyMintAidlTestBase::GetCharacteristics(const vector<uint8_t>& key_blob,
+ const vector<uint8_t>& app_id,
+ const vector<uint8_t>& app_data,
+ vector<KeyCharacteristics>* key_characteristics) {
+ Status result =
+ keymint_->getKeyCharacteristics(key_blob, app_id, app_data, key_characteristics);
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::GetCharacteristics(const vector<uint8_t>& key_blob,
+ vector<KeyCharacteristics>* key_characteristics) {
+ vector<uint8_t> empty_app_id, empty_app_data;
+ return GetCharacteristics(key_blob, empty_app_id, empty_app_data, key_characteristics);
+}
+
+void KeyMintAidlTestBase::CheckCharacteristics(
+ const vector<uint8_t>& key_blob,
+ const vector<KeyCharacteristics>& generate_characteristics) {
+ // Any key characteristics that were in SecurityLevel::KEYSTORE when returned from
+ // generateKey() should be excluded, as KeyMint will have no record of them.
+ // This applies to CREATION_DATETIME in particular.
+ vector<KeyCharacteristics> expected_characteristics(generate_characteristics);
+ strip_keystore_tags(&expected_characteristics);
+
+ vector<KeyCharacteristics> retrieved;
+ ASSERT_EQ(ErrorCode::OK, GetCharacteristics(key_blob, &retrieved));
+ EXPECT_EQ(expected_characteristics, retrieved);
+}
+
+void KeyMintAidlTestBase::CheckAppIdCharacteristics(
+ const vector<uint8_t>& key_blob, std::string_view app_id_string,
+ std::string_view app_data_string,
+ const vector<KeyCharacteristics>& generate_characteristics) {
+ // Exclude any SecurityLevel::KEYSTORE characteristics for comparisons.
+ vector<KeyCharacteristics> expected_characteristics(generate_characteristics);
+ strip_keystore_tags(&expected_characteristics);
+
+ vector<uint8_t> app_id(app_id_string.begin(), app_id_string.end());
+ vector<uint8_t> app_data(app_data_string.begin(), app_data_string.end());
+ vector<KeyCharacteristics> retrieved;
+ ASSERT_EQ(ErrorCode::OK, GetCharacteristics(key_blob, app_id, app_data, &retrieved));
+ EXPECT_EQ(expected_characteristics, retrieved);
+
+ // Check that key characteristics can't be retrieved if the app ID or app data is missing.
+ vector<uint8_t> empty;
+ vector<KeyCharacteristics> not_retrieved;
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, empty, app_data, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, app_id, empty, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, empty, empty, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+}
+
ErrorCode KeyMintAidlTestBase::DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
Status result = keymint_->deleteKey(*key_blob);
if (!keep_key_blob) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index d8f1bb3..82f192a 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -16,8 +16,12 @@
#pragma once
+#include <functional>
+#include <string_view>
+
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <android-base/properties.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <gtest/gtest.h>
@@ -104,6 +108,18 @@
unwrapping_params, 0 /* password_sid */, 0 /* biometric_sid */);
}
+ ErrorCode GetCharacteristics(const vector<uint8_t>& key_blob, const vector<uint8_t>& app_id,
+ const vector<uint8_t>& app_data,
+ vector<KeyCharacteristics>* key_characteristics);
+ ErrorCode GetCharacteristics(const vector<uint8_t>& key_blob,
+ vector<KeyCharacteristics>* key_characteristics);
+
+ void CheckCharacteristics(const vector<uint8_t>& key_blob,
+ const vector<KeyCharacteristics>& generate_characteristics);
+ void CheckAppIdCharacteristics(const vector<uint8_t>& key_blob, std::string_view app_id_string,
+ std::string_view app_data_string,
+ const vector<KeyCharacteristics>& generate_characteristics);
+
ErrorCode DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
ErrorCode DeleteKey(bool keep_key_blob = false);
@@ -192,50 +208,58 @@
template <typename TagType>
std::tuple<KeyData /* aesKey */, KeyData /* hmacKey */, KeyData /* rsaKey */,
KeyData /* ecdsaKey */>
- CreateTestKeys(TagType tagToTest, ErrorCode expectedReturn) {
+ CreateTestKeys(
+ TagType tagToTest, ErrorCode expectedReturn,
+ std::function<void(AuthorizationSetBuilder*)> tagModifier =
+ [](AuthorizationSetBuilder*) {}) {
/* AES */
KeyData aesKeyData;
- ErrorCode errorCode = GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(tagToTest)
- .BlockMode(BlockMode::ECB)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED),
- &aesKeyData.blob, &aesKeyData.characteristics);
+ AuthorizationSetBuilder aesBuilder = AuthorizationSetBuilder()
+ .AesEncryptionKey(128)
+ .Authorization(tagToTest)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ tagModifier(&aesBuilder);
+ ErrorCode errorCode =
+ GenerateKey(aesBuilder, &aesKeyData.blob, &aesKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* HMAC */
KeyData hmacKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Authorization(tagToTest)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)
- .Authorization(TAG_NO_AUTH_REQUIRED),
- &hmacKeyData.blob, &hmacKeyData.characteristics);
+ AuthorizationSetBuilder hmacBuilder = AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Authorization(tagToTest)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ tagModifier(&hmacBuilder);
+ errorCode = GenerateKey(hmacBuilder, &hmacKeyData.blob, &hmacKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* RSA */
KeyData rsaKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Authorization(tagToTest)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &rsaKeyData.blob, &rsaKeyData.characteristics);
+ AuthorizationSetBuilder rsaBuilder = AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Authorization(tagToTest)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity();
+ tagModifier(&rsaBuilder);
+ errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* ECDSA */
KeyData ecdsaKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(256)
- .Authorization(tagToTest)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
+ AuthorizationSetBuilder ecdsaBuilder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(256)
+ .Authorization(tagToTest)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity();
+ tagModifier(&ecdsaBuilder);
+ errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
}
@@ -290,6 +314,16 @@
long challenge_;
};
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+ if (!prop_value.empty()) {
+ tags->Authorization(ttag, prop_value.data(), prop_value.size());
+ }
+}
+
vector<uint8_t> build_serial_blob(const uint64_t serial_int);
void verify_subject(const X509* cert, const string& subject, bool self_signed);
void verify_serial(X509* cert, const uint64_t expected_serial);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 8b1eb30..295be1a 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -560,6 +560,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -742,6 +743,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -788,6 +790,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -865,6 +868,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -911,6 +915,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -978,6 +983,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1108,6 +1114,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1176,6 +1183,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1211,6 +1219,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1266,6 +1275,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1362,6 +1372,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1405,6 +1416,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1452,6 +1464,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1511,6 +1524,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1555,6 +1569,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1594,6 +1609,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1726,6 +1742,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -1761,6 +1778,7 @@
ASSERT_GT(key_blob.size(), 0U);
ASSERT_EQ(cert_chain_.size(), 0);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -1791,6 +1809,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -2044,6 +2063,9 @@
.Authorization(TAG_APPLICATION_ID, "clientid")
.Authorization(TAG_APPLICATION_DATA, "appdata")
.SetDefaultValidity()));
+
+ CheckAppIdCharacteristics(key_blob_, "clientid", "appdata", key_characteristics_);
+
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN,
AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
@@ -2558,6 +2580,9 @@
.Authorization(TAG_APPLICATION_ID, "clientid")
.Authorization(TAG_APPLICATION_DATA, "appdata")
.SetDefaultValidity()));
+
+ CheckAppIdCharacteristics(key_blob_, "clientid", "appdata", key_characteristics_);
+
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE)));
AbortIfNeeded();
@@ -6330,6 +6355,11 @@
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+ for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ ASSERT_GT(keyData.blob.size(), 0U);
+ AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
+ }
CheckedDeleteKey(&aesKeyData.blob);
CheckedDeleteKey(&hmacKeyData.blob);
CheckedDeleteKey(&rsaKeyData.blob);
@@ -6337,7 +6367,30 @@
}
/*
- * EarlyBootKeyTest.UsetEarlyBootKeyFailure
+ * EarlyBootKeyTest.CreateAttestedEarlyBootKey
+ *
+ * Verifies that creating an early boot key with attestation succeeds.
+ */
+TEST_P(EarlyBootKeyTest, CreateAttestedEarlyBootKey) {
+ auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] = CreateTestKeys(
+ TAG_EARLY_BOOT_ONLY, ErrorCode::OK, [](AuthorizationSetBuilder* builder) {
+ builder->AttestationChallenge("challenge");
+ builder->AttestationApplicationId("app_id");
+ });
+
+ for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ ASSERT_GT(keyData.blob.size(), 0U);
+ AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
+ }
+ CheckedDeleteKey(&aesKeyData.blob);
+ CheckedDeleteKey(&hmacKeyData.blob);
+ CheckedDeleteKey(&rsaKeyData.blob);
+ CheckedDeleteKey(&ecdsaKeyData.blob);
+}
+
+/*
+ * EarlyBootKeyTest.UseEarlyBootKeyFailure
*
* Verifies that using early boot keys at a later stage fails.
*/
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index a2071c2..a177317 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -340,6 +340,7 @@
cppbor::Array() // SignedMacAad
.add(challenge_)
.add(std::move(deviceInfoMap))
+ .add(keysToSignMac)
.encode());
ASSERT_TRUE(macKey) << macKey.message();
diff --git a/security/keymint/support/attestation_record.cpp b/security/keymint/support/attestation_record.cpp
index a48f770..2462228 100644
--- a/security/keymint/support/attestation_record.cpp
+++ b/security/keymint/support/attestation_record.cpp
@@ -64,6 +64,7 @@
} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+// Fields ordered in tag order.
typedef struct km_auth_list {
ASN1_INTEGER_SET* purpose;
ASN1_INTEGER* algorithm;
@@ -72,32 +73,38 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_INTEGER_SET* mgf_digest;
+ ASN1_NULL* rollback_resistance;
+ ASN1_NULL* early_boot_only;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
+ ASN1_INTEGER* usage_count_limit;
ASN1_NULL* no_auth_required;
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
- ASN1_NULL* all_applications;
- ASN1_OCTET_STRING* application_id;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
- ASN1_NULL* trusted_user_presence_required;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
- ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
- ASN1_NULL* storage_key;
ASN1_NULL* identity_credential;
- ASN1_INTEGER* usage_count_limit;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -109,13 +116,18 @@
ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, mgf_digest, ASN1_INTEGER,
+ TAG_RSA_OAEP_MGF_DIGEST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
+ TAG_USAGE_COUNT_LIMIT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
@@ -133,19 +145,31 @@
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, storage_key, ASN1_NULL, TAG_STORAGE_KEY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
- TAG_USAGE_COUNT_LIMIT.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -155,9 +179,9 @@
ASN1_INTEGER* keymint_version;
ASN1_ENUMERATED* keymint_security_level;
ASN1_OCTET_STRING* attestation_challenge;
+ ASN1_INTEGER* unique_id;
KM_AUTH_LIST* software_enforced;
KM_AUTH_LIST* tee_enforced;
- ASN1_INTEGER* unique_id;
} KM_KEY_DESCRIPTION;
ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
@@ -253,41 +277,52 @@
}
// Extract the values from the specified ASN.1 record and place them in auth_list.
+// Does nothing with root-of-trust field.
static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
if (!record) return ErrorCode::OK;
- copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
- copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
- copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
- copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
- copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
- copyAuthTag(record->digest, TAG_DIGEST, auth_list);
- copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
- copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
- copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
- copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
- copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
- copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
- copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
- copyAuthTag(record->padding, TAG_PADDING, auth_list);
+ // Fields ordered in tag order.
copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
- copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+ copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+ copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+ copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+ copyAuthTag(record->padding, TAG_PADDING, auth_list);
+ copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+ copyAuthTag(record->mgf_digest, TAG_RSA_OAEP_MGF_DIGEST, auth_list);
+ copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+ copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+ copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+ copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+ copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
+ copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
- copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
- copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
- copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
+ copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+ copyAuthTag(record->allow_while_on_body, TAG_ALLOW_WHILE_ON_BODY, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
auth_list);
copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
auth_list);
copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
- copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+ copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+ copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+ // root_of_trust dealt with separately
+ copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+ copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
+ copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+ copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+ copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+ copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+ copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+ copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+ copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+ copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
+ copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
+ copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
- copyAuthTag(record->storage_key, TAG_STORAGE_KEY, auth_list);
copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
- copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
return ErrorCode::OK;
}
diff --git a/security/keymint/support/keymint_utils.cpp b/security/keymint/support/keymint_utils.cpp
index 2dbdfa8..1e0733f 100644
--- a/security/keymint/support/keymint_utils.cpp
+++ b/security/keymint/support/keymint_utils.cpp
@@ -32,10 +32,11 @@
constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
-constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
constexpr size_t kYearMatch = 1;
constexpr size_t kMonthMatch = 2;
-constexpr size_t kPatchlevelMatchCount = kMonthMatch + 1;
+constexpr size_t kDayMatch = 3;
+constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
if (match.rm_so == -1) return 0;
@@ -53,8 +54,6 @@
return prop_value;
}
-} // anonymous namespace
-
uint32_t getOsVersion(const char* version_str) {
regex_t regex;
if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) {
@@ -76,12 +75,9 @@
return (major * 100 + minor) * 100 + subminor;
}
-uint32_t getOsVersion() {
- std::string version = wait_and_get_property(kPlatformVersionProp);
- return getOsVersion(version.c_str());
-}
+enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
-uint32_t getPatchlevel(const char* patchlevel_str) {
+uint32_t getPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
regex_t regex;
if (regcomp(®ex, kPatchlevelRegex, REG_EXTENDED) != 0) {
return 0;
@@ -100,17 +96,35 @@
if (month < 1 || month > 12) {
return 0;
}
- return year * 100 + month;
+
+ switch (detail) {
+ case PatchlevelOutput::kYearMonthDay: {
+ uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
+ if (day < 1 || day > 31) {
+ return 0;
+ }
+ return year * 10000 + month * 100 + day;
+ }
+ case PatchlevelOutput::kYearMonth:
+ return year * 100 + month;
+ }
+}
+
+} // anonymous namespace
+
+uint32_t getOsVersion() {
+ std::string version = wait_and_get_property(kPlatformVersionProp);
+ return getOsVersion(version.c_str());
}
uint32_t getOsPatchlevel() {
std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
- return getPatchlevel(patchlevel.c_str());
+ return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonth);
}
uint32_t getVendorPatchlevel() {
std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
- return getPatchlevel(patchlevel.c_str());
+ return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
}
} // namespace aidl::android::hardware::security::keymint
diff --git a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
index 31f4854..bf332d5 100644
--- a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
+++ b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
@@ -114,6 +114,7 @@
EXPECT_EQ(ErrorCode::OK, result1.error);
EXPECT_EQ(1U, result1.token.challenge);
EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result1.token.mac.size());
unsigned long time_to_sleep = 200;
sleep_ms(time_to_sleep);
@@ -123,6 +124,7 @@
EXPECT_EQ(ErrorCode::OK, result2.error);
EXPECT_EQ(2U, result2.token.challenge);
EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result2.token.mac.size());
auto host_time_delta = result2_time - result1_time;
@@ -153,6 +155,7 @@
EXPECT_EQ(ErrorCode::OK, result1.error);
EXPECT_EQ(0U, result1.token.challenge);
EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result1.token.mac.size());
unsigned long time_to_sleep = 200;
sleep_ms(time_to_sleep);
@@ -162,6 +165,7 @@
EXPECT_EQ(ErrorCode::OK, result2.error);
EXPECT_EQ(1U, result2.token.challenge);
EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result2.token.mac.size());
auto host_time_delta = result2_time - result1_time;
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 8426120..919f882 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -48,6 +48,9 @@
SharedSecretParameters params;
auto error = GetReturnErrorCode(sharedSecret->getSharedSecretParameters(¶ms));
EXPECT_EQ(ErrorCode::OK, error);
+ EXPECT_TRUE(params.seed.size() == 0 || params.seed.size() == 32);
+ EXPECT_TRUE(params.nonce.size() == 32);
+
GetParamsResult result;
result.tie() = std::tie(error, params);
return result;
@@ -234,6 +237,45 @@
}
}
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortNonce) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
+ auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+
+ auto params = getAllSharedSecretParameters();
+ ASSERT_EQ(sharedSecrets.size(), params.size())
+ << "One or more shared secret services failed to provide parameters.";
+
+ // All should be well in the normal case
+ auto responses = computeAllSharedSecrets(params);
+
+ ASSERT_GT(responses.size(), 0U);
+ vector<uint8_t> correct_response = responses[0].sharing_check;
+ verifyResponses(correct_response, responses);
+
+ // Pick a random param and shorten that nonce by one.
+ size_t param_to_tweak = rand() % params.size();
+ auto& to_tweak = params[param_to_tweak].nonce;
+ ASSERT_TRUE(to_tweak.size() == 32);
+ to_tweak.resize(31);
+
+ responses = computeAllSharedSecrets(params);
+ for (size_t i = 0; i < responses.size(); ++i) {
+ if (i == param_to_tweak) {
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+ << "Shared secret service that provided tweaked param should fail to compute "
+ "shared secret";
+ } else {
+ EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+ EXPECT_NE(correct_response, responses[i].sharing_check)
+ << "Others should calculate a different shared secret, due to the tweaked "
+ "nonce.";
+ }
+ }
+}
+
TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptSeed) {
auto sharedSecrets = allSharedSecrets();
if (sharedSecrets.empty()) {
@@ -275,6 +317,45 @@
}
}
}
+
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortSeed) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
+ auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+ auto params = getAllSharedSecretParameters();
+ ASSERT_EQ(sharedSecrets.size(), params.size())
+ << "One or more shared secret service failed to provide parameters.";
+
+ // All should be well in the normal case
+ auto responses = computeAllSharedSecrets(params);
+
+ ASSERT_GT(responses.size(), 0U);
+ vector<uint8_t> correct_response = responses[0].sharing_check;
+ verifyResponses(correct_response, responses);
+
+ // Pick a random param and modify the seed to be of (invalid) length 31.
+ auto param_to_tweak = rand() % params.size();
+ auto& to_tweak = params[param_to_tweak].seed;
+ ASSERT_TRUE(to_tweak.size() == 32 || to_tweak.size() == 0);
+ to_tweak.resize(31);
+
+ responses = computeAllSharedSecrets(params);
+ for (size_t i = 0; i < responses.size(); ++i) {
+ if (i == param_to_tweak) {
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+ << "Shared secret service that provided tweaked param should fail to compute "
+ "shared secret";
+ } else {
+ EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+ EXPECT_NE(correct_response, responses[i].sharing_check)
+ << "Others should calculate a different shared secret, due to the tweaked "
+ "nonce.";
+ }
+ }
+}
+
} // namespace aidl::android::hardware::security::sharedsecret::test
int main(int argc, char** argv) {
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 1f579ba..d46cf5a 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -24,7 +24,9 @@
#include <log/log.h>
#include <utils/SystemClock.h>
+#include <algorithm>
#include <cinttypes>
+#include <unordered_map>
#include <vector>
using ::android::hardware::Return;
@@ -149,6 +151,7 @@
TEST_P(SensorsHidlTest, SensorListValid) {
S()->getSensorsList([&](const auto& list) {
const size_t count = list.size();
+ std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap;
for (size_t i = 0; i < count; ++i) {
const auto& s = list[i];
SCOPED_TRACE(::testing::Message()
@@ -167,6 +170,14 @@
EXPECT_FALSE(s.name.empty());
EXPECT_FALSE(s.vendor.empty());
+ // Make sure that sensors of the same type have a unique name.
+ std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(s.type)];
+ bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end();
+ EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name;
+ if (isUniqueName) {
+ v.push_back(s.name);
+ }
+
// Test power > 0, maxRange > 0
EXPECT_LE(0, s.power);
EXPECT_LT(0, s.maxRange);
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 47a8cc0..ea5dc70 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -26,10 +26,12 @@
#include <log/log.h>
#include <utils/SystemClock.h>
+#include <algorithm>
#include <cinttypes>
#include <condition_variable>
#include <cstring>
#include <map>
+#include <unordered_map>
#include <vector>
/**
@@ -373,6 +375,7 @@
TEST_P(SensorsHidlTest, SensorListValid) {
getSensors()->getSensorsList([&](const auto& list) {
const size_t count = list.size();
+ std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap;
for (size_t i = 0; i < count; ++i) {
const auto& s = list[i];
SCOPED_TRACE(::testing::Message()
@@ -393,6 +396,14 @@
EXPECT_FALSE(s.name.empty());
EXPECT_FALSE(s.vendor.empty());
+ // Make sure that sensors of the same type have a unique name.
+ std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(s.type)];
+ bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end();
+ EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name;
+ if (isUniqueName) {
+ v.push_back(s.name);
+ }
+
// Test power > 0, maxRange > 0
EXPECT_LE(0, s.power);
EXPECT_LT(0, s.maxRange);
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
index 96cfa08..20df5bb 100644
--- a/tests/extension/vibrator/aidl/Android.bp
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -24,6 +24,9 @@
// This is agreeing to keep the interface stable.
stability: "vintf",
+ // This is a testing-purpose interface. Fine to use unstable version on REL platform.
+ owner: "test",
+
// This happens to use types from a core interface, so we import it, but
// this won't always be needed.
imports: [
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 8358291..7243a42 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -79,7 +79,6 @@
FrontendTests mFrontendTests;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest);
class TunerLnbHidlTest : public testing::TestWithParam<std::string> {
@@ -101,7 +100,6 @@
LnbTests mLnbTests;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerLnbHidlTest);
class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
@@ -127,7 +125,6 @@
FilterTests mFilterTests;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxHidlTest);
class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
@@ -179,7 +176,6 @@
FilterTests mFilterTests;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest);
class TunerBroadcastHidlTest : public testing::TestWithParam<std::string> {
@@ -218,7 +214,6 @@
uint32_t* mLnbId = nullptr;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
class TunerPlaybackHidlTest : public testing::TestWithParam<std::string> {
@@ -250,7 +245,6 @@
void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackHidlTest);
class TunerRecordHidlTest : public testing::TestWithParam<std::string> {
@@ -290,7 +284,6 @@
uint32_t* mLnbId = nullptr;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest);
class TunerDescramblerHidlTest : public testing::TestWithParam<std::string> {
@@ -327,6 +320,5 @@
DvrTests mDvrTests;
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDescramblerHidlTest);
} // namespace
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
index c487d98..93f4519 100644
--- a/tv/tuner/1.1/default/Dvr.cpp
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -81,7 +81,6 @@
return status;
}
- // TODO check if the attached filter is a record filter
if (!mDemux->attachRecordFilter(filterId)) {
return Result::INVALID_ARGUMENT;
}
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index 007e3d5..13b9640 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -156,6 +156,5 @@
FrontendConfig1_1 frontendConf);
};
-// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
-} // namespace
\ No newline at end of file
+} // namespace
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index c6682b3..5755ce5 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -138,6 +138,11 @@
ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
int32_t* durationMs) {
+ std::vector<CompositePrimitive> supported;
+ getSupportedPrimitives(&supported);
+ if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
if (primitive != CompositePrimitive::NOOP) {
*durationMs = 100;
} else {
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index 9789188..44fa3be 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -71,6 +71,11 @@
std::vector<int32_t> vibratorIds;
};
+inline bool isUnknownOrUnsupported(Status status) {
+ return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION;
+}
+
TEST_P(VibratorAidl, ValidateExistingVibrators) {
sp<IVibrator> vibrator;
for (auto& id : vibratorIds) {
@@ -101,8 +106,8 @@
TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- manager->prepareSynced(vibratorIds).exceptionCode());
+ Status status = manager->prepareSynced(vibratorIds);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -116,8 +121,8 @@
for (auto& id : vibratorIds) {
EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
ASSERT_NE(vibrator, nullptr);
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- vibrator->on(durationMs, nullptr).exceptionCode());
+ Status status = vibrator->on(durationMs, nullptr);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
EXPECT_TRUE(manager->cancelSynced().isOk());
}
@@ -134,7 +139,7 @@
ASSERT_NE(vibrator, nullptr);
int32_t lengthMs = 0;
Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
EXPECT_TRUE(manager->cancelSynced().isOk());
}
@@ -157,7 +162,7 @@
EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
ASSERT_NE(vibrator, nullptr);
Status status = vibrator->compose(composite, nullptr);
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
EXPECT_TRUE(manager->cancelSynced().isOk());
}
@@ -191,8 +196,8 @@
TEST_P(VibratorAidl, TriggerSyncNotSupported) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- manager->triggerSynced(nullptr).exceptionCode());
+ Status status = manager->triggerSynced(nullptr);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -201,8 +206,8 @@
if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- manager->triggerSynced(callback).exceptionCode());
+ Status status = manager->triggerSynced(callback);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 713ec75..c56bd9a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -112,6 +112,11 @@
int32_t capabilities;
};
+inline bool isUnknownOrUnsupported(Status status) {
+ return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION;
+}
+
static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
float resonantFrequencyHz;
Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
@@ -119,7 +124,7 @@
EXPECT_GT(resonantFrequencyHz, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
return resonantFrequencyHz;
}
@@ -131,7 +136,7 @@
EXPECT_GT(freqResolutionHz, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
return freqResolutionHz;
}
@@ -147,7 +152,7 @@
EXPECT_GT(freqMinimumHz, 0);
EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
return freqMinimumHz;
}
@@ -158,7 +163,7 @@
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
float freqMaximumHz =
@@ -219,7 +224,8 @@
TEST_P(VibratorAidl, OnCallbackNotSupported) {
if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
+ Status status = vibrator->on(250, callback);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -240,8 +246,8 @@
EXPECT_GT(lengthMs, 0);
usleep(lengthMs * 1000);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ EXPECT_TRUE(isUnknownOrUnsupported(status))
+ << status << " " << toString(effect) << " " << toString(strength);
}
}
}
@@ -270,7 +276,7 @@
EXPECT_TRUE(status.isOk());
EXPECT_GT(lengthMs, 0);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
if (!status.isOk())
@@ -293,7 +299,7 @@
sp<CompletionCallback> callback = new CompletionCallback([] {});
int lengthMs;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
}
@@ -303,16 +309,16 @@
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ EXPECT_TRUE(isUnknownOrUnsupported(status))
+ << status << toString(effect) << " " << toString(strength);
}
}
for (Effect effect : kEffects) {
for (EffectStrength strength : kInvalidEffectStrengths) {
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ EXPECT_TRUE(isUnknownOrUnsupported(status))
+ << status << " " << toString(effect) << " " << toString(strength);
}
}
}
@@ -338,7 +344,8 @@
TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->setAmplitude(1).exceptionCode());
+ Status status = vibrator->setAmplitude(1);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -362,7 +369,7 @@
if (supportsExternalAmplitudeControl) {
EXPECT_TRUE(amplitudeStatus.isOk());
} else {
- EXPECT_EQ(amplitudeStatus.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus;
}
EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
} else {
@@ -372,8 +379,8 @@
TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- vibrator->setExternalControl(true).exceptionCode());
+ Status status = vibrator->setExternalControl(true);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -410,7 +417,7 @@
if (isPrimitiveSupported) {
EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
} else {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
}
@@ -473,8 +480,8 @@
effect.primitive = primitive;
effect.scale = 1.0f;
}
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
- vibrator->compose(composite, nullptr).exceptionCode());
+ Status status = vibrator->compose(composite, nullptr);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
vibrator->off();
}
}
@@ -618,8 +625,8 @@
EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
<< toString(effect) << " " << toString(strength);
} else {
- EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
- << toString(effect) << " " << toString(strength);
+ EXPECT_TRUE(isUnknownOrUnsupported(status))
+ << status << " " << toString(effect) << " " << toString(strength);
}
}
}
@@ -639,7 +646,7 @@
ASSERT_GT(qFactor, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -668,7 +675,7 @@
ASSERT_LE(e, 1.0);
}
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -679,7 +686,7 @@
ASSERT_NE(durationMs, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -690,7 +697,7 @@
ASSERT_NE(maxSize, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
@@ -703,7 +710,7 @@
ASSERT_TRUE(isDefaultNoneSupported);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.5/default/OWNERS b/wifi/1.5/default/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.5/default/OWNERS
+++ b/wifi/1.5/default/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ b/wifi/supplicant/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ b/wifi/supplicant/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
etancohen@google.com