Merge "Ensure non-empty SvInfo is received" into sc-dev
diff --git a/audio/common/all-versions/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
index 1602d25..757f8a8 100644
--- a/audio/common/all-versions/test/utility/Android.bp
+++ b/audio/common/all-versions/test/utility/Android.bp
@@ -25,7 +25,7 @@
cc_library_static {
name: "android.hardware.audio.common.test.utility",
- defaults : ["hidl_defaults"],
+ defaults: ["hidl_defaults"],
srcs: ["src/ValidateXml.cpp"],
cflags: [
"-O0",
@@ -34,7 +34,34 @@
],
local_include_dirs: ["include/utility"],
export_include_dirs: ["include"],
- shared_libs: ["libxml2", "liblog"],
+ shared_libs: [
+ "libxml2",
+ "liblog",
+ ],
static_libs: ["libgtest"],
export_static_lib_headers: ["libgtest"],
}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of test utilities.
+cc_test {
+ name: "android.hardware.audio.common.test.utility_tests",
+ host_supported: true,
+ local_include_dirs: ["include/utility"],
+ srcs: [
+ "src/ValidateXml.cpp",
+ "tests/utility_tests.cpp",
+ ],
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-g",
+ ],
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ "liblog",
+ ],
+ static_libs: ["libgtest"],
+ test_suites: ["general-tests"],
+}
diff --git a/audio/common/all-versions/test/utility/TEST_MAPPING b/audio/common/all-versions/test/utility/TEST_MAPPING
new file mode 100644
index 0000000..0bc1871
--- /dev/null
+++ b/audio/common/all-versions/test/utility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "android.hardware.audio.common.test.utility_tests"
+ }
+ ]
+}
diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
index a866104..f111c01 100644
--- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -112,7 +112,8 @@
return ::testing::AssertionFailure() << "Failed to parse xml\n" << context();
}
- if (xmlXIncludeProcess(doc.get()) == -1) {
+ // Process 'include' directives w/o modifying elements loaded from included files.
+ if (xmlXIncludeProcessFlags(doc.get(), XML_PARSE_NOBASEFIX) == -1) {
return ::testing::AssertionFailure() << "Failed to resolve xincludes in xml\n" << context();
}
diff --git a/audio/common/all-versions/test/utility/tests/utility_tests.cpp b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
new file mode 100644
index 0000000..c523066
--- /dev/null
+++ b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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 <android-base/file.h>
+#include <gtest/gtest.h>
+
+#include <ValidateXml.h>
+
+using ::android::hardware::audio::common::test::utility::validateXml;
+
+const char* XSD_SOURCE =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<xs:schema version=\"2.0\""
+ " elementFormDefault=\"qualified\""
+ " attributeFormDefault=\"unqualified\""
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
+ " <xs:element name=\"audioPolicyConfiguration\">"
+ " <xs:complexType>"
+ " <xs:sequence>"
+ " <xs:element name=\"modules\">"
+ " <xs:complexType>"
+ " <xs:sequence>"
+ " <xs:element name=\"module\" maxOccurs=\"unbounded\">"
+ " <xs:complexType>"
+ " <xs:attribute name=\"name\" type=\"xs:string\" use=\"required\"/>"
+ " </xs:complexType>"
+ " </xs:element>"
+ " </xs:sequence>"
+ " </xs:complexType>"
+ " </xs:element>"
+ " </xs:sequence>"
+ " </xs:complexType>"
+ " </xs:element>"
+ "</xs:schema>";
+
+const char* INVALID_XML_SOURCE =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<audioPolicyKonfiguration />";
+
+const char* VALID_XML_SOURCE =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<audioPolicyConfiguration>"
+ " <modules>"
+ " <module name=\"aaa\" />"
+ " %s"
+ " </modules>"
+ "</audioPolicyConfiguration>";
+
+const char* MODULE_SOURCE = "<module name=\"bbb\" />";
+
+const char* XI_INCLUDE = "<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"%s\" />";
+
+const char* XML_INCLUDED_SOURCE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%s";
+
+namespace {
+
+std::string substitute(const char* fmt, const char* param) {
+ std::string buffer(static_cast<size_t>(strlen(fmt) + strlen(param)), '\0');
+ snprintf(buffer.data(), buffer.size(), fmt, param);
+ return buffer;
+}
+
+std::string substitute(const char* fmt, const std::string& s) {
+ return substitute(fmt, s.c_str());
+}
+
+} // namespace
+
+TEST(ValidateXml, InvalidXml) {
+ TemporaryFile xml;
+ ASSERT_TRUE(android::base::WriteStringToFile(INVALID_XML_SOURCE, xml.path)) << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_FALSE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, ValidXml) {
+ TemporaryFile xml;
+ ASSERT_TRUE(
+ android::base::WriteStringToFile(substitute(VALID_XML_SOURCE, MODULE_SOURCE), xml.path))
+ << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeAbsolutePath) {
+ TemporaryFile xmlInclude;
+ ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+ xmlInclude.path))
+ << strerror(errno);
+ TemporaryFile xml;
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ substitute(VALID_XML_SOURCE, substitute(XI_INCLUDE, xmlInclude.path)), xml.path))
+ << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeSameDirRelativePath) {
+ TemporaryFile xmlInclude;
+ ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+ xmlInclude.path))
+ << strerror(errno);
+ TemporaryFile xml;
+ ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ substitute(VALID_XML_SOURCE,
+ substitute(XI_INCLUDE, android::base::Basename(xmlInclude.path))),
+ xml.path))
+ << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeSubdirRelativePath) {
+ TemporaryDir xmlIncludeDir;
+ TemporaryFile xmlInclude(xmlIncludeDir.path);
+ ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+ xmlInclude.path))
+ << strerror(errno);
+ TemporaryFile xml;
+ ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ substitute(VALID_XML_SOURCE,
+ substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
+ android::base::Basename(xmlInclude.path))),
+ xml.path))
+ << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeParentDirRelativePath) {
+ // An XML file from a subdirectory includes a file from the parent directory using '..' syntax.
+ TemporaryFile xmlInclude;
+ ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+ xmlInclude.path))
+ << strerror(errno);
+ TemporaryDir xmlIncludeDir;
+ TemporaryFile xmlParentInclude(xmlIncludeDir.path);
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ substitute(XML_INCLUDED_SOURCE,
+ substitute(XI_INCLUDE, "../" + android::base::Basename(xmlInclude.path))),
+ xmlParentInclude.path))
+ << strerror(errno);
+ TemporaryFile xml;
+ ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
+ ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ substitute(
+ VALID_XML_SOURCE,
+ substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
+ android::base::Basename(xmlParentInclude.path))),
+ xml.path))
+ << strerror(errno);
+ TemporaryFile xsd;
+ ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+ EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index b96cc83..787654b 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -53,6 +53,11 @@
GTEST_SKIP() << "getMicrophones is not supported"; // returns
}
ASSERT_OK(res);
+
+#if MAJOR_VERSION <= 6
+ // In V7, 'getActiveMicrophones' is tested by the 'MicrophoneInfoInputStream'
+ // test which uses the actual configuration of the device.
+
if (microphones.size() > 0) {
// When there is microphone on the phone, try to open an input stream
// and query for the active microphones.
@@ -60,30 +65,13 @@
"Make sure getMicrophones always succeeds"
"and getActiveMicrophones always succeeds when recording from these microphones.");
AudioConfig config{};
-#if MAJOR_VERSION <= 6
config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
config.sampleRateHz = 8000;
config.format = AudioFormat::PCM_16_BIT;
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
-#elif MAJOR_VERSION >= 7
- config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
- config.base.sampleRateHz = 8000;
- config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
- hidl_vec<hidl_string> flags;
- const SinkMetadata initMetadata = {
- {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
- .gain = 1,
- .tags = {},
- .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
-#endif
for (auto microphone : microphones) {
-#if MAJOR_VERSION <= 6
if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
-#elif MAJOR_VERSION >= 7
- if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) !=
- xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) {
-#endif
continue;
}
sp<IStreamIn> stream;
@@ -106,6 +94,7 @@
EXPECT_NE(0U, activeMicrophones.size());
}
}
+#endif // MAJOR_VERSION <= 6
}
TEST_P(AudioHidlDeviceTest, SetConnectedState) {
@@ -343,18 +332,21 @@
#endif
for (int mode : {-2, -1, maxMode + 1}) {
- ASSERT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode)))
+ EXPECT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode)))
<< "mode=" << mode;
}
- // Test valid values
- for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
- AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) {
- ASSERT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode);
- }
+
// AudioMode::CALL_SCREEN as support is optional
#if MAJOR_VERSION >= 6
- ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setMode(AudioMode::CALL_SCREEN));
+ EXPECT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setMode(AudioMode::CALL_SCREEN));
#endif
+ // Test valid values
+ for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
+ AudioMode::NORMAL}) {
+ EXPECT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode);
+ }
+ // Make sure to leave the test in normal mode
+ getDevice()->setMode(AudioMode::NORMAL);
}
TEST_P(AudioPrimaryHidlTest, setBtHfpSampleRate) {
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 0b3098b..0cc6a5b 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -839,3 +839,64 @@
::testing::ValuesIn(getInputDevicePcmOnlyConfigParameters()),
&DeviceConfigParameterToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigInputStreamTest);
+
+static const std::vector<DeviceConfigParameter>& getBuiltinMicConfigParameters() {
+ static const std::vector<DeviceConfigParameter> parameters = [] {
+ auto allParams = getInputDeviceConfigParameters();
+ std::vector<DeviceConfigParameter> builtinMicParams;
+ std::copy_if(allParams.begin(), allParams.end(), std::back_inserter(builtinMicParams),
+ [](auto cfg) {
+ // The built in mic may participate in various scenarios:
+ // FAST, HW_HOTWORD, MMAP NOIRQ, which are indicated by flags.
+ // We are only interested in testing the simplest scenario w/o any flags.
+ if (!std::get<PARAM_FLAGS>(cfg).empty()) return false;
+ auto maybeSourceDevice = getCachedPolicyConfig().getSourceDeviceForMixPort(
+ std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
+ std::get<PARAM_PORT_NAME>(cfg));
+ return maybeSourceDevice.has_value() &&
+ xsd::stringToAudioDevice(maybeSourceDevice.value().deviceType) ==
+ xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC;
+ });
+ return builtinMicParams;
+ }();
+ return parameters;
+}
+
+class MicrophoneInfoInputStreamTest : public InputStreamTest {};
+
+TEST_P(MicrophoneInfoInputStreamTest, GetActiveMicrophones) {
+ doc::test(
+ "Make sure getActiveMicrophones always succeeds when recording "
+ "from the built-in microphone.");
+ hidl_vec<MicrophoneInfo> microphones;
+ ASSERT_OK(getDevice()->getMicrophones(returnIn(res, microphones)));
+ if (res == Result::NOT_SUPPORTED) {
+ GTEST_SKIP() << "getMicrophones is not supported"; // returns
+ }
+ ASSERT_OK(res);
+
+ auto maybeSourceAddress =
+ getCachedPolicyConfig().getSourceDeviceForMixPort(getDeviceName(), getMixPortName());
+ ASSERT_TRUE(maybeSourceAddress.has_value())
+ << "No source device found for mix port " << getMixPortName() << " (module "
+ << getDeviceName() << ")";
+
+ for (auto microphone : microphones) {
+ if (microphone.deviceAddress == maybeSourceAddress.value()) {
+ StreamReader reader(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(reader.start());
+ reader.pause(); // This ensures that at least one read has happened.
+ EXPECT_FALSE(reader.hasError());
+
+ hidl_vec<MicrophoneInfo> activeMicrophones;
+ ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
+ ASSERT_OK(res);
+ EXPECT_NE(0U, activeMicrophones.size());
+ }
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(MicrophoneInfoInputStream, MicrophoneInfoInputStreamTest,
+ ::testing::ValuesIn(getBuiltinMicConfigParameters()),
+ &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MicrophoneInfoInputStreamTest);
diff --git a/camera/device/3.7/types.hal b/camera/device/3.7/types.hal
index 6910e65..55aceb8 100644
--- a/camera/device/3.7/types.hal
+++ b/camera/device/3.7/types.hal
@@ -42,7 +42,7 @@
/**
* The surface group id used for multi-resolution output streams.
*
- * This works simliar to the surfaceGroupId of OutputConfiguration in the
+ * This works similar to the surfaceGroupId of OutputConfiguration in the
* public API, with the exception that this is for multi-resolution image
* reader and is used by the camera HAL to choose a target stream within
* the same group to which images are written. All streams in the same group
diff --git a/camera/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal
index ad671d9..4b02830 100644
--- a/camera/metadata/3.2/types.hal
+++ b/camera/metadata/3.2/types.hal
@@ -686,7 +686,9 @@
/** android.jpeg.maxSize [static, int32, system]
*
* <p>Maximum size in bytes for the compressed
- * JPEG buffer</p>
+ * JPEG buffer, in default sensor pixel mode (see ANDROID_SENSOR_PIXEL_MODE)</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
*/
ANDROID_JPEG_MAX_SIZE,
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 41a08f9..49e00f4 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -230,10 +230,10 @@
return false;
}
- int getCameraDeviceVersion(const hidl_string& deviceName,
- const hidl_string &providerType) {
+ int getCameraDeviceVersionAndId(const hidl_string& deviceName,
+ const hidl_string &providerType, std::string* id) {
std::string version;
- bool match = matchDeviceName(deviceName, providerType, &version, nullptr);
+ bool match = matchDeviceName(deviceName, providerType, &version, id);
if (!match) {
return -1;
}
@@ -256,6 +256,11 @@
return 0;
}
+ int getCameraDeviceVersion(const hidl_string& deviceName,
+ const hidl_string &providerType) {
+ return getCameraDeviceVersionAndId(deviceName, providerType, nullptr);
+ }
+
bool parseProviderName(const std::string& name, std::string *type /*out*/,
uint32_t *id /*out*/) {
if (!type || !id) {
@@ -930,6 +935,7 @@
camera_metadata_ro_entry* streamConfigs,
camera_metadata_ro_entry* maxResolutionStreamConfigs,
const camera_metadata_t* staticMetadata);
+ static bool isColorCamera(const camera_metadata_t *metadata);
static V3_2::DataspaceFlags getDataspace(PixelFormat format);
@@ -6179,6 +6185,167 @@
}
}
+// Test the multi-camera API requirement for Google Requirement Freeze S
+// Note that this requirement can only be partially tested. If a vendor
+// device doesn't expose a physical camera in any shape or form, there is no way
+// the test can catch it.
+TEST_P(CameraHidlTest, grfSMultiCameraTest) {
+ const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
+ if (socGrfApi < 31 /*S*/) {
+ // Non-GRF devices, or version < 31 Skip
+ ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
+ return;
+ }
+
+ // Test that if more than one color cameras facing the same direction are
+ // supported, there must be at least one logical camera facing that
+ // direction.
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ // Front and back facing non-logical color cameras
+ std::set<std::string> frontColorCameras, rearColorCameras;
+ // Front and back facing logical cameras' physical camera Id sets
+ std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds;
+ for (const auto& name : cameraDeviceNames) {
+ std::string cameraId;
+ int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
+ switch (deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_3_7:
+ case CAMERA_DEVICE_API_VERSION_3_6:
+ case CAMERA_DEVICE_API_VERSION_3_5:
+ case CAMERA_DEVICE_API_VERSION_3_4:
+ case CAMERA_DEVICE_API_VERSION_3_3:
+ case CAMERA_DEVICE_API_VERSION_3_2: {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
+ ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+ Return<void> ret;
+ ret = mProvider->getCameraDeviceInterface_V3_x(
+ name, [&](auto status, const auto& device) {
+ ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ device3_x = device;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
+ ASSERT_EQ(Status::OK, status);
+ const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+
+ // Skip if this is not a color camera.
+ if (!CameraHidlTest::isColorCamera(metadata)) {
+ return;
+ }
+
+ // Check camera facing. Skip if facing is neither FRONT
+ // nor BACK. If this is not a logical camera, only note down
+ // the camera ID, and skip.
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(
+ metadata, ANDROID_LENS_FACING, &entry);
+ ASSERT_EQ(retcode, 0);
+ ASSERT_GT(entry.count, 0);
+ uint8_t facing = entry.data.u8[0];
+ bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
+ if (facing == ANDROID_LENS_FACING_FRONT) {
+ if (!isLogicalCamera) {
+ frontColorCameras.insert(cameraId);
+ return;
+ }
+ } else if (facing == ANDROID_LENS_FACING_BACK) {
+ if (!isLogicalCamera) {
+ rearColorCameras.insert(cameraId);
+ return;
+ }
+ } else {
+ // Not FRONT or BACK facing. Skip.
+ return;
+ }
+
+ // Check logical camera's physical camera IDs for color
+ // cameras.
+ std::unordered_set<std::string> physicalCameraIds;
+ Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
+ ASSERT_EQ(Status::OK, s);
+ if (facing == ANDROID_LENS_FACING_FRONT) {
+ frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
+ } else {
+ rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
+ }
+ for (const auto& physicalId : physicalCameraIds) {
+ // Skip if the physicalId is publicly available
+ for (auto& deviceName : cameraDeviceNames) {
+ std::string publicVersion, publicId;
+ ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
+ &publicVersion, &publicId));
+ if (physicalId == publicId) {
+ // Skip because public Ids will be iterated in outer loop.
+ return;
+ }
+ }
+
+ auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
+ ASSERT_TRUE(castResult.isOk());
+ ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
+ device3_5 = castResult;
+ ASSERT_NE(device3_5, nullptr);
+
+ // Check camera characteristics for hidden camera id
+ Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
+ physicalId, [&](auto status, const auto& chars) {
+ ASSERT_EQ(Status::OK, status);
+ const camera_metadata_t* physicalMetadata =
+ (camera_metadata_t*)chars.data();
+
+ if (CameraHidlTest::isColorCamera(physicalMetadata)) {
+ if (facing == ANDROID_LENS_FACING_FRONT) {
+ frontColorCameras.insert(physicalId);
+ } else if (facing == ANDROID_LENS_FACING_BACK) {
+ rearColorCameras.insert(physicalId);
+ }
+ }
+ });
+ ASSERT_TRUE(ret.isOk());
+ }
+ });
+ ASSERT_TRUE(ret.isOk());
+ } break;
+ case CAMERA_DEVICE_API_VERSION_1_0: {
+ // Not applicable
+ } break;
+ default: {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ } break;
+ }
+ }
+
+ // If there are more than one color cameras facing one direction, a logical
+ // multi-camera must be defined consisting of all color cameras facing that
+ // direction.
+ if (frontColorCameras.size() > 1) {
+ bool hasFrontLogical = false;
+ for (const auto& physicalIds : frontPhysicalIds) {
+ if (std::includes(physicalIds.begin(), physicalIds.end(),
+ frontColorCameras.begin(), frontColorCameras.end())) {
+ hasFrontLogical = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(hasFrontLogical);
+ }
+ if (rearColorCameras.size() > 1) {
+ bool hasRearLogical = false;
+ for (const auto& physicalIds : rearPhysicalIds) {
+ if (std::includes(physicalIds.begin(), physicalIds.end(),
+ rearColorCameras.begin(), rearColorCameras.end())) {
+ hasRearLogical = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(hasRearLogical);
+ }
+}
+
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -6651,6 +6818,23 @@
return ret;
}
+bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(
+ metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
+ entry.data.u8 + entry.count);
+ bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
+ entry.data.u8 + entry.count);
+ bool isColor = isBackwardCompatible && !isMonochrome;
+ return isColor;
+ }
+ return false;
+}
+
// Retrieve the reprocess input-output format map from the static
// camera characteristics.
Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
diff --git a/current.txt b/current.txt
index 908ecc4..fbad3da 100644
--- a/current.txt
+++ b/current.txt
@@ -768,6 +768,8 @@
98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
# ABI preserving changes to HALs during Android S
+# b/193346383
+93d29fbe2fcc5e4e053a9db7c9abbd9190c46b85b443f2698a3460db2ee76c8d android.hardware.camera.metadata@3.2::types
159a0069336035852e9eca6354b86b7990680d1b239f23ef2f631b01807c4cb9 android.hardware.camera.metadata@3.5::types
e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub
c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback
@@ -838,7 +840,7 @@
1a1dff6e8d25dbc02a69fed3c077dd0782b30331ca3f345848ec52fc67744224 android.hardware.camera.device@3.7::ICameraDevice
3be6faa3d11ad9c7ec01a1a0a009cf11cb65d701d109dab37613ce9cfb3cdd60 android.hardware.camera.device@3.7::ICameraDeviceSession
3740ec773b2eb8fa6bd8c6e879eedb56c4e4306b88f1c20fa51103d791d871b1 android.hardware.camera.device@3.7::ICameraInjectionSession
-21f023685571daf46148097d98b89cea353f07e3ed83b2ed5685b23bd136c3ee android.hardware.camera.device@3.7::types
+d272697484c41bbf76a0924d2aaebf065ce37a822fcb438316eb5dd2d112f052 android.hardware.camera.device@3.7::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
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 7a1568b..7a053f1 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -458,6 +458,7 @@
<< " pixel format: PixelFormat::RGBA_8888 dataspace: "
<< ReadbackHelper::getDataspaceString(clientDataspace)
<< " unsupported for display" << std::endl;
+ mReader->mCompositionChanges.clear();
continue;
}
diff --git a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
index 13c3389..88b090b 100644
--- a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
+++ b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
@@ -44,6 +44,12 @@
* This category should report all GPU private allocations for the specified
* PID that are not accounted in /proc/<pid>/smaps.
*
+ * getMemory() called with PID 0 should report the global total GPU-private
+ * memory, for MemtrackType::GL and MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.
+ *
+ * getMemory() called with PID 0 for a MemtrackType other than GL should
+ * report 0.
+ *
* - MemtrackType::OTHER and MemtrackRecord::FLAG_SMAPS_UNACCOUNTED
* Any other memory not accounted for in /proc/<pid>/smaps if any, otherwise
* this should return 0.
@@ -52,6 +58,9 @@
* VM_PFNMAP flag set. For these mappings PSS and RSS are reported as 0 in smaps.
* Such mappings have no backing page structs from which PSS/RSS can be calculated.
*
+ * Any memtrack operation that is not supported should return a binder status with
+ * exception code EX_UNSUPPORTED_OPERATION.
+ *
* Constructor for the interface should be used to perform memtrack management
* setup actions and must be called once before any calls to getMemory().
*/
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 32d69cd..b0761bf 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -44,6 +44,12 @@
* ? "vendor_patch_level" : uint, // YYYYMMDD
* "version" : 1, // The CDDL schema version.
* "security_level" : "tee" / "strongbox"
+ * "att_id_state": "locked" / "open", // Attestation IDs State. If "locked", this
+ * // indicates a device's attestable IDs are
+ * // factory-locked and immutable. If "open",
+ * // this indicates the device is still in a
+ * // provisionable state and the attestable IDs
+ * // are not yet frozen.
* }
*/
byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 31dbb28..24cdbc1 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -158,20 +158,7 @@
* payload: bstr .cbor BccPayload
* ]
*
- * VerifiedDeviceInfo = {
- * ? "brand" : tstr,
- * ? "manufacturer" : tstr,
- * ? "product" : tstr,
- * ? "model" : tstr,
- * ? "board" : tstr,
- * ? "device" : tstr,
- * ? "vb_state" : "green" / "yellow" / "orange",
- * ? "bootloader_state" : "locked" / "unlocked",
- * ? "os_version" : tstr,
- * ? "system_patch_level" : uint, // YYYYMMDD
- * ? "boot_patch_level" : uint, // YYYYMMDD
- * ? "vendor_patch_level" : uint, // YYYYMMDD
- * }
+ * VerifiedDeviceInfo = DeviceInfo // See DeviceInfo.aidl
*
* PubKeyX25519 = { // COSE_Key
* 1 : 1, // Key type : Octet Key Pair
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 270574b..67a0214 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -18,10 +18,6 @@
import android.hardware.security.keymint.TagType;
-// TODO(seleneh) : note aidl currently does not support double nested enum definitions such as
-// ROOT_OF_TRUST = TagType:BYTES | 704. So we are forced to write definitions as
-// ROOT_OF_TRUST = (9 << 28) for now. Will need to flip this back later when aidl support is added.
-
/**
* Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
* data are stored in KeyParameter.
@@ -33,7 +29,7 @@
/**
* Tag::INVALID should never be set. It means you hit an error.
*/
- INVALID = (0 << 28) | 0,
+ INVALID = 0,
/**
* Tag::PURPOSE specifies the set of purposes for which the key may be used. Possible values
@@ -47,7 +43,7 @@
*
* Must be hardware-enforced.
*/
- PURPOSE = (2 << 28) /* TagType:ENUM_REP */ | 1,
+ PURPOSE = TagType.ENUM_REP | 1,
/**
* Tag::ALGORITHM specifies the cryptographic algorithm with which the key is used. This tag
@@ -56,7 +52,7 @@
*
* Must be hardware-enforced.
*/
- ALGORITHM = (1 << 28) /* TagType:ENUM */ | 2,
+ ALGORITHM = TagType.ENUM | 2,
/**
* Tag::KEY_SIZE specifies the size, in bits, of the key, measuring in the normal way for the
@@ -68,7 +64,7 @@
*
* Must be hardware-enforced.
*/
- KEY_SIZE = (3 << 28) /* TagType:UINT */ | 3,
+ KEY_SIZE = TagType.UINT | 3,
/**
* Tag::BLOCK_MODE specifies the block cipher mode(s) with which the key may be used. This tag
@@ -81,7 +77,7 @@
*
* Must be hardware-enforced.
*/
- BLOCK_MODE = (2 << 28) /* TagType:ENUM_REP */ | 4,
+ BLOCK_MODE = TagType.ENUM_REP | 4,
/**
* Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
@@ -95,7 +91,7 @@
*
* Must be hardware-enforced.
*/
- DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 5,
+ DIGEST = TagType.ENUM_REP | 5,
/**
* Tag::PADDING specifies the padding modes that may be used with the key. This tag is relevant
@@ -123,7 +119,7 @@
*
* Must be hardware-enforced.
*/
- PADDING = (2 << 28) /* TagType:ENUM_REP */ | 6,
+ PADDING = TagType.ENUM_REP | 6,
/**
* Tag::CALLER_NONCE specifies that the caller can provide a nonce for nonce-requiring
@@ -136,7 +132,7 @@
*
* Must be hardware-enforced.
*/
- CALLER_NONCE = (7 << 28) /* TagType:BOOL */ | 7,
+ CALLER_NONCE = TagType.BOOL | 7,
/**
* Tag::MIN_MAC_LENGTH specifies the minimum length of MAC that can be requested or verified
@@ -149,7 +145,7 @@
*
* Must be hardware-enforced.
*/
- MIN_MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 8,
+ MIN_MAC_LENGTH = TagType.UINT | 8,
// Tag 9 reserved
@@ -159,7 +155,7 @@
*
* Must be hardware-enforced.
*/
- EC_CURVE = (1 << 28) /* TagType:ENUM */ | 10,
+ EC_CURVE = TagType.ENUM | 10,
/**
* Tag::RSA_PUBLIC_EXPONENT specifies the value of the public exponent for an RSA key pair.
@@ -173,7 +169,7 @@
*
* Must be hardware-enforced.
*/
- RSA_PUBLIC_EXPONENT = (5 << 28) /* TagType:ULONG */ | 200,
+ RSA_PUBLIC_EXPONENT = TagType.ULONG | 200,
// Tag 201 reserved
@@ -184,7 +180,7 @@
*
* Must be hardware-enforced.
*/
- INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,
+ INCLUDE_UNIQUE_ID = TagType.BOOL | 202,
/**
* Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with RSA
@@ -197,7 +193,7 @@
*
* Must be hardware-enforced.
*/
- RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
+ RSA_OAEP_MGF_DIGEST = TagType.ENUM_REP | 203,
// Tag 301 reserved
@@ -209,7 +205,7 @@
*
* Must be hardware-enforced.
*/
- BOOTLOADER_ONLY = (7 << 28) /* TagType:BOOL */ | 302,
+ BOOTLOADER_ONLY = TagType.BOOL | 302,
/**
* Tag::ROLLBACK_RESISTANCE specifies that the key has rollback resistance, meaning that when
@@ -224,10 +220,10 @@
*
* Must be hardware-enforced.
*/
- ROLLBACK_RESISTANCE = (7 << 28) /* TagType:BOOL */ | 303,
+ ROLLBACK_RESISTANCE = TagType.BOOL | 303,
// Reserved for future use.
- HARDWARE_TYPE = (1 << 28) /* TagType:ENUM */ | 304,
+ HARDWARE_TYPE = TagType.ENUM | 304,
/**
* Keys tagged with EARLY_BOOT_ONLY may only be used during early boot, until
@@ -236,7 +232,7 @@
* provided to IKeyMintDevice::importKey, the import must fail with
* ErrorCode::EARLY_BOOT_ENDED.
*/
- EARLY_BOOT_ONLY = (7 << 28) /* TagType:BOOL */ | 305,
+ EARLY_BOOT_ONLY = TagType.BOOL | 305,
/**
* Tag::ACTIVE_DATETIME specifies the date and time at which the key becomes active, in
@@ -245,7 +241,7 @@
*
* Need not be hardware-enforced.
*/
- ACTIVE_DATETIME = (6 << 28) /* TagType:DATE */ | 400,
+ ACTIVE_DATETIME = TagType.DATE | 400,
/**
* Tag::ORIGINATION_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -257,7 +253,7 @@
*
* Need not be hardware-enforced.
*/
- ORIGINATION_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 401,
+ ORIGINATION_EXPIRE_DATETIME = TagType.DATE | 401,
/**
* Tag::USAGE_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -269,7 +265,7 @@
*
* Need not be hardware-enforced.
*/
- USAGE_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 402,
+ USAGE_EXPIRE_DATETIME = TagType.DATE | 402,
/**
* TODO(seleneh) this tag need to be deleted.
@@ -293,8 +289,10 @@
* fails because the table is full, KeyMint returns ErrorCode::TOO_MANY_OPERATIONS.
*
* Must be hardware-enforced.
+ *
+ * TODO(b/191738660): Remove in KeyMint V2. Currently only used for FDE.
*/
- MIN_SECONDS_BETWEEN_OPS = (3 << 28) /* TagType:UINT */ | 403,
+ MIN_SECONDS_BETWEEN_OPS = TagType.UINT | 403,
/**
* Tag::MAX_USES_PER_BOOT specifies the maximum number of times that a key may be used between
@@ -314,7 +312,7 @@
*
* Must be hardware-enforced.
*/
- MAX_USES_PER_BOOT = (3 << 28) /* TagType:UINT */ | 404,
+ MAX_USES_PER_BOOT = TagType.UINT | 404,
/**
* Tag::USAGE_COUNT_LIMIT specifies the number of times that a key may be used. This can be
@@ -343,14 +341,14 @@
* record. This tag must have the same SecurityLevel as the tag that is added to the key
* characteristics.
*/
- USAGE_COUNT_LIMIT = (3 << 28) | 405, /* TagType:UINT */
+ USAGE_COUNT_LIMIT = TagType.UINT | 405,
/**
* Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
*
* Must not be hardware-enforced.
*/
- USER_ID = (3 << 28) /* TagType:UINT */ | 501,
+ USER_ID = TagType.UINT | 501,
/**
* Tag::USER_SECURE_ID specifies that a key may only be used under a particular secure user
@@ -383,7 +381,7 @@
*
* Must be hardware-enforced.
*/
- USER_SECURE_ID = (10 << 28) /* TagType:ULONG_REP */ | 502,
+ USER_SECURE_ID = TagType.ULONG_REP | 502,
/**
* Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key. This tag
@@ -391,7 +389,7 @@
*
* Must be hardware-enforced.
*/
- NO_AUTH_REQUIRED = (7 << 28) /* TagType:BOOL */ | 503,
+ NO_AUTH_REQUIRED = TagType.BOOL | 503,
/**
* Tag::USER_AUTH_TYPE specifies the types of user authenticators that may be used to authorize
@@ -410,7 +408,7 @@
*
* Must be hardware-enforced.
*/
- USER_AUTH_TYPE = (1 << 28) /* TagType:ENUM */ | 504,
+ USER_AUTH_TYPE = TagType.ENUM | 504,
/**
* Tag::AUTH_TIMEOUT specifies the time in seconds for which the key is authorized for use,
@@ -424,7 +422,7 @@
*
* Must be hardware-enforced.
*/
- AUTH_TIMEOUT = (3 << 28) /* TagType:UINT */ | 505,
+ AUTH_TIMEOUT = TagType.UINT | 505,
/**
* Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication timeout if
@@ -432,7 +430,7 @@
*
* Cannot be hardware-enforced.
*/
- ALLOW_WHILE_ON_BODY = (7 << 28) /* TagType:BOOL */ | 506,
+ ALLOW_WHILE_ON_BODY = TagType.BOOL | 506,
/**
* TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
@@ -479,7 +477,7 @@
*
* Must be hardware-enforced.
*/
- TRUSTED_USER_PRESENCE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 507,
+ TRUSTED_USER_PRESENCE_REQUIRED = TagType.BOOL | 507,
/**
* Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
@@ -493,7 +491,7 @@
*
* Must be hardware-enforced.
*/
- TRUSTED_CONFIRMATION_REQUIRED = (7 << 28) /* TagType:BOOL */ | 508,
+ TRUSTED_CONFIRMATION_REQUIRED = TagType.BOOL | 508,
/**
* Tag::UNLOCKED_DEVICE_REQUIRED specifies that the key may only be used when the device is
@@ -503,7 +501,7 @@
* Must be hardware-enforced (but is also keystore-enforced on a per-user basis: see the
* deviceLocked() documentation).
*/
- UNLOCKED_DEVICE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 509,
+ UNLOCKED_DEVICE_REQUIRED = TagType.BOOL | 509,
/**
* Tag::APPLICATION_ID. When provided to generateKey or importKey, this tag specifies data
@@ -519,7 +517,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 601,
+ APPLICATION_ID = TagType.BYTES | 601,
/*
* Semantically unenforceable tags, either because they have no specific meaning or because
@@ -540,7 +538,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- APPLICATION_DATA = (9 << 28) /* TagType:BYTES */ | 700,
+ APPLICATION_DATA = TagType.BYTES | 700,
/**
* Tag::CREATION_DATETIME specifies the date and time the key was created, in milliseconds since
@@ -548,7 +546,7 @@
*
* Must be in the software-enforced list, if provided.
*/
- CREATION_DATETIME = (6 << 28) /* TagType:DATE */ | 701,
+ CREATION_DATETIME = TagType.DATE | 701,
/**
* Tag::ORIGIN specifies where the key was created, if known. This tag must not be specified
@@ -557,7 +555,7 @@
*
* Must be hardware-enforced.
*/
- ORIGIN = (1 << 28) /* TagType:ENUM */ | 702,
+ ORIGIN = TagType.ENUM | 702,
// 703 is unused.
@@ -569,7 +567,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ROOT_OF_TRUST = (9 << 28) /* TagType:BYTES */ | 704,
+ ROOT_OF_TRUST = TagType.BYTES | 704,
/**
* Tag::OS_VERSION specifies the system OS version with which the key may be used. This tag is
@@ -592,7 +590,7 @@
*
* Must be hardware-enforced.
*/
- OS_VERSION = (3 << 28) /* TagType:UINT */ | 705,
+ OS_VERSION = TagType.UINT | 705,
/**
* Tag::OS_PATCHLEVEL specifies the system security patch level with which the key may be used.
@@ -613,7 +611,7 @@
*
* Must be hardware-enforced.
*/
- OS_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 706,
+ OS_PATCHLEVEL = TagType.UINT | 706,
/**
* Tag::UNIQUE_ID specifies a unique, time-based identifier. This tag is never provided to or
@@ -648,7 +646,7 @@
*
* Must be hardware-enforced.
*/
- UNIQUE_ID = (9 << 28) /* TagType:BYTES */ | 707,
+ UNIQUE_ID = TagType.BYTES | 707,
/**
* Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attested key
@@ -657,7 +655,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_CHALLENGE = (9 << 28) /* TagType:BYTES */ | 708,
+ ATTESTATION_CHALLENGE = TagType.BYTES | 708,
/**
* Tag::ATTESTATION_APPLICATION_ID identifies the set of applications which may use a key, used
@@ -683,7 +681,7 @@
*
* Cannot be hardware-enforced.
*/
- ATTESTATION_APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 709,
+ ATTESTATION_APPLICATION_ID = TagType.BYTES | 709,
/**
* Tag::ATTESTATION_ID_BRAND provides the device's brand name, as returned by Build.BRAND in
@@ -696,7 +694,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_BRAND = (9 << 28) /* TagType:BYTES */ | 710,
+ ATTESTATION_ID_BRAND = TagType.BYTES | 710,
/**
* Tag::ATTESTATION_ID_DEVICE provides the device's device name, as returned by Build.DEVICE in
@@ -709,7 +707,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_DEVICE = (9 << 28) /* TagType:BYTES */ | 711,
+ ATTESTATION_ID_DEVICE = TagType.BYTES | 711,
/**
* Tag::ATTESTATION_ID_PRODUCT provides the device's product name, as returned by Build.PRODUCT
@@ -722,7 +720,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_PRODUCT = (9 << 28) /* TagType:BYTES */ | 712,
+ ATTESTATION_ID_PRODUCT = TagType.BYTES | 712,
/**
* Tag::ATTESTATION_ID_SERIAL the device's serial number. This field must be set only when
@@ -734,7 +732,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_SERIAL = (9 << 28) /* TagType:BYTES */ | 713,
+ ATTESTATION_ID_SERIAL = TagType.BYTES | 713,
/**
* Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attested key
@@ -747,7 +745,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_IMEI = (9 << 28) /* TagType:BYTES */ | 714,
+ ATTESTATION_ID_IMEI = TagType.BYTES | 714,
/**
* Tag::ATTESTATION_ID_MEID provides the MEIDs for all radios on the device to attested key
@@ -760,7 +758,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MEID = (9 << 28) /* TagType:BYTES */ | 715,
+ ATTESTATION_ID_MEID = TagType.BYTES | 715,
/**
* Tag::ATTESTATION_ID_MANUFACTURER provides the device's manufacturer name, as returned by
@@ -773,7 +771,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MANUFACTURER = (9 << 28) /* TagType:BYTES */ | 716,
+ ATTESTATION_ID_MANUFACTURER = TagType.BYTES | 716,
/**
* Tag::ATTESTATION_ID_MODEL provides the device's model name, as returned by Build.MODEL in
@@ -786,7 +784,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MODEL = (9 << 28) /* TagType:BYTES */ | 717,
+ ATTESTATION_ID_MODEL = TagType.BYTES | 717,
/**
* Tag::VENDOR_PATCHLEVEL specifies the vendor image security patch level with which the key may
@@ -808,7 +806,7 @@
*
* Must be hardware-enforced.
*/
- VENDOR_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 718,
+ VENDOR_PATCHLEVEL = TagType.UINT | 718,
/**
* Tag::BOOT_PATCHLEVEL specifies the boot image (kernel) security patch level with which the
@@ -828,16 +826,26 @@
*
* Must be hardware-enforced.
*/
- BOOT_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 719,
+ BOOT_PATCHLEVEL = TagType.UINT | 719,
/**
* 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, the returned chain should contain two
- * certificates:
+ * than a batch key. When a device-unique key is used, the returned chain contains two or
+ * three certificates.
+ *
+ * In case the chain contains two certificates, they should be:
* * The attestation certificate, containing the attestation extension, as described in
- KeyCreationResult.aidl.
+ * KeyCreationResult.aidl.
* * A self-signed root certificate, signed by the device-unique key.
+ *
+ * In case the chain contains three certificates, they should be:
+ * * The attestation certificate, containing the attestation extension, as described in
+ * KeyCreationResult.aidl, signed by the device-unique key.
+ * * An intermediate certificate, containing the public portion of the device-unique key.
+ * * A self-signed root certificate, signed by a dedicated key, certifying the
+ * intermediate.
+ *
* 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
@@ -854,7 +862,7 @@
* IKeyMintDevice implementations that support device-unique attestation MUST add the
* DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
*/
- DEVICE_UNIQUE_ATTESTATION = (7 << 28) /* TagType:BOOL */ | 720,
+ DEVICE_UNIQUE_ATTESTATION = TagType.BOOL | 720,
/**
* IDENTITY_CREDENTIAL_KEY is never used by IKeyMintDevice, is not a valid argument to key
@@ -862,7 +870,7 @@
* attestation. It is used in attestations produced by the IIdentityCredential HAL when that
* HAL attests to Credential Keys. IIdentityCredential produces KeyMint-style attestations.
*/
- IDENTITY_CREDENTIAL_KEY = (7 << 28) /* TagType:BOOL */ | 721,
+ IDENTITY_CREDENTIAL_KEY = TagType.BOOL | 721,
/**
* To prevent keys from being compromised if an attacker acquires read access to system / kernel
@@ -880,12 +888,13 @@
* ErrorCode::INVALID_OPERATION is returned when a key with Tag::STORAGE_KEY is provided to
* begin().
*/
- STORAGE_KEY = (7 << 28) /* TagType:BOOL */ | 722,
+ STORAGE_KEY = TagType.BOOL | 722,
/**
- * TODO: Delete when keystore1 is deleted.
+ * OBSOLETE: Do not use. See IKeyMintOperation.updateAad instead.
+ * TODO(b/191738660): Remove in KeyMint v2.
*/
- ASSOCIATED_DATA = (9 << 28) /* TagType:BYTES */ | 1000,
+ ASSOCIATED_DATA = TagType.BYTES | 1000,
/**
* Tag::NONCE is used to provide or return a nonce or Initialization Vector (IV) for AES-GCM,
@@ -900,7 +909,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- NONCE = (9 << 28) /* TagType:BYTES */ | 1001,
+ NONCE = TagType.BYTES | 1001,
/**
* Tag::MAC_LENGTH provides the requested length of a MAC or GCM authentication tag, in bits.
@@ -911,7 +920,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 1003,
+ MAC_LENGTH = TagType.UINT | 1003,
/**
* Tag::RESET_SINCE_ID_ROTATION specifies whether the device has been factory reset since the
@@ -919,7 +928,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- RESET_SINCE_ID_ROTATION = (7 << 28) /* TagType:BOOL */ | 1004,
+ RESET_SINCE_ID_ROTATION = TagType.BOOL | 1004,
/**
* OBSOLETE: Do not use. See the authToken parameter for IKeyMintDevice::begin and for
@@ -927,7 +936,7 @@
*
* TODO(b/191738660): Delete when keystore1 is deleted.
*/
- CONFIRMATION_TOKEN = (9 << 28) /* TagType:BYTES */ | 1005,
+ CONFIRMATION_TOKEN = TagType.BYTES | 1005,
/**
* Tag::CERTIFICATE_SERIAL specifies the serial number to be assigned to the attestation
@@ -935,7 +944,7 @@
* keyMint in the attestation parameters during generateKey() and importKey(). If not provided,
* the serial shall default to 1.
*/
- CERTIFICATE_SERIAL = (8 << 28) /* TagType:BIGNUM */ | 1006,
+ CERTIFICATE_SERIAL = TagType.BIGNUM | 1006,
/**
* Tag::CERTIFICATE_SUBJECT the certificate subject. The value is a DER encoded X509 NAME.
@@ -943,7 +952,7 @@
* during generateKey and importKey. If not provided the subject name shall default to
* CN="Android Keystore Key".
*/
- CERTIFICATE_SUBJECT = (9 << 28) /* TagType:BYTES */ | 1007,
+ CERTIFICATE_SUBJECT = TagType.BYTES | 1007,
/**
* Tag::CERTIFICATE_NOT_BEFORE the beginning of the validity of the certificate in UNIX epoch
@@ -951,7 +960,7 @@
* certificates. ErrorCode::MISSING_NOT_BEFORE must be returned if this tag is not provided if
* this tag is not provided to generateKey or importKey.
*/
- CERTIFICATE_NOT_BEFORE = (6 << 28) /* TagType:DATE */ | 1008,
+ CERTIFICATE_NOT_BEFORE = TagType.DATE | 1008,
/**
* Tag::CERTIFICATE_NOT_AFTER the end of the validity of the certificate in UNIX epoch time in
@@ -959,7 +968,7 @@
* ErrorCode::MISSING_NOT_AFTER must be returned if this tag is not provided to generateKey or
* importKey.
*/
- CERTIFICATE_NOT_AFTER = (6 << 28) /* TagType:DATE */ | 1009,
+ CERTIFICATE_NOT_AFTER = TagType.DATE | 1009,
/**
* Tag::MAX_BOOT_LEVEL specifies a maximum boot level at which a key should function.
@@ -970,5 +979,5 @@
*
* Cannot be hardware enforced in this version.
*/
- MAX_BOOT_LEVEL = (3 << 28) /* TagType:UINT */ | 1010,
+ MAX_BOOT_LEVEL = TagType.UINT | 1010,
}
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 386029f..77eea8a 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -94,6 +94,7 @@
"libkeymint_vts_test_utils",
"libpuresoftkeymasterdevice",
],
+ test_config: "VtsRemotelyProvisionedComponentTests.xml",
test_suites: [
"general-tests",
"vts",
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index a3ed3ad..d7abf07 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -40,11 +40,16 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
- // The device-unique attestation chain should contain exactly two certificates:
+ // The device-unique attestation chain should contain exactly three 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_));
+ // * An intermediate, signing the leaf using the device-unique key.
+ // * A self-signed root, signed using some authority's key, certifying
+ // the device-unique key.
+ const size_t chain_length = cert_chain_.size();
+ ASSERT_TRUE(chain_length == 2 || chain_length == 3);
+ // TODO(b/191361618): Once StrongBox implementations use a correctly-issued
+ // certificate chain, do not skip issuers matching.
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_, /* strict_issuer_check= */ false));
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 5359b3b..2032411 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1493,7 +1493,8 @@
return authList;
}
-AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain) {
+AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
+ bool strict_issuer_check) {
std::stringstream cert_data;
for (size_t i = 0; i < chain.size(); ++i) {
@@ -1520,7 +1521,7 @@
string cert_issuer = x509NameToStr(X509_get_issuer_name(key_cert.get()));
string signer_subj = x509NameToStr(X509_get_subject_name(signing_cert.get()));
- if (cert_issuer != signer_subj) {
+ if (cert_issuer != signer_subj && strict_issuer_check) {
return AssertionFailure() << "Cert " << i << " has wrong issuer.\n"
<< " Signer subject is " << signer_subj
<< " Issuer subject is " << cert_issuer << endl
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index d592d36..ec3fcf6 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -349,7 +349,8 @@
AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
-::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain);
+::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
+ bool strict_issuer_check = true);
#define INSTANTIATE_KEYMINT_AIDL_TEST(name) \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index d41d270..5a87b83 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1487,9 +1487,8 @@
tag.tag == TAG_ROLLBACK_RESISTANCE) {
continue;
}
- if (result == ErrorCode::UNSUPPORTED_TAG &&
- (tag.tag == TAG_ALLOW_WHILE_ON_BODY || tag.tag == TAG_TRUSTED_USER_PRESENCE_REQUIRED)) {
- // Optional tag not supported by this KeyMint implementation.
+ if (result == ErrorCode::UNSUPPORTED_TAG && tag.tag == TAG_TRUSTED_USER_PRESENCE_REQUIRED) {
+ // Tag not required to be supported by all KeyMint implementations.
continue;
}
ASSERT_EQ(result, ErrorCode::OK);
@@ -1501,9 +1500,8 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- if (tag.tag != TAG_ATTESTATION_APPLICATION_ID) {
- // Expect to find most of the extra tags in the key characteristics
- // of the generated key (but not for ATTESTATION_APPLICATION_ID).
+ // Some tags are optional, so don't require them to be in the enforcements.
+ if (tag.tag != TAG_ATTESTATION_APPLICATION_ID && tag.tag != TAG_ALLOW_WHILE_ON_BODY) {
EXPECT_TRUE(hw_enforced.Contains(tag.tag) || sw_enforced.Contains(tag.tag))
<< tag << " not in hw:" << hw_enforced << " nor sw:" << sw_enforced;
}
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 78f8f08..af951e8 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -29,6 +29,7 @@
#include <openssl/ec_key.h>
#include <openssl/x509.h>
#include <remote_prov/remote_prov_utils.h>
+#include <vector>
#include "KeyMintAidlTestBase.h"
@@ -102,8 +103,8 @@
return std::move(corruptSig);
}
-ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) {
- auto [chain, _, parseErr] = cppbor::parse(eek.chain);
+ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
+ auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
if (!chain || !chain->asArray()) {
return "EekChain parse failed";
}
@@ -125,7 +126,7 @@
corruptChain.add(eekChain->get(ii)->clone());
}
}
- return EekChain{corruptChain.encode(), eek.last_pubkey, eek.last_privkey};
+ return corruptChain.encode();
}
string device_suffix(const string& name) {
@@ -271,14 +272,14 @@
class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
protected:
CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
- generateEek(3);
+ generateTestEekChain(3);
}
- void generateEek(size_t eekLength) {
+ void generateTestEekChain(size_t eekLength) {
auto chain = generateEekChain(eekLength, eekId_);
EXPECT_TRUE(chain) << chain.message();
- if (chain) eekChain_ = chain.moveValue();
- eekLength_ = eekLength;
+ if (chain) testEekChain_ = chain.moveValue();
+ testEekLength_ = eekLength;
}
void generateKeys(bool testMode, size_t numKeys) {
@@ -297,7 +298,8 @@
}
void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
- const bytevec& keysToSignMac, const ProtectedData& protectedData) {
+ const bytevec& keysToSignMac, const ProtectedData& protectedData,
+ std::vector<BccEntryData>* bccOutput = nullptr) {
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
ASSERT_TRUE(parsedProtectedData->asArray());
@@ -307,8 +309,9 @@
ASSERT_TRUE(senderPubkey) << senderPubkey.message();
EXPECT_EQ(senderPubkey->second, eekId_);
- auto sessionKey = x25519_HKDF_DeriveKey(eekChain_.last_pubkey, eekChain_.last_privkey,
- senderPubkey->first, false /* senderIsA */);
+ auto sessionKey =
+ x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+ senderPubkey->first, false /* senderIsA */);
ASSERT_TRUE(sessionKey) << sessionKey.message();
auto protectedDataPayload =
@@ -354,11 +357,15 @@
auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
ASSERT_TRUE(macPayload) << macPayload.message();
+
+ if (bccOutput) {
+ *bccOutput = std::move(*bccContents);
+ }
}
bytevec eekId_;
- size_t eekLength_;
- EekChain eekChain_;
+ size_t testEekLength_;
+ EekChain testEekChain_;
bytevec challenge_;
std::vector<MacedPublicKey> keysToSign_;
cppbor::Array cborKeysToSign_;
@@ -372,13 +379,13 @@
bool testMode = true;
for (size_t eekLength : {2, 3, 7}) {
SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
- generateEek(eekLength);
+ generateTestEekChain(eekLength);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo,
+ testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
@@ -387,31 +394,62 @@
}
/**
- * Generate an empty certificate request in prod mode. Generation will fail because we don't have a
- * valid GEEK.
- *
- * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be
- * able to decrypt.
+ * Ensure that test mode outputs a unique BCC root key every time we request a
+ * certificate request. Else, it's possible that the test mode API could be used
+ * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
+ * device public key multiple times.
*/
-TEST_P(CertificateRequestTest, EmptyRequest_prodMode) {
- bool testMode = false;
- for (size_t eekLength : {2, 3, 7}) {
- SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
- generateEek(eekLength);
+TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
+ constexpr bool testMode = true;
- bytevec keysToSignMac;
- DeviceInfo deviceInfo;
- ProtectedData protectedData;
- auto status = provisionable_->generateCertificateRequest(
- testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo,
- &protectedData, &keysToSignMac);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(status.getServiceSpecificError(),
- BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
+ bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
+ ProtectedData protectedData;
+ auto status = provisionable_->generateCertificateRequest(
+ testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ std::vector<BccEntryData> firstBcc;
+ checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
+ &firstBcc);
+
+ status = provisionable_->generateCertificateRequest(
+ testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ std::vector<BccEntryData> secondBcc;
+ checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
+ &secondBcc);
+
+ // Verify that none of the keys in the first BCC are repeated in the second one.
+ for (const auto& i : firstBcc) {
+ for (auto& j : secondBcc) {
+ ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
+ << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
+ }
}
}
/**
+ * Generate an empty certificate request in prod mode. This test must be run explicitly, and
+ * is not run by default. Not all devices are GMS devices, and therefore they do not all
+ * trust the Google EEK root.
+ */
+TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
+ bool testMode = false;
+
+ bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
+ ProtectedData protectedData;
+ auto status = provisionable_->generateCertificateRequest(
+ testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
+ EXPECT_TRUE(status.isOk());
+}
+
+/**
* Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
*/
TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
@@ -420,13 +458,13 @@
for (size_t eekLength : {2, 3, 7}) {
SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
- generateEek(eekLength);
+ generateTestEekChain(eekLength);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
+ testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
&keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
@@ -435,30 +473,21 @@
}
/**
- * Generate a non-empty certificate request in prod mode. Must fail because we don't have a valid
- * GEEK.
- *
- * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be
- * able to decrypt.
+ * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
+ * is not run by default. Not all devices are GMS devices, and therefore they do not all
+ * trust the Google EEK root.
*/
-TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) {
+TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
bool testMode = false;
generateKeys(testMode, 4 /* numKeys */);
- for (size_t eekLength : {2, 3, 7}) {
- SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
- generateEek(eekLength);
-
- bytevec keysToSignMac;
- DeviceInfo deviceInfo;
- ProtectedData protectedData;
- auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
- &keysToSignMac);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(status.getServiceSpecificError(),
- BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
- }
+ bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
+ ProtectedData protectedData;
+ auto status = provisionable_->generateCertificateRequest(
+ testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
+ &keysToSignMac);
+ EXPECT_TRUE(status.isOk());
}
/**
@@ -473,8 +502,8 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
- &keysToSignMac);
+ testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk()) << status.getMessage();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
@@ -483,7 +512,7 @@
* Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
*/
TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
- bool testMode = true;
+ bool testMode = false;
generateKeys(testMode, 1 /* numKeys */);
MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
@@ -491,38 +520,35 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
- &keysToSignMac);
+ testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk()) << status.getMessage();
- auto rc = status.getServiceSpecificError();
-
- // TODO(drysdale): drop the INVALID_EEK potential error code when a real GEEK is available.
- EXPECT_TRUE(rc == BnRemotelyProvisionedComponent::STATUS_INVALID_EEK ||
- rc == BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
+ EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
/**
* Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
* Confirm that the request is rejected.
- *
- * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the
- * implementation is checking signatures.
*/
TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
bool testMode = false;
generateKeys(testMode, 4 /* numKeys */);
- for (size_t ii = 0; ii < eekLength_; ii++) {
- auto chain = corrupt_sig_chain(eekChain_, ii);
+ auto prodEekChain = getProdEekChain();
+ auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
+ ASSERT_NE(parsedChain, nullptr) << parseErr;
+ ASSERT_NE(parsedChain->asArray(), nullptr);
+
+ for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
+ auto chain = corrupt_sig_chain(prodEekChain, ii);
ASSERT_TRUE(chain) << chain.message();
- EekChain corruptEek = chain.moveValue();
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
- auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, corruptEek.chain, challenge_, &deviceInfo, &protectedData,
- &keysToSignMac);
+ auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
+ challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
@@ -532,9 +558,6 @@
/**
* Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
* Confirm that the request is rejected.
- *
- * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the
- * implementation is checking signatures.
*/
TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
bool testMode = false;
@@ -542,7 +565,7 @@
// Build an EEK chain that omits the first self-signed cert.
auto truncatedChain = cppbor::Array();
- auto [chain, _, parseErr] = cppbor::parse(eekChain_.chain);
+ auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
ASSERT_TRUE(chain);
auto eekChain = chain->asArray();
ASSERT_NE(eekChain, nullptr);
@@ -571,7 +594,7 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- true /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo,
+ true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
@@ -589,7 +612,7 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- false /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo,
+ false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml
new file mode 100644
index 0000000..2375bde
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRemotelyProvisionedComponentTargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file"
+ key="VtsHalRemotelyProvisionedComponentTargetTest"
+ value="/data/local/tmp/VtsHalRemotelyProvisionedComponentTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalRemotelyProvisionedComponentTargetTest" />
+ <option name="native-test-timeout" value="900000"/> <!-- 15 minutes -->
+ </test>
+</configuration>
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index c56bd9a..553d7f0 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -60,9 +60,10 @@
android::enum_range<CompositePrimitive>().begin(),
android::enum_range<CompositePrimitive>().end()};
-const std::vector<CompositePrimitive> kOptionalPrimitives = {
- CompositePrimitive::THUD,
- CompositePrimitive::SPIN,
+const std::vector<CompositePrimitive> kRequiredPrimitives = {
+ CompositePrimitive::CLICK, CompositePrimitive::LIGHT_TICK,
+ CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
+ CompositePrimitive::QUICK_FALL,
};
const std::vector<CompositePrimitive> kInvalidPrimitives = {
@@ -393,11 +394,11 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
- bool isPrimitiveOptional =
- std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
- kOptionalPrimitives.end();
+ bool isPrimitiveRequired =
+ std::find(kRequiredPrimitives.begin(), kRequiredPrimitives.end(), primitive) !=
+ kRequiredPrimitives.end();
- EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
+ EXPECT_TRUE(isPrimitiveSupported || !isPrimitiveRequired) << toString(primitive);
}
}
}
diff --git a/wifi/1.5/default/ringbuffer.cpp b/wifi/1.5/default/ringbuffer.cpp
index 26971ff..f554111 100644
--- a/wifi/1.5/default/ringbuffer.cpp
+++ b/wifi/1.5/default/ringbuffer.cpp
@@ -47,6 +47,11 @@
return data_;
}
+void Ringbuffer::clear() {
+ data_.clear();
+ size_ = 0;
+}
+
} // namespace implementation
} // namespace V1_5
} // namespace wifi
diff --git a/wifi/1.5/default/ringbuffer.h b/wifi/1.5/default/ringbuffer.h
index d8b87f2..03fb37a 100644
--- a/wifi/1.5/default/ringbuffer.h
+++ b/wifi/1.5/default/ringbuffer.h
@@ -37,6 +37,7 @@
// within |maxSize_|.
void append(const std::vector<uint8_t>& input);
const std::list<std::vector<uint8_t>>& getData() const;
+ void clear();
private:
std::list<std::vector<uint8_t>> data_;
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 6fa9601..82d794c 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -1948,8 +1948,8 @@
// write ringbuffers to file
{
std::unique_lock<std::mutex> lk(lock_t);
- for (const auto& item : ringbuffer_map_) {
- const Ringbuffer& cur_buffer = item.second;
+ for (auto& item : ringbuffer_map_) {
+ Ringbuffer& cur_buffer = item.second;
if (cur_buffer.getData().empty()) {
continue;
}
@@ -1967,6 +1967,7 @@
PLOG(ERROR) << "Error writing to file";
}
}
+ cur_buffer.clear();
}
// unique_lock unlocked here
}