Merge "Extend 1.0 dynamic config reader to read 1.1 Tuner HAL types" into sc-dev
diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp
index 4e82b0a..9f0c4c4 100644
--- a/atrace/1.0/default/AtraceDevice.cpp
+++ b/atrace/1.0/default/AtraceDevice.cpp
@@ -16,6 +16,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "AtraceDevice.h"
@@ -39,15 +40,11 @@
// gfx
{
"gfx",
- {"Graphics",
- {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
- {"/sys/kernel/debug/tracing/events/sde/enable", false},
- {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
+ {"Graphics", {{"mdss", false}, {"sde", false}, {"mali_systrace", false}}},
},
{
"ion",
- {"ION allocation",
- {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", false}}},
+ {"ION allocation", {{"kmem/ion_alloc_buffer_start", false}}},
},
};
@@ -65,16 +62,31 @@
return Void();
}
+AtraceDevice::AtraceDevice() {
+ struct stat st;
+
+ tracefs_event_root_ = "/sys/kernel/tracing/events/";
+ if (stat(tracefs_event_root_.c_str(), &st) != 0) {
+ tracefs_event_root_ = "/sys/kernel/debug/tracing/events/";
+ CHECK(stat(tracefs_event_root_.c_str(), &st) == 0) << "tracefs must be mounted at either"
+ "/sys/kernel/tracing or "
+ "/sys/kernel/debug/tracing";
+ }
+}
+
Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::enableCategories(
- const hidl_vec<hidl_string>& categories) {
+ const hidl_vec<hidl_string>& categories) {
if (!categories.size()) {
return Status::ERROR_INVALID_ARGUMENT;
}
+
for (auto& c : categories) {
if (kTracingMap.count(c)) {
for (auto& p : kTracingMap.at(c).paths) {
- if (!android::base::WriteStringToFile("1", p.first)) {
- LOG(ERROR) << "Failed to enable tracing on: " << p.first;
+ std::string tracefs_event_enable_path = android::base::StringPrintf(
+ "%s%s/enable", tracefs_event_root_.c_str(), p.first.c_str());
+ if (!android::base::WriteStringToFile("1", tracefs_event_enable_path)) {
+ LOG(ERROR) << "Failed to enable tracing on: " << tracefs_event_enable_path;
if (p.second) {
// disable before return
disableAllCategories();
@@ -91,10 +103,13 @@
Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::disableAllCategories() {
auto ret = Status::SUCCESS;
+
for (auto& c : kTracingMap) {
for (auto& p : c.second.paths) {
- if (!android::base::WriteStringToFile("0", p.first)) {
- LOG(ERROR) << "Failed to disable tracing on: " << p.first;
+ std::string tracefs_event_enable_path = android::base::StringPrintf(
+ "%s%s/enable", tracefs_event_root_.c_str(), p.first.c_str());
+ if (!android::base::WriteStringToFile("0", tracefs_event_enable_path)) {
+ LOG(ERROR) << "Failed to disable tracing on: " << tracefs_event_enable_path;
if (p.second) {
ret = Status::ERROR_TRACING_POINT;
}
diff --git a/atrace/1.0/default/AtraceDevice.h b/atrace/1.0/default/AtraceDevice.h
index e700f89..ab87c65 100644
--- a/atrace/1.0/default/AtraceDevice.h
+++ b/atrace/1.0/default/AtraceDevice.h
@@ -36,12 +36,16 @@
using ::android::hardware::Void;
struct AtraceDevice : public IAtraceDevice {
+ AtraceDevice();
// Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
Return<void> listCategories(listCategories_cb _hidl_cb) override;
Return<::android::hardware::atrace::V1_0::Status> enableCategories(
const hidl_vec<hidl_string>& categories) override;
Return<::android::hardware::atrace::V1_0::Status> disableAllCategories() override;
+ private:
+ std::string tracefs_event_root_;
+
// Methods from ::android::hidl::base::V1_0::IBase follow.
};
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
index eb54c39..7110b45 100644
--- a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -1,10 +1,14 @@
on late-init
# vendor graphics trace points
chmod 0666 /sys/kernel/debug/tracing/events/sde/enable
+ chmod 0666 /sys/kernel/tracing/events/sde/enable
chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable
+ chmod 0666 /sys/kernel/tracing/events/mdss/enable
chmod 0666 /sys/kernel/debug/tracing/events/mali_systrace/enable
+ chmod 0666 /sys/kernel/tracing/events/mali_systrace/enable
# ion allocation trace point
chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/ion_alloc_buffer_start/enable
service vendor.atrace-hal-1-0 /vendor/bin/hw/android.hardware.atrace@1.0-service
interface android.hardware.atrace@1.0::IAtraceDevice default
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index 7d2706c..3716cf0 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -45,6 +45,8 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_NONE;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT_360RA;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_22POINT2;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1POINT2;
@@ -104,6 +106,7 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI_EARC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_IP;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LINE;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
@@ -138,6 +141,7 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_FM;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI_EARC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_IP;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_LINE;
@@ -206,9 +210,11 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_CELT;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DEFAULT;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DRA;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DSD;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS_HD;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS_UHD;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCB;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCNW;
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 2030921..7f7fb61 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -253,6 +253,7 @@
<xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_EARC"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
@@ -304,6 +305,7 @@
<xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
<xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
<xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_EARC"/>
<xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
<xs:enumeration value="AUDIO_DEVICE_IN_BLE_HEADSET"/>
<xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
@@ -412,6 +414,8 @@
<xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L3"/>
<xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L4"/>
<xs:enumeration value="AUDIO_FORMAT_IEC60958"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_UHD"/>
+ <xs:enumeration value="AUDIO_FORMAT_DRA"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extendableAudioFormat">
@@ -505,6 +509,8 @@
<xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT_360RA"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_22POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_A"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_HAPTIC_AB"/>
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index 7d83556..a92a277 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -94,6 +94,7 @@
case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12:
return 12;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_13POINT_360RA:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
return 13;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
@@ -116,6 +117,7 @@
return 22;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23:
return 23;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_22POINT2:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24:
return 24;
case AudioChannelMask::UNKNOWN:
@@ -155,6 +157,7 @@
case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
case AudioDevice::AUDIO_DEVICE_OUT_LINE:
case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
+ case AudioDevice::AUDIO_DEVICE_OUT_HDMI_EARC:
case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
case AudioDevice::AUDIO_DEVICE_OUT_FM:
case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
@@ -197,6 +200,7 @@
case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
+ case AudioDevice::AUDIO_DEVICE_IN_HDMI_EARC:
case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
case AudioDevice::AUDIO_DEVICE_IN_BLE_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index 599f3c3..2aeee43 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -413,8 +413,8 @@
// Create and launch the thread.
auto tempReadThread =
- std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
- tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
+ sp<ReadThread>::make(&mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+ tempStatusMQ.get(), tempElfGroup.get());
if (!tempReadThread->init()) {
ALOGW("failed to start reader thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
@@ -430,7 +430,7 @@
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
- mReadThread = tempReadThread.release();
+ mReadThread = tempReadThread;
mEfGroup = tempElfGroup.release();
#if MAJOR_VERSION <= 6
threadInfo.pid = getpid();
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 5e4dd2a..6eed3da 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -398,8 +398,8 @@
// Create and launch the thread.
auto tempWriteThread =
- std::make_unique<WriteThread>(&mStopWriteThread, mStream, tempCommandMQ.get(),
- tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
+ sp<WriteThread>::make(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+ tempStatusMQ.get(), tempElfGroup.get());
if (!tempWriteThread->init()) {
ALOGW("failed to start writer thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
@@ -415,7 +415,7 @@
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
- mWriteThread = tempWriteThread.release();
+ mWriteThread = tempWriteThread;
mEfGroup = tempElfGroup.release();
#if MAJOR_VERSION <= 6
threadInfo.pid = getpid();
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
index 14f76f3..773be21 100644
--- a/audio/core/all-versions/default/util/CoreUtils.cpp
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -66,13 +66,13 @@
CONVERT_CHECKED(
deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress),
result);
- size_t chCount;
- for (chCount = 0; chCount < AUDIO_CHANNEL_COUNT_MAX; ++chCount) {
- if (halMicInfo.channel_mapping[chCount] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
+ int chCount;
+ for (chCount = AUDIO_CHANNEL_COUNT_MAX - 1; chCount >= 0; --chCount) {
+ if (halMicInfo.channel_mapping[chCount] != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
break;
}
}
- micInfo->channelMapping.resize(chCount);
+ micInfo->channelMapping.resize(chCount + 1);
for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) {
micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]);
}
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
index fec2a3a..6fc5024 100644
--- a/automotive/evs/OWNERS
+++ b/automotive/evs/OWNERS
@@ -1,3 +1,3 @@
changyeon@google.com
+garysungang@google.com
haoxiangl@google.com
-swan@google.com
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index b2f8bf6..21c1a6e 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -78,6 +78,7 @@
name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
vendor: true,
defaults: ["vhal_v2_0_target_defaults"],
+ cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
srcs: [
"impl/vhal_v2_0/CommConn.cpp",
"impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
@@ -91,13 +92,13 @@
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
"impl/vhal_v2_0/GeneratorHub.cpp",
+ "impl/vhal_v2_0/qemu_pipe.cpp",
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
whole_static_libs: [
"android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
"android.hardware.automotive.vehicle@2.0-manager-lib",
- "libqemu_pipe",
],
shared_libs: [
"libbase",
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index f5b53d3..abf33a3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -115,6 +115,28 @@
*/
const int32_t kMixedTypePropertyForTest =
0x1111 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+/**
+ * Converts the system property to the vendor property.
+ * WARNING: This is only for the end-to-end testing, Should NOT include in the
+ * user build */
+inline constexpr int32_t toVendor(VehicleProperty prop) {
+ return (toInt(prop) & ~toInt(VehiclePropertyGroup::MASK)) | VehiclePropertyGroup::VENDOR;
+}
+
+/**
+ * These properties are used for the end-to-end testing of ClusterHomeService.
+ */
+constexpr int32_t VENDOR_CLUSTER_SWITCH_UI = toVendor(VehicleProperty::CLUSTER_SWITCH_UI);
+constexpr int32_t VENDOR_CLUSTER_DISPLAY_STATE = toVendor(VehicleProperty::CLUSTER_DISPLAY_STATE);
+constexpr int32_t VENDOR_CLUSTER_REPORT_STATE = toVendor(VehicleProperty::CLUSTER_REPORT_STATE);
+constexpr int32_t VENDOR_CLUSTER_REQUEST_DISPLAY =
+ toVendor(VehicleProperty::CLUSTER_REQUEST_DISPLAY);
+constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE =
+ toVendor(VehicleProperty::CLUSTER_NAVIGATION_STATE);
+#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
/**
* FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty.
* All those commands can be send independently with each other. And each will override the one sent
@@ -439,22 +461,22 @@
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
.areaConfigs = {VehicleAreaConfig{
.areaId = WHEEL_FRONT_LEFT,
- .minFloatValue = 100.0f,
+ .minFloatValue = 193.0f,
.maxFloatValue = 300.0f,
},
VehicleAreaConfig{
.areaId = WHEEL_FRONT_RIGHT,
- .minFloatValue = 100.0f,
+ .minFloatValue = 193.0f,
.maxFloatValue = 300.0f,
},
VehicleAreaConfig{
.areaId = WHEEL_REAR_LEFT,
- .minFloatValue = 100.0f,
+ .minFloatValue = 193.0f,
.maxFloatValue = 300.0f,
},
VehicleAreaConfig{
.areaId = WHEEL_REAR_RIGHT,
- .minFloatValue = 100.0f,
+ .minFloatValue = 193.0f,
.maxFloatValue = 300.0f,
}},
.minSampleRate = 1.0f,
@@ -464,6 +486,17 @@
{.config =
{
+ .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ },
+ .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
+ {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
+ {WHEEL_REAR_RIGHT, {.floatValues = {137.0f}}},
+ {WHEEL_REAR_LEFT, {.floatValues = {137.0f}}}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -668,6 +701,7 @@
{.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {160, 280, 5, 605, 825, 10},
.areaConfigs = {VehicleAreaConfig{
.areaId = HVAC_LEFT,
.minFloatValue = 16,
@@ -683,6 +717,14 @@
{.config =
{
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.floatValues = {66.2f, (float)VehicleUnit::FAHRENHEIT, 19.0f, 66.5f}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
.access = VehiclePropertyAccess::READ,
// TODO(bryaneyler): Support ON_CHANGE as well.
@@ -1218,7 +1260,7 @@
.prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
.access = VehiclePropertyAccess::WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0, 0, 9, 0, 0, 0, 0, 16},
+ .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
},
},
{
@@ -1237,6 +1279,50 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+ // Vendor propetry for E2E ClusterHomeService testing.
+ {
+ .config =
+ {
+ .prop = VENDOR_CLUSTER_SWITCH_UI,
+ .access = VehiclePropertyAccess::WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ },
+ {
+ .config =
+ {
+ .prop = VENDOR_CLUSTER_DISPLAY_STATE,
+ .access = VehiclePropertyAccess::WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ },
+ {
+ .config =
+ {
+ .prop = VENDOR_CLUSTER_REPORT_STATE,
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
+ },
+ },
+ {
+ .config =
+ {
+ .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ },
+ {
+ .config =
+ {
+ .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ },
+#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
index f024287..81e7c78 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
@@ -18,9 +18,9 @@
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <log/log.h>
-#include <qemu_pipe.h>
#include "PipeComm.h"
+#include "qemu_pipe.h"
#define CAR_SERVICE_NAME "pipe:qemud:car"
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
index 0ee1835..6b87052 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -247,6 +247,28 @@
break;
}
break;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+ case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
+ case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
+ case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
+ case VENDOR_CLUSTER_SWITCH_UI:
+ case VENDOR_CLUSTER_DISPLAY_STATE: {
+ auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
+ updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
+ if (isSystemProperty(value.prop)) {
+ updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
+ } else {
+ updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
+ }
+ updatedPropValue->value = value.value;
+ updatedPropValue->timestamp = elapsedRealtimeNano();
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
default:
break;
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
new file mode 100644
index 0000000..cf1a002
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 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 "qemu_pipe.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+
+using android::base::ReadFully;
+using android::base::WriteFully;
+
+// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
+// occurs during pipe operations. The macro should simply take a printf-style
+// formatting string followed by optional arguments.
+#ifndef QEMU_PIPE_DEBUG
+#define QEMU_PIPE_DEBUG(...) (void)0
+#endif
+
+int qemu_pipe_open(const char* pipeName) {
+ if (!pipeName) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
+ if (fd < 0) {
+ QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno));
+ return -1;
+ }
+
+ // Write the pipe name, *including* the trailing zero which is necessary.
+ size_t pipeNameLen = strlen(pipeName);
+ if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
+ return fd;
+ }
+
+ // now, add 'pipe:' prefix and try again
+ // Note: host side will wait for the trailing '\0' to start
+ // service lookup.
+ const char pipe_prefix[] = "pipe:";
+ if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
+ WriteFully(fd, pipeName, pipeNameLen + 1U)) {
+ return fd;
+ }
+ QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s", __FUNCTION__, pipeName,
+ strerror(errno));
+ close(fd);
+ return -1;
+}
+
+int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
+ char header[5];
+ snprintf(header, sizeof(header), "%04zx", len);
+ if (!WriteFully(fd, header, 4)) {
+ QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
+ return -1;
+ }
+ if (!WriteFully(fd, buff, len)) {
+ QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
+ char header[5];
+ if (!ReadFully(fd, header, 4)) {
+ QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
+ return -1;
+ }
+ header[4] = '\0';
+ size_t size;
+ if (sscanf(header, "%04zx", &size) != 1) {
+ QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
+ return -1;
+ }
+ if (size > len) {
+ QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size, len);
+ return -1;
+ }
+ if (!ReadFully(fd, buff, size)) {
+ QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s", strerror(errno));
+ return -1;
+ }
+ return size;
+}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
new file mode 100644
index 0000000..0987498
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_CORE_INCLUDE_QEMU_PIPE_H
+#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Try to open a new Qemu fast-pipe. This function returns a file descriptor
+// that can be used to communicate with a named service managed by the
+// emulator.
+//
+// This file descriptor can be used as a standard pipe/socket descriptor.
+//
+// 'pipeName' is the name of the emulator service you want to connect to,
+// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
+// For backward compatibility, the 'pipe:' prefix can be omitted, and in
+// that case, qemu_pipe_open will add it for you.
+
+// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
+//
+// EINVAL -> unknown/unsupported pipeName
+// ENOSYS -> fast pipes not available in this system.
+//
+// ENOSYS should never happen, except if you're trying to run within a
+// misconfigured emulator.
+//
+// You should be able to open several pipes to the same pipe service,
+// except for a few special cases (e.g. GSM modem), where EBUSY will be
+// returned if more than one client tries to connect to it.
+int qemu_pipe_open(const char* pipeName);
+
+// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
+// This really adds a 4-hexchar prefix describing the payload size.
+// Returns 0 on success, and -1 on error.
+int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
+
+// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
+// If the framed message is larger than |len|, then this returns -1 and the
+// content is lost. Otherwise, this returns the size of the message. NOTE:
+// empty messages are possible in a framed wire protocol and do not mean
+// end-of-stream.
+int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 1fb7dc7..e22f9fa 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -641,6 +641,25 @@
| VehicleArea:WHEEL),
/**
+ * Critically low tire pressure
+ *
+ * This property indicates the critically low pressure threshold for each tire.
+ * It indicates when it is time for tires to be replaced or fixed. The value
+ * must be less than or equal to minFloatValue in TIRE_PRESSURE.
+ * Minimum and maximum property values (that is, minFloatValue, maxFloatValue)
+ * are not applicable to this property.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:KILOPASCAL
+ */
+ CRITICALLY_LOW_TIRE_PRESSURE = (
+ 0x030A
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:FLOAT
+ | VehicleArea:WHEEL),
+
+ /**
* Currently selected gear
*
* This is the gear selected by the user.
@@ -881,6 +900,24 @@
/**
* HVAC, target temperature set.
*
+ * The configArray is used to indicate the valid values for HVAC in Fahrenheit and Celsius.
+ * Android might use it in the HVAC app UI.
+ * The configArray is set as follows:
+ * configArray[0] = [the lower bound of the supported temperature in Celsius] * 10.
+ * configArray[1] = [the upper bound of the supported temperature in Celsius] * 10.
+ * configArray[2] = [the increment in Celsius] * 10.
+ * configArray[3] = [the lower bound of the supported temperature in Fahrenheit] * 10.
+ * configArray[4] = [the upper bound of the supported temperature in Fahrenheit] * 10.
+ * configArray[5] = [the increment in Fahrenheit] * 10.
+ * For example, if the vehicle supports temperature values as:
+ * [16.0, 16.5, 17.0 ,..., 28.0] in Celsius
+ * [60.5, 61.5, 62.5 ,..., 85.5] in Fahrenheit.
+ * The configArray should be configArray = {160, 280, 5, 605, 825, 10}.
+ *
+ * If the vehicle supports HVAC_TEMPERATURE_VALUE_SUGGESTION, the application can use
+ * that property to get the suggested value before setting HVAC_TEMPERATURE_SET. Otherwise,
+ * the application may choose the value in HVAC_TEMPERATURE_SET configArray by itself.
+ *
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ_WRITE
* @unit VehicleUnit:CELSIUS
@@ -1229,6 +1266,50 @@
| VehiclePropertyType:BOOLEAN
| VehicleArea:WINDOW),
+ /**
+ * Suggested values for setting HVAC temperature.
+ *
+ * Implement the property to help applications understand the closest supported temperature
+ * value in Celsius or Fahrenheit.
+ *
+ * floatValues[0] = the requested value that an application wants to set a temperature to.
+ * floatValues[1] = the unit for floatValues[0]. It should be one of
+ * {VehicleUnit:CELSIUS, VehicleUnit:FAHRENHEIT}.
+ * floatValues[2] = the value OEMs suggested in CELSIUS. This value is not included
+ * in the request.
+ * floatValues[3] = the value OEMs suggested in FAHRENHEIT. This value is not included
+ * in the request.
+ *
+ * An application calls set(VehiclePropValue propValue) with the requested value and unit for
+ * the value. OEMs need to return the suggested values in floatValues[2] and floatValues[3] by
+ * onPropertyEvent() callbacks.
+ *
+ * For example, when a user uses the voice assistant to set HVAC temperature to 66.2 in
+ * Fahrenheit.
+ * First, an application will set this property with the value
+ * [66.2, (float)VehicleUnit:FAHRENHEIT,0,0].
+ * If OEMs suggest to set 19.0 in Celsius or 66.5 in Fahrenheit for user's request, then VHAL
+ * must generate a callback with property value
+ * [66.2, (float)VehicleUnit:FAHRENHEIT, 19.0, 66.5]. After the voice assistant gets the
+ * callback, it will inform the user and set HVAC temperature to the suggested value.
+ *
+ * Another example, an application receives 21 Celsius as the current temperature value by
+ * querying HVC_TEMPERATURE_SET. But the application wants to know what value is displayed on
+ * the car's UI in Fahrenheit.
+ * For this, the application sets the property to [21, (float)VehicleUnit:CELSIUS, 0, 0]. If
+ * the suggested value by the OEM for 21 Celsius is 70 Fahrenheit, then VHAL must generate a
+ * callback with property value [21, (float)VehicleUnit:CELSIUS, 21.0, 70.0].
+ * In this case, the application can know that the value is 70.0 Fahrenheit in the car’s UI.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_TEMPERATURE_VALUE_SUGGESTION = (
+ 0x0515
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:FLOAT_VEC
+ | VehicleArea:GLOBAL),
+
/**
* Distance units for display
*
@@ -3119,15 +3200,21 @@
/**
* Changes the state of the cluster display.
*
+ * Bounds: the area to render the cluster Activity.
+ * Inset: the area which Activity should avoid from placing any important
+ * information.
+ *
* int32[0]: on/off: 0 - off, 1 - on, -1 - don't care
- * int32[1]: width: positive number - actual width in pixels
- -1 - don't care (should set "don't care" both width and height)
- * int32[2]: height: same format with 'width'
- * int32[3]: Inset - left: positive number - actual left inset value in pixels
+ * int32[1]: Bounds - left: positive number - left position in pixels
+ -1 - don't care (should set all Bounds fields)
+ * int32[2]: Bounds - top: same format with 'left'
+ * int32[3]: Bounds - right: same format with 'left'
+ * int32[4]: Bounds - bottom: same format with 'left'
+ * int32[5]: Inset - left: positive number - actual left inset value in pixels
-1 - don't care (should set "don't care" all Inset fields)
- * int32[4]: Inset - top: same format with 'left'
- * int32[5]: Inset - right: same format with 'left'
- * int32[6]: Inset - bottom: same format with 'left'
+ * int32[6]: Inset - top: same format with 'left'
+ * int32[7]: Inset - right: same format with 'left'
+ * int32[8]: Inset - bottom: same format with 'left'
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ
@@ -3149,16 +3236,18 @@
* match the state.
*
* int32[0]: on/off: 0 - off, 1 - on
- * int32[1]: width
- * int32[2]: height
- * int32[3]: Inset - left
- * int32[4]: Inset - top
- * int32[5]: Inset - right
- * int32[6]: Inset - bottom
- * int32[7]: the type of ClusterUI in the fullscreen or main screen.
+ * int32[1]: Bounds - left
+ * int32[2]: Bounds - top
+ * int32[3]: Bounds - right
+ * int32[4]: Bounds - bottom
+ * int32[5]: Inset - left
+ * int32[6]: Inset - top
+ * int32[7]: Inset - right
+ * int32[8]: Inset - bottom
+ * int32[9]: the type of ClusterUI in the fullscreen or main screen.
* 0 indicates ClusterHome.
* the other values are followed by OEM's definition.
- * int32[8]: the type of ClusterUI in sub screen if the currently two UIs are shown.
+ * int32[10]: the type of ClusterUI in sub screen if the currently two UIs are shown.
* -1 indicates the area isn't used any more.
* bytes: the array to represent the availability of ClusterUI.
* 0 indicates non-available and 1 indicates available.
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
index c19534c..eaa43f3 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -34,30 +34,31 @@
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum AcquiredInfo {
- GOOD = 0,
- INSUFFICIENT = 1,
- TOO_BRIGHT = 2,
- TOO_DARK = 3,
- TOO_CLOSE = 4,
- TOO_FAR = 5,
- FACE_TOO_HIGH = 6,
- FACE_TOO_LOW = 7,
- FACE_TOO_RIGHT = 8,
- FACE_TOO_LEFT = 9,
- POOR_GAZE = 10,
- NOT_DETECTED = 11,
- TOO_MUCH_MOTION = 12,
- RECALIBRATE = 13,
- TOO_DIFFERENT = 14,
- TOO_SIMILAR = 15,
- PAN_TOO_EXTREME = 16,
- TILT_TOO_EXTREME = 17,
- ROLL_TOO_EXTREME = 18,
- FACE_OBSCURED = 19,
- START = 20,
- SENSOR_DIRTY = 21,
- VENDOR = 22,
- FIRST_FRAME_RECEIVED = 23,
- DARK_GLASSES_DETECTED = 24,
- MOUTH_COVERING_DETECTED = 25,
+ UNKNOWN = 0,
+ GOOD = 1,
+ INSUFFICIENT = 2,
+ TOO_BRIGHT = 3,
+ TOO_DARK = 4,
+ TOO_CLOSE = 5,
+ TOO_FAR = 6,
+ FACE_TOO_HIGH = 7,
+ FACE_TOO_LOW = 8,
+ FACE_TOO_RIGHT = 9,
+ FACE_TOO_LEFT = 10,
+ POOR_GAZE = 11,
+ NOT_DETECTED = 12,
+ TOO_MUCH_MOTION = 13,
+ RECALIBRATE = 14,
+ TOO_DIFFERENT = 15,
+ TOO_SIMILAR = 16,
+ PAN_TOO_EXTREME = 17,
+ TILT_TOO_EXTREME = 18,
+ ROLL_TOO_EXTREME = 19,
+ FACE_OBSCURED = 20,
+ START = 21,
+ SENSOR_DIRTY = 22,
+ VENDOR = 23,
+ FIRST_FRAME_RECEIVED = 24,
+ DARK_GLASSES_DETECTED = 25,
+ MOUTH_COVERING_DETECTED = 26,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl
index aa51343..67b5cf4 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl
@@ -34,7 +34,7 @@
package android.hardware.biometrics.face;
@VintfStability
parcelable BaseFrame {
- android.hardware.biometrics.face.AcquiredInfo acquiredInfo = android.hardware.biometrics.face.AcquiredInfo.INSUFFICIENT;
+ android.hardware.biometrics.face.AcquiredInfo acquiredInfo = android.hardware.biometrics.face.AcquiredInfo.UNKNOWN;
int vendorCode;
float pan;
float tilt;
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl
index 982e759..0ea10d6 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl
@@ -35,6 +35,6 @@
@VintfStability
parcelable EnrollmentFrame {
@nullable android.hardware.biometrics.face.Cell cell;
- android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.FIRST_FRAME_RECEIVED;
+ android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN;
android.hardware.biometrics.face.BaseFrame data;
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl
index 6be6e0b..ce5679a 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl
@@ -34,10 +34,11 @@
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum EnrollmentStage {
- FIRST_FRAME_RECEIVED = 0,
- WAITING_FOR_CENTERING = 1,
- HOLD_STILL_IN_CENTER = 2,
- ENROLLING_MOVEMENT_1 = 3,
- ENROLLING_MOVEMENT_2 = 4,
- ENROLLMENT_FINISHED = 5,
+ UNKNOWN = 0,
+ FIRST_FRAME_RECEIVED = 1,
+ WAITING_FOR_CENTERING = 2,
+ HOLD_STILL_IN_CENTER = 3,
+ ENROLLING_MOVEMENT_1 = 4,
+ ENROLLING_MOVEMENT_2 = 5,
+ ENROLLMENT_FINISHED = 6,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
index 232bd52..48db2cf 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
@@ -34,6 +34,6 @@
package android.hardware.biometrics.face;
@VintfStability
parcelable EnrollmentStageConfig {
- android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.FIRST_FRAME_RECEIVED;
+ android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN;
List<android.hardware.biometrics.face.Cell> cells;
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
index 0437f07..1a21661 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
@@ -34,12 +34,13 @@
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum Error {
+ UNKNOWN = 0,
HW_UNAVAILABLE = 1,
UNABLE_TO_PROCESS = 2,
TIMEOUT = 3,
NO_SPACE = 4,
CANCELED = 5,
UNABLE_TO_REMOVE = 6,
- VENDOR = 8,
- REENROLL_REQUIRED = 16,
+ VENDOR = 7,
+ REENROLL_REQUIRED = 8,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
index a8faf06..1875b97 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
@@ -34,7 +34,7 @@
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum Feature {
- WAVE_ATTENTION_REQUIREMENT = 0,
- WAVE_DIVERSE_POSES_REQUIREMENT = 1,
+ REQUIRE_ATTENTION = 0,
+ REQUIRE_DIVERSE_POSES = 1,
DEBUG = 2,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
index 9033989..d1c2c1d 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -36,13 +36,14 @@
interface ISession {
void generateChallenge();
void revokeChallenge(in long challenge);
+ android.hardware.biometrics.face.EnrollmentStageConfig[] getEnrollmentConfig(in android.hardware.biometrics.face.EnrollmentType enrollmentType);
android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in android.hardware.common.NativeHandle previewSurface);
android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
android.hardware.biometrics.common.ICancellationSignal detectInteraction();
void enumerateEnrollments();
void removeEnrollments(in int[] enrollmentIds);
- void getFeatures(in int enrollmentId);
- void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in int enrollmentId, in android.hardware.biometrics.face.Feature feature, boolean enabled);
+ void getFeatures();
+ void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.Feature feature, boolean enabled);
void getAuthenticatorId();
void invalidateAuthenticatorId();
void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
index 2bb053a..bbace29 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -47,8 +47,8 @@
void onLockoutCleared();
void onInteractionDetected();
void onEnrollmentsEnumerated(in int[] enrollmentIds);
- void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features, in int enrollmentId);
- void onFeatureSet(in int enrollmentId, android.hardware.biometrics.face.Feature feature);
+ void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features);
+ void onFeatureSet(android.hardware.biometrics.face.Feature feature);
void onEnrollmentsRemoved(in int[] enrollmentIds);
void onAuthenticatorIdRetrieved(in long authenticatorId);
void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
index c55a600..8b3c51b 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
@@ -35,8 +35,9 @@
@VintfStability
parcelable SensorProps {
android.hardware.biometrics.common.CommonProps commonProps;
- android.hardware.biometrics.face.FaceSensorType sensorType = android.hardware.biometrics.face.FaceSensorType.RGB;
+ android.hardware.biometrics.face.FaceSensorType sensorType = android.hardware.biometrics.face.FaceSensorType.UNKNOWN;
boolean halControlsPreview;
+ int previewDisplayId;
int enrollPreviewWidth;
int enrollPreviewHeight;
float enrollTranslationX;
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
index a3b229e..cf68421 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -19,18 +19,24 @@
@VintfStability
@Backing(type="byte")
enum AcquiredInfo {
+ /**
+ * Placeholder value used for default initialization of AcquiredInfo. This
+ * value means AcquiredInfo wasn't explicitly initialized and must be
+ * discarded by the recipient.
+ */
+ UNKNOWN,
/**
* The acquired face data was good, no further user interaction is necessary.
*/
- GOOD = 0,
+ GOOD,
/**
* The acquired face data was too noisy or did not have sufficient detail.
* This is a catch-all for all acquisition errors not captured by the other
* constants.
*/
- INSUFFICIENT = 1,
+ INSUFFICIENT,
/**
* Because there was too much ambient light, the captured face data was too
@@ -40,7 +46,7 @@
* The user is expected to take action to retry the operation in better
* lighting conditions when this is returned.
*/
- TOO_BRIGHT = 2,
+ TOO_BRIGHT,
/**
* Because there was not enough illumination, the captured face data was too
@@ -50,7 +56,7 @@
* The user is expected to take action to retry the operation in better
* lighting conditions when this is returned.
*/
- TOO_DARK = 3,
+ TOO_DARK,
/**
* The detected face is too close to the sensor, and the image cannot be
@@ -59,7 +65,7 @@
* The user is expected to be informed to move further from the sensor when
* this is returned.
*/
- TOO_CLOSE = 4,
+ TOO_CLOSE,
/**
* The detected face is too small, as the user might be too far away from
@@ -68,7 +74,7 @@
* The user is expected to be informed to move closer to the sensor when
* this is returned.
*/
- TOO_FAR = 5,
+ TOO_FAR,
/**
* Only the upper part of the face was detected. The sensor's field of view
@@ -77,7 +83,7 @@
* The user should be informed to move up with respect to the sensor when
* this is returned.
*/
- FACE_TOO_HIGH = 6,
+ FACE_TOO_HIGH,
/**
* Only the lower part of the face was detected. The sensor's field of view
@@ -86,7 +92,7 @@
* The user should be informed to move down with respect to the sensor when
* this is returned.
*/
- FACE_TOO_LOW = 7,
+ FACE_TOO_LOW,
/**
* Only the right part of the face was detected. The sensor's field of view
@@ -95,7 +101,7 @@
* The user should be informed to move to the right with respect to the
* sensor when this is returned.
*/
- FACE_TOO_RIGHT = 8,
+ FACE_TOO_RIGHT,
/**
* Only the left part of the face was detected. The sensor's field of view
@@ -104,7 +110,7 @@
* The user should be informed to move to the left with respect to the
* sensor when this is returned.
*/
- FACE_TOO_LEFT = 9,
+ FACE_TOO_LEFT,
/**
* The user's eyes have strayed away from the sensor. If this message is
@@ -112,7 +118,7 @@
* can't be found in the frame, one of the other acquisition messages
* must be sent, e.g. NOT_DETECTED.
*/
- POOR_GAZE = 10,
+ POOR_GAZE,
/**
* No face was detected within the sensor's field of view.
@@ -120,7 +126,7 @@
* The user should be informed to point the sensor to a face when this is
* returned.
*/
- NOT_DETECTED = 11,
+ NOT_DETECTED,
/**
* Too much motion was detected.
@@ -128,7 +134,7 @@
* The user should be informed to keep their face steady relative to the
* sensor.
*/
- TOO_MUCH_MOTION = 12,
+ TOO_MUCH_MOTION,
/**
* The sensor needs to be re-calibrated. This is an unexpected condition,
@@ -137,20 +143,20 @@
* re-enrolling. The expected response to this message is to direct the
* user to re-enroll.
*/
- RECALIBRATE = 13,
+ RECALIBRATE,
/**
* The face is too different from a previous acquisition. This condition
* only applies to enrollment. This can happen if the user passes the
* device to someone else in the middle of enrollment.
*/
- TOO_DIFFERENT = 14,
+ TOO_DIFFERENT,
/**
* The face is too similar to a previous acquisition. This condition only
* applies to enrollment. The user should change their pose.
*/
- TOO_SIMILAR = 15,
+ TOO_SIMILAR,
/**
* The magnitude of the pan angle of the user’s face with respect to the sensor’s
@@ -162,7 +168,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- PAN_TOO_EXTREME = 16,
+ PAN_TOO_EXTREME,
/**
* The magnitude of the tilt angle of the user’s face with respect to the sensor’s
@@ -173,7 +179,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- TILT_TOO_EXTREME = 17,
+ TILT_TOO_EXTREME,
/**
* The magnitude of the roll angle of the user’s face with respect to the sensor’s
@@ -185,7 +191,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- ROLL_TOO_EXTREME = 18,
+ ROLL_TOO_EXTREME,
/**
* The user’s face has been obscured by some object.
@@ -193,7 +199,7 @@
* The user should be informed to remove any objects from the line of sight from
* the sensor to the user’s face.
*/
- FACE_OBSCURED = 19,
+ FACE_OBSCURED,
/**
* This message represents the earliest message sent at the beginning of the authentication
@@ -202,33 +208,33 @@
* will measure latency based on the time between the last START message and the onAuthenticated
* callback.
*/
- START = 20,
+ START,
/**
* The sensor is dirty. The user should be informed to clean the sensor.
*/
- SENSOR_DIRTY = 21,
+ SENSOR_DIRTY,
/**
* Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode
* documentation.
*/
- VENDOR = 22,
+ VENDOR,
/**
* The first frame from the camera has been received.
*/
- FIRST_FRAME_RECEIVED = 23,
+ FIRST_FRAME_RECEIVED,
/**
* Dark glasses detected. This can be useful for providing relevant feedback to the user and
* enabling an alternative authentication logic if the implementation supports it.
*/
- DARK_GLASSES_DETECTED = 24,
+ DARK_GLASSES_DETECTED,
/**
* A face mask or face covering detected. This can be useful for providing relevant feedback to
* the user and enabling an alternative authentication logic if the implementation supports it.
*/
- MOUTH_COVERING_DETECTED = 25,
+ MOUTH_COVERING_DETECTED,
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl
index 47cad3c..be61a20 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl
@@ -23,7 +23,6 @@
*/
@VintfStability
parcelable AuthenticationFrame {
-
/**
* The frame metadata. Can be used by the framework to provide user feedback.
*/
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl
index 85535f9..58ad01a 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl
@@ -29,7 +29,7 @@
* Information about the frame that can be used by the framework to provide feedback to the
* user, for example ask the user to move their face in a certain way.
*/
- AcquiredInfo acquiredInfo = AcquiredInfo.INSUFFICIENT;
+ AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
/**
* If acquiredInfo is set to AcquiredInfo::VENDOR. This is the index into the configuration
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl
index ea0a502..ecb0e79 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl
@@ -33,7 +33,7 @@
/**
* The enrollment stage for which this frame was captured.
*/
- EnrollmentStage stage = EnrollmentStage.FIRST_FRAME_RECEIVED;
+ EnrollmentStage stage = EnrollmentStage.UNKNOWN;
/**
* The frame metadata. Can be used by the framework to provide user feedback.
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl
index bbc874f..5974838 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl
@@ -22,34 +22,40 @@
@VintfStability
@Backing(type="byte")
enum EnrollmentStage {
+ /**
+ * Placeholder value used for default initialization of EnrollmentStage. This
+ * value means EnrollmentStage wasn't explicitly initialized and must be
+ * discarded by the recipient.
+ */
+ UNKNOWN,
- /**
- * HAL has obtained the first camera frame.
- */
- FIRST_FRAME_RECEIVED,
+ /**
+ * HAL has obtained the first camera frame.
+ */
+ FIRST_FRAME_RECEIVED,
- /**
- * HAL is waiting for the user's face to be centered.
- */
- WAITING_FOR_CENTERING,
+ /**
+ * HAL is waiting for the user's face to be centered.
+ */
+ WAITING_FOR_CENTERING,
- /**
- * HAL is expecting the user's face to stay centered.
- */
- HOLD_STILL_IN_CENTER,
+ /**
+ * HAL is expecting the user's face to stay centered.
+ */
+ HOLD_STILL_IN_CENTER,
- /**
- * Vendor defined movement 1.
- */
- ENROLLING_MOVEMENT_1,
+ /**
+ * Vendor defined movement 1.
+ */
+ ENROLLING_MOVEMENT_1,
- /**
- * Vendor defined movement 2.
- */
- ENROLLING_MOVEMENT_2,
+ /**
+ * Vendor defined movement 2.
+ */
+ ENROLLING_MOVEMENT_2,
- /**
- * HAL has finished the enrollment.
- */
- ENROLLMENT_FINISHED,
+ /**
+ * HAL has finished the enrollment.
+ */
+ ENROLLMENT_FINISHED,
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
index 3c31fcc..a8fa9ab 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
@@ -24,7 +24,7 @@
/**
* The stage that's being configured.
*/
- EnrollmentStage stage = EnrollmentStage.FIRST_FRAME_RECEIVED;
+ EnrollmentStage stage = EnrollmentStage.UNKNOWN;
/**
* Optional list of cells that must be completed to finish this stage.
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl
index 6f3264b..e99415a 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl
@@ -20,22 +20,22 @@
@Backing(type="byte")
enum Error {
/**
- * Reserved for testing and to keep subsequent numbering consistent with
- * older interfaces.
- *
- * NO_ERROR = 0,
+ * Placeholder value used for default initialization of Error. This value
+ * means Error wasn't explicitly initialized and must be discarded by the
+ * recipient.
*/
+ UNKNOWN,
/**
* A hardware error has occurred that cannot be resolved. Try again later.
*/
- HW_UNAVAILABLE = 1,
+ HW_UNAVAILABLE,
/**
* The current operation could not be completed, e.g. the sensor was unable
* to process the current image or the HAT was invalid.
*/
- UNABLE_TO_PROCESS = 2,
+ UNABLE_TO_PROCESS,
/**
* The current operation took too long to complete. This is intended to
@@ -48,48 +48,34 @@
* indicate that the implementation is no longer looking and the framework
* should restart the operation on the next user interaction.
*/
- TIMEOUT = 3,
+ TIMEOUT,
/**
* The current operation could not be completed because there is not enough
* storage space remaining to do so.
*/
- NO_SPACE = 4,
+ NO_SPACE,
/**
* The current operation has been cancelled. This may happen if a new
* request (authenticate, remove, enumerate, enroll) is initiated while
* an on-going operation is in progress, or if cancel() was called.
*/
- CANCELED = 5,
+ CANCELED,
/**
* The current remove operation could not be completed; the face template
* provided could not be removed.
*/
- UNABLE_TO_REMOVE = 6,
-
- /**
- * Reserved to maintain backwards compatibility. See
- * ISessionCallback#onLockoutTimed instead.
- *
- * LOCKOUT = 7,
- */
+ UNABLE_TO_REMOVE,
/**
* Used to enable a vendor-specific error message.
*/
- VENDOR = 8,
-
- /**
- * Reserved to maintain backwards compatibility. See
- * ISessionCallback#onLockoutPermanent instead.
- *
- * LOCKOUT_PERMANENT = 9
- */
+ VENDOR,
/**
* Authentication cannot be performed because re-enrollment is required.
*/
- REENROLL_REQUIRED = 16,
+ REENROLL_REQUIRED,
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
index b88050a..bff1a02 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
@@ -20,20 +20,19 @@
@Backing(type="byte")
enum Feature {
/**
- * Do not require the user to look at the device during enrollment and authentication. Note
- * this is to accommodate people who have limited vision.
+ * Require the user to look at the device during enrollment and authentication. This feature
+ * can be disabled to accommodate people who have limited vision.
*/
- WAVE_ATTENTION_REQUIREMENT,
+ REQUIRE_ATTENTION,
/**
- * Do not require a diverse set of poses during enrollment. This is to accommodate people with
- * limited mobility.
+ * Require a diverse set of poses during enrollment. This feature can be disabled to accommodate
+ * people with limited mobility.
*/
- WAVE_DIVERSE_POSES_REQUIREMENT,
+ REQUIRE_DIVERSE_POSES,
/**
* Enable debugging functionality.
*/
DEBUG,
}
-
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 9734873..a9a8c16 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -17,6 +17,7 @@
package android.hardware.biometrics.face;
import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.face.EnrollmentStageConfig;
import android.hardware.biometrics.face.EnrollmentType;
import android.hardware.biometrics.face.Feature;
import android.hardware.common.NativeHandle;
@@ -104,9 +105,9 @@
* each of the stages.
*
* @param enrollmentType See the EnrollmentType enum.
- * @return A list of EnrollmentStageConfig that describes each enrollment stage.
- *
- List<EnrollmentStageConfig> getEnrollmentConfig(in EnrollmentType enrollmentType);
+ * @return An EnrollmentStageConfig array that describes each enrollment stage.
+ */
+ EnrollmentStageConfig[] getEnrollmentConfig(in EnrollmentType enrollmentType);
/**
* enroll:
@@ -249,38 +250,34 @@
/**
* getFeatures:
*
- * Returns a list of currently enabled features for the provided enrollmentId.
+ * Returns a list of currently enabled features for this (sensorId, userId) pair.
*
- * If the enrollmentId is invalid, the HAL must invoke ISessionCallback#onError with
+ * If the user is not enrolled, the HAL must invoke ISessionCallback#onError with
* Error::UNABLE_TO_PROCESS.
*
* The HAL must notify the framework about the result by calling
* ISessionCallback#onFeaturesRetrieved.
- *
- * @param enrollmentId the ID of the enrollment for which the features are requested.
*/
- void getFeatures(in int enrollmentId);
+ void getFeatures();
/**
* setFeature:
*
- * Enables or disables a feature for the given enrollmentId. Because certain features may
+ * Enables or disables a feature for this (sensorId, userId) pair. Because certain features may
* decrease security, the user must enter their password before this method is invoked
* (see @param hat). The HAL must verify the hat before changing any feature state.
*
- * If either the hat or enrollmentId is invalid, the HAL must invoke ISessionCallback#onError
- * with Error::UNABLE_TO_PROCESS.
+ * If the hat is invalid or if the user is not enrolled, the HAL must invoke
+ * ISessionCallback#onError with Error::UNABLE_TO_PROCESS.
*
* After the feature is successfully set, the HAL must notify the framework by calling
* ISessionCallback#onFeatureSet.
*
* @param hat HardwareAuthToken See above documentation.
- * @param enrollmentId the ID of the enrollment for which the feature update is requested.
* @param feature The feature to be enabled or disabled.
* @param enabled Whether the provided features should be enabled or disabled.
*/
- void setFeature(
- in HardwareAuthToken hat, in int enrollmentId, in Feature feature, boolean enabled);
+ void setFeature(in HardwareAuthToken hat, in Feature feature, boolean enabled);
/**
* getAuthenticatorId:
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index a2601e7..23570bd 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -172,22 +172,21 @@
/**
* This method must only be used to notify the framework during ISession#getFeatures.
*
- * Provides a list of features that are currently enabled for the given enrollmentId.
+ * Provides a list of features that are currently enabled for the session's (userId, sensorId)
+ * pair.
*
* @param features A list of currently enabled features. See the Feature enum.
- * @param enrollmentId The enrollment for which the features were requested.
*/
- void onFeaturesRetrieved(in Feature[] features, in int enrollmentId);
+ void onFeaturesRetrieved(in Feature[] features);
/**
* This method must only be used to notify the framework during ISession#setFeature.
*
* Notifies the framework that ISession#setFeature has completed.
*
- * @param enrollmentId The enrollment for which a feature was set.
* @param feature The feature that was set.
*/
- void onFeatureSet(in int enrollmentId, Feature feature);
+ void onFeatureSet(Feature feature);
/**
* This method must only be used to notify the framework during
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl
index b11b436..5f881ca 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl
@@ -29,7 +29,7 @@
/**
* A statically configured sensor type representing this face sensor.
*/
- FaceSensorType sensorType = FaceSensorType.RGB;
+ FaceSensorType sensorType = FaceSensorType.UNKNOWN;
/**
* Whether or not the HAL is responsible for showing the face enrollment preview to the user.
@@ -41,6 +41,13 @@
boolean halControlsPreview;
/**
+ * The ID of the display that's used for enrollment preview. This must correspond to the
+ * android.hardware.DisplayManager#getDisplay Android API. This is useful for devices with
+ * multiple displays to ensure the correct display is used for this face sensor.
+ */
+ int previewDisplayId;
+
+ /**
* For implementations where the HAL manages the preview, this is the width, in pixels, of each
* frame that the camera is set up to output.
*/
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index b5eb717..d980c5f 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -52,6 +52,12 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Session::getEnrollmentConfig(EnrollmentType /*enrollmentType*/,
+ std::vector<EnrollmentStageConfig>* return_val) {
+ *return_val = {};
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Session::enroll(
const keymaster::HardwareAuthToken& /*hat*/, EnrollmentType /*enrollmentType*/,
const std::vector<Feature>& /*features*/, const NativeHandle& /*previewSurface*/,
@@ -92,14 +98,13 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::getFeatures(int32_t /*enrollmentId*/) {
+ndk::ScopedAStatus Session::getFeatures() {
LOG(INFO) << "getFeatures";
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::setFeature(const keymaster::HardwareAuthToken& /*hat*/,
- int32_t /*enrollmentId*/, Feature /*feature*/,
- bool /*enabled*/) {
+ Feature /*feature*/, bool /*enabled*/) {
LOG(INFO) << "setFeature";
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index 73cdf08..caf81f8 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -34,6 +34,9 @@
ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
+ ndk::ScopedAStatus getEnrollmentConfig(EnrollmentType enrollmentType,
+ std::vector<EnrollmentStageConfig>* return_val) override;
+
ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat,
EnrollmentType enrollmentType, const std::vector<Feature>& features,
const NativeHandle& previewSurface,
@@ -50,10 +53,10 @@
ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
- ndk::ScopedAStatus getFeatures(int32_t enrollmentId) override;
+ ndk::ScopedAStatus getFeatures() override;
- ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, int32_t enrollmentId,
- Feature feature, bool enabled) override;
+ ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, Feature feature,
+ bool enabled) override;
ndk::ScopedAStatus getAuthenticatorId() override;
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 60e0a2a..ada6f73 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -104,12 +104,11 @@
return ndk::ScopedAStatus::ok();
}
- ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& /*features*/,
- int32_t /*enrollmentId*/) override {
+ ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& /*features*/) override {
return ndk::ScopedAStatus::ok();
}
- ndk::ScopedAStatus onFeatureSet(int32_t /*enrollmentId*/, Feature /*feature*/) override {
+ ndk::ScopedAStatus onFeatureSet(Feature /*feature*/) override {
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index 2c2011a..c51aa03 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -34,16 +34,17 @@
package android.hardware.biometrics.fingerprint;
@Backing(type="byte") @VintfStability
enum AcquiredInfo {
- GOOD = 0,
- PARTIAL = 1,
- INSUFFICIENT = 2,
- SENSOR_DIRTY = 3,
- TOO_SLOW = 4,
- TOO_FAST = 5,
- VENDOR = 6,
- START = 7,
- TOO_DARK = 8,
- TOO_BRIGHT = 9,
- IMMOBILE = 10,
- RETRYING_CAPTURE = 11,
+ UNKNOWN = 0,
+ GOOD = 1,
+ PARTIAL = 2,
+ INSUFFICIENT = 3,
+ SENSOR_DIRTY = 4,
+ TOO_SLOW = 5,
+ TOO_FAST = 6,
+ VENDOR = 7,
+ START = 8,
+ TOO_DARK = 9,
+ TOO_BRIGHT = 10,
+ IMMOBILE = 11,
+ RETRYING_CAPTURE = 12,
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
index f79c576..060379d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
@@ -34,11 +34,12 @@
package android.hardware.biometrics.fingerprint;
@Backing(type="byte") @VintfStability
enum Error {
+ UNKNOWN = 0,
HW_UNAVAILABLE = 1,
UNABLE_TO_PROCESS = 2,
TIMEOUT = 3,
NO_SPACE = 4,
CANCELED = 5,
UNABLE_TO_REMOVE = 6,
- VENDOR = 8,
+ VENDOR = 7,
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
index c7a4002..782d289 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -39,4 +39,6 @@
android.hardware.biometrics.fingerprint.SensorLocation[] sensorLocations;
boolean supportsNavigationGestures;
boolean supportsDetectInteraction;
+ boolean halHandlesDisplayTouches;
+ boolean halControlsIllumination;
}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index b406947..8ec8574 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -20,6 +20,13 @@
@Backing(type="byte")
enum AcquiredInfo {
/**
+ * Placeholder value used for default initialization of AcquiredInfo. This
+ * value means AcquiredInfo wasn't explicitly initialized and must be
+ * discarded by the recipient.
+ */
+ UNKNOWN,
+
+ /**
* A high quality fingerprint image was detected, no further user interaction is necessary.
*/
GOOD,
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
index 4fe7f5f..fc89da2 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
@@ -20,57 +20,47 @@
@Backing(type="byte")
enum Error {
/**
- * Used for testing, and to keep subsequent numbering consistent with older HIDLs.
+ * Placeholder value used for default initialization of Error. This value
+ * means Error wasn't explicitly initialized and must be discarded by the
+ * recipient.
*/
- // NO_ERROR = 0,
+ UNKNOWN,
/**
* A hardware error has occurred that cannot be resolved. For example, I2C failure or a broken
* sensor.
*/
- HW_UNAVAILABLE = 1,
+ HW_UNAVAILABLE,
/**
* The implementation is unable to process the request. For example, invalid arguments were
* supplied.
*/
- UNABLE_TO_PROCESS = 2,
+ UNABLE_TO_PROCESS,
/**
* The current operation took too long to complete.
*/
- TIMEOUT = 3,
+ TIMEOUT,
/**
* No space available to store additional enrollments.
*/
- NO_SPACE = 4,
+ NO_SPACE,
/**
* The operation was canceled. See common::ICancellationSignal.
*/
- CANCELED = 5,
+ CANCELED,
/**
* The implementation was unable to remove an enrollment.
* See ISession#removeEnrollments.
*/
- UNABLE_TO_REMOVE = 6,
-
- /**
- * Reserved to maintain backwards compatibility. See ISessionCallback#onLockoutTimed instead.
- */
- // LOCKOUT = 7,
+ UNABLE_TO_REMOVE,
/**
* Used to enable vendor-specific error messages.
*/
- VENDOR = 8,
-
- /**
- * Reserved to maintain backwards compatibility. See ISessionCallback#onLockoutPermanent
- * instead.
- */
- // LOCKOUT_PERMANENT = 9,
+ VENDOR,
}
-
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
index 765a2ed..dbe7137 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
@@ -26,4 +26,3 @@
POWER_BUTTON,
HOME_BUTTON
}
-
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index 940548b..02ef138 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -42,8 +42,8 @@
* have callbacks.
*
* ISession only supports execution of one non-interrupting operation at a time, regardless of
- * whether it's cancellable. The framework must wait for a corresponding callback indicating the end of
- * the current non-interrupting operation before a new non-interrupting operation can be started.
+ * whether it's cancellable. The framework must wait for a corresponding callback indicating the end
+ * of the current non-interrupting operation before a new non-interrupting operation can be started.
*/
@VintfStability
interface ISession {
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
index 62a2e8c..b1618b2 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -51,4 +51,4 @@
* in pixels.
*/
int sensorRadius;
-}
\ No newline at end of file
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
index fd2cf47..fb516da 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -48,4 +48,26 @@
* Specifies whether or not the implementation supports ISession#detectInteraction.
*/
boolean supportsDetectInteraction;
+
+ /**
+ * Whether the HAL is responsible for detecting and processing of display touches. This is only
+ * applicable to under-display fingerprint sensors (UDFPS). If the value is false, the framework
+ * will be responsible for handling the display touch events and passing them down to the HAL by
+ * using ISession#onPointerDown and ISession#onPointerUp. If the value is true, the framework
+ * will not notify the HAL about touch events.
+ *
+ * This value must be ignored for non-UDFPS sensors.
+ */
+ boolean halHandlesDisplayTouches;
+
+ /**
+ * Whether the HAL is responsible for fingerprint illumination, for example through enabling the
+ * display's high-brightness mode. This is only applicable to optical under-display fingerprint
+ * sensors (optical UDFPS). If the value is false, the framework will be responsible for
+ * illuminating the finger and reporting ISession#onUiReady. If the value is true, the framework
+ * will not illuminate the finger and will not report ISession#onUiReady.
+ *
+ * This value must be ignored for sensors that aren't optical UDFPS.
+ */
+ boolean halControlsIllumination;
}
diff --git a/biometrics/fingerprint/aidl/vts/Android.bp b/biometrics/fingerprint/aidl/vts/Android.bp
index 0d83e74..5539548 100644
--- a/biometrics/fingerprint/aidl/vts/Android.bp
+++ b/biometrics/fingerprint/aidl/vts/Android.bp
@@ -14,9 +14,13 @@
"use_libaidlvintf_gtest_helper_static",
],
srcs: ["VtsHalBiometricsFingerprintTargetTest.cpp"],
+ static_libs: [
+ "android.hardware.biometrics.common-V1-ndk_platform",
+ "android.hardware.biometrics.fingerprint-V1-ndk_platform",
+ "android.hardware.keymaster-V3-ndk_platform",
+ ],
shared_libs: [
"libbinder_ndk",
- "android.hardware.biometrics.fingerprint-V1-ndk_platform",
],
test_suites: [
"general-tests",
diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp
index 15c1b5c..be08e91 100644
--- a/camera/device/3.7/Android.bp
+++ b/camera/device/3.7/Android.bp
@@ -16,6 +16,7 @@
"types.hal",
"ICameraDevice.hal",
"ICameraDeviceSession.hal",
+ "ICameraInjectionSession.hal",
],
interfaces: [
"android.hardware.camera.common@1.0",
diff --git a/camera/device/3.7/ICameraInjectionSession.hal b/camera/device/3.7/ICameraInjectionSession.hal
new file mode 100644
index 0000000..f5797c3
--- /dev/null
+++ b/camera/device/3.7/ICameraInjectionSession.hal
@@ -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.
+ */
+
+package android.hardware.camera.device@3.7;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.2::BufferCache;
+import @3.2::CameraMetadata;
+import @3.5::StreamConfiguration;
+import @3.6::HalStreamConfiguration;
+import @3.7::ICameraDeviceSession;
+
+/**
+ * Injection Camera device active session interface.
+ *
+ * When an external camera is injected to replace the internal camera session, the
+ * injection session will be established in camera framework, and then
+ * configureInjectionStreams() will be called to ask the external camera to
+ * configure itself to match the stream configuration of the internal camera.
+ *
+ * Camera framework is responsible to close the injection session once the client
+ * switch back to internal camera streaming.
+ *
+ * If the external camera cannot support the configuration ILLEGAL_ARGUMENT will
+ * be returned.
+ */
+interface ICameraInjectionSession extends @3.7::ICameraDeviceSession {
+ /**
+ * configureInjectionStreams:
+ *
+ * Identical to @3.7::ICameraDeviceSession.configureStreams_3_7, except that:
+ *
+ * @param requestedConfiguration
+ * The current stream configuration of the internal camera session and
+ * the injection camera must follow the configuration without overriding
+ * any part of it.
+ * @param characteristics
+ * The characteristics of internal camera contains a list of keys so that
+ * the stream continuity can be maintained after the external camera is
+ * injected.
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On successful stream configuration.
+ * INTERNAL_ERROR:
+ * If there has been a fatal error and the device is no longer
+ * operational. Only close() can be called successfully by the
+ * framework after this error is returned.
+ * ILLEGAL_ARGUMENT:
+ * If the requested stream configuration is invalid. Some examples
+ * of invalid stream configurations include:
+ * - Not including any OUTPUT streams
+ * - Including streams with unsupported formats, or an unsupported
+ * size for that format.
+ * - Including too many output streams of a certain format.
+ * - Unsupported rotation configuration
+ * - Stream sizes/formats don't satisfy the
+ * StreamConfigurationMode requirements
+ * for non-NORMAL mode, or the requested operation_mode is not
+ * supported by the HAL.
+ * - Unsupported usage flag
+ * The camera service cannot filter out all possible illegal stream
+ * configurations, since some devices may support more simultaneous
+ * streams or larger stream resolutions than the minimum required
+ * for a given camera device hardware level. The HAL must return an
+ * ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+ * ready to accept a future valid stream configuration in a later
+ * configureInjectionStreams call.
+ */
+ configureInjectionStreams(StreamConfiguration requestedConfiguration,
+ CameraMetadata characteristics) generates (Status status);
+};
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl
new file mode 100644
index 0000000..a438031
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable Ashmem {
+ ParcelFileDescriptor fd;
+ long size;
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl
new file mode 100644
index 0000000..394ea8f
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable MappableFile {
+ long length;
+ int prot;
+ ParcelFileDescriptor fd;
+ long offset;
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
index f37b7d5..2ed5c0b 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/aidl/android/hardware/common/Ashmem.aidl b/common/aidl/android/hardware/common/Ashmem.aidl
new file mode 100644
index 0000000..8e40266
--- /dev/null
+++ b/common/aidl/android/hardware/common/Ashmem.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.common;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Type that holds same memory as the "ashmem" hidl_memory type from HIDL.
+ */
+@VintfStability
+parcelable Ashmem {
+ /**
+ * A handle to a memory region.
+ */
+ ParcelFileDescriptor fd;
+ /**
+ * Size of the memory region in bytes.
+ */
+ long size;
+}
diff --git a/common/aidl/android/hardware/common/MappableFile.aidl b/common/aidl/android/hardware/common/MappableFile.aidl
new file mode 100644
index 0000000..a7763ea
--- /dev/null
+++ b/common/aidl/android/hardware/common/MappableFile.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.common;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * A region of a file that can be mapped into memory.
+ *
+ * In Linux, MappableFile may be used with mmap as `MAP_SHARED`.
+ *
+ * MappableFile is compatible with ::android::base::MappedFile.
+ */
+@VintfStability
+parcelable MappableFile {
+ /**
+ * Length of the mapping region in bytes.
+ */
+ long length;
+ /**
+ * The desired memory protection for the mapping.
+ *
+ * In Linux, prot is either `PROT_NONE` (indicating that mapped pages may not be accessed) or
+ * the bitwise OR of one or more of the following flags:
+ * - `PROT_READ` (indicating that the mapped pages may be read)
+ * - `PROT_WRITE` (indicating that the mapped pages may be written)
+ */
+ int prot;
+ /**
+ * A handle to a mappable file.
+ */
+ ParcelFileDescriptor fd;
+ /**
+ * The offset in the file to the beginning of the mapping region in number of bytes.
+ *
+ * Note: Some mapping functions require that the offset is aligned to the page size.
+ */
+ long offset;
+}
diff --git a/common/support/Android.bp b/common/support/Android.bp
index 8aea306..730798d 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -18,6 +18,11 @@
"android.hardware.common-V2-ndk_platform",
"libcutils",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
+ min_sdk_version: "29",
}
cc_test {
diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp
index 0dfff26..2d1068d 100644
--- a/drm/1.2/vts/functional/drm_hal_test.cpp
+++ b/drm/1.2/vts/functional/drm_hal_test.cpp
@@ -172,6 +172,7 @@
TEST_P(DrmHalTest, OfflineLicenseTest) {
auto sessionId = openSession();
hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
+ closeSession(sessionId);
auto res = drmPlugin->getOfflineLicenseKeySetIds(
[&](Status status, const hidl_vec<KeySetId>& keySetIds) {
@@ -201,8 +202,6 @@
err = drmPlugin->removeOfflineLicense(keySetId);
EXPECT_EQ(Status::BAD_VALUE, err);
-
- closeSession(sessionId);
}
/**
@@ -212,6 +211,8 @@
auto sessionId = openSession();
DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE);
hidl_vec<uint8_t> keySetId = loadKeys(sessionId, content, KeyType::OFFLINE);
+ closeSession(sessionId);
+
drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::OK, OfflineLicenseState::USABLE>);
hidl_vec<uint8_t> keyRequest = getKeyRequest(keySetId, content, KeyType::RELEASE);
@@ -226,7 +227,6 @@
provideKeyResponse(keySetId, keyResponse);
drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::BAD_VALUE, OfflineLicenseState::UNKNOWN>);
- closeSession(sessionId);
}
/**
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 2a46f9d..cadd13c 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -34,6 +34,7 @@
apex_available: [
"//apex_available:platform",
"com.android.media.swcodec",
+ "com.android.neuralnetworks",
],
min_sdk_version: "29",
},
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index b179f35..19f5e8c 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -15,6 +15,8 @@
*/
#include <composer-vts/2.2/ReadbackVts.h>
+#include <composer-vts/2.2/RenderEngineVts.h>
+#include "renderengine/ExternalTexture.h"
namespace android {
namespace hardware {
@@ -257,10 +259,11 @@
}
TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
- const std::shared_ptr<Gralloc>& gralloc, Display display,
- int32_t width, int32_t height, PixelFormat format,
+ const std::shared_ptr<Gralloc>& gralloc,
+ TestRenderEngine& renderEngine, Display display, int32_t width,
+ int32_t height, PixelFormat format,
IComposerClient::Composition composition)
- : TestLayer{client, display} {
+ : TestLayer{client, display}, mRenderEngine(renderEngine) {
mGralloc = gralloc;
mComposition = composition;
mWidth = width;
@@ -293,9 +296,11 @@
LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
- layerSettings.source.buffer.buffer =
+ layerSettings.source.buffer.buffer = std::make_shared<renderengine::ExternalTexture>(
new GraphicBuffer(mBufferHandle, GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
- static_cast<int32_t>(mFormat), 1, mUsage, mStride);
+ static_cast<int32_t>(mFormat), 1, mUsage, mStride),
+ mRenderEngine.getInternalRenderEngine(),
+ renderengine::ExternalTexture::Usage::READABLE);
layerSettings.source.buffer.usePremultipliedAlpha =
mBlendMode == IComposerClient::BlendMode::PREMULTIPLIED;
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 3becace..f78dda2 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -69,7 +69,9 @@
[](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
return &settings;
});
- mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, mGraphicBuffer, true,
+ auto texture = std::make_shared<renderengine::ExternalTexture>(
+ mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE);
+ mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, texture, true,
std::move(bufferFence), &readyFence);
int fd = readyFence.release();
if (fd != -1) {
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 d5eedf1..b24e3b6 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
@@ -50,6 +50,8 @@
static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff};
static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff};
+class TestRenderEngine;
+
class TestLayer {
public:
TestLayer(const std::shared_ptr<ComposerClient>& client, Display display)
@@ -110,7 +112,8 @@
public:
TestBufferLayer(
const std::shared_ptr<ComposerClient>& client, const std::shared_ptr<Gralloc>& gralloc,
- Display display, int32_t width, int32_t height, PixelFormat format,
+ TestRenderEngine& renderEngine, Display display, int32_t width, int32_t height,
+ PixelFormat format,
IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
~TestBufferLayer();
@@ -138,6 +141,7 @@
protected:
IComposerClient::Composition mComposition;
std::shared_ptr<Gralloc> mGralloc;
+ TestRenderEngine& mRenderEngine;
int32_t mFillFence;
const native_handle_t* mBufferHandle = nullptr;
};
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
index f2d5f19..26027d3 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
@@ -14,9 +14,12 @@
* limitations under the License.
*/
+#pragma once
+
#include <composer-vts/2.2/ReadbackVts.h>
#include <math/half.h>
#include <math/vec3.h>
+#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferAllocator.h>
@@ -51,12 +54,15 @@
void drawLayers();
void checkColorBuffer(std::vector<V2_2::IComposerClient::Color>& expectedColors);
+ renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; }
+
private:
common::V1_1::PixelFormat mFormat;
std::vector<renderengine::LayerSettings> mCompositionLayers;
std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
std::vector<renderengine::LayerSettings> mRenderLayers;
sp<GraphicBuffer> mGraphicBuffer;
+
DisplaySettings mDisplaySettings;
};
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 1463c3b..8d52173 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -288,9 +288,9 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mDisplayWidth, mDisplayHeight,
- PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -422,9 +422,9 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mDisplayWidth, mDisplayHeight,
- PixelFormat::RGBA_FP16);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_FP16);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -538,8 +538,8 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
auto deviceLayer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2,
- PixelFormat::RGBA_8888);
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight / 2, PixelFormat::RGBA_8888);
std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth *
deviceLayer->mHeight);
ReadbackHelper::fillColorsArea(deviceColors, deviceLayer->mWidth,
@@ -575,8 +575,8 @@
}
auto clientLayer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, mPrimaryDisplay, clientWidth, clientHeight,
- PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, clientWidth,
+ clientHeight, PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
clientLayer->setDisplayFrame(clientFrame);
clientLayer->setZOrder(0);
@@ -657,9 +657,9 @@
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mDisplayWidth, mDisplayHeight,
- PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -805,9 +805,9 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mDisplayWidth, mDisplayHeight,
- PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -957,9 +957,9 @@
backgroundLayer->setZOrder(0);
backgroundLayer->setColor(mBackgroundColor);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mDisplayWidth, mDisplayHeight,
- PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(Dataspace::UNKNOWN, mWriter);
@@ -1195,9 +1195,9 @@
IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength,
mSideLength};
- mLayer =
- std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
- mSideLength, mSideLength, PixelFormat::RGBA_8888);
+ mLayer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, *mTestRenderEngine,
+ mPrimaryDisplay, mSideLength, mSideLength,
+ PixelFormat::RGBA_8888);
mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
mLayer->setZOrder(10);
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 25c990b..0df2b8d 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -73,10 +73,15 @@
IComposerClient::Rect getFrameRect() const { return {0, 0, mDisplayWidth, mDisplayHeight}; }
+ void setDimensions(int32_t displayWidth, int32_t displayHeight) const {
+ mDisplayWidth = displayWidth;
+ mDisplayHeight = displayHeight;
+ }
+
private:
const Display mDisplay;
- const int32_t mDisplayWidth;
- const int32_t mDisplayHeight;
+ mutable int32_t mDisplayWidth;
+ mutable int32_t mDisplayHeight;
};
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
@@ -194,6 +199,31 @@
const std::vector<ContentType>& capabilities,
const ContentType& contentType, const char* contentTypeStr);
+ Error setActiveConfigWithConstraints(
+ const VtsDisplay& display, Config config,
+ const IComposerClient::VsyncPeriodChangeConstraints& constraints,
+ VsyncPeriodChangeTimeline* timeline) {
+ const auto error = mComposerClient->setActiveConfigWithConstraints(display.get(), config,
+ constraints, timeline);
+ if (error == Error::NONE) {
+ const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::WIDTH);
+ const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::HEIGHT);
+ display.setDimensions(displayWidth, displayHeight);
+ }
+ return error;
+ }
+
+ void setActiveConfig(const VtsDisplay& display, Config config) {
+ mComposerClient->setActiveConfig(display.get(), config);
+ const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::WIDTH);
+ const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::HEIGHT);
+ display.setDimensions(displayWidth, displayHeight);
+ }
+
private:
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
@@ -358,8 +388,8 @@
constraints.desiredTimeNanos = systemTime();
constraints.seamlessRequired = false;
- EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
- display.get(), config, constraints, &timeline));
+ EXPECT_EQ(Error::NONE,
+ setActiveConfigWithConstraints(display, config, constraints, &timeline));
if (timeline.refreshRequired) {
sendRefreshFrame(display, &timeline);
@@ -414,8 +444,7 @@
for (const auto& display : mDisplays) {
Config invalidConfigId = GetInvalidConfigId(display.get());
EXPECT_EQ(Error::BAD_CONFIG,
- mComposerClient->setActiveConfigWithConstraints(display.get(), invalidConfigId,
- constraints, &timeline));
+ setActiveConfigWithConstraints(display, invalidConfigId, constraints, &timeline));
}
}
@@ -435,11 +464,10 @@
display.get(), config2,
IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
if (configGroup1 != configGroup2) {
- mComposerClient->setActiveConfig(display.get(), config1);
+ setActiveConfig(display, config1);
sendRefreshFrame(display, nullptr);
EXPECT_EQ(Error::SEAMLESS_NOT_ALLOWED,
- mComposerClient->setActiveConfigWithConstraints(display.get(), config2,
- constraints, &timeline));
+ setActiveConfigWithConstraints(display, config2, constraints, &timeline));
}
});
}
@@ -505,6 +533,8 @@
mWriter->presentDisplay();
execute();
+
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer));
}
void GraphicsComposerHidlTest::waitForVsyncPeriodChange(Display display,
@@ -528,7 +558,7 @@
void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(const TestParameters& params) {
for (const auto& display : mDisplays) {
forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
- mComposerClient->setActiveConfig(display.get(), config1);
+ setActiveConfig(display, config1);
sendRefreshFrame(display, nullptr);
int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
@@ -546,8 +576,8 @@
IComposerClient::VsyncPeriodChangeConstraints constraints = {
.desiredTimeNanos = systemTime() + params.delayForChange,
.seamlessRequired = false};
- EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
- display.get(), config2, constraints, &timeline));
+ EXPECT_EQ(Error::NONE,
+ setActiveConfigWithConstraints(display, config2, constraints, &timeline));
EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
// Refresh rate should change within a reasonable time
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 05b3662..7c68aee 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -31,7 +31,8 @@
],
static_libs: [
"libbase",
- "libcppbor",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libutils",
"libsoft_attestation_cert",
"libkeymaster_portable",
@@ -91,7 +92,8 @@
],
static_libs: [
"libbase",
- "libcppbor",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libutils",
"libsoft_attestation_cert",
"libkeymaster_portable",
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index c8ee0dd..95557b5 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -488,7 +488,7 @@
}
for (size_t n = 0; n < nsMap->size(); n++) {
- auto [nsKeyItem, nsValueItem] = (*nsMap)[n];
+ auto& [nsKeyItem, nsValueItem] = (*nsMap)[n];
const cppbor::Tstr* nsKey = nsKeyItem->asTstr();
const cppbor::Map* nsInnerMap = nsValueItem->asMap();
if (nsKey == nullptr || nsInnerMap == nullptr) {
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index 9913b86..ef9d133 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -27,7 +27,7 @@
#include <string>
#include <vector>
-#include <cppbor/cppbor.h>
+#include <cppbor.h>
#include "IdentityCredentialStore.h"
#include "SecureHardwareProxy.h"
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 2d897c7..25f129b 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -23,8 +23,8 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
-#include <cppbor/cppbor.h>
-#include <cppbor/cppbor_parse.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
#include <utility>
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 82c4011..61d15d2 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -34,7 +34,8 @@
"libcrypto",
],
static_libs: [
- "libcppbor",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libkeymaster_portable",
"libpuresoftkeymasterdevice",
"android.hardware.keymaster@4.0",
diff --git a/identity/aidl/vts/AuthenticationKeyTests.cpp b/identity/aidl/vts/AuthenticationKeyTests.cpp
index bda3e70..25d74d4 100644
--- a/identity/aidl/vts/AuthenticationKeyTests.cpp
+++ b/identity/aidl/vts/AuthenticationKeyTests.cpp
@@ -118,7 +118,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index 1d30067..d3addf4 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -126,7 +126,7 @@
optional<vector<uint8_t>> proofOfDeletion =
support::coseSignGetPayload(proofOfDeletionSignature);
ASSERT_TRUE(proofOfDeletion);
- string cborPretty = support::cborPrettyPrint(proofOfDeletion.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', true, ]", cborPretty);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {}, // Additional data
credentialPubKey_));
@@ -153,7 +153,7 @@
optional<vector<uint8_t>> proofOfDeletion =
support::coseSignGetPayload(proofOfDeletionSignature);
ASSERT_TRUE(proofOfDeletion);
- string cborPretty = support::cborPrettyPrint(proofOfDeletion.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {0x41, 0x42, 0x43}, true, ]",
cborPretty);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {}, // Additional data
diff --git a/identity/aidl/vts/EndToEndTests.cpp b/identity/aidl/vts/EndToEndTests.cpp
index 5798b4c..67db915 100644
--- a/identity/aidl/vts/EndToEndTests.cpp
+++ b/identity/aidl/vts/EndToEndTests.cpp
@@ -231,7 +231,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+ cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
@@ -339,8 +339,8 @@
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
cppbor::Array sessionTranscript = cppbor::Array()
- .add(cppbor::Semantic(24, deviceEngagementBytes))
- .add(cppbor::Semantic(24, eReaderPubBytes));
+ .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+ .add(cppbor::SemanticTag(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes =
@@ -353,7 +353,7 @@
.add("Home address", true))
.add("Image", cppbor::Map().add("Portrait image", false)))
.encode();
- cborPretty = support::cborPrettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
+ cborPretty = cppbor::prettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
EXPECT_EQ(
"{\n"
" 'nameSpaces' : {\n"
@@ -373,10 +373,10 @@
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
- .add(cppbor::Semantic(24, itemsRequestBytes))
+ .add(cppbor::SemanticTag(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
- cppbor::Semantic(24, encodedReaderAuthentication).encode();
+ cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
optional<vector<uint8_t>> readerSignature =
support::coseSignEcDsa(readerKey, {}, // content
encodedReaderAuthenticationBytes, // detached content
@@ -443,7 +443,7 @@
vector<uint8_t> mac;
vector<uint8_t> deviceNameSpacesEncoded;
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+ cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ(
"{\n"
" 'PersonalData' : {\n"
@@ -462,10 +462,11 @@
string docType = "org.iso.18013-5.2019.mdl";
optional<vector<uint8_t>> readerEphemeralPrivateKey =
support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
- optional<vector<uint8_t>> eMacKey = support::calcEMacKey(
- readerEphemeralPrivateKey.value(), // Private Key
- signingPubKey.value(), // Public Key
- cppbor::Semantic(24, sessionTranscript.encode()).encode()); // SessionTranscriptBytes
+ optional<vector<uint8_t>> eMacKey =
+ support::calcEMacKey(readerEphemeralPrivateKey.value(), // Private Key
+ signingPubKey.value(), // Public Key
+ cppbor::SemanticTag(24, sessionTranscript.encode())
+ .encode()); // SessionTranscriptBytes
optional<vector<uint8_t>> calculatedMac =
support::calcMac(sessionTranscript.encode(), // SessionTranscript
docType, // DocType
@@ -486,7 +487,7 @@
testEntriesEntryCounts)
.isOk());
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+ cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ("{}", cborPretty);
// Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
calculatedMac = support::calcMac(sessionTranscript.encode(), // SessionTranscript
@@ -508,7 +509,7 @@
testEntriesEntryCounts)
.isOk());
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+ cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ("{}", cborPretty);
// Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
calculatedMac = support::calcMac(sessionTranscript.encode(), // SessionTranscript
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index d1a3d39..fa0e293 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -131,7 +131,7 @@
optional<vector<uint8_t>> proofOfOwnership =
support::coseSignGetPayload(proofOfOwnershipSignature);
ASSERT_TRUE(proofOfOwnership);
- string cborPretty = support::cborPrettyPrint(proofOfOwnership.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfOwnership.value(), 32, {});
EXPECT_EQ("['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {0x11, 0x12}, true, ]", cborPretty);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfOwnershipSignature, {}, // Additional data
credentialPubKey_));
diff --git a/identity/aidl/vts/ReaderAuthTests.cpp b/identity/aidl/vts/ReaderAuthTests.cpp
index 7656c8e..c4a58c3 100644
--- a/identity/aidl/vts/ReaderAuthTests.cpp
+++ b/identity/aidl/vts/ReaderAuthTests.cpp
@@ -262,8 +262,8 @@
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
cppbor::Array sessionTranscript = cppbor::Array()
- .add(cppbor::Semantic(24, deviceEngagementBytes))
- .add(cppbor::Semantic(24, eReaderPubBytes));
+ .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+ .add(cppbor::SemanticTag(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes;
@@ -293,10 +293,10 @@
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
- .add(cppbor::Semantic(24, itemsRequestBytes))
+ .add(cppbor::SemanticTag(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
- cppbor::Semantic(24, encodedReaderAuthentication).encode();
+ cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
optional<vector<uint8_t>> readerSignature =
support::coseSignEcDsa(readerPrivateKey, // private key for reader
@@ -517,8 +517,8 @@
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
cppbor::Array sessionTranscript = cppbor::Array()
- .add(cppbor::Semantic(24, deviceEngagementBytes))
- .add(cppbor::Semantic(24, eReaderPubBytes));
+ .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+ .add(cppbor::SemanticTag(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes;
@@ -535,10 +535,10 @@
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
- .add(cppbor::Semantic(24, itemsRequestBytes))
+ .add(cppbor::SemanticTag(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
- cppbor::Semantic(24, encodedReaderAuthentication).encode();
+ cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
vector<vector<uint8_t>> readerCertChain = {cert_reader_SelfSigned_};
optional<vector<uint8_t>> readerSignature =
diff --git a/identity/aidl/vts/TestCredentialTests.cpp b/identity/aidl/vts/TestCredentialTests.cpp
index d53de3b..46c2229 100644
--- a/identity/aidl/vts/TestCredentialTests.cpp
+++ b/identity/aidl/vts/TestCredentialTests.cpp
@@ -114,7 +114,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/UpdateCredentialTests.cpp b/identity/aidl/vts/UpdateCredentialTests.cpp
index 9c5ca55..e05bb3b 100644
--- a/identity/aidl/vts/UpdateCredentialTests.cpp
+++ b/identity/aidl/vts/UpdateCredentialTests.cpp
@@ -114,7 +114,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
@@ -195,7 +195,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/UserAuthTests.cpp b/identity/aidl/vts/UserAuthTests.cpp
index ef89d1c..edd1725 100644
--- a/identity/aidl/vts/UserAuthTests.cpp
+++ b/identity/aidl/vts/UserAuthTests.cpp
@@ -160,8 +160,8 @@
// Let SessionTranscript be a map here (it's an array in EndToEndTest) just
// to check that the implementation can deal with either.
cppbor::Map sessionTranscript;
- sessionTranscript.add(42, cppbor::Semantic(24, deviceEngagementBytes));
- sessionTranscript.add(43, cppbor::Semantic(24, eReaderPubBytes));
+ sessionTranscript.add(42, cppbor::SemanticTag(24, deviceEngagementBytes));
+ sessionTranscript.add(43, cppbor::SemanticTag(24, eReaderPubBytes));
return sessionTranscript;
}
@@ -209,7 +209,7 @@
vector<uint8_t> dataToSign = cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript_.clone())
- .add(cppbor::Semantic(24, itemsRequestBytes))
+ .add(cppbor::SemanticTag(24, itemsRequestBytes))
.encode();
}
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index cc63c48..bc37020 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -338,8 +338,7 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty =
- support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
@@ -449,9 +448,9 @@
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
- string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
- 32, //
- {"readerCertificate"});
+ string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(),
+ 32, //
+ {"readerCertificate"});
EXPECT_EQ(
"[\n"
" 'ProofOfProvisioning',\n"
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index d00f59a..db1a945 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -35,6 +35,7 @@
"android.hardware.keymaster@4.0",
"libcrypto",
"libbase",
+ "libcppcose_rkp",
"libhidlbase",
"libhardware",
"libkeymaster_portable",
@@ -42,7 +43,7 @@
"libpuresoftkeymasterdevice",
],
static_libs: [
- "libcppbor",
+ "libcppbor_external",
],
}
@@ -59,7 +60,7 @@
"libhardware",
],
static_libs: [
- "libcppbor",
+ "libcppbor_external",
"libgmock",
],
test_suites: ["general-tests"],
@@ -89,7 +90,7 @@
"tests/cppbor_test.cpp",
],
shared_libs: [
- "libcppbor",
+ "libcppbor_external",
"libbase",
],
static_libs: [
@@ -104,7 +105,7 @@
"tests/cppbor_test.cpp",
],
shared_libs: [
- "libcppbor",
+ "libcppbor_external",
"libbase",
],
static_libs: [
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index aba89c1..4547624 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -148,199 +148,6 @@
}
// ---------------------------------------------------------------------------
-// CBOR utilities.
-// ---------------------------------------------------------------------------
-
-static bool cborAreAllElementsNonCompound(const cppbor::CompoundItem* compoundItem) {
- if (compoundItem->type() == cppbor::ARRAY) {
- const cppbor::Array* array = compoundItem->asArray();
- for (size_t n = 0; n < array->size(); n++) {
- const cppbor::Item* entry = (*array)[n].get();
- switch (entry->type()) {
- case cppbor::ARRAY:
- case cppbor::MAP:
- return false;
- default:
- break;
- }
- }
- } else {
- const cppbor::Map* map = compoundItem->asMap();
- for (size_t n = 0; n < map->size(); n++) {
- auto [keyEntry, valueEntry] = (*map)[n];
- switch (keyEntry->type()) {
- case cppbor::ARRAY:
- case cppbor::MAP:
- return false;
- default:
- break;
- }
- switch (valueEntry->type()) {
- case cppbor::ARRAY:
- case cppbor::MAP:
- return false;
- default:
- break;
- }
- }
- }
- return true;
-}
-
-static bool cborPrettyPrintInternal(const cppbor::Item* item, string& out, size_t indent,
- size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
- char buf[80];
-
- string indentString(indent, ' ');
-
- switch (item->type()) {
- case cppbor::UINT:
- snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
- out.append(buf);
- break;
-
- case cppbor::NINT:
- snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
- out.append(buf);
- break;
-
- case cppbor::BSTR: {
- const cppbor::Bstr* bstr = item->asBstr();
- const vector<uint8_t>& value = bstr->value();
- if (value.size() > maxBStrSize) {
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA_CTX ctx;
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, value.data(), value.size());
- SHA1_Final(digest, &ctx);
- char buf2[SHA_DIGEST_LENGTH * 2 + 1];
- for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
- snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
- }
- snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", value.size(), buf2);
- out.append(buf);
- } else {
- out.append("{");
- for (size_t n = 0; n < value.size(); n++) {
- if (n > 0) {
- out.append(", ");
- }
- snprintf(buf, sizeof(buf), "0x%02x", value[n]);
- out.append(buf);
- }
- out.append("}");
- }
- } break;
-
- case cppbor::TSTR:
- out.append("'");
- {
- // TODO: escape "'" characters
- out.append(item->asTstr()->value().c_str());
- }
- out.append("'");
- break;
-
- case cppbor::ARRAY: {
- const cppbor::Array* array = item->asArray();
- if (array->size() == 0) {
- out.append("[]");
- } else if (cborAreAllElementsNonCompound(array)) {
- out.append("[");
- for (size_t n = 0; n < array->size(); n++) {
- if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
- mapKeysToNotPrint)) {
- return false;
- }
- out.append(", ");
- }
- out.append("]");
- } else {
- out.append("[\n" + indentString);
- for (size_t n = 0; n < array->size(); n++) {
- out.append(" ");
- if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
- mapKeysToNotPrint)) {
- return false;
- }
- out.append(",\n" + indentString);
- }
- out.append("]");
- }
- } break;
-
- case cppbor::MAP: {
- const cppbor::Map* map = item->asMap();
-
- if (map->size() == 0) {
- out.append("{}");
- } else {
- out.append("{\n" + indentString);
- for (size_t n = 0; n < map->size(); n++) {
- out.append(" ");
-
- auto [map_key, map_value] = (*map)[n];
-
- if (!cborPrettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
- mapKeysToNotPrint)) {
- return false;
- }
- out.append(" : ");
- if (map_key->type() == cppbor::TSTR &&
- std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
- map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
- out.append("<not printed>");
- } else {
- if (!cborPrettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
- mapKeysToNotPrint)) {
- return false;
- }
- }
- out.append(",\n" + indentString);
- }
- out.append("}");
- }
- } break;
-
- case cppbor::SEMANTIC: {
- const cppbor::Semantic* semantic = item->asSemantic();
- snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", semantic->value());
- out.append(buf);
- cborPrettyPrintInternal(semantic->child().get(), out, indent, maxBStrSize,
- mapKeysToNotPrint);
- } break;
-
- case cppbor::SIMPLE:
- const cppbor::Bool* asBool = item->asSimple()->asBool();
- const cppbor::Null* asNull = item->asSimple()->asNull();
- if (asBool != nullptr) {
- out.append(asBool->value() ? "true" : "false");
- } else if (asNull != nullptr) {
- out.append("null");
- } else {
- LOG(ERROR) << "Only boolean/null is implemented for SIMPLE";
- return false;
- }
- break;
- }
-
- return true;
-}
-
-string cborPrettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
- const vector<string>& mapKeysToNotPrint) {
- auto [item, _, message] = cppbor::parse(encodedCbor);
- if (item == nullptr) {
- LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
- return "";
- }
-
- string out;
- cborPrettyPrintInternal(item.get(), out, 0, maxBStrSize, mapKeysToNotPrint);
- return out;
-}
-
-// ---------------------------------------------------------------------------
// Crypto functionality / abstraction.
// ---------------------------------------------------------------------------
@@ -2140,7 +1947,7 @@
}
for (size_t n = 0; n < protectedHeaders->size(); n++) {
- auto [keyItem, valueItem] = (*protectedHeaders)[n];
+ auto& [keyItem, valueItem] = (*protectedHeaders)[n];
const cppbor::Int* number = keyItem->asInt();
if (number == nullptr) {
LOG(ERROR) << "Key item in top-level map is not a number";
@@ -2183,7 +1990,7 @@
}
for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
- auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
+ auto& [keyItem, valueItem] = (*unprotectedHeaders)[n];
const cppbor::Int* number = keyItem->asInt();
if (number == nullptr) {
LOG(ERROR) << "Key item in top-level map is not a number";
@@ -2335,9 +2142,9 @@
.add("DeviceAuthentication")
.add(std::move(sessionTranscriptItem))
.add(docType)
- .add(cppbor::Semantic(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
+ .add(cppbor::SemanticTag(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
vector<uint8_t> deviceAuthenticationBytes =
- cppbor::Semantic(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
+ cppbor::SemanticTag(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
optional<vector<uint8_t>> calculatedMac =
support::coseMac0(eMacKey, {}, // payload
deviceAuthenticationBytes); // detached content
diff --git a/identity/support/tests/IdentityCredentialSupportTest.cpp b/identity/support/tests/IdentityCredentialSupportTest.cpp
index 509133c..4c9b87a 100644
--- a/identity/support/tests/IdentityCredentialSupportTest.cpp
+++ b/identity/support/tests/IdentityCredentialSupportTest.cpp
@@ -55,99 +55,6 @@
EXPECT_FALSE(support::decodeHex("012"));
}
-TEST(IdentityCredentialSupport, CborPrettyPrint) {
- EXPECT_EQ("'Some text'", support::cborPrettyPrint(cppbor::Tstr("Some text").encode()));
-
- EXPECT_EQ("''", support::cborPrettyPrint(cppbor::Tstr("").encode()));
-
- EXPECT_EQ("{0x01, 0x00, 0x02, 0xf0, 0xff, 0x40}",
- support::cborPrettyPrint(
- cppbor::Bstr(vector<uint8_t>({1, 0, 2, 240, 255, 64})).encode()));
-
- EXPECT_EQ("{}", support::cborPrettyPrint(cppbor::Bstr(vector<uint8_t>()).encode()));
-
- EXPECT_EQ("true", support::cborPrettyPrint(cppbor::Bool(true).encode()));
-
- EXPECT_EQ("false", support::cborPrettyPrint(cppbor::Bool(false).encode()));
-
- EXPECT_EQ("42", support::cborPrettyPrint(cppbor::Uint(42).encode()));
-
- EXPECT_EQ("9223372036854775807", // 0x7fff ffff ffff ffff
- support::cborPrettyPrint(cppbor::Uint(std::numeric_limits<int64_t>::max()).encode()));
-
- EXPECT_EQ("-42", support::cborPrettyPrint(cppbor::Nint(-42).encode()));
-
- EXPECT_EQ("-9223372036854775808", // -0x8000 0000 0000 0000
- support::cborPrettyPrint(cppbor::Nint(std::numeric_limits<int64_t>::min()).encode()));
-}
-
-TEST(IdentityCredentialSupport, CborPrettyPrintCompound) {
- cppbor::Array array = cppbor::Array("foo", "bar", "baz");
- EXPECT_EQ("['foo', 'bar', 'baz', ]", support::cborPrettyPrint(array.encode()));
-
- cppbor::Map map = cppbor::Map().add("foo", 42).add("bar", 43).add("baz", 44);
- EXPECT_EQ(
- "{\n"
- " 'foo' : 42,\n"
- " 'bar' : 43,\n"
- " 'baz' : 44,\n"
- "}",
- support::cborPrettyPrint(map.encode()));
-
- cppbor::Array array2 = cppbor::Array(cppbor::Tstr("Some text"), cppbor::Nint(-42));
- EXPECT_EQ("['Some text', -42, ]", support::cborPrettyPrint(array2.encode()));
-
- cppbor::Map map2 = cppbor::Map().add(42, "foo").add(43, "bar").add(44, "baz");
- EXPECT_EQ(
- "{\n"
- " 42 : 'foo',\n"
- " 43 : 'bar',\n"
- " 44 : 'baz',\n"
- "}",
- support::cborPrettyPrint(map2.encode()));
-
- cppbor::Array deeplyNestedArrays =
- cppbor::Array(cppbor::Array(cppbor::Array("a", "b", "c")),
- cppbor::Array(cppbor::Array("d", "e", cppbor::Array("f", "g"))));
- EXPECT_EQ(
- "[\n"
- " ['a', 'b', 'c', ],\n"
- " [\n 'd',\n"
- " 'e',\n"
- " ['f', 'g', ],\n"
- " ],\n"
- "]",
- support::cborPrettyPrint(deeplyNestedArrays.encode()));
-
- EXPECT_EQ(
- "[\n"
- " {0x0a, 0x0b},\n"
- " 'foo',\n"
- " 42,\n"
- " ['foo', 'bar', 'baz', ],\n"
- " {\n"
- " 'foo' : 42,\n"
- " 'bar' : 43,\n"
- " 'baz' : 44,\n"
- " },\n"
- " {\n"
- " 'deep1' : ['Some text', -42, ],\n"
- " 'deep2' : {\n"
- " 42 : 'foo',\n"
- " 43 : 'bar',\n"
- " 44 : 'baz',\n"
- " },\n"
- " },\n"
- "]",
- support::cborPrettyPrint(cppbor::Array(cppbor::Bstr(vector<uint8_t>{10, 11}),
- cppbor::Tstr("foo"), cppbor::Uint(42),
- std::move(array), std::move(map),
- (cppbor::Map()
- .add("deep1", std::move(array2))
- .add("deep2", std::move(map2))))
- .encode()));
-}
-
TEST(IdentityCredentialSupport, Signatures) {
vector<uint8_t> data = {1, 2, 3};
@@ -219,7 +126,7 @@
ASSERT_EQ(data, payload.value());
// Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
- string out = support::cborPrettyPrint(coseSign1.value());
+ string out = cppbor::prettyPrint(coseSign1.value());
out = replaceLine(out, -2, " [] // Signature Removed");
EXPECT_EQ(
"[\n"
@@ -250,7 +157,7 @@
ASSERT_EQ(0, payload.value().size());
// Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
- string out = support::cborPrettyPrint(coseSign1.value());
+ string out = cppbor::prettyPrint(coseSign1.value());
out = replaceLine(out, -2, " [] // Signature Removed");
EXPECT_EQ(
"[\n"
@@ -411,7 +318,7 @@
"0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
"0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
"]",
- support::cborPrettyPrint(mac.value()));
+ cppbor::prettyPrint(mac.value()));
}
TEST(IdentityCredentialSupport, CoseMac0DetachedContent) {
@@ -433,7 +340,7 @@
"0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
"0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
"]",
- support::cborPrettyPrint(mac.value()));
+ cppbor::prettyPrint(mac.value()));
}
// Generates a private key in DER format for a small value of 'd'.
@@ -460,8 +367,8 @@
const cppbor::Item* findValueForTstr(const cppbor::Map* map, const string& keyValue) {
// TODO: Need cast until libcppbor's Map::get() is marked as const
- auto [item, found] = ((cppbor::Map*)map)->get(keyValue);
- if (!found) {
+ const auto& item = map->get(keyValue);
+ if (!item) {
return nullptr;
}
return item.get();
@@ -483,12 +390,13 @@
return item->asMap();
}
-const cppbor::Semantic* findSemanticValueForTstr(const cppbor::Map* map, const string& keyValue) {
+const cppbor::SemanticTag* findSemanticValueForTstr(const cppbor::Map* map,
+ const string& keyValue) {
const cppbor::Item* item = findValueForTstr(map, keyValue);
if (item == nullptr) {
return nullptr;
}
- return item->asSemantic();
+ return item->asSemanticTag();
}
const std::string findStringValueForTstr(const cppbor::Map* map, const string& keyValue) {
@@ -576,11 +484,11 @@
auto [sessionEstablishmentItem, _se, _se2] = cppbor::parse(sessionEstablishmentEncoded.value());
const cppbor::Map* sessionEstablishment = sessionEstablishmentItem->asMap();
ASSERT_NE(sessionEstablishment, nullptr);
- const cppbor::Semantic* eReaderKeyBytes =
+ const cppbor::SemanticTag* eReaderKeyBytes =
findSemanticValueForTstr(sessionEstablishment, "eReaderKeyBytes");
ASSERT_NE(eReaderKeyBytes, nullptr);
- ASSERT_EQ(eReaderKeyBytes->value(), 24);
- const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->child()->asBstr();
+ ASSERT_EQ(eReaderKeyBytes->semanticTag(), 24);
+ const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->asBstr();
ASSERT_NE(eReaderKeyBstr, nullptr);
vector<uint8_t> eReaderKeyEncoded = eReaderKeyBstr->value();
// TODO: verify this agrees with ephemeralReaderKeyX and ephemeralReaderKeyY
@@ -605,12 +513,12 @@
// SessionTranscriptBytes = #6.24(bstr .cbor SessionTranscript)
//
cppbor::Array sessionTranscript;
- sessionTranscript.add(cppbor::Semantic(24, deviceEngagementEncoded));
- sessionTranscript.add(cppbor::Semantic(24, eReaderKeyEncoded));
+ sessionTranscript.add(cppbor::SemanticTag(24, deviceEngagementEncoded));
+ sessionTranscript.add(cppbor::SemanticTag(24, eReaderKeyEncoded));
sessionTranscript.add(cppbor::Null());
vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
vector<uint8_t> sessionTranscriptBytes =
- cppbor::Semantic(24, sessionTranscriptEncoded).encode();
+ cppbor::SemanticTag(24, sessionTranscriptEncoded).encode();
// The expected EMacKey is 4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2
//
@@ -696,11 +604,11 @@
// Dig out the encoded form of DeviceNameSpaces
//
- const cppbor::Semantic* deviceNameSpacesBytes =
+ const cppbor::SemanticTag* deviceNameSpacesBytes =
findSemanticValueForTstr(deviceSigned, "nameSpaces");
ASSERT_NE(deviceNameSpacesBytes, nullptr);
- ASSERT_EQ(deviceNameSpacesBytes->value(), 24);
- const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->child()->asBstr();
+ ASSERT_EQ(deviceNameSpacesBytes->semanticTag(), 24);
+ const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->asBstr();
ASSERT_NE(deviceNameSpacesBstr, nullptr);
vector<uint8_t> deviceNameSpacesEncoded = deviceNameSpacesBstr->value();
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
index 4681b9e..db3b2ad 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -52,7 +52,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index bb31a26..93bd81a 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -106,10 +106,6 @@
return nn::DeviceType::OTHER;
}
-bool Device::isUpdatable() const {
- return false;
-}
-
const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
index 3aec8ee..5e224b5 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -52,7 +52,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index d2ef57f..3197ef4 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -106,10 +106,6 @@
return nn::DeviceType::UNKNOWN;
}
-bool Device::isUpdatable() const {
- return false;
-}
-
const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index 489f857..b4bef5e 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -71,7 +71,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 1954dfa..9fe0de2 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -199,10 +199,6 @@
return kDeviceType;
}
-bool Device::isUpdatable() const {
- return false;
-}
-
const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
index f36b6c0..84f606a 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -54,7 +54,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 87c9f32..d710b85 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -150,10 +150,6 @@
return kDeviceType;
}
-bool Device::isUpdatable() const {
- return false;
-}
-
const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index b1860e2..ebf4654 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -16,6 +16,7 @@
stability: "vintf",
imports: [
"android.hardware.common",
+ "android.hardware.graphics.common",
],
backend: {
java: {
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
index 634f39e..eb3d0b0 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
@@ -34,6 +34,6 @@
package android.hardware.neuralnetworks;
@VintfStability
interface IBurst {
- android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
void releaseMemoryResource(in long memoryIdentifierToken);
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
index b328b29..c9c67f2 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
@@ -41,8 +41,8 @@
boolean[] getSupportedOperations(in android.hardware.neuralnetworks.Model model);
android.hardware.neuralnetworks.DeviceType getType();
String getVersionString();
- void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadline, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
- void prepareModelFromCache(in long deadline, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+ void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+ void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
const int MAX_NUMBER_OF_CACHE_FILES = 32;
const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15;
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
index 52882cd..fccb5dc 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -34,8 +34,8 @@
package android.hardware.neuralnetworks;
@VintfStability
interface IPreparedModel {
- android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
- android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadline, in long loopTimeoutDuration, in long duration);
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
+ android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs);
android.hardware.neuralnetworks.IBurst configureExecutionBurst();
const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
index 8207b25..37fa102 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
@@ -33,8 +33,8 @@
package android.hardware.neuralnetworks;
@VintfStability
-parcelable Memory {
- android.hardware.common.NativeHandle handle;
- long size;
- String name;
+union Memory {
+ android.hardware.common.Ashmem ashmem;
+ android.hardware.common.MappableFile mappableFile;
+ android.hardware.graphics.common.HardwareBuffer hardwareBuffer;
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
index 9690e01..bcc83cf 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
@@ -34,6 +34,6 @@
package android.hardware.neuralnetworks;
@VintfStability
parcelable Timing {
- long timeOnDevice;
- long timeInDriver;
+ long timeOnDeviceNs;
+ long timeInDriverNs;
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
index 861b6f0..df015ca 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
@@ -22,8 +22,20 @@
@VintfStability
@Backing(type="int")
enum FusedActivationFunc {
+ /**
+ * No activation.
+ */
NONE,
+ /**
+ * ReLU(x) = max(0, x)
+ */
RELU,
+ /**
+ * ReLU1(x) = min(1, max(-1, x))
+ */
RELU1,
+ /**
+ * ReLU6(x) = min(6, max(0, x))
+ */
RELU6,
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
index 85d2a03..decdc48 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
@@ -77,18 +77,18 @@
* @param measure Specifies whether or not to measure duration of the execution. The duration
* runs from the time the driver sees the call to the executeSynchronously
* function to the time the driver returns from the function.
- * @param deadline The time by which the execution is expected to complete. The time is measured
- * in nanoseconds since epoch of the steady clock (as from
- * std::chrono::steady_clock). If the execution cannot be finished by the
- * deadline, the execution may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
- * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
- * executing a {@link OperationType::WHILE} operation. If a loop
- * condition model does not output false within this duration, the
- * execution must be aborted. If -1 is provided, the maximum amount
- * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
- * negative values are invalid. When provided, the duration must not
- * exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since epoch of the steady clock (as from
+ * std::chrono::steady_clock). If the execution cannot be finished by the
+ * deadline, the execution may be aborted. Passing -1 means the deadline is
+ * omitted. Other negative values are invalid.
+ * @param loopTimeoutDurationNs The maximum amount of time in nanoseconds that should be spent
+ * executing a {@link OperationType::WHILE} operation. If a loop
+ * condition model does not output false within this duration, the
+ * execution must be aborted. If -1 is provided, the maximum amount
+ * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
+ * negative values are invalid. When provided, the duration must
+ * not exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
* @return ExecutionResult parcelable, containing the status of the execution, output shapes and
* timing information.
* @throws ServiceSpecificException with one of the following ErrorStatus values:
@@ -100,7 +100,7 @@
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
ExecutionResult executeSynchronously(in Request request, in long[] memoryIdentifierTokens,
- in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
+ in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
/**
* releaseMemoryResource is used by the client to signal to the service that a memory buffer
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
index c5b4ab1..72e2623 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
@@ -306,11 +306,11 @@
* @param preference Indicates the intended execution behavior of a prepared model.
* @param priority The priority of the prepared model relative to other prepared models owned by
* the client.
- * @param deadline The time by which the model is expected to be prepared. The time is measured
- * in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts)
- * or ::android::base::boot_clock). If the model cannot be prepared by the
- * deadline, the preparation may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
+ * @param deadlineNs The time by which the model is expected to be prepared. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the model cannot be prepared by
+ * the deadline, the preparation may be aborted. Passing -1 means the deadline
+ * is omitted. Other negative values are invalid.
* @param modelCache A vector of file descriptors for the security-sensitive cache. The length
* of the vector must either be 0 indicating that caching information is not
* provided, or match the numModelCache returned from
@@ -344,7 +344,7 @@
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
void prepareModel(in Model model, in ExecutionPreference preference, in Priority priority,
- in long deadline, in ParcelFileDescriptor[] modelCache,
+ in long deadlineNs, in ParcelFileDescriptor[] modelCache,
in ParcelFileDescriptor[] dataCache, in byte[] token,
in IPreparedModelCallback callback);
@@ -395,11 +395,11 @@
* with a set of inputs to the model. Note that the same prepared model object may be used with
* different shapes of inputs on different (possibly concurrent) executions.
*
- * @param deadline The time by which the model is expected to be prepared. The time is measured
- * in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
- * ::android::base::boot_clock). If the model cannot be prepared by the
- * deadline, the preparation may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
+ * @param deadlineNs The time by which the model is expected to be prepared. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the model cannot be prepared by
+ * the deadline, the preparation may be aborted. Passing -1 means the deadline
+ * is omitted. Other negative values are invalid.
* @param modelCache A vector of file descriptors for the security-sensitive cache. The length
* of the vector must match the numModelCache returned from
* getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
@@ -426,7 +426,7 @@
* the deadline
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
- void prepareModelFromCache(in long deadline, in ParcelFileDescriptor[] modelCache,
+ void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache,
in ParcelFileDescriptor[] dataCache, in byte[] token,
in IPreparedModelCallback callback);
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index bfab906..956b626 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -72,18 +72,18 @@
* @param measure Specifies whether or not to measure duration of the execution. The duration
* runs from the time the driver sees the call to the executeSynchronously
* function to the time the driver returns from the function.
- * @param deadline The time by which the execution is expected to complete. The time is measured
- * in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
- * ::android::base::boot_clock). If the execution cannot be finished by the
- * deadline, the execution may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
- * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
- * executing a {@link OperationType::WHILE} operation. If a loop
- * condition model does not output false within this duration, the
- * execution must be aborted. If -1 is provided, the maximum amount
- * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
- * negative values are invalid. When provided, the duration must not
- * exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
+ * @param loopTimeoutDurationNs The maximum amount of time in nanoseconds that should be spent
+ * executing a {@link OperationType::WHILE} operation. If a loop
+ * condition model does not output false within this duration, the
+ * execution must be aborted. If -1 is provided, the maximum amount
+ * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
+ * negative values are invalid. When provided, the duration must
+ * not exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
* @return ExecutionResult parcelable, containing the status of the execution, output shapes and
* timing information.
* @throws ServiceSpecificException with one of the following ErrorStatus values:
@@ -95,7 +95,7 @@
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
ExecutionResult executeSynchronously(in Request request, in boolean measureTiming,
- in long deadline, in long loopTimeoutDuration);
+ in long deadlineNs, in long loopTimeoutDurationNs);
/**
* Launch a fenced asynchronous execution on a prepared model.
@@ -137,22 +137,23 @@
* @param waitFor A vector of sync fence file descriptors. Execution must not start until all
* sync fences have been signaled.
* @param measure Specifies whether or not to measure duration of the execution.
- * @param deadline The time by which the execution is expected to complete. The time is measured
- * in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
- * ::android::base::boot_clock). If the execution cannot be finished by the
- * deadline, the execution may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
- * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
- * executing a {@link OperationType::WHILE} operation. If a loop
- * condition model does not output false within this duration, the
- * execution must be aborted. If -1 is provided, the maximum amount
- * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
- * negative values are invalid. When provided, the duration must not
- * exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
- * @param duration The length of time in nanoseconds within which the execution is expected to
- * complete after all sync fences in waitFor are signaled. If the execution
- * cannot be finished within the duration, the execution may be aborted. Passing
- * -1 means the duration is omitted. Other negative values are invalid.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
+ * @param loopTimeoutDurationNs The maximum amount of time in nanoseconds that should be spent
+ * executing a {@link OperationType::WHILE} operation. If a loop
+ * condition model does not output false within this duration, the
+ * execution must be aborted. If -1 is provided, the maximum amount
+ * of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
+ * negative values are invalid. When provided, the duration must
+ * not exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+ * @param durationNs The length of time in nanoseconds within which the execution is expected to
+ * complete after all sync fences in waitFor are signaled. If the execution
+ * cannot be finished within the duration, the execution may be aborted.
+ * Passing -1 means the duration is omitted. Other negative values are
+ * invalid.
* @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
* sync fence.
* @throws ServiceSpecificException with one of the following ErrorStatus values:
@@ -165,8 +166,8 @@
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
FencedExecutionResult executeFenced(in Request request, in ParcelFileDescriptor[] waitFor,
- in boolean measureTiming, in long deadline, in long loopTimeoutDuration,
- in long duration);
+ in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs,
+ in long durationNs);
/**
* Configure a Burst object used to execute multiple inferences on a prepared model in rapid
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
index 870f0ae..244ac87 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
@@ -15,16 +15,26 @@
*/
package android.hardware.neuralnetworks;
-import android.hardware.common.NativeHandle;
-import android.os.ParcelFileDescriptor;
+
+import android.hardware.common.Ashmem;
+import android.hardware.common.MappableFile;
+import android.hardware.graphics.common.HardwareBuffer;
/**
- * A type that is used to pass pieces of shared memory between processes.
- * The type structure mimics hidl_memory type from HIDL.
+ * The different types of memory that can be shared across processes.
*/
@VintfStability
-parcelable Memory {
- NativeHandle handle;
- long size;
- String name;
+union Memory {
+ /**
+ * Ashmem hidl_memory type from HIDL.
+ */
+ Ashmem ashmem;
+ /**
+ * File that can be mapped.
+ */
+ MappableFile mappableFile;
+ /**
+ * AIDL representation of AHardwareBuffer.
+ */
+ HardwareBuffer hardwareBuffer;
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/Timing.aidl
index 8130e08..5225096 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/Timing.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/Timing.aidl
@@ -28,9 +28,9 @@
/**
* Execution time on device (not driver, which runs on host processor).
*/
- long timeOnDevice;
+ long timeOnDeviceNs;
/**
* Execution time in driver (including time on device).
*/
- long timeInDriver;
+ long timeInDriverNs;
}
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index ad961cf..0ccc711 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -31,6 +31,8 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "android.hardware.graphics.common-V2-ndk_platform",
+ "libaidlcommonsupport",
"libarect",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
@@ -51,7 +53,9 @@
],
static_libs: [
"android.hardware.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.neuralnetworks-V1-ndk_platform",
+ "libaidlcommonsupport",
"libgmock",
"libneuralnetworks_common",
"neuralnetworks_types",
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index eb194e3..1457646 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -54,7 +54,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
new file mode 100644
index 0000000..e66507a
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <android/binder_auto_utils.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks {
+
+class InvalidDevice : public BnDevice {
+ public:
+ static std::shared_ptr<InvalidDevice> create();
+
+ InvalidDevice(Capabilities capabilities, const NumberOfCacheFiles& numberOfCacheFiles,
+ std::vector<Extension> extensions, DeviceType deviceType,
+ std::string versionString);
+
+ ndk::ScopedAStatus allocate(const BufferDesc& desc,
+ const std::vector<IPreparedModelParcel>& preparedModels,
+ const std::vector<BufferRole>& inputRoles,
+ const std::vector<BufferRole>& outputRoles,
+ DeviceBuffer* deviceBuffer) override;
+ ndk::ScopedAStatus getCapabilities(Capabilities* capabilities) override;
+ ndk::ScopedAStatus getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) override;
+ ndk::ScopedAStatus getSupportedExtensions(std::vector<Extension>* extensions) override;
+ ndk::ScopedAStatus getSupportedOperations(const Model& model,
+ std::vector<bool>* supportedOperations) override;
+ ndk::ScopedAStatus getType(DeviceType* deviceType) override;
+ ndk::ScopedAStatus getVersionString(std::string* versionString) override;
+ ndk::ScopedAStatus prepareModel(
+ const Model& model, ExecutionPreference preference, Priority priority, int64_t deadline,
+ const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
+ ndk::ScopedAStatus prepareModelFromCache(
+ int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
+
+ private:
+ const Capabilities kCapabilities;
+ const NumberOfCacheFiles kNumberOfCacheFiles;
+ const std::vector<Extension> kExtensions;
+ const DeviceType kDeviceType;
+ const std::string kVersionString;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index d5f7f81..4b263ee 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -16,8 +16,13 @@
#include "Conversions.h"
+#include <aidl/android/hardware/common/Ashmem.h>
+#include <aidl/android/hardware/common/MappableFile.h>
#include <aidl/android/hardware/common/NativeHandle.h>
+#include <aidl/android/hardware/graphics/common/HardwareBuffer.h>
+#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
+#include <android-base/mapped_file.h>
#include <android-base/unique_fd.h>
#include <android/binder_auto_utils.h>
#include <android/hardware_buffer.h>
@@ -125,28 +130,17 @@
using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
-static GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
- std::vector<base::unique_fd> fds;
- fds.reserve(handle.fds.size());
- for (const auto& fd : handle.fds) {
- auto duplicatedFd = NN_TRY(dupFd(fd.get()));
- fds.emplace_back(duplicatedFd.release());
+GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
+ auto nativeHandle = UniqueNativeHandle(dupFromAidl(handle));
+ if (nativeHandle.get() == nullptr) {
+ return NN_ERROR() << "android::dupFromAidl failed to convert the common::NativeHandle to a "
+ "native_handle_t";
}
-
- constexpr size_t kIntMax = std::numeric_limits<int>::max();
- CHECK_LE(handle.fds.size(), kIntMax);
- CHECK_LE(handle.ints.size(), kIntMax);
- native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
- static_cast<int>(handle.ints.size()));
- if (nativeHandle == nullptr) {
- return NN_ERROR() << "Failed to create native_handle";
+ if (!std::all_of(nativeHandle->data + 0, nativeHandle->data + nativeHandle->numFds,
+ [](int fd) { return fd >= 0; })) {
+ return NN_ERROR() << "android::dupFromAidl returned an invalid native_handle_t";
}
- for (size_t i = 0; i < fds.size(); ++i) {
- nativeHandle->data[i] = fds[i].release();
- }
- std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
-
- return UniqueNativeHandle(nativeHandle);
+ return nativeHandle;
}
} // anonymous namespace
@@ -353,75 +347,74 @@
return measureTiming ? MeasureTiming::YES : MeasureTiming::NO;
}
-static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
- return (value + multiple - 1) / multiple * multiple;
-}
-
GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory) {
- VERIFY_NON_NEGATIVE(memory.size) << "Memory size must not be negative";
- if (memory.size > std::numeric_limits<size_t>::max()) {
- return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
- }
+ using Tag = aidl_hal::Memory::Tag;
+ switch (memory.getTag()) {
+ case Tag::ashmem: {
+ const auto& ashmem = memory.get<Tag::ashmem>();
+ VERIFY_NON_NEGATIVE(ashmem.size) << "Memory size must not be negative";
+ if (ashmem.size > std::numeric_limits<size_t>::max()) {
+ return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
+ }
- if (memory.name != "hardware_buffer_blob") {
- return std::make_shared<const Memory>(Memory{
- .handle = NN_TRY(unvalidatedConvertHelper(memory.handle)),
- .size = static_cast<size_t>(memory.size),
- .name = memory.name,
- });
- }
+ auto handle = Memory::Ashmem{
+ .fd = NN_TRY(dupFd(ashmem.fd.get())),
+ .size = static_cast<size_t>(ashmem.size),
+ };
+ return std::make_shared<const Memory>(Memory{.handle = std::move(handle)});
+ }
+ case Tag::mappableFile: {
+ const auto& mappableFile = memory.get<Tag::mappableFile>();
+ VERIFY_NON_NEGATIVE(mappableFile.length) << "Memory size must not be negative";
+ VERIFY_NON_NEGATIVE(mappableFile.offset) << "Memory offset must not be negative";
+ if (mappableFile.length > std::numeric_limits<size_t>::max()) {
+ return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
+ }
+ if (mappableFile.offset > std::numeric_limits<size_t>::max()) {
+ return NN_ERROR() << "Memory: offset must be <= std::numeric_limits<size_t>::max()";
+ }
- const auto size = static_cast<uint32_t>(memory.size);
- const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
- const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
- const uint32_t width = size;
- const uint32_t height = 1; // height is always 1 for BLOB mode AHardwareBuffer.
- const uint32_t layers = 1; // layers is always 1 for BLOB mode AHardwareBuffer.
+ const size_t size = static_cast<size_t>(mappableFile.length);
+ const int prot = mappableFile.prot;
+ const int fd = mappableFile.fd.get();
+ const size_t offset = static_cast<size_t>(mappableFile.offset);
- const UniqueNativeHandle handle = NN_TRY(nativeHandleFromAidlHandle(memory.handle));
- const native_handle_t* nativeHandle = handle.get();
+ return createSharedMemoryFromFd(size, prot, fd, offset);
+ }
+ case Tag::hardwareBuffer: {
+ const auto& hardwareBuffer = memory.get<Tag::hardwareBuffer>();
- // AHardwareBuffer_createFromHandle() might fail because an allocator
- // expects a specific stride value. In that case, we try to guess it by
- // aligning the width to small powers of 2.
- // TODO(b/174120849): Avoid stride assumptions.
- AHardwareBuffer* hardwareBuffer = nullptr;
- status_t status = UNKNOWN_ERROR;
- for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
- const uint32_t stride = roundUpToMultiple(width, alignment);
- AHardwareBuffer_Desc desc{
- .width = width,
- .height = height,
- .layers = layers,
- .format = format,
- .usage = usage,
- .stride = stride,
- };
- status = AHardwareBuffer_createFromHandle(&desc, nativeHandle,
- AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
- &hardwareBuffer);
- if (status == NO_ERROR) {
- break;
+ const UniqueNativeHandle handle =
+ NN_TRY(nativeHandleFromAidlHandle(hardwareBuffer.handle));
+ const native_handle_t* nativeHandle = handle.get();
+
+ const AHardwareBuffer_Desc desc{
+ .width = static_cast<uint32_t>(hardwareBuffer.description.width),
+ .height = static_cast<uint32_t>(hardwareBuffer.description.height),
+ .layers = static_cast<uint32_t>(hardwareBuffer.description.layers),
+ .format = static_cast<uint32_t>(hardwareBuffer.description.format),
+ .usage = static_cast<uint64_t>(hardwareBuffer.description.usage),
+ .stride = static_cast<uint32_t>(hardwareBuffer.description.stride),
+ };
+ AHardwareBuffer* ahwb = nullptr;
+ const status_t status = AHardwareBuffer_createFromHandle(
+ &desc, nativeHandle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &ahwb);
+ if (status != NO_ERROR) {
+ return NN_ERROR() << "createFromHandle failed";
+ }
+
+ return createSharedMemoryFromAHWB(ahwb, /*takeOwnership=*/true);
}
}
- if (status != NO_ERROR) {
- return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
- << "Can't create AHardwareBuffer from handle. Error: " << status;
- }
-
- return std::make_shared<const Memory>(Memory{
- .handle = HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
- .size = static_cast<size_t>(memory.size),
- .name = memory.name,
- });
+ return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
}
GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
- if (timing.timeInDriver < -1) {
- return NN_ERROR() << "Timing: timeInDriver must not be less than -1";
+ if (timing.timeInDriverNs < -1) {
+ return NN_ERROR() << "Timing: timeInDriverNs must not be less than -1";
}
- if (timing.timeOnDevice < -1) {
- return NN_ERROR() << "Timing: timeOnDevice must not be less than -1";
+ if (timing.timeOnDeviceNs < -1) {
+ return NN_ERROR() << "Timing: timeOnDeviceNs must not be less than -1";
}
constexpr auto convertTiming = [](int64_t halTiming) -> OptionalDuration {
if (halTiming == kNoTiming) {
@@ -429,8 +422,8 @@
}
return nn::Duration(static_cast<uint64_t>(halTiming));
};
- return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
- .timeInDriver = convertTiming(timing.timeInDriver)};
+ return Timing{.timeOnDevice = convertTiming(timing.timeOnDeviceNs),
+ .timeInDriver = convertTiming(timing.timeInDriverNs)};
}
GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues) {
@@ -645,20 +638,95 @@
template <class... Ts>
overloaded(Ts...)->overloaded<Ts...>;
-static nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
- const native_handle_t& handle) {
- common::NativeHandle aidlNativeHandle;
+nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
+ const native_handle_t& nativeHandle) {
+ auto handle = ::android::dupToAidl(&nativeHandle);
+ if (!std::all_of(handle.fds.begin(), handle.fds.end(),
+ [](const ndk::ScopedFileDescriptor& fd) { return fd.get() >= 0; })) {
+ return NN_ERROR() << "android::dupToAidl returned an invalid common::NativeHandle";
+ }
+ return handle;
+}
- aidlNativeHandle.fds.reserve(handle.numFds);
- for (int i = 0; i < handle.numFds; ++i) {
- auto duplicatedFd = NN_TRY(nn::dupFd(handle.data[i]));
- aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Ashmem& memory) {
+ if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
+ if (memory.size > std::numeric_limits<int64_t>::max()) {
+ return (
+ NN_ERROR()
+ << "Memory::Ashmem: size must be <= std::numeric_limits<int64_t>::max()")
+ .
+ operator nn::GeneralResult<Memory>();
+ }
}
- aidlNativeHandle.ints = std::vector<int>(&handle.data[handle.numFds],
- &handle.data[handle.numFds + handle.numInts]);
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+ auto handle = common::Ashmem{
+ .fd = ndk::ScopedFileDescriptor(fd.release()),
+ .size = static_cast<int64_t>(memory.size),
+ };
+ return Memory::make<Memory::Tag::ashmem>(std::move(handle));
+}
- return aidlNativeHandle;
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Fd& memory) {
+ if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
+ if (memory.size > std::numeric_limits<int64_t>::max()) {
+ return (NN_ERROR() << "Memory::Fd: size must be <= std::numeric_limits<int64_t>::max()")
+ .
+ operator nn::GeneralResult<Memory>();
+ }
+ if (memory.offset > std::numeric_limits<int64_t>::max()) {
+ return (
+ NN_ERROR()
+ << "Memory::Fd: offset must be <= std::numeric_limits<int64_t>::max()")
+ .
+ operator nn::GeneralResult<Memory>();
+ }
+ }
+
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+ auto handle = common::MappableFile{
+ .length = static_cast<int64_t>(memory.size),
+ .prot = memory.prot,
+ .fd = ndk::ScopedFileDescriptor(fd.release()),
+ .offset = static_cast<int64_t>(memory.offset),
+ };
+ return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
+}
+
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& memory) {
+ const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(memory.handle.get());
+ if (nativeHandle == nullptr) {
+ return (NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
+ "returned nullptr")
+ .
+ operator nn::GeneralResult<Memory>();
+ }
+
+ auto handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle));
+
+ AHardwareBuffer_Desc desc;
+ AHardwareBuffer_describe(memory.handle.get(), &desc);
+
+ const auto description = graphics::common::HardwareBufferDescription{
+ .width = static_cast<int32_t>(desc.width),
+ .height = static_cast<int32_t>(desc.height),
+ .layers = static_cast<int32_t>(desc.layers),
+ .format = static_cast<graphics::common::PixelFormat>(desc.format),
+ .usage = static_cast<graphics::common::BufferUsage>(desc.usage),
+ .stride = static_cast<int32_t>(desc.stride),
+ };
+
+ auto hardwareBuffer = graphics::common::HardwareBuffer{
+ .description = std::move(description),
+ .handle = std::move(handle),
+ };
+ return Memory::make<Memory::Tag::hardwareBuffer>(std::move(hardwareBuffer));
+}
+
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Unknown& /*memory*/) {
+ return (NN_ERROR() << "Unable to convert Unknown memory type")
+ .
+ operator nn::GeneralResult<Memory>();
}
} // namespace
@@ -693,41 +761,12 @@
}
nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
- CHECK(memory != nullptr);
- if (memory->size > std::numeric_limits<int64_t>::max()) {
- return NN_ERROR() << "Memory size doesn't fit into int64_t.";
+ if (memory == nullptr) {
+ return (NN_ERROR() << "Unable to convert nullptr memory")
+ .
+ operator nn::GeneralResult<Memory>();
}
- if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
- return Memory{
- .handle = NN_TRY(unvalidatedConvert(*handle)),
- .size = static_cast<int64_t>(memory->size),
- .name = memory->name,
- };
- }
-
- const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
- AHardwareBuffer_Desc bufferDesc;
- AHardwareBuffer_describe(ahwb, &bufferDesc);
-
- if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
- CHECK_EQ(memory->size, bufferDesc.width);
- CHECK_EQ(memory->name, "hardware_buffer_blob");
- } else {
- CHECK_EQ(memory->size, 0u);
- CHECK_EQ(memory->name, "hardware_buffer");
- }
-
- const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
- if (nativeHandle == nullptr) {
- return NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
- "returned nullptr";
- }
-
- return Memory{
- .handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle)),
- .size = static_cast<int64_t>(memory->size),
- .name = memory->name,
- };
+ return std::visit([](const auto& x) { return unvalidatedConvert(x); }, memory->handle);
}
nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
@@ -925,8 +964,8 @@
nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
return Timing{
- .timeOnDevice = NN_TRY(unvalidatedConvert(timing.timeOnDevice)),
- .timeInDriver = NN_TRY(unvalidatedConvert(timing.timeInDriver)),
+ .timeOnDeviceNs = NN_TRY(unvalidatedConvert(timing.timeOnDevice)),
+ .timeInDriverNs = NN_TRY(unvalidatedConvert(timing.timeInDriver)),
};
}
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index 02ca861..0fd453b 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -178,10 +178,6 @@
return kDeviceType;
}
-bool Device::isUpdatable() const {
- return false;
-}
-
const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
new file mode 100644
index 0000000..c9d9955
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "InvalidDevice"
+
+#include "InvalidDevice.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <android/binder_auto_utils.h>
+
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks {
+namespace {
+
+ndk::ScopedAStatus toAStatus(ErrorStatus errorStatus, const std::string& errorMessage) {
+ if (errorStatus == ErrorStatus::NONE) {
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(errorStatus), errorMessage.c_str());
+}
+
+} // namespace
+
+std::shared_ptr<InvalidDevice> InvalidDevice::create() {
+ constexpr auto perf = PerformanceInfo{
+ .execTime = std::numeric_limits<float>::max(),
+ .powerUsage = std::numeric_limits<float>::max(),
+ };
+ auto capabilities = Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar = perf,
+ .relaxedFloat32toFloat16PerformanceTensor = perf,
+ .operandPerformance = {},
+ .ifPerformance = perf,
+ .whilePerformance = perf,
+ };
+ constexpr auto numberOfCacheFiles = NumberOfCacheFiles{
+ .numModelCache = 0,
+ .numDataCache = 0,
+ };
+ std::vector<Extension> extensions{};
+ constexpr auto deviceType = DeviceType::OTHER;
+ std::string versionString = "invalid";
+
+ return ndk::SharedRefBase::make<InvalidDevice>(std::move(capabilities), numberOfCacheFiles,
+ std::move(extensions), deviceType,
+ std::move(versionString));
+}
+
+InvalidDevice::InvalidDevice(Capabilities capabilities,
+ const NumberOfCacheFiles& numberOfCacheFiles,
+ std::vector<Extension> extensions, DeviceType deviceType,
+ std::string versionString)
+ : kCapabilities(std::move(capabilities)),
+ kNumberOfCacheFiles(numberOfCacheFiles),
+ kExtensions(std::move(extensions)),
+ kDeviceType(deviceType),
+ kVersionString(std::move(versionString)) {}
+
+ndk::ScopedAStatus InvalidDevice::allocate(
+ const BufferDesc& /*desc*/, const std::vector<IPreparedModelParcel>& /*preparedModels*/,
+ const std::vector<BufferRole>& /*inputRoles*/,
+ const std::vector<BufferRole>& /*outputRoles*/, DeviceBuffer* /*deviceBuffer*/) {
+ return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
+}
+
+ndk::ScopedAStatus InvalidDevice::getCapabilities(Capabilities* capabilities) {
+ *capabilities = kCapabilities;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getNumberOfCacheFilesNeeded(
+ NumberOfCacheFiles* numberOfCacheFiles) {
+ *numberOfCacheFiles = kNumberOfCacheFiles;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getSupportedExtensions(std::vector<Extension>* extensions) {
+ *extensions = kExtensions;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getSupportedOperations(const Model& model,
+ std::vector<bool>* supportedOperations) {
+ if (const auto result = utils::validate(model); !result.ok()) {
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+ }
+ *supportedOperations = std::vector<bool>(model.main.operations.size(), false);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getType(DeviceType* deviceType) {
+ *deviceType = kDeviceType;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getVersionString(std::string* versionString) {
+ *versionString = kVersionString;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::prepareModel(
+ const Model& model, ExecutionPreference preference, Priority priority, int64_t deadline,
+ const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+ "invalid callback passed to InvalidDevice::prepareModel");
+ }
+ if (const auto result = utils::validate(model); !result.ok()) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+ }
+ if (const auto result = utils::validate(preference); !result.ok()) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+ }
+ if (const auto result = utils::validate(priority); !result.ok()) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+ }
+ if (deadline < -1) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+ "Invalid deadline " + std::to_string(deadline));
+ }
+ if (modelCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numModelCache)) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+ "Invalid modelCache, size = " + std::to_string(modelCache.size()));
+ }
+ if (dataCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numDataCache)) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+ "Invalid modelCache, size = " + std::to_string(dataCache.size()));
+ }
+ if (token.size() != IDevice::BYTE_SIZE_OF_CACHE_TOKEN) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(
+ ErrorStatus::INVALID_ARGUMENT,
+ "Invalid cache token, size = " + std::to_string(IDevice::BYTE_SIZE_OF_CACHE_TOKEN));
+ }
+ callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::prepareModelFromCache(
+ int64_t /*deadline*/, const std::vector<ndk::ScopedFileDescriptor>& /*modelCache*/,
+ const std::vector<ndk::ScopedFileDescriptor>& /*dataCache*/,
+ const std::vector<uint8_t>& /*token*/,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
+ return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
+}
+
+} // namespace aidl::android::hardware::neuralnetworks
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index 511de55..ac182a2 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -16,6 +16,7 @@
#include "Service.h"
+#include <AndroidVersionUtil.h>
#include <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -35,13 +36,23 @@
hal::utils::ResilientDevice::Factory makeDevice =
[instanceName,
name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
- const auto& getService =
- blocking ? AServiceManager_getService : AServiceManager_checkService;
+ std::add_pointer_t<AIBinder*(const char*)> getService;
+ if (blocking) {
+ if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
+ getService = AServiceManager_waitForService;
+ } else {
+ getService = AServiceManager_getService;
+ }
+ } else {
+ getService = AServiceManager_checkService;
+ }
+
auto service = IDevice::fromBinder(ndk::SpAIBinder(getService(name.c_str())));
if (service == nullptr) {
- return NN_ERROR() << (blocking ? "AServiceManager_getService"
- : "AServiceManager_checkService")
- << " returned nullptr";
+ return NN_ERROR()
+ << (blocking ? "AServiceManager_waitForService (or AServiceManager_getService)"
+ : "AServiceManager_checkService")
+ << " returned nullptr";
}
ABinderProcess_startThreadPool();
return Device::create(instanceName, std::move(service));
diff --git a/neuralnetworks/aidl/utils/src/Utils.cpp b/neuralnetworks/aidl/utils/src/Utils.cpp
index 95516c8..03407be 100644
--- a/neuralnetworks/aidl/utils/src/Utils.cpp
+++ b/neuralnetworks/aidl/utils/src/Utils.cpp
@@ -16,12 +16,20 @@
#include "Utils.h"
+#include <aidl/android/hardware/common/Ashmem.h>
+#include <aidl/android/hardware/common/MappableFile.h>
+#include <aidl/android/hardware/graphics/common/HardwareBuffer.h>
+#include <android/binder_auto_utils.h>
#include <android/binder_status.h>
#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
namespace aidl::android::hardware::neuralnetworks::utils {
namespace {
+nn::GeneralResult<ndk::ScopedFileDescriptor> clone(const ndk::ScopedFileDescriptor& fd);
+using utils::clone;
+
template <typename Type>
nn::GeneralResult<std::vector<Type>> cloneVec(const std::vector<Type>& arguments) {
std::vector<Type> clonedObjects;
@@ -37,24 +45,52 @@
return cloneVec(arguments);
}
+nn::GeneralResult<ndk::ScopedFileDescriptor> clone(const ndk::ScopedFileDescriptor& fd) {
+ auto duplicatedFd = NN_TRY(nn::dupFd(fd.get()));
+ return ndk::ScopedFileDescriptor(duplicatedFd.release());
+}
+
+nn::GeneralResult<common::NativeHandle> clone(const common::NativeHandle& handle) {
+ return common::NativeHandle{
+ .fds = NN_TRY(cloneVec(handle.fds)),
+ .ints = handle.ints,
+ };
+}
+
} // namespace
nn::GeneralResult<Memory> clone(const Memory& memory) {
- common::NativeHandle nativeHandle;
- nativeHandle.ints = memory.handle.ints;
- nativeHandle.fds.reserve(memory.handle.fds.size());
- for (const auto& fd : memory.handle.fds) {
- const int newFd = dup(fd.get());
- if (newFd < 0) {
- return NN_ERROR() << "Couldn't dup a file descriptor";
+ switch (memory.getTag()) {
+ case Memory::Tag::ashmem: {
+ const auto& ashmem = memory.get<Memory::Tag::ashmem>();
+ auto handle = common::Ashmem{
+ .fd = NN_TRY(clone(ashmem.fd)),
+ .size = ashmem.size,
+ };
+ return Memory::make<Memory::Tag::ashmem>(std::move(handle));
}
- nativeHandle.fds.emplace_back(newFd);
+ case Memory::Tag::mappableFile: {
+ const auto& memFd = memory.get<Memory::Tag::mappableFile>();
+ auto handle = common::MappableFile{
+ .length = memFd.length,
+ .prot = memFd.prot,
+ .fd = NN_TRY(clone(memFd.fd)),
+ .offset = memFd.offset,
+ };
+ return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
+ }
+ case Memory::Tag::hardwareBuffer: {
+ const auto& hardwareBuffer = memory.get<Memory::Tag::hardwareBuffer>();
+ auto handle = graphics::common::HardwareBuffer{
+ .description = hardwareBuffer.description,
+ .handle = NN_TRY(clone(hardwareBuffer.handle)),
+ };
+ return Memory::make<Memory::Tag::hardwareBuffer>(std::move(handle));
+ }
}
- return Memory{
- .handle = std::move(nativeHandle),
- .size = memory.size,
- .name = memory.name,
- };
+ return (NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag())
+ .
+ operator nn::GeneralResult<Memory>();
}
nn::GeneralResult<RequestMemoryPool> clone(const RequestMemoryPool& requestPool) {
diff --git a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
index 630a460..ff98a7d 100644
--- a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
@@ -39,7 +39,7 @@
using ::testing::SetArgPointee;
const std::shared_ptr<IPreparedModel> kInvalidPreparedModel;
-constexpr auto kNoTiming = Timing{.timeOnDevice = -1, .timeInDriver = -1};
+constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 7804c2a..d5b150a 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -50,9 +50,11 @@
],
static_libs: [
"android.hardware.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.neuralnetworks-V1-ndk_platform",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libaidlcommonsupport",
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index 1440429..d3b041d 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -547,7 +547,7 @@
makeOutputInsufficientSize(kInsufficientOutputIndex, &request);
}
- int64_t loopTimeoutDuration = kOmittedTimeoutDuration;
+ int64_t loopTimeoutDurationNs = kOmittedTimeoutDuration;
// OutputType::MISSED_DEADLINE is only used by
// TestKind::INTINITE_LOOP_TIMEOUT tests to verify that an infinite loop is
// aborted after a timeout.
@@ -555,7 +555,7 @@
// Override the default loop timeout duration with a small value to
// speed up test execution.
constexpr int64_t kMillisecond = 1'000'000;
- loopTimeoutDuration = 1 * kMillisecond;
+ loopTimeoutDurationNs = 1 * kMillisecond;
}
ErrorStatus executionStatus;
@@ -568,7 +568,7 @@
ExecutionResult executionResult;
// execute
const auto ret = preparedModel->executeSynchronously(request, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDuration,
+ kNoDeadline, loopTimeoutDurationNs,
&executionResult);
ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription();
@@ -608,7 +608,7 @@
ExecutionResult executionResult;
// execute
ret = burst->executeSynchronously(request, slots, testConfig.measureTiming, kNoDeadline,
- loopTimeoutDuration, &executionResult);
+ loopTimeoutDurationNs, &executionResult);
ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription();
if (ret.isOk()) {
@@ -635,7 +635,7 @@
ErrorStatus result = ErrorStatus::NONE;
FencedExecutionResult executionResult;
auto ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDuration, kNoDuration,
+ kNoDeadline, loopTimeoutDurationNs, kNoDuration,
&executionResult);
ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription();
@@ -649,7 +649,7 @@
waitFor.emplace_back(dupFd);
// If a sync fence is returned, try start another run waiting for the sync fence.
ret = preparedModel->executeFenced(request, waitFor, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDuration, kNoDuration,
+ kNoDeadline, loopTimeoutDurationNs, kNoDuration,
&executionResult);
ASSERT_TRUE(ret.isOk());
waitForSyncFence(executionResult.syncFence.get());
@@ -686,8 +686,8 @@
if (!testConfig.measureTiming) {
EXPECT_EQ(timing, kNoTiming);
} else {
- if (timing.timeOnDevice != -1 && timing.timeInDriver != -1) {
- EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
+ if (timing.timeOnDeviceNs != -1 && timing.timeInDriverNs != -1) {
+ EXPECT_LE(timing.timeOnDeviceNs, timing.timeInDriverNs);
}
}
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 596f8ae..e8313f1 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "neuralnetworks_aidl_hal_test"
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
#include <android/binder_interface_utils.h>
@@ -659,10 +660,26 @@
return allocateBuffer(preparedModel, inputIndexes, outputIndexes, {});
}
+ size_t getSize(const Memory& memory) {
+ switch (memory.getTag()) {
+ case Memory::Tag::ashmem:
+ return memory.get<Memory::Tag::ashmem>().size;
+ case Memory::Tag::mappableFile:
+ return memory.get<Memory::Tag::mappableFile>().length;
+ case Memory::Tag::hardwareBuffer: {
+ const auto& hardwareBuffer = memory.get<Memory::Tag::hardwareBuffer>();
+ const bool isBlob =
+ hardwareBuffer.description.format == graphics::common::PixelFormat::BLOB;
+ return isBlob ? hardwareBuffer.description.width : 0;
+ }
+ }
+ return 0;
+ }
+
Memory allocateSharedMemory(uint32_t size) {
const auto sharedMemory = nn::createSharedMemory(size).value();
auto memory = utils::convert(sharedMemory).value();
- EXPECT_EQ(memory.size, size);
+ EXPECT_EQ(getSize(memory), size);
return memory;
}
@@ -690,7 +707,7 @@
void initializeDeviceMemory(const std::shared_ptr<IBuffer>& buffer) {
Memory memory = allocateSharedMemory(kTestOperandDataSize);
- ASSERT_EQ(memory.size, kTestOperandDataSize);
+ ASSERT_EQ(getSize(memory), kTestOperandDataSize);
testCopyFrom(buffer, memory, utils::toSigned(kTestOperand.dimensions).value(),
ErrorStatus::NONE);
}
diff --git a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
index e803e38..bbba887 100644
--- a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
@@ -53,7 +53,7 @@
using ExecutionFunction =
std::function<MaybeResults(const std::shared_ptr<IPreparedModel>& preparedModel,
- const Request& request, int64_t deadline)>;
+ const Request& request, int64_t deadlineNs)>;
static int64_t makeDeadline(DeadlineBoundType deadlineBoundType) {
const auto getNanosecondsSinceEpoch = [](const auto& time) -> int64_t {
@@ -79,9 +79,9 @@
void runPrepareModelTest(const std::shared_ptr<IDevice>& device, const Model& model,
Priority priority, std::optional<DeadlineBoundType> deadlineBound) {
- int64_t deadline = kNoDeadline;
+ int64_t deadlineNs = kNoDeadline;
if (deadlineBound.has_value()) {
- deadline = makeDeadline(deadlineBound.value());
+ deadlineNs = makeDeadline(deadlineBound.value());
}
// see if service can handle model
@@ -96,8 +96,8 @@
const std::shared_ptr<PreparedModelCallback> preparedModelCallback =
ndk::SharedRefBase::make<PreparedModelCallback>();
const auto prepareLaunchStatus =
- device->prepareModel(model, ExecutionPreference::FAST_SINGLE_ANSWER, priority, deadline,
- {}, {}, kEmptyCacheToken, preparedModelCallback);
+ device->prepareModel(model, ExecutionPreference::FAST_SINGLE_ANSWER, priority,
+ deadlineNs, {}, {}, kEmptyCacheToken, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk())
<< "prepareLaunchStatus: " << prepareLaunchStatus.getDescription();
@@ -156,13 +156,13 @@
}
static MaybeResults executeSynchronously(const std::shared_ptr<IPreparedModel>& preparedModel,
- const Request& request, int64_t deadline) {
+ const Request& request, int64_t deadlineNs) {
SCOPED_TRACE("synchronous");
const bool measure = false;
// run execution
ExecutionResult executionResult;
- const auto ret = preparedModel->executeSynchronously(request, measure, deadline,
+ const auto ret = preparedModel->executeSynchronously(request, measure, deadlineNs,
kOmittedTimeoutDuration, &executionResult);
EXPECT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription();
@@ -182,7 +182,7 @@
}
static MaybeResults executeBurst(const std::shared_ptr<IPreparedModel>& preparedModel,
- const Request& request, int64_t deadline) {
+ const Request& request, int64_t deadlineNs) {
SCOPED_TRACE("burst");
const bool measure = false;
@@ -200,7 +200,7 @@
// run execution
ExecutionResult executionResult;
- ret = burst->executeSynchronously(request, slots, measure, deadline, kOmittedTimeoutDuration,
+ ret = burst->executeSynchronously(request, slots, measure, deadlineNs, kOmittedTimeoutDuration,
&executionResult);
EXPECT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< ret.getDescription();
@@ -224,10 +224,10 @@
const ExecutionContext& context, bool synchronous,
DeadlineBoundType deadlineBound) {
const ExecutionFunction execute = synchronous ? executeSynchronously : executeBurst;
- const auto deadline = makeDeadline(deadlineBound);
+ const auto deadlineNs = makeDeadline(deadlineBound);
// Perform execution and unpack results.
- const auto results = execute(preparedModel, request, deadline);
+ const auto results = execute(preparedModel, request, deadlineNs);
if (!results.has_value()) return;
const auto& [status, outputShapes, timing] = results.value();
diff --git a/neuralnetworks/aidl/vts/functional/Utils.h b/neuralnetworks/aidl/vts/functional/Utils.h
index 266301c..77085a7 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -43,7 +43,7 @@
inline constexpr Priority kDefaultPriority = Priority::MEDIUM;
-inline constexpr Timing kNoTiming = {.timeOnDevice = -1, .timeInDriver = -1};
+inline constexpr Timing kNoTiming = {.timeOnDeviceNs = -1, .timeInDriverNs = -1};
inline constexpr int64_t kNoDeadline = -1;
inline constexpr int64_t kOmittedTimeoutDuration = -1;
inline constexpr int64_t kNoDuration = -1;
diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
index 94d3daf..698c054 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
@@ -259,12 +259,16 @@
size_t sizeForBinder(const Memory& memory) {
// This is just a guess.
- size_t size = 0;
- const NativeHandle& handle = memory.handle;
- size += sizeof(decltype(handle.fds)::value_type) * handle.fds.size();
- size += sizeof(decltype(handle.ints)::value_type) * handle.ints.size();
- size += sizeForBinder(memory.name);
- size += sizeof(memory);
+ size_t size = sizeof(Memory);
+
+ // Only hardwareBuffer type memory has dynamic memory that needs to be accounted for (in the
+ // form of a NativeHandle type). The other other types of memory (MappableFile, Ashmem) use a
+ // single file descriptor (with metadata) instead.
+ if (memory.getTag() == Memory::Tag::hardwareBuffer) {
+ const NativeHandle& handle = memory.get<Memory::Tag::hardwareBuffer>().handle;
+ size += sizeof(decltype(handle.fds)::value_type) * handle.fds.size();
+ size += sizeof(decltype(handle.ints)::value_type) * handle.ints.size();
+ }
return size;
}
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index 0c3a196..ee7cf89 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -94,7 +94,7 @@
}
static NamedDevice makeNamedDevice(const std::string& name) {
- ndk::SpAIBinder binder(AServiceManager_getService(name.c_str()));
+ ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
return {name, IDevice::fromBinder(binder)};
}
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
index d843526..5e62b9a 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -32,7 +32,7 @@
class InvalidDevice final : public nn::IDevice {
public:
InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
- nn::DeviceType type, bool isUpdatable, std::vector<nn::Extension> extensions,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
nn::Capabilities capabilities,
std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded);
@@ -40,7 +40,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
@@ -71,7 +70,6 @@
const std::string kVersionString;
const nn::Version kFeatureLevel;
const nn::DeviceType kType;
- const bool kIsUpdatable;
const std::vector<nn::Extension> kExtensions;
const nn::Capabilities kCapabilities;
const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 8199c52..84ae799 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -53,7 +53,6 @@
const std::string& getVersionString() const override;
nn::Version getFeatureLevel() const override;
nn::DeviceType getType() const override;
- bool isUpdatable() const override;
const std::vector<nn::Extension>& getSupportedExtensions() const override;
const nn::Capabilities& getCapabilities() const override;
std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index 924ecb2..4d26795 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -89,6 +89,59 @@
});
}
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+ const std::vector<int32_t>& ints) {
+ constexpr size_t kIntMax = std::numeric_limits<int>::max();
+ CHECK_LE(ints.size(), kIntMax);
+ native_handle_t* nativeHandle = native_handle_create(1, static_cast<int>(ints.size()));
+ if (nativeHandle == nullptr) {
+ return NN_ERROR() << "Failed to create native_handle";
+ }
+
+ nativeHandle->data[0] = fd.release();
+ std::copy(ints.begin(), ints.end(), nativeHandle->data + 1);
+
+ hidl_handle handle;
+ handle.setTo(nativeHandle, /*shouldOwn=*/true);
+ return handle;
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+ auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
+ return hidl_memory("ashmem", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+
+ const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
+ const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
+
+ auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
+ return hidl_memory("mmap_fd", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
+ const auto* ahwb = memory.handle.get();
+ AHardwareBuffer_Desc bufferDesc;
+ AHardwareBuffer_describe(ahwb, &bufferDesc);
+
+ const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
+ const size_t size = isBlob ? bufferDesc.width : 0;
+ const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
+
+ const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
+ const hidl_handle hidlHandle(nativeHandle);
+ hidl_handle copiedHandle(hidlHandle);
+
+ return hidl_memory(name, std::move(copiedHandle), size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
+ return hidl_memory(memory.name, NN_TRY(hidlHandleFromSharedHandle(memory.handle)), memory.size);
+}
+
} // anonymous namespace
nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
@@ -255,27 +308,7 @@
if (memory == nullptr) {
return NN_ERROR() << "Memory must be non-empty";
}
- if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
- return hidl_memory(memory->name, NN_TRY(hidlHandleFromSharedHandle(*handle)), memory->size);
- }
-
- const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
- AHardwareBuffer_Desc bufferDesc;
- AHardwareBuffer_describe(ahwb, &bufferDesc);
-
- if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
- CHECK_EQ(memory->size, bufferDesc.width);
- CHECK_EQ(memory->name, "hardware_buffer_blob");
- } else {
- CHECK_EQ(memory->size, 0u);
- CHECK_EQ(memory->name, "hardware_buffer");
- }
-
- const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
- const hidl_handle hidlHandle(nativeHandle);
- hidl_handle handle(hidlHandle);
-
- return hidl_memory(memory->name, std::move(handle), memory->size);
+ return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
}
static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
@@ -283,14 +316,53 @@
}
nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
- CHECK_LE(memory.size(), std::numeric_limits<uint32_t>::max());
+ CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
+ if (!memory.valid()) {
+ return NN_ERROR() << "Unable to convert invalid hidl_memory";
+ }
+
+ if (memory.name() == "ashmem") {
+ if (memory.handle()->numFds != 1) {
+ return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+ << memory.handle()->numFds << " numFds, but expected 1";
+ }
+ if (memory.handle()->numInts != 0) {
+ return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+ << memory.handle()->numInts << " numInts, but expected 0";
+ }
+ auto handle = nn::Memory::Ashmem{
+ .fd = NN_TRY(nn::dupFd(memory.handle()->data[0])),
+ .size = static_cast<size_t>(memory.size()),
+ };
+ return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
+ }
+
+ if (memory.name() == "mmap_fd") {
+ if (memory.handle()->numFds != 1) {
+ return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+ << memory.handle()->numFds << " numFds, but expected 1";
+ }
+ if (memory.handle()->numInts != 3) {
+ return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+ << memory.handle()->numInts << " numInts, but expected 3";
+ }
+
+ const int fd = memory.handle()->data[0];
+ const int prot = memory.handle()->data[1];
+ const int lower = memory.handle()->data[2];
+ const int higher = memory.handle()->data[3];
+ const size_t offset = nn::getOffsetFromInts(lower, higher);
+
+ return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
+ }
if (memory.name() != "hardware_buffer_blob") {
- return std::make_shared<const nn::Memory>(nn::Memory{
+ auto handle = nn::Memory::Unknown{
.handle = NN_TRY(sharedHandleFromNativeHandle(memory.handle())),
- .size = static_cast<uint32_t>(memory.size()),
+ .size = static_cast<size_t>(memory.size()),
.name = memory.name(),
- });
+ };
+ return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
}
const auto size = memory.size();
@@ -328,11 +400,7 @@
<< "Can't create AHardwareBuffer from handle. Error: " << status;
}
- return std::make_shared<const nn::Memory>(nn::Memory{
- .handle = nn::HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
- .size = static_cast<uint32_t>(memory.size()),
- .name = memory.name(),
- });
+ return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
}
nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
index 81bca7f..535ccb4 100644
--- a/neuralnetworks/utils/common/src/InvalidDevice.cpp
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -32,14 +32,13 @@
namespace android::hardware::neuralnetworks::utils {
InvalidDevice::InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
- nn::DeviceType type, bool isUpdatable,
- std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded)
: kName(std::move(name)),
kVersionString(std::move(versionString)),
kFeatureLevel(featureLevel),
kType(type),
- kIsUpdatable(isUpdatable),
kExtensions(std::move(extensions)),
kCapabilities(std::move(capabilities)),
kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded) {}
@@ -60,10 +59,6 @@
return kType;
}
-bool InvalidDevice::isUpdatable() const {
- return kIsUpdatable;
-}
-
const std::vector<nn::Extension>& InvalidDevice::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 13965af..2023c9a 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -122,14 +122,12 @@
};
if (compare(&IDevice::getName) || compare(&IDevice::getVersionString) ||
compare(&IDevice::getFeatureLevel) || compare(&IDevice::getType) ||
- compare(&IDevice::isUpdatable) || compare(&IDevice::getSupportedExtensions) ||
- compare(&IDevice::getCapabilities)) {
+ compare(&IDevice::getSupportedExtensions) || compare(&IDevice::getCapabilities)) {
LOG(ERROR) << "Recovered device has different metadata than what is cached. Marking "
"IDevice object as invalid.";
device = std::make_shared<const InvalidDevice>(
- kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(),
- mDevice->isUpdatable(), kExtensions, kCapabilities,
- mDevice->getNumberOfCacheFilesNeeded());
+ kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(), kExtensions,
+ kCapabilities, mDevice->getNumberOfCacheFilesNeeded());
mIsValid = false;
}
@@ -153,10 +151,6 @@
return getDevice()->getType();
}
-bool ResilientDevice::isUpdatable() const {
- return getDevice()->isUpdatable();
-}
-
const std::vector<nn::Extension>& ResilientDevice::getSupportedExtensions() const {
return kExtensions;
}
diff --git a/neuralnetworks/utils/common/test/MockDevice.h b/neuralnetworks/utils/common/test/MockDevice.h
index b274716..a9428bc 100644
--- a/neuralnetworks/utils/common/test/MockDevice.h
+++ b/neuralnetworks/utils/common/test/MockDevice.h
@@ -29,7 +29,6 @@
MOCK_METHOD(const std::string&, getVersionString, (), (const, override));
MOCK_METHOD(Version, getFeatureLevel, (), (const, override));
MOCK_METHOD(DeviceType, getType, (), (const, override));
- MOCK_METHOD(bool, isUpdatable, (), (const, override));
MOCK_METHOD(const std::vector<Extension>&, getSupportedExtensions, (), (const, override));
MOCK_METHOD(const Capabilities&, getCapabilities, (), (const, override));
MOCK_METHOD((std::pair<uint32_t, uint32_t>), getNumberOfCacheFilesNeeded, (),
diff --git a/neuralnetworks/utils/service/include/nnapi/hal/Service.h b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
index e339627..2fd5237 100644
--- a/neuralnetworks/utils/service/include/nnapi/hal/Service.h
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -22,10 +22,15 @@
#include <memory>
#include <vector>
-namespace android::nn::hal {
+namespace android::hardware::neuralnetworks::service {
-std::vector<nn::SharedDevice> getDevices();
+struct SharedDeviceAndUpdatability {
+ nn::SharedDevice device;
+ bool isDeviceUpdatable = false;
+};
-} // namespace android::nn::hal
+std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers);
+
+} // namespace android::hardware::neuralnetworks::service
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_SERVICE_H
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index c83bcc9..2286288 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -16,6 +16,7 @@
#include "Service.h"
+#include <AndroidVersionUtil.h>
#include <aidl/android/hardware/neuralnetworks/IDevice.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
@@ -34,6 +35,7 @@
#include <nnapi/hal/1.2/Service.h>
#include <nnapi/hal/1.3/Service.h>
#include <nnapi/hal/aidl/Service.h>
+#include <nnapi/hal/aidl/Utils.h>
#include <functional>
#include <memory>
@@ -49,7 +51,7 @@
using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
- std::vector<nn::SharedDevice>* devices,
+ std::vector<SharedDeviceAndUpdatability>* devices,
std::unordered_set<std::string>* registeredDevices) {
CHECK(devices != nullptr);
CHECK(registeredDevices != nullptr);
@@ -61,7 +63,7 @@
if (maybeDevice.has_value()) {
auto device = std::move(maybeDevice).value();
CHECK(device != nullptr);
- devices->push_back(std::move(device));
+ devices->push_back({.device = std::move(device)});
} else {
LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
<< ": " << maybeDevice.error().message;
@@ -70,8 +72,9 @@
}
}
-void getAidlDevices(std::vector<nn::SharedDevice>* devices,
- std::unordered_set<std::string>* registeredDevices) {
+void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
+ std::unordered_set<std::string>* registeredDevices,
+ bool includeUpdatableDrivers) {
CHECK(devices != nullptr);
CHECK(registeredDevices != nullptr);
@@ -82,18 +85,27 @@
// Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
// there is no need for a workaround supported on lower levels.
- if (__builtin_available(android __ANDROID_API_S__, *)) {
+ if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
static_cast<void*>(&names), callback);
}
for (const auto& name : names) {
+ bool isDeviceUpdatable = false;
+ if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
+ const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name;
+ isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str());
+ }
+ if (isDeviceUpdatable && !includeUpdatableDrivers) {
+ continue;
+ }
if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
auto maybeDevice = aidl_hal::utils::getDevice(name);
if (maybeDevice.has_value()) {
auto device = std::move(maybeDevice).value();
CHECK(device != nullptr);
- devices->push_back(std::move(device));
+ devices->push_back(
+ {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable});
} else {
LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
<< ": " << maybeDevice.error().message;
@@ -102,11 +114,13 @@
}
}
-std::vector<nn::SharedDevice> getDevices() {
- std::vector<nn::SharedDevice> devices;
+} // namespace
+
+std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers) {
+ std::vector<SharedDeviceAndUpdatability> devices;
std::unordered_set<std::string> registeredDevices;
- getAidlDevices(&devices, ®isteredDevices);
+ getAidlDevices(&devices, ®isteredDevices, includeUpdatableDrivers);
getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
®isteredDevices);
@@ -120,13 +134,4 @@
return devices;
}
-} // namespace
} // namespace android::hardware::neuralnetworks::service
-
-namespace android::nn::hal {
-
-std::vector<nn::SharedDevice> getDevices() {
- return hardware::neuralnetworks::service::getDevices();
-}
-
-} // namespace android::nn::hal
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 9a85bee..c289448 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -43,17 +43,17 @@
void reportActualWorkDuration(in WorkDuration[] durations);
/**
- * Pause the session when the application is not in foreground and above
+ * Pause the session when the application is not allowed to send hint in framework.
*/
void pause();
/**
- * Resume the session when the application is not in foreground and above
+ * Resume the session when the application is allowed to send hint in framework.
*/
void resume();
/**
- * Close the session to release resources
+ * Close the session to release resources.
*/
void close();
}
diff --git a/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
index db2cfd8..c7ba96c 100644
--- a/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
+++ b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
@@ -239,12 +239,22 @@
ASSERT_OK(powerstats->getEnergyMeterInfo(&info));
}
-// Each channel must have a valid name and subsystem
+// Each channel must have a valid name
TEST_P(PowerStatsAidl, ValidateChannelNames) {
std::vector<Channel> channels;
ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
+
for (auto channel : channels) {
testNameValid(channel.name);
+ }
+}
+
+// Each channel must have a valid subsystem
+TEST_P(PowerStatsAidl, ValidateSubsystemNames) {
+ std::vector<Channel> channels;
+ ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
+
+ for (auto channel : channels) {
testNameValid(channel.subsystem);
}
}
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index a4e8811..e2d35d0 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -145,7 +145,6 @@
*
* Response function is IRadioResponse.setupDataCallResponse_1_6()
*
- * Note this API is the same as the 1.5
*/
oneway setupDataCall_1_6(int32_t serial, AccessNetwork accessNetwork,
DataProfileInfo dataProfileInfo, bool roamingAllowed,
@@ -177,7 +176,7 @@
* @param serial Serial number of request.
* @param message GsmSmsMessage as defined in types.hal
*
- * Response function is IRadioResponse.sendSMSExpectMoreResponse_1_6()
+ * Response function is IRadioResponse.sendSmsExpectMoreResponse_1_6()
*
* Note this API is the same as the 1.0
*
@@ -185,7 +184,7 @@
* fails. RadioError:SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332)
* and RadioError:GENERIC_FAILURE means no retry (i.e. error cause is 500)
*/
- oneway sendSMSExpectMore_1_6(int32_t serial, GsmSmsMessage message);
+ oneway sendSmsExpectMore_1_6(int32_t serial, GsmSmsMessage message);
/**
* Send a CDMA SMS message
@@ -267,7 +266,7 @@
* 2. Disable NR dual connectivity {NrDualConnectivityState:DISABLE}
* 3. Disable NR dual connectivity and force secondary cell to be released
* {NrDualConnectivityState:DISABLE_IMMEDIATE}
-
+ *
* Response callback is IRadioResponse.setNRDualConnectivityStateResponse()
*/
oneway setNrDualConnectivityState(int32_t serial,
@@ -372,7 +371,7 @@
*
* Response callback is IRadioResponse.getAllowedNetworkTypesBitmapResponse()
*/
- oneway getAllowedNetworkTypesBitmap(uint32_t serial);
+ oneway getAllowedNetworkTypesBitmap(int32_t serial);
/**
* Control data throttling at modem.
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index 9788345..05a7585 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -107,7 +107,7 @@
/**
* Indicates physical channel configurations.
*
- * An empty configs list indicates that the radio is in idle mode.
+ * An empty configs list shall be returned when the radio is in idle mode (i.e. RRC idle).
*
* @param type Type of radio indication
* @param configs Vector of PhysicalChannelConfigs
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index 33fe94f..3ee46c2 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -139,7 +139,7 @@
* RadioError:ACCESS_BARRED
* RadioError:BLOCKED_DUE_TO_CALL
*/
- oneway sendSMSExpectMoreResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
+ oneway sendSmsExpectMoreResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
/**
* @param info Response info struct containing response type, serial no. and error
@@ -232,6 +232,7 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_STATE
*/
oneway setNrDualConnectivityStateResponse(RadioResponseInfo info);
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 3fd31cc..1b697a9 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -55,9 +55,9 @@
struct QosBandwidth {
/** Maximum bit rate possible on the bearer */
- int32_t maxBitrateKbps;
+ uint32_t maxBitrateKbps;
/** Minimum bit rate that is guaranteed to be provided by the network */
- int32_t guaranteedBitrateKbps;
+ uint32_t guaranteedBitrateKbps;
};
/** LTE/EPS Quality of Service parameters as per 3gpp spec 24.301 sec 9.9.4.3. */
@@ -106,7 +106,7 @@
/**
* Next header protocol numbers defined by IANA, RFC 5237
*/
-enum QosProtocol : int32_t {
+enum QosProtocol : int8_t {
/** No protocol specified */
UNSPECIFIED = -1,
/** Transmission Control Protocol */
@@ -119,14 +119,14 @@
AH = 51,
};
-enum QosFilterDirection : int32_t {
+enum QosFilterDirection : int8_t {
DOWNLINK = 0,
UPLINK = 1,
BIDIRECTIONAL = 2,
};
/** Allowed port numbers */
-enum QosPortRange : int32_t {
+enum QosPortRange : uint16_t {
MIN = 20,
MAX = 65535
};
@@ -248,7 +248,7 @@
};
/** The allowed failure modes on an IWLAN handover failure. */
-enum HandoverFailureMode : int32_t {
+enum HandoverFailureMode : int8_t {
/**
* On data handover failure, fallback to the source data transport when the
* fail cause is due to a hand off preference change.
@@ -379,7 +379,7 @@
/**
* NR Dual connectivity state
*/
-enum NrDualConnectivityState: int32_t {
+enum NrDualConnectivityState: int8_t {
/**
* Enable NR dual connectivity. Enabled state does not mean dual connectivity
* is active. It means device is allowed to connect to both primary and secondary.
@@ -408,7 +408,7 @@
* the estimated maximum sustainable link bandwidth (as would be measured
* at the Upper PDCP or SNDCP SAP). If the DL Aggregate Maximum Bit Rate is known,
* this value shall not exceed the DL-AMBR for the Internet PDN connection.
- * This must be filled with -1 if network is not connected.
+ * This must be filled with 0 if network is not connected.
*/
uint32_t downlinkCapacityKbps;
@@ -418,7 +418,7 @@
* estimated maximum sustainable link bandwidth (as would be measured at the
* Upper PDCP or SNDCP SAP). If the UL Aggregate Maximum Bit Rate is known,
* this value shall not exceed the UL-AMBR for the Internet PDN connection.
- * This must be filled with -1 if network is not connected.
+ * This must be filled with 0 if network is not connected.
*/
uint32_t uplinkCapacityKbps;
@@ -427,7 +427,7 @@
* This bandwidth estimate shall be the estimated maximum sustainable link bandwidth
* (as would be measured at the Upper PDCP or SNDCP SAP). This is valid only
* in if device is connected to both primary and secodary in dual connected
- * mode. This must be filled with -1 if secondary is not connected or if
+ * mode. This must be filled with 0 if secondary is not connected or if
* modem does not support this feature.
*/
uint32_t secondaryDownlinkCapacityKbps;
@@ -437,13 +437,13 @@
* This bandwidth estimate shall be the estimated
* maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
* This is valid only in if device is connected to both primary and secodary in dual connected
- * mode.This must be filled with -1 if secondary is not connected or if modem
+ * mode.This must be filled with 0 if secondary is not connected or if modem
* does not support this feature.
*/
uint32_t secondaryUplinkCapacityKbps;
};
-enum DataThrottlingAction : int32_t {
+enum DataThrottlingAction : int8_t {
/* Clear all existing data throttling. */
NO_DATA_THROTTLING = 0,
@@ -581,9 +581,9 @@
*
* Reference: 3GPP TS 138.214 section 5.2.2.1.
*
- * Range [0, 15], INT_MAX means invalid/unreported.
+ * Range [0, 15], 0xFF means invalid/unreported.
*/
- vec<uint32_t> csiCqiReport;
+ vec<uint8_t> csiCqiReport;
};
/**
@@ -740,22 +740,19 @@
EutranRegistrationInfo eutranInfo;
- struct NgranRegistrationInfo {
- /**
- * Network capabilities for voice over PS services. This info is valid only on NR
- * network and must be present when the device is camped on NR. VopsInfo must be
- * empty when the device is not camped on NR.
- */
- NrVopsInfo nrVopsInfo;
- } ngranInfo;
+ /**
+ * Network capabilities for voice over PS services. This info is valid only on NR
+ * network and must be present when the device is camped on NR. VopsInfo must be
+ * empty when the device is not camped on NR.
+ */
+ NrVopsInfo ngranNrVopsInfo;
- struct GeranRegistrationInfo {
- /**
- * True if the dual transfer mode is supported.
- * Refer to 3GPP TS 44.108 section 3.4.25.3
- */
- bool dtmSupported;
- } geranInfo;
+ /**
+ * True if the dual transfer mode is supported.
+ * Refer to 3GPP TS 44.108 section 3.4.25.3
+ */
+ bool geranDtmSupported;
+
} accessTechnologySpecificInfo;
};
@@ -874,10 +871,10 @@
int32_t uplinkChannelNumber;
/** Downlink cell bandwidth, in kHz */
- int32_t cellBandwidthDownlink;
+ int32_t cellBandwidthDownlinkKhz;
/** Uplink cell bandwidth, in kHz */
- int32_t cellBandwidthUplink;
+ int32_t cellBandwidthUplinkKhz;
/**
* A list of data calls mapped to this physical channel. The context id must match the cid of
@@ -1059,7 +1056,7 @@
SscMode value;
};
-enum SliceStatus : int32_t {
+enum SliceStatus : int8_t {
UNKNOWN,
CONFIGURED, // Configured but not allowed or rejected yet
ALLOWED, // Allowed to be used
@@ -1072,7 +1069,7 @@
* Enum representing session and service continuity mode as defined in
* 3GPP TS 23.501.
*/
-enum SscMode : int32_t {
+enum SscMode : int8_t {
MODE_1 = 1,
MODE_2 = 2,
MODE_3 = 3,
@@ -1081,7 +1078,7 @@
/**
* Public key type from carrier certificate.
*/
-enum PublicKeyType : int32_t {
+enum PublicKeyType : int8_t {
EPDG = 1, // Key type to be used for ePDG
WLAN = 2, // Key type to be used for WLAN
};
@@ -1190,7 +1187,7 @@
* chunk of phonebook data, means this is a last indication with the left
* data.
*/
-enum PbReceivedStatus : int32_t {
+enum PbReceivedStatus : int8_t {
PB_RECEIVED_OK = 1,
PB_RECEIVED_ERROR = 2,
PB_RECEIVED_ABORT = 3,
diff --git a/radio/1.6/vts/functional/Android.bp b/radio/1.6/vts/functional/Android.bp
index 65b0dd0..2bc6af3 100644
--- a/radio/1.6/vts/functional/Android.bp
+++ b/radio/1.6/vts/functional/Android.bp
@@ -28,6 +28,7 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"radio_hidl_hal_api.cpp",
+ "radio_hidl_hal_misc.cpp",
"radio_hidl_hal_test.cpp",
"radio_response.cpp",
"radio_indication.cpp",
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 6cf4567..f09b74e 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -175,12 +175,17 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
} else {
- 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::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR}));
}
}
@@ -213,10 +218,10 @@
}
/*
- * Test IRadio_1_6.sendSMSExpectMore() for the response returned.
+ * Test IRadio_1_6.sendSmsExpectMore() for the response returned.
*/
-TEST_P(RadioHidlTest_v1_6, sendSMSExpectMore_1_6) {
- LOG(DEBUG) << "sendSMSExpectMore";
+TEST_P(RadioHidlTest_v1_6, sendSmsExpectMore_1_6) {
+ LOG(DEBUG) << "sendSmsExpectMore";
serial = GetRandomSerialNumber();
GsmSmsMessage msg;
msg.smscPdu = "";
@@ -236,7 +241,7 @@
::android::hardware::radio::V1_6::RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
- LOG(DEBUG) << "sendSMSExpectMore finished";
+ LOG(DEBUG) << "sendSmsExpectMore finished";
}
/*
@@ -378,7 +383,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -387,6 +392,7 @@
CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
::android::hardware::radio::V1_6::RadioError::NONE}));
}
}
@@ -403,7 +409,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -429,7 +435,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -449,7 +455,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -469,7 +475,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -488,7 +494,7 @@
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().modemReducedFeatureSet1) {
+ if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
{::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -750,7 +756,7 @@
/*
* Test IRadio.getSimPhonebookRecords() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_6, getSimPhonebookRecords) {
+TEST_P(RadioHidlTest_v1_6, getSimPhonebookRecords) {
serial = GetRandomSerialNumber();
radio_v1_6->getSimPhonebookRecords(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.6/vts/functional/radio_hidl_hal_misc.cpp
new file mode 100644
index 0000000..4222441
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_misc.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 <regex>
+
+#include <android-base/logging.h>
+#include <radio_hidl_hal_utils_v1_6.h>
+
+/*
+ * Test IRadio.getAvailableNetworks() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getAvailableNetworks) {
+ LOG(DEBUG) << "getAvailableNetworks";
+ serial = GetRandomSerialNumber();
+
+ radio_v1_6->getAvailableNetworks(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo_v1_0.serial);
+ ASSERT_TRUE(radioRsp_v1_6->rspInfo_v1_0.type == RadioResponseType::SOLICITED ||
+ radioRsp_v1_6->rspInfo_v1_0.type == RadioResponseType::SOLICITED_ACK_EXP);
+
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo_v1_0.error,
+ {::android::hardware::radio::V1_0::RadioError::NONE,
+ ::android::hardware::radio::V1_0::RadioError::CANCELLED,
+ ::android::hardware::radio::V1_0::RadioError::DEVICE_IN_USE,
+ ::android::hardware::radio::V1_0::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_0::RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ } else if (radioRsp_v1_6->rspInfo_v1_0.error ==
+ ::android::hardware::radio::V1_0::RadioError::NONE) {
+ static const std::regex kOperatorNumericRe("^[0-9]{5,6}$");
+ for (OperatorInfo info : radioRsp_v1_6->networkInfos) {
+ if (info.operatorNumeric != nullptr) {
+ ASSERT_TRUE(
+ std::regex_match(std::string(info.operatorNumeric), kOperatorNumericRe));
+ }
+ }
+ }
+
+ LOG(DEBUG) << "getAvailableNetworks finished";
+}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
index 6255f66..5d514a0 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
@@ -86,16 +86,14 @@
* disabled.
* <p/>
* Typical usage within VTS:
- * if (getRadioHalCapabilities().modemReducedFeatureSet) return;
+ * if (getRadioHalCapabilities()) return;
*/
-HalDeviceCapabilities RadioHidlTest_v1_6::getRadioHalCapabilities() {
+bool RadioHidlTest_v1_6::getRadioHalCapabilities() {
sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig_v1_3 =
::android::hardware::radio::config::V1_3::IRadioConfig::getService();
if (radioConfig_v1_3.get() == nullptr) {
// If v1_3 isn't present, the values are initialized to false
- HalDeviceCapabilities radioHalCapabilities;
- memset(&radioHalCapabilities, 0, sizeof(radioHalCapabilities));
- return radioHalCapabilities;
+ return false;
} else {
// Get radioHalDeviceCapabilities from the radio config
sp<RadioConfigResponse> radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
@@ -104,6 +102,6 @@
radioConfig_v1_3->getHalDeviceCapabilities(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- return radioConfigRsp->halDeviceCapabilities;
+ return radioConfigRsp->modemReducedFeatureSet1;
}
}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index 4fc17e5..3185f98 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -38,14 +38,12 @@
using namespace ::android::hardware::radio::V1_2;
using namespace ::android::hardware::radio::V1_1;
using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config::V1_3;
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::hardware::radio::config::V1_3::HalDeviceCapabilities;
#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
@@ -62,6 +60,7 @@
public:
hidl_vec<RadioBandMode> radioBandModes;
+ hidl_vec<OperatorInfo> networkInfos;
::android::hardware::radio::V1_0::RadioResponseInfo rspInfo_v1_0;
::android::hardware::radio::V1_6::RadioResponseInfo rspInfo;
@@ -762,7 +761,7 @@
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const SendSmsResult& sms);
- Return<void> sendSMSExpectMoreResponse_1_6(
+ Return<void> sendSmsExpectMoreResponse_1_6(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const SendSmsResult& sms);
@@ -1115,7 +1114,7 @@
public:
virtual void SetUp() override;
- HalDeviceCapabilities getRadioHalCapabilities();
+ bool getRadioHalCapabilities();
/* radio service handle */
sp<::android::hardware::radio::V1_6::IRadio> radio_v1_6;
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index 2b6d1bb..6e7b86f 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -274,8 +274,11 @@
}
Return<void> RadioResponse_v1_6::getAvailableNetworksResponse(
- const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
- const ::android::hardware::hidl_vec<OperatorInfo>& /*networkInfos*/) {
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<OperatorInfo>& networkInfos) {
+ rspInfo_v1_0 = info;
+ this->networkInfos = networkInfos;
+ parent_v1_6.notify(info.serial);
return Void();
}
@@ -1090,7 +1093,7 @@
return Void();
}
-Return<void> RadioResponse_v1_6::sendSMSExpectMoreResponse_1_6(
+Return<void> RadioResponse_v1_6::sendSmsExpectMoreResponse_1_6(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const SendSmsResult& sms) {
rspInfo = info;
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
index cc5944d..dc0d82c 100644
--- a/radio/config/1.3/Android.bp
+++ b/radio/config/1.3/Android.bp
@@ -13,7 +13,6 @@
name: "android.hardware.radio.config@1.3",
root: "android.hardware",
srcs: [
- "types.hal",
"IRadioConfig.hal",
"IRadioConfigResponse.hal",
],
diff --git a/radio/config/1.3/IRadioConfigResponse.hal b/radio/config/1.3/IRadioConfigResponse.hal
index 863754f..f6aee31 100644
--- a/radio/config/1.3/IRadioConfigResponse.hal
+++ b/radio/config/1.3/IRadioConfigResponse.hal
@@ -18,7 +18,6 @@
import android.hardware.radio@1.6::RadioResponseInfo;
import @1.2::IRadioConfigResponse;
-import HalDeviceCapabilities;
/**
* Interface declaring response functions to solicited radio config requests.
@@ -26,8 +25,20 @@
interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
/**
* @param info Response info struct containing response type, serial no. and error
- * @param capabilities Capabilities struct containing the capabilities of the
- * device related to the Radio HAL
+ * @param modemReducedFeatureSet1 True indicates that the modem does NOT support the following
+ * features.
+ * - Providing either
+ * android.hardware.radio@1.6::LinkCapacityEstimate:secondaryDownlinkCapacityKbps
+ * or android.hardware.radio@1.6::LinkCapacityEstimate:secondaryUplinkCapacityKbps
+ * when given from
+ * android.hardware.radio@1.6::RadioIndication:currentLinkCapacityEstimate
+ * - Calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState
+ * or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled
+ * - Requesting android.hardware.radio@1.6::IRadio.setDataThrottling()
+ * - Providing android.hardware.radio@1.6::SlicingConfig through
+ * android.hardware.radio@1.6::getSlicingConfig()
+ * - Providing android.hardware.radio@1.6::PhysicalChannelConfig through
+ * android.hardware.radio@1.6::IRadioIndication.currentPhysicalChannelConfigs_1_6()
*
* Valid errors returned:
* RadioError:NONE
@@ -35,5 +46,5 @@
* RadioError:INTERNAL_ERR
*/
oneway getHalDeviceCapabilitiesResponse(RadioResponseInfo info,
- HalDeviceCapabilities capabilities);
+ bool modemReducedFeatureSet1);
};
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
deleted file mode 100644
index 8667f0a..0000000
--- a/radio/config/1.3/types.hal
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.radio.config@1.3;
-
-/**
- * Contains the device capabilities with respect to the Radio HAL.
- */
-struct HalDeviceCapabilities {
- /**
- * True indicates that the modem does NOT support the following features:
- * <ul>
- * <li>Providing either
- * android.hardware.radio@1.6::LinkCapacityEstimate:secondaryDownlinkCapacityKbps
- * or android.hardware.radio@1.6::LinkCapacityEstimate:secondaryUplinkCapacityKbps
- * when given from android.hardware.radio@1.6::RadioIndication:currentLinkCapacityEstimate
- * </li>
- * <li> calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState
- * or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled
- * </li>
- * <li>Requesting android.hardware.radio@1.6::IRadio.setDataThrottling()
- * </li>
- * <li>Providing android.hardware.radio@1.6::SlicingConfig through
- * android.hardware.radio@1.6::getSlicingConfig()
- * </li>
- * </ul>
- */
- bool modemReducedFeatureSet1;
-};
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
index 50038eb..7235798 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -29,7 +29,6 @@
#include <android/hardware/radio/config/1.2/types.h>
#include <android/hardware/radio/config/1.3/IRadioConfig.h>
#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/types.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -48,7 +47,6 @@
using ::android::hardware::radio::config::V1_1::PhoneCapability;
using ::android::hardware::radio::config::V1_2::IRadioConfigIndication;
using ::android::hardware::radio::config::V1_2::SimSlotStatus;
-using ::android::hardware::radio::config::V1_3::HalDeviceCapabilities;
using ::android::hardware::radio::config::V1_3::IRadioConfig;
using ::android::hardware::radio::config::V1_3::IRadioConfigResponse;
using ::android::hardware::radio::V1_0::RadioResponseInfo;
@@ -65,7 +63,7 @@
public:
RadioResponseInfo rspInfo;
PhoneCapability phoneCap;
- HalDeviceCapabilities halDeviceCapabilities;
+ bool modemReducedFeatureSet1;
RadioConfigResponse(RadioResponseWaiter& parent);
virtual ~RadioConfigResponse() = default;
@@ -93,7 +91,7 @@
Return<void> getHalDeviceCapabilitiesResponse(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
- const HalDeviceCapabilities& halDeviceCapabilities);
+ bool modemReducedFeatureSet1);
};
/* Callback class for radio config indication */
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
index 5501ae2..6188733 100644
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -65,8 +65,8 @@
Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
- const ::android::hardware::radio::config::V1_3::HalDeviceCapabilities& capabilities) {
- halDeviceCapabilities = capabilities;
+ bool modemReducedFeatures) {
+ modemReducedFeatureSet1 = modemReducedFeatures;
parent.notify(info.serial);
return Void();
}
diff --git a/rebootescrow/aidl/default/Android.bp b/rebootescrow/aidl/default/Android.bp
index b9fb2a9..1f67a3e 100644
--- a/rebootescrow/aidl/default/Android.bp
+++ b/rebootescrow/aidl/default/Android.bp
@@ -87,7 +87,9 @@
],
static_libs: [
"libhadamardutils",
- "libgtest_prod",
+ ],
+ header_libs: [
+ "libgtest_prod_headers",
],
shared_libs: [
"liblog",
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 88c479c..f566462 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -35,6 +35,7 @@
/* @hide */
@VintfStability
interface IRemotelyProvisionedComponent {
+ android.hardware.security.keymint.RpcHardwareInfo getHardwareInfo();
byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData);
const int STATUS_FAILED = 1;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
new file mode 100644
index 0000000..06bce19
--- /dev/null
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.keymint;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable RpcHardwareInfo {
+ int versionNumber;
+ @utf8InCpp String rpcAuthorName;
+ int supportedEekCurve = 0;
+ const int CURVE_NONE = 0;
+ const int CURVE_P256 = 1;
+ const int CURVE_25519 = 2;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 1ae6762..b6285d9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -19,6 +19,7 @@
import android.hardware.security.keymint.DeviceInfo;
import android.hardware.security.keymint.MacedPublicKey;
import android.hardware.security.keymint.ProtectedData;
+import android.hardware.security.keymint.RpcHardwareInfo;
/**
* An IRemotelyProvisionedComponent is a secure-side component for which certificates can be
@@ -121,6 +122,12 @@
const int STATUS_INVALID_EEK = 5;
/**
+ * @return info which contains information about the underlying IRemotelyProvisionedComponent
+ * hardware, such as version number, component name, author name, and supported curve.
+ */
+ RpcHardwareInfo getHardwareInfo();
+
+ /**
* generateKeyPair generates a new ECDSA P-256 key pair that can be certified. Note that this
* method only generates ECDSA P-256 key pairs, but the interface can be extended to add methods
* for generating keys for other algorithms, if necessary.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index f3c5477..c2e21b6 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -60,29 +60,36 @@
* `attestationKey` parameter of `generateKey()`, `importKey()` or `importWrappedKey()`), and in
* the non-attestaion case, whether the key can self-sign.
*
- * 1. Attestation with factory key. If Tag::ATTESTATION_CHALLENGE is provided and the
- * `attestationKey` parameter on the generate/import call is null, the returned certificate
- * chain must contain an attestation certificate signed with a factory-provisioned
- * attestation key, and the full certificate chain for that factory-provisioned attestation
- * key.
+ * 1. Asymmetric key attestation with factory key. If Tag::ATTESTATION_CHALLENGE is provided
+ * and the `attestationKey` parameter on the generate/import call is null, the returned
+ * certificate chain must contain an attestation certificate signed with a factory-
+ * provisioned attestation key, and the full certificate chain for that factory-provisioned
+ * attestation key. Tag::ATTESTATION_APPLICATION_ID must also be provided when the
+ * ATTESTATION_CHALLENGE is provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be
+ * returned.
*
- * 2. Attestation with caller-provided key. If Tag::ATTESTATION_CHALLENGE is provided and the
- * `attestationKey` parameter on the generat/import call is non-null and contains the key
- * blob of a key with KeyPurpose::ATTEST_KEY, the returned certificate chain must contain
- * only an attestation certificate signed with the specified key. The caller must know the
- * certificate chain for the provided key.
+ * 2. Asymmetric key attestation with caller-provided key. If Tag::ATTESTATION_CHALLENGE is
+ * provided and the `attestationKey` parameter on the generat/import call is non-null and
+ * contains the key blob of a key with KeyPurpose::ATTEST_KEY, the returned certificate
+ * chain must contain only an attestation certificate signed with the specified key. The
+ * caller must know the certificate chain for the provided key. Tag::
+ * ATTESTATION_APPLICATION_ID must also be provided when the ATTESTATION_CHALLENGE is
+ * provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be returned.
*
- * 3. Non-attestation with signing key. If Tag::ATTESTATION_CHALLENGE is not provided and the
- * generated/imported key has KeyPurpose::SIGN, then the returned certificate chain must
- * contain only a single self-signed certificate with no attestation extension.
+ * 3. Asymmetric key non-attestation with signing key. If Tag::ATTESTATION_CHALLENGE is not
+ * provided and the generated/imported key has KeyPurpose::SIGN, then the returned
+ * certificate chain must contain only a single self-signed certificate with no attestation
+ * extension. Tag::ATTESTATION_APPLICATION_ID will be ignored if provided.
*
- * 4. Non-attestation with non-signing key. If TAG::ATTESTATION_CHALLENGE is not provided and
- * the generated/imported key does not have KeyPurpose::SIGN, then the returned certificate
- * chain must contain only a single certificate with an empty signature and no attestation
- * extension.
+ * 4. Asymmetric key non-attestation with non-signing key. If TAG::ATTESTATION_CHALLENGE is
+ * not provided and the generated/imported key does not have KeyPurpose::SIGN, then the
+ * returned certificate chain must contain only a single certificate with an empty signature
+ * and no attestation extension. Tag::ATTESTATION_APPLICATION_ID will be ignored if
+ * provided.
*
- * 5. Symmetric key. If the generated/imported key is symmetric, the certificate chain must be
- * empty.
+ * 5. Symmetric key. If the generated/imported key is symmetric, the certificate chain must
+ * return empty, any Tag::ATTESTATION_CHALLENGE or Tag::ATTESTATION_APPLICATION_ID inputs,
+ * if provided, are ignored.
*/
Certificate[] certificateChain;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
new file mode 100644
index 0000000..d297f87
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.keymint;
+
+/**
+ * RpcHardwareInfo is the hardware information returned by calling RemotelyProvisionedComponent
+ * getHardwareInfo()
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable RpcHardwareInfo {
+ const int CURVE_NONE = 0;
+ const int CURVE_P256 = 1;
+ const int CURVE_25519 = 2;
+
+ /**
+ * Implementation version of the remotely provisioned component hardware. The version number is
+ * implementation defined, and not necessarily globally meaningful. The version is used to
+ * distinguish between different versions of a given implementation.
+ */
+ int versionNumber;
+
+ /**
+ * rpcAuthorName is the name of the author of the IRemotelyProvisionedComponent implementation
+ * (organization name, not individual). This name is implementation defined, so it can be used
+ * to distinguish between different implementations from the same author.
+ */
+ @utf8InCpp String rpcAuthorName;
+
+ /**
+ * supportedEekCurve returns an int representing which curve is supported for validating
+ * signatures over the Endpoint Encryption Key certificate chain and for using the corresponding
+ * signed encryption key in ECDH. Only one curve should be supported, with preference for 25519
+ * if it's available. These values are defined as constants above.
+ *
+ * CURVE_NONE is made the default to help ensure that an implementor doesn't accidentally forget
+ * to provide the correct information here, as the VTS tests will check to make certain that
+ * a passing implementation does not provide CURVE_NONE.
+ */
+ int supportedEekCurve = CURVE_NONE;
+}
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index ebdc9b7..230534c 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -33,7 +33,6 @@
"libkeymint",
"liblog",
"libpuresoftkeymasterdevice",
- "libremote_provisioner",
"libutils",
],
srcs: [
@@ -51,28 +50,3 @@
vendor: true,
src: "android.hardware.hardware_keystore.xml",
}
-
-cc_library {
- name: "libremote_provisioner",
- vendor_available: true,
- static_libs: [
- "libkeymint_remote_prov_support",
- ],
- shared_libs: [
- "android.hardware.security.keymint-V1-ndk_platform",
- "libbinder_ndk",
- "libcppbor_external",
- "libcppcose",
- "libcrypto",
- "libkeymaster_portable",
- "libkeymint",
- "liblog",
- "libpuresoftkeymasterdevice",
- ],
- export_include_dirs: [
- ".",
- ],
- srcs: [
- "RemotelyProvisionedComponent.cpp",
- ],
-}
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
deleted file mode 100644
index 5b02729..0000000
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * 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 "RemotelyProvisionedComponent.h"
-
-#include <assert.h>
-#include <variant>
-
-#include <cppbor.h>
-#include <cppbor_parse.h>
-
-#include <KeyMintUtils.h>
-#include <cppcose/cppcose.h>
-#include <keymaster/keymaster_configuration.h>
-#include <remote_prov/remote_prov_utils.h>
-
-#include <openssl/bn.h>
-#include <openssl/ec.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-
-namespace aidl::android::hardware::security::keymint {
-
-using ::std::string;
-using ::std::tuple;
-using ::std::unique_ptr;
-using ::std::variant;
-using ::std::vector;
-using bytevec = ::std::vector<uint8_t>;
-
-using namespace cppcose;
-using namespace keymaster;
-
-namespace {
-
-// Hard-coded set of acceptable public keys that can act as roots of EEK chains.
-inline const vector<bytevec> kAuthorizedEekRoots = {
- // TODO(drysdale): replace this random value with real root pubkey(s).
- {0x5c, 0xea, 0x4b, 0xd2, 0x31, 0x27, 0x15, 0x5e, 0x62, 0x94, 0x70,
- 0x53, 0x94, 0x43, 0x0f, 0x9a, 0x89, 0xd5, 0xc5, 0x0f, 0x82, 0x9b,
- 0xcd, 0x10, 0xe0, 0x79, 0xef, 0xf3, 0xfa, 0x40, 0xeb, 0x0a},
-};
-
-constexpr auto STATUS_FAILED = RemotelyProvisionedComponent::STATUS_FAILED;
-constexpr auto STATUS_INVALID_EEK = RemotelyProvisionedComponent::STATUS_INVALID_EEK;
-constexpr auto STATUS_INVALID_MAC = RemotelyProvisionedComponent::STATUS_INVALID_MAC;
-constexpr uint32_t kAffinePointLength = 32;
-struct AStatusDeleter {
- void operator()(AStatus* p) { AStatus_delete(p); }
-};
-
-// TODO(swillden): Remove the dependency on AStatus stuff. The COSE lib should use something like
-// StatusOr, but it shouldn't depend on AStatus.
-class Status {
- public:
- Status() {}
- Status(int32_t errCode, const std::string& errMsg)
- : status_(AStatus_fromServiceSpecificErrorWithMessage(errCode, errMsg.c_str())) {}
- explicit Status(const std::string& errMsg)
- : status_(AStatus_fromServiceSpecificErrorWithMessage(STATUS_FAILED, errMsg.c_str())) {}
- Status(AStatus* status) : status_(status) {}
- Status(Status&&) = default;
- Status(const Status&) = delete;
-
- operator ::ndk::ScopedAStatus() && { return ndk::ScopedAStatus(status_.release()); }
-
- bool isOk() { return !status_; }
-
- // Don't call getMessage() unless isOk() returns false;
- const char* getMessage() const { return AStatus_getMessage(status_.get()); }
-
- private:
- std::unique_ptr<AStatus, AStatusDeleter> status_;
-};
-
-template <typename T>
-class StatusOr {
- public:
- StatusOr(AStatus* status) : status_(status) {}
- StatusOr(Status status) : status_(std::move(status)) {}
- StatusOr(T val) : value_(std::move(val)) {}
-
- bool isOk() { return status_.isOk(); }
-
- T* operator->() & {
- assert(isOk());
- return &value_.value();
- }
- T& operator*() & {
- assert(isOk());
- return value_.value();
- }
- T&& operator*() && {
- assert(isOk());
- return std::move(value_).value();
- }
-
- const char* getMessage() const {
- assert(!isOk());
- return status_.getMessage();
- }
-
- Status moveError() {
- assert(!isOk());
- return std::move(status_);
- }
-
- T moveValue() { return std::move(value_).value(); }
-
- private:
- Status status_;
- std::optional<T> value_;
-};
-
-StatusOr<std::pair<bytevec /* EEK pub */, bytevec /* EEK ID */>> validateAndExtractEekPubAndId(
- bool testMode, const bytevec& endpointEncryptionCertChain) {
- auto [item, newPos, errMsg] = cppbor::parse(endpointEncryptionCertChain);
-
- if (!item || !item->asArray()) {
- return Status("Error parsing EEK chain" + errMsg);
- }
-
- const cppbor::Array* certArr = item->asArray();
- bytevec lastPubKey;
- for (int i = 0; i < certArr->size(); ++i) {
- auto cosePubKey = verifyAndParseCoseSign1(testMode, certArr->get(i)->asArray(),
- std::move(lastPubKey), bytevec{} /* AAD */);
- if (!cosePubKey) {
- return Status(STATUS_INVALID_EEK,
- "Failed to validate EEK chain: " + cosePubKey.moveMessage());
- }
- lastPubKey = *std::move(cosePubKey);
-
- // In prod mode the first pubkey should match a well-known Google public key.
- if (!testMode && i == 0 &&
- std::find(kAuthorizedEekRoots.begin(), kAuthorizedEekRoots.end(), lastPubKey) ==
- kAuthorizedEekRoots.end()) {
- return Status(STATUS_INVALID_EEK, "Unrecognized root of EEK chain");
- }
- }
-
- auto eek = CoseKey::parseX25519(lastPubKey, true /* requireKid */);
- if (!eek) return Status(STATUS_INVALID_EEK, "Failed to get EEK: " + eek.moveMessage());
-
- return std::make_pair(eek->getBstrValue(CoseKey::PUBKEY_X).value(),
- eek->getBstrValue(CoseKey::KEY_ID).value());
-}
-
-StatusOr<bytevec /* pubkeys */> validateAndExtractPubkeys(bool testMode,
- const vector<MacedPublicKey>& keysToSign,
- const bytevec& macKey) {
- auto pubKeysToMac = cppbor::Array();
- for (auto& keyToSign : keysToSign) {
- auto [macedKeyItem, _, coseMacErrMsg] = cppbor::parse(keyToSign.macedKey);
- if (!macedKeyItem || !macedKeyItem->asArray() ||
- macedKeyItem->asArray()->size() != kCoseMac0EntryCount) {
- return Status("Invalid COSE_Mac0 structure");
- }
-
- auto protectedParms = macedKeyItem->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
- auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
- auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
- auto tag = macedKeyItem->asArray()->get(kCoseMac0Tag)->asBstr();
- if (!protectedParms || !unprotectedParms || !payload || !tag) {
- return Status("Invalid COSE_Mac0 contents");
- }
-
- auto [protectedMap, __, errMsg] = cppbor::parse(protectedParms);
- if (!protectedMap || !protectedMap->asMap()) {
- return Status("Invalid Mac0 protected: " + errMsg);
- }
- auto& algo = protectedMap->asMap()->get(ALGORITHM);
- if (!algo || !algo->asInt() || algo->asInt()->value() != HMAC_256) {
- return Status("Unsupported Mac0 algorithm");
- }
-
- auto pubKey = CoseKey::parse(payload->value(), EC2, ES256, P256);
- if (!pubKey) return Status(pubKey.moveMessage());
-
- bool testKey = static_cast<bool>(pubKey->getMap().get(CoseKey::TEST_KEY));
- if (testMode && !testKey) {
- return Status(BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST,
- "Production key in test request");
- } else if (!testMode && testKey) {
- return Status(BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST,
- "Test key in production request");
- }
-
- auto macTag = generateCoseMac0Mac(macKey, {} /* external_aad */, payload->value());
- if (!macTag) return Status(STATUS_INVALID_MAC, macTag.moveMessage());
- if (macTag->size() != tag->value().size() ||
- CRYPTO_memcmp(macTag->data(), tag->value().data(), macTag->size()) != 0) {
- return Status(STATUS_INVALID_MAC, "MAC tag mismatch");
- }
-
- pubKeysToMac.add(pubKey->moveMap());
- }
-
- return pubKeysToMac.encode();
-}
-
-StatusOr<std::pair<bytevec, bytevec>> buildCosePublicKeyFromKmCert(
- const keymaster_blob_t* km_cert) {
- if (km_cert == nullptr) {
- return Status(STATUS_FAILED, "km_cert is a nullptr");
- }
- const uint8_t* temp = km_cert->data;
- X509* cert = d2i_X509(NULL, &temp, km_cert->data_length);
- if (cert == nullptr) {
- return Status(STATUS_FAILED, "d2i_X509 returned null when attempting to get the cert.");
- }
- EVP_PKEY* pubKey = X509_get_pubkey(cert);
- if (pubKey == nullptr) {
- return Status(STATUS_FAILED, "Boringssl failed to get the public key from the cert");
- }
- EC_KEY* ecKey = EVP_PKEY_get0_EC_KEY(pubKey);
- if (ecKey == nullptr) {
- return Status(STATUS_FAILED,
- "The key in the certificate returned from GenerateKey is not "
- "an EC key.");
- }
- const EC_POINT* jacobian_coords = EC_KEY_get0_public_key(ecKey);
- BIGNUM x;
- BIGNUM y;
- BN_CTX* ctx = BN_CTX_new();
- if (ctx == nullptr) {
- return Status(STATUS_FAILED, "Memory allocation failure for BN_CTX");
- }
- if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ecKey), jacobian_coords, &x, &y,
- ctx)) {
- return Status(STATUS_FAILED, "Failed to get affine coordinates");
- }
- bytevec x_bytestring(kAffinePointLength);
- bytevec y_bytestring(kAffinePointLength);
- if (BN_bn2binpad(&x, x_bytestring.data(), kAffinePointLength) != kAffinePointLength) {
- return Status(STATUS_FAILED, "Wrote incorrect number of bytes for x coordinate");
- }
- if (BN_bn2binpad(&y, y_bytestring.data(), kAffinePointLength) != kAffinePointLength) {
- return Status(STATUS_FAILED, "Wrote incorrect number of bytes for y coordinate");
- }
- BN_CTX_free(ctx);
- return std::make_pair(x_bytestring, y_bytestring);
-}
-
-cppbor::Array buildCertReqRecipients(const bytevec& pubkey, const bytevec& kid) {
- return cppbor::Array() // Array of recipients
- .add(cppbor::Array() // Recipient
- .add(cppbor::Map() // Protected
- .add(ALGORITHM, ECDH_ES_HKDF_256)
- .canonicalize()
- .encode())
- .add(cppbor::Map() // Unprotected
- .add(COSE_KEY, cppbor::Map()
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::CURVE, cppcose::X25519)
- .add(CoseKey::PUBKEY_X, pubkey)
- .canonicalize())
- .add(KEY_ID, kid)
- .canonicalize())
- .add(cppbor::Null())); // No ciphertext
-}
-
-static keymaster_key_param_t kKeyMintEcdsaP256Params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC), Authorization(TAG_KEY_SIZE, 256),
- Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
- Authorization(TAG_EC_CURVE, KM_EC_CURVE_P_256), Authorization(TAG_NO_AUTH_REQUIRED),
- // The certificate generated by KM will be discarded, these values don't matter.
- Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0), Authorization(TAG_CERTIFICATE_NOT_AFTER, 0)};
-
-} // namespace
-
-RemotelyProvisionedComponent::RemotelyProvisionedComponent(
- std::shared_ptr<keymint::AndroidKeyMintDevice> keymint) {
- std::tie(devicePrivKey_, bcc_) = generateBcc();
- impl_ = keymint->getKeymasterImpl();
-}
-
-RemotelyProvisionedComponent::~RemotelyProvisionedComponent() {}
-
-ScopedAStatus RemotelyProvisionedComponent::generateEcdsaP256KeyPair(bool testMode,
- MacedPublicKey* macedPublicKey,
- bytevec* privateKeyHandle) {
- // TODO(jbires): The following should move from ->GenerateKey to ->GenerateRKPKey and everything
- // after the GenerateKey call should basically be moved into that new function call
- // as well once the issue with libcppbor in system/keymaster is sorted out
- GenerateKeyRequest request(impl_->message_version());
- request.key_description.Reinitialize(kKeyMintEcdsaP256Params,
- array_length(kKeyMintEcdsaP256Params));
- GenerateKeyResponse response(impl_->message_version());
- impl_->GenerateKey(request, &response);
- if (response.error != KM_ERROR_OK) {
- return km_utils::kmError2ScopedAStatus(response.error);
- }
-
- if (response.certificate_chain.entry_count != 1) {
- // Error: Need the single non-signed certificate with the public key in it.
- return Status(STATUS_FAILED,
- "Expected to receive a single certificate from GenerateKey. Instead got: " +
- std::to_string(response.certificate_chain.entry_count));
- }
- auto affineCoords = buildCosePublicKeyFromKmCert(response.certificate_chain.begin());
- if (!affineCoords.isOk()) return affineCoords.moveError();
- cppbor::Map cosePublicKeyMap = cppbor::Map()
- .add(CoseKey::KEY_TYPE, EC2)
- .add(CoseKey::ALGORITHM, ES256)
- .add(CoseKey::CURVE, cppcose::P256)
- .add(CoseKey::PUBKEY_X, affineCoords->first)
- .add(CoseKey::PUBKEY_Y, affineCoords->second);
- if (testMode) {
- cosePublicKeyMap.add(CoseKey::TEST_KEY, cppbor::Null());
- }
-
- bytevec cosePublicKey = cosePublicKeyMap.canonicalize().encode();
-
- auto macedKey = constructCoseMac0(testMode ? remote_prov::kTestMacKey : macKey_,
- {} /* externalAad */, cosePublicKey);
- if (!macedKey) return Status(macedKey.moveMessage());
-
- macedPublicKey->macedKey = macedKey->encode();
- *privateKeyHandle = km_utils::kmBlob2vector(response.key_blob);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest(
- bool testMode, const vector<MacedPublicKey>& keysToSign,
- const bytevec& endpointEncCertChain, const bytevec& challenge, DeviceInfo* deviceInfo,
- ProtectedData* protectedData, bytevec* keysToSignMac) {
- auto pubKeysToSign = validateAndExtractPubkeys(testMode, keysToSign,
- testMode ? remote_prov::kTestMacKey : macKey_);
- if (!pubKeysToSign.isOk()) return pubKeysToSign.moveError();
-
- bytevec ephemeralMacKey = remote_prov::randomBytes(SHA256_DIGEST_LENGTH);
-
- auto pubKeysToSignMac = generateCoseMac0Mac(ephemeralMacKey, bytevec{}, *pubKeysToSign);
- if (!pubKeysToSignMac) return Status(pubKeysToSignMac.moveMessage());
- *keysToSignMac = *std::move(pubKeysToSignMac);
-
- bytevec devicePrivKey;
- cppbor::Array bcc;
- if (testMode) {
- std::tie(devicePrivKey, bcc) = generateBcc();
- } else {
- devicePrivKey = devicePrivKey_;
- bcc = bcc_.clone();
- }
-
- std::unique_ptr<cppbor::Map> deviceInfoMap = createDeviceInfo();
- deviceInfo->deviceInfo = deviceInfoMap->encode();
- auto signedMac = constructCoseSign1(devicePrivKey /* Signing key */, //
- ephemeralMacKey /* Payload */,
- cppbor::Array() /* AAD */
- .add(challenge)
- .add(std::move(deviceInfoMap))
- .encode());
- if (!signedMac) return Status(signedMac.moveMessage());
-
- bytevec ephemeralPrivKey(X25519_PRIVATE_KEY_LEN);
- bytevec ephemeralPubKey(X25519_PUBLIC_VALUE_LEN);
- X25519_keypair(ephemeralPubKey.data(), ephemeralPrivKey.data());
-
- auto eek = validateAndExtractEekPubAndId(testMode, endpointEncCertChain);
- if (!eek.isOk()) return eek.moveError();
-
- auto sessionKey = x25519_HKDF_DeriveKey(ephemeralPubKey, ephemeralPrivKey, eek->first,
- true /* senderIsA */);
- if (!sessionKey) return Status(sessionKey.moveMessage());
-
- auto coseEncrypted =
- constructCoseEncrypt(*sessionKey, remote_prov::randomBytes(kAesGcmNonceLength),
- cppbor::Array() // payload
- .add(signedMac.moveValue())
- .add(std::move(bcc))
- .encode(),
- {}, // aad
- buildCertReqRecipients(ephemeralPubKey, eek->second));
-
- if (!coseEncrypted) return Status(coseEncrypted.moveMessage());
- protectedData->protectedData = coseEncrypted->encode();
-
- return ScopedAStatus::ok();
-}
-
-bytevec RemotelyProvisionedComponent::deriveBytesFromHbk(const string& context,
- size_t numBytes) const {
- bytevec fakeHbk(32, 0);
- bytevec result(numBytes);
-
- // TODO(swillden): Figure out if HKDF can fail. It doesn't seem like it should be able to,
- // but the function does return an error code.
- HKDF(result.data(), numBytes, //
- EVP_sha256(), //
- fakeHbk.data(), fakeHbk.size(), //
- nullptr /* salt */, 0 /* salt len */, //
- reinterpret_cast<const uint8_t*>(context.data()), context.size());
-
- return result;
-}
-
-std::unique_ptr<cppbor::Map> RemotelyProvisionedComponent::createDeviceInfo() const {
- auto result = std::make_unique<cppbor::Map>(cppbor::Map());
-
- // The following placeholders show how the DeviceInfo map would be populated.
- // result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google"));
- // result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google"));
- // result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake"));
- // result->add(cppbor::Tstr("model"), cppbor::Tstr("Imaginary"));
- // result->add(cppbor::Tstr("board"), cppbor::Tstr("Chess"));
- // result->add(cppbor::Tstr("vb_state"), cppbor::Tstr("orange"));
- // result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr("unlocked"));
- // result->add(cppbor::Tstr("os_version"), cppbor::Tstr("SC"));
- // result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(20210331));
- // result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(20210331));
- // result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(20210331));
-
- result->canonicalize();
- return result;
-}
-
-std::pair<bytevec /* privKey */, cppbor::Array /* BCC */>
-RemotelyProvisionedComponent::generateBcc() {
- bytevec privKey(ED25519_PRIVATE_KEY_LEN);
- bytevec pubKey(ED25519_PUBLIC_KEY_LEN);
-
- ED25519_keypair(pubKey.data(), privKey.data());
-
- auto coseKey = cppbor::Map()
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::ALGORITHM, EDDSA)
- .add(CoseKey::CURVE, ED25519)
- .add(CoseKey::KEY_OPS, VERIFY)
- .add(CoseKey::PUBKEY_X, pubKey)
- .canonicalize()
- .encode();
- auto sign1Payload = cppbor::Map()
- .add(1 /* Issuer */, "Issuer")
- .add(2 /* Subject */, "Subject")
- .add(-4670552 /* Subject Pub Key */, coseKey)
- .add(-4670553 /* Key Usage (little-endian order) */,
- std::vector<uint8_t>{0x20} /* keyCertSign = 1<<5 */)
- .canonicalize()
- .encode();
- auto coseSign1 = constructCoseSign1(privKey, /* signing key */
- cppbor::Map(), /* extra protected */
- sign1Payload, {} /* AAD */);
- assert(coseSign1);
-
- return {privKey, cppbor::Array().add(coseKey).add(coseSign1.moveValue())};
-}
-
-} // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.h b/security/keymint/aidl/default/RemotelyProvisionedComponent.h
deleted file mode 100644
index 8185e26..0000000
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <AndroidKeyMintDevice.h>
-#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.h>
-#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
-#include <cppbor.h>
-#include <keymaster/UniquePtr.h>
-#include <keymaster/android_keymaster.h>
-
-namespace aidl::android::hardware::security::keymint {
-
-using ::ndk::ScopedAStatus;
-
-class RemotelyProvisionedComponent : public BnRemotelyProvisionedComponent {
- public:
- explicit RemotelyProvisionedComponent(std::shared_ptr<keymint::AndroidKeyMintDevice> keymint);
- virtual ~RemotelyProvisionedComponent();
-
- ScopedAStatus generateEcdsaP256KeyPair(bool testMode, MacedPublicKey* macedPublicKey,
- std::vector<uint8_t>* privateKeyHandle) override;
-
- ScopedAStatus generateCertificateRequest(bool testMode,
- const std::vector<MacedPublicKey>& keysToSign,
- const std::vector<uint8_t>& endpointEncCertChain,
- const std::vector<uint8_t>& challenge,
- DeviceInfo* deviceInfo, ProtectedData* protectedData,
- std::vector<uint8_t>* keysToSignMac) override;
-
- private:
- // TODO(swillden): Move these into an appropriate Context class.
- std::vector<uint8_t> deriveBytesFromHbk(const std::string& context, size_t numBytes) const;
- std::unique_ptr<cppbor::Map> createDeviceInfo() const;
- std::pair<std::vector<uint8_t>, cppbor::Array> generateBcc();
-
- std::vector<uint8_t> macKey_ = deriveBytesFromHbk("Key to MAC public keys", 32);
- std::vector<uint8_t> devicePrivKey_;
- cppbor::Array bcc_;
- std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
-};
-
-} // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp
index bcebbaf..8092e34 100644
--- a/security/keymint/aidl/default/service.cpp
+++ b/security/keymint/aidl/default/service.cpp
@@ -21,14 +21,13 @@
#include <android/binder_process.h>
#include <AndroidKeyMintDevice.h>
+#include <AndroidRemotelyProvisionedComponentDevice.h>
#include <AndroidSecureClock.h>
#include <AndroidSharedSecret.h>
#include <keymaster/soft_keymaster_logger.h>
-#include "RemotelyProvisionedComponent.h"
-
using aidl::android::hardware::security::keymint::AndroidKeyMintDevice;
-using aidl::android::hardware::security::keymint::RemotelyProvisionedComponent;
+using aidl::android::hardware::security::keymint::AndroidRemotelyProvisionedComponentDevice;
using aidl::android::hardware::security::keymint::SecurityLevel;
using aidl::android::hardware::security::secureclock::AndroidSecureClock;
using aidl::android::hardware::security::sharedsecret::AndroidSharedSecret;
@@ -56,7 +55,7 @@
// Add Shared Secret Service
addService<AndroidSharedSecret>(keyMint);
// Add Remotely Provisioned Component Service
- addService<RemotelyProvisionedComponent>(keyMint);
+ addService<AndroidRemotelyProvisionedComponentDevice>(keyMint);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index c1affa6..d5c45e2 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -31,6 +31,7 @@
],
srcs: [
"AttestKeyTest.cpp",
+ "DeviceUniqueAttestationTest.cpp",
"KeyMintTest.cpp",
],
shared_libs: [
@@ -43,6 +44,8 @@
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
"libcppbor_external",
+ "libcppcose_rkp",
+ "libkeymint_remote_prov_support",
"libkeymint_vts_test_utils",
],
test_suites: [
@@ -73,6 +76,9 @@
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
"libcppbor_external",
+ "libcppcose_rkp",
+ "libgmock_ndk",
+ "libkeymint_remote_prov_support",
],
}
@@ -87,21 +93,20 @@
],
shared_libs: [
"libbinder_ndk",
- "libcppbor_external",
"libcrypto",
- "libkeymaster_portable",
- "libpuresoftkeymasterdevice",
],
static_libs: [
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
- "libcppcose",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libgmock_ndk",
+ "libkeymaster_portable",
"libkeymint",
"libkeymint_support",
"libkeymint_remote_prov_support",
"libkeymint_vts_test_utils",
- "libremote_provisioner",
+ "libpuresoftkeymasterdevice",
],
test_suites: [
"general-tests",
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
new file mode 100644
index 0000000..7009c6e
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "keymint_1_attest_key_test"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <keymint_support/key_param_output.h>
+#include <keymint_support/openssl_utils.h>
+
+#include "KeyMintAidlTestBase.h"
+
+namespace aidl::android::hardware::security::keymint::test {
+
+class DeviceUniqueAttestationTest : public KeyMintAidlTestBase {
+ protected:
+ void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob,
+ const vector<KeyCharacteristics>& key_characteristics,
+ const AuthorizationSet& hw_enforced, int key_size) {
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ if (KeyMintAidlTestBase::dump_Attestations) {
+ std::cout << bin2hex(cert_chain_[0].encodedCertificate) << std::endl;
+ }
+
+ ASSERT_GT(key_blob.size(), 0U);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) << "Key size missing";
+
+ 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,
+ SecLevel(), cert_chain_[0].encodedCertificate));
+ }
+};
+
+/*
+ * DeviceUniqueAttestationTest.RsaNonStrongBoxUnimplemented
+ *
+ * Verifies that non strongbox implementations do not implement Rsa device unique
+ * attestation.
+ */
+TEST_P(DeviceUniqueAttestationTest, RsaNonStrongBoxUnimplemented) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ // Check RSA implementation
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
+ &key_blob, &key_characteristics);
+
+ ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_TAG);
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaNonStrongBoxUnimplemented
+ *
+ * Verifies that non strongbox implementations do not implement Ecdsa device unique
+ * attestation.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaNonStrongBoxUnimplemented) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ // Check Ecdsa implementation
+ auto result = GenerateKey(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),
+ &key_blob, &key_characteristics);
+
+ ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_TAG);
+}
+
+/*
+ * DeviceUniqueAttestationTest.RsaDeviceUniqueAttestation
+ *
+ * Verifies that strongbox implementations of Rsa implements device unique
+ * attestation correctly, if implemented.
+ */
+TEST_P(DeviceUniqueAttestationTest, RsaDeviceUniqueAttestation) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ int key_size = 2048;
+
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
+ &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);
+
+ 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());
+
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestation
+ *
+ * Verifies that strongbox implementations of Rsa implements device unique
+ * attestation correctly, if implemented.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ int key_size = 256;
+
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
+ &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);
+
+ 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());
+
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(DeviceUniqueAttestationTest);
+
+} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index ce6f67a..59cb57b 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -22,9 +22,13 @@
#include <android-base/logging.h>
#include <android/binder_manager.h>
+#include <cppbor_parse.h>
#include <cutils/properties.h>
+#include <gmock/gmock.h>
#include <openssl/mem.h>
+#include <remote_prov/remote_prov_utils.h>
+#include <keymaster/cppcose/cppcose.h>
#include <keymint_support/attestation_record.h>
#include <keymint_support/key_param_output.h>
#include <keymint_support/keymint_utils.h>
@@ -32,6 +36,7 @@
namespace aidl::android::hardware::security::keymint {
+using namespace cppcose;
using namespace std::literals::chrono_literals;
using std::endl;
using std::optional;
@@ -39,6 +44,7 @@
using ::testing::AssertionFailure;
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;
+using ::testing::MatchesRegex;
::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
if (set.size() == 0)
@@ -877,16 +883,20 @@
if (error != ErrorCode::OK) return false;
EXPECT_GE(att_attestation_version, 3U);
+ vector<uint8_t> appId(app_id.begin(), app_id.end());
- expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID,
- vector<uint8_t>(app_id.begin(), app_id.end()));
+ // check challenge and app id only if we expects a non-fake certificate
+ if (challenge.length() > 0) {
+ EXPECT_EQ(challenge.length(), att_challenge.size());
+ EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
+
+ expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
+ }
EXPECT_GE(att_keymaster_version, 4U);
EXPECT_EQ(security_level, att_keymaster_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
- EXPECT_EQ(challenge.length(), att_challenge.size());
- EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
char property_value[PROPERTY_VALUE_MAX] = {};
// TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
@@ -897,7 +907,7 @@
if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
std::string date =
- std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::dateTime>());
+ std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
// strptime seems to require delimiters, but the tag value will
// be YYYYMMDD
date.insert(6, "-");
@@ -1118,6 +1128,121 @@
return retval;
}
+namespace {
+
+void check_cose_key(const vector<uint8_t>& data, bool testMode) {
+ auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
+ ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
+
+ // The following check assumes that canonical CBOR encoding is used for the COSE_Key.
+ if (testMode) {
+ EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
+ MatchesRegex("{\n"
+ " 1 : 2,\n" // kty: EC2
+ " 3 : -7,\n" // alg: ES256
+ " -1 : 1,\n" // EC id: P256
+ // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+ // sequence of 32 hexadecimal bytes, enclosed in braces and
+ // separated by commas. In this case, some Ed25519 public key.
+ " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
+ " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
+ " -70000 : null,\n" // test marker
+ "}"));
+ } else {
+ EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
+ MatchesRegex("{\n"
+ " 1 : 2,\n" // kty: EC2
+ " 3 : -7,\n" // alg: ES256
+ " -1 : 1,\n" // EC id: P256
+ // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+ // sequence of 32 hexadecimal bytes, enclosed in braces and
+ // separated by commas. In this case, some Ed25519 public key.
+ " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
+ " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
+ "}"));
+ }
+}
+
+} // namespace
+
+void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
+ vector<uint8_t>* payload_value) {
+ auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
+ ASSERT_TRUE(coseMac0) << "COSE Mac0 parse failed " << mac0ParseErr;
+
+ ASSERT_NE(coseMac0->asArray(), nullptr);
+ ASSERT_EQ(coseMac0->asArray()->size(), kCoseMac0EntryCount);
+
+ auto protParms = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
+ ASSERT_NE(protParms, nullptr);
+
+ // Header label:value of 'alg': HMAC-256
+ ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n 1 : 5,\n}");
+
+ auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
+ ASSERT_NE(unprotParms, nullptr);
+ ASSERT_EQ(unprotParms->size(), 0);
+
+ // The payload is a bstr holding an encoded COSE_Key
+ auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
+ ASSERT_NE(payload, nullptr);
+ check_cose_key(payload->value(), testMode);
+
+ auto coseMac0Tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
+ ASSERT_TRUE(coseMac0Tag);
+ auto extractedTag = coseMac0Tag->value();
+ EXPECT_EQ(extractedTag.size(), 32U);
+
+ // Compare with tag generated with kTestMacKey. Should only match in test mode
+ auto testTag = cppcose::generateCoseMac0Mac(remote_prov::kTestMacKey, {} /* external_aad */,
+ payload->value());
+ ASSERT_TRUE(testTag) << "Tag calculation failed: " << testTag.message();
+
+ if (testMode) {
+ EXPECT_EQ(*testTag, extractedTag);
+ } else {
+ EXPECT_NE(*testTag, extractedTag);
+ }
+ if (payload_value != nullptr) {
+ *payload_value = payload->value();
+ }
+}
+
+void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey) {
+ // Extract x and y affine coordinates from the encoded Cose_Key.
+ auto [parsedPayload, __, payloadParseErr] = cppbor::parse(coseKeyData);
+ ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
+ auto coseKey = parsedPayload->asMap();
+ const std::unique_ptr<cppbor::Item>& xItem = coseKey->get(cppcose::CoseKey::PUBKEY_X);
+ ASSERT_NE(xItem->asBstr(), nullptr);
+ vector<uint8_t> x = xItem->asBstr()->value();
+ const std::unique_ptr<cppbor::Item>& yItem = coseKey->get(cppcose::CoseKey::PUBKEY_Y);
+ ASSERT_NE(yItem->asBstr(), nullptr);
+ vector<uint8_t> y = yItem->asBstr()->value();
+
+ // Concatenate: 0x04 (uncompressed form marker) | x | y
+ vector<uint8_t> pubKeyData{0x04};
+ pubKeyData.insert(pubKeyData.end(), x.begin(), x.end());
+ pubKeyData.insert(pubKeyData.end(), y.begin(), y.end());
+
+ EC_KEY_Ptr ecKey = EC_KEY_Ptr(EC_KEY_new());
+ ASSERT_NE(ecKey, nullptr);
+ EC_GROUP_Ptr group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ ASSERT_NE(group, nullptr);
+ ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
+ EC_POINT_Ptr point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+ ASSERT_NE(point, nullptr);
+ ASSERT_EQ(EC_POINT_oct2point(group.get(), point.get(), pubKeyData.data(), pubKeyData.size(),
+ nullptr),
+ 1);
+ ASSERT_EQ(EC_KEY_set_public_key(ecKey.get(), point.get()), 1);
+
+ EVP_PKEY_Ptr pubKey = EVP_PKEY_Ptr(EVP_PKEY_new());
+ ASSERT_NE(pubKey, nullptr);
+ EVP_PKEY_assign_EC_KEY(pubKey.get(), ecKey.release());
+ *signingKey = std::move(pubKey);
+}
+
} // namespace test
} // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 4d97ea9..da174ce 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -25,6 +25,7 @@
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
#include <keymint_support/authorization_set.h>
#include <keymint_support/openssl_utils.h>
@@ -277,6 +278,10 @@
string bin2hex(const vector<uint8_t>& data);
X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
vector<uint8_t> make_name_from_str(const string& name);
+void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
+ vector<uint8_t>* payload_value);
+void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
+
AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 7ecfa37..09cdab1 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -27,6 +27,9 @@
#include <cutils/properties.h>
+#include <android/binder_manager.h>
+
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/KeyFormat.h>
#include <keymint_support/key_param_output.h>
@@ -134,6 +137,54 @@
"d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
"3492d6");
+/*
+ * DER-encoded PKCS#8 format RSA key. Generated using:
+ *
+ * openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -outform der | hexdump -e '30/1 "%02X" "\n"'
+ */
+string rsa_2048_key =
+ hex2str("308204BD020100300D06092A864886F70D0101010500048204A7308204A3"
+ "0201000282010100BEBC342B56D443B1299F9A6A7056E80A897E318476A5"
+ "A18029E63B2ED739A61791D339F58DC763D9D14911F2EDEC383DEE11F631"
+ "9B44510E7A3ECD9B79B97382E49500ACF8117DC89CAF0E621F77756554A2"
+ "FD4664BFE7AB8B59AB48340DBFA27B93B5A81F6ECDEB02D0759307128DF3"
+ "E3BAD4055C8B840216DFAA5700670E6C5126F0962FCB70FF308F25049164"
+ "CCF76CC2DA66A7DD9A81A714C2809D69186133D29D84568E892B6FFBF319"
+ "9BDB14383EE224407F190358F111A949552ABA6714227D1BD7F6B20DD0CB"
+ "88F9467B719339F33BFF35B3870B3F62204E4286B0948EA348B524544B5F"
+ "9838F29EE643B079EEF8A713B220D7806924CDF7295070C5020301000102"
+ "82010069F377F35F2F584EF075353CCD1CA99738DB3DBC7C7FF35F9366CE"
+ "176DFD1B135AB10030344ABF5FBECF1D4659FDEF1C0FC430834BE1BE3911"
+ "951377BB3D563A2EA9CA8F4AD9C48A8CE6FD516A735C662686C7B4B3C09A"
+ "7B8354133E6F93F790D59EAEB92E84C9A4339302CCE28FDF04CCCAFA7DE3"
+ "F3A827D4F6F7D38E68B0EC6AB706645BF074A4E4090D06FB163124365FD5"
+ "EE7A20D350E9958CC30D91326E1B292E9EF5DB408EC42DAF737D20149704"
+ "D0A678A0FB5B5446863B099228A352D604BA8091A164D01D5AB05397C71E"
+ "AD20BE2A08FC528FE442817809C787FEE4AB97F97B9130D022153EDC6EB6"
+ "CBE7B0F8E3473F2E901209B5DB10F93604DB0102818100E83C0998214941"
+ "EA4F9293F1B77E2E99E6CF305FAF358238E126124FEAF2EB9724B2EA7B78"
+ "E6032343821A80E55D1D88FB12D220C3F41A56142FEC85796D1917F1E8C7"
+ "74F142B67D3D6E7B7E6B4383E94DB5929089DBB346D5BDAB40CC2D96EE04"
+ "09475E175C63BF78CFD744136740838127EA723FF3FE7FA368C1311B4A4E"
+ "0502818100D240FCC0F5D7715CDE21CB2DC86EA146132EA3B06F61FF2AF5"
+ "4BF38473F59DADCCE32B5F4CC32DD0BA6F509347B4B5B1B58C39F95E4798"
+ "CCBB43E83D0119ACF532F359CA743C85199F0286610E200997D731291717"
+ "9AC9B67558773212EC961E8BCE7A3CC809BC5486A96E4B0E6AF394D94E06"
+ "6A0900B7B70E82A44FB30053C102818100AD15DA1CBD6A492B66851BA8C3"
+ "16D38AB700E2CFDDD926A658003513C54BAA152B30021D667D20078F500F"
+ "8AD3E7F3945D74A891ED1A28EAD0FEEAEC8C14A8E834CF46A13D1378C99D"
+ "18940823CFDD27EC5810D59339E0C34198AC638E09C87CBB1B634A9864AE"
+ "9F4D5EB2D53514F67B4CAEC048C8AB849A02E397618F3271350281801FA2"
+ "C1A5331880A92D8F3E281C617108BF38244F16E352E69ED417C7153F9EC3"
+ "18F211839C643DCF8B4DD67CE2AC312E95178D5D952F06B1BF779F491692"
+ "4B70F582A23F11304E02A5E7565AE22A35E74FECC8B6FDC93F92A1A37703"
+ "E4CF0E63783BD02EB716A7ECBBFA606B10B74D01579522E7EF84D91FC522"
+ "292108D902C1028180796FE3825F9DCC85DF22D58690065D93898ACD65C0"
+ "87BEA8DA3A63BF4549B795E2CD0E3BE08CDEBD9FCF1720D9CDC5070D74F4"
+ "0DED8E1102C52152A31B6165F83A6722AECFCC35A493D7634664B888A08D"
+ "3EB034F12EA28BFEE346E205D334827F778B16ED40872BD29FCB36536B6E"
+ "93FFB06778696B4A9D81BB0A9423E63DE5");
+
string ec_256_key =
hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
"6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
@@ -209,6 +260,32 @@
string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
};
+string device_suffix(const string& name) {
+ size_t pos = name.find('/');
+ if (pos == string::npos) {
+ return name;
+ }
+ return name.substr(pos + 1);
+}
+
+bool matching_rp_instance(const string& km_name,
+ std::shared_ptr<IRemotelyProvisionedComponent>* rp) {
+ string km_suffix = device_suffix(km_name);
+
+ vector<string> rp_names =
+ ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
+ for (const string& rp_name : rp_names) {
+ // If the suffix of the RemotelyProvisionedComponent instance equals the suffix of the
+ // KeyMint instance, assume they match.
+ if (device_suffix(rp_name) == km_suffix && AServiceManager_isDeclared(rp_name.c_str())) {
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService(rp_name.c_str()));
+ *rp = IRemotelyProvisionedComponent::fromBinder(binder);
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
class NewKeyGenerationTest : public KeyMintAidlTestBase {
@@ -282,10 +359,10 @@
* have correct characteristics.
*/
TEST_P(NewKeyGenerationTest, RsaWithAttestation) {
- for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
- auto challenge = "hello";
- auto app_id = "foo";
+ auto challenge = "hello";
+ auto app_id = "foo";
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -322,6 +399,234 @@
}
/*
+ * NewKeyGenerationTest.RsaWithRpkAttestation
+ *
+ * Verifies that keymint can generate all required RSA key sizes, using an attestation key
+ * that has been generated using an associate IRemotelyProvisionedComponent.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithRpkAttestation) {
+ // There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
+ // instance.
+ std::shared_ptr<IRemotelyProvisionedComponent> rp;
+ ASSERT_TRUE(matching_rp_instance(GetParam(), &rp))
+ << "No IRemotelyProvisionedComponent found that matches KeyMint device " << GetParam();
+
+ // Generate a P-256 keypair to use as an attestation key.
+ MacedPublicKey macedPubKey;
+ std::vector<uint8_t> privateKeyBlob;
+ auto status =
+ rp->generateEcdsaP256KeyPair(/* testMode= */ false, &macedPubKey, &privateKeyBlob);
+ ASSERT_TRUE(status.isOk());
+ vector<uint8_t> coseKeyData;
+ check_maced_pubkey(macedPubKey, /* testMode= */ false, &coseKeyData);
+
+ AttestationKey attestation_key;
+ attestation_key.keyBlob = std::move(privateKeyBlob);
+ attestation_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ // Attestation by itself is not valid (last entry is not self-signed).
+ EXPECT_FALSE(ChainSignaturesAreValid(cert_chain_));
+
+ // The signature over the attested key should correspond to the P256 public key.
+ X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_TRUE(key_cert.get());
+ EVP_PKEY_Ptr signing_pubkey;
+ p256_pub_key(coseKeyData, &signing_pubkey);
+ ASSERT_TRUE(signing_pubkey.get());
+
+ ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
+ << "Verification of attested certificate failed "
+ << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.RsaEncryptionWithAttestation
+ *
+ * Verifies that keymint attestation for RSA encryption keys with challenge and
+ * app id is also successful.
+ */
+TEST_P(NewKeyGenerationTest, RsaEncryptionWithAttestation) {
+ auto key_size = 2048;
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+
+ EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+ EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT));
+
+ // Verify that App data and ROT are NOT included.
+ EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
+ EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA));
+
+ // Check that some unexpected tags/values are NOT present.
+ EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
+ EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY));
+
+ EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U));
+
+ auto os_ver = auths.GetTagValue(TAG_OS_VERSION);
+ ASSERT_TRUE(os_ver);
+ EXPECT_EQ(*os_ver, os_version());
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ sw_enforced, hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+}
+
+/*
+ * NewKeyGenerationTest.RsaWithSelfSign
+ *
+ * Verifies that attesting to RSA key generation is successful, and returns
+ * self signed certificate if no challenge is provided. And signing etc
+ * works as expected.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithSelfSign) {
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_EQ(cert_chain_.size(), 1);
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.RsaWithAttestationMissAppId
+ *
+ * Verifies that attesting to RSA checks for missing app ID.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithAttestationMissAppId) {
+ auto challenge = "hello";
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+}
+
+/*
+ * NewKeyGenerationTest.RsaWithAttestationAppIdIgnored
+ *
+ * Verifies that attesting to RSA ignores app id if challenge is missing.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithAttestationAppIdIgnored) {
+ auto key_size = 2048;
+ auto app_id = "foo";
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_EQ(cert_chain_.size(), 1);
+
+ CheckedDeleteKey(&key_blob);
+}
+
+/*
* NewKeyGenerationTest.LimitedUsageRsa
*
* Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
@@ -368,10 +673,10 @@
* resulting keys have correct characteristics and attestation.
*/
TEST_P(NewKeyGenerationTest, LimitedUsageRsaWithAttestation) {
- for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
- auto challenge = "hello";
- auto app_id = "foo";
+ auto challenge = "hello";
+ auto app_id = "foo";
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -480,6 +785,188 @@
}
/*
+ * NewKeyGenerationTest.EcdsaAttestation
+ *
+ * Verifies that for all Ecdsa key sizes, if challenge and app id is provided,
+ * an attestation will be generated.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestation) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ sw_enforced, hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaSelfSignAttestation
+ *
+ * Verifies that if no challenge is provided to an Ecdsa key generation, then
+ * the key will generate a self signed attestation.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaSelfSignAttestation) {
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_EQ(cert_chain_.size(), 1);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAttestationRequireAppId
+ *
+ * Verifies that if attestation challenge is provided to Ecdsa key generation, then
+ * app id must also be provided or else it will fail.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationRequireAppId) {
+ auto challenge = "hello";
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaIgnoreAppId
+ *
+ * Verifies that if no challenge is provided to the Ecdsa key generation, then
+ * any appid will be ignored, and keymint will generate a self sign certificate.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaIgnoreAppId) {
+ auto app_id = "foo";
+
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .AttestationApplicationId(app_id)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_EQ(cert_chain_.size(), 1);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.AttestationApplicationIDLengthProperlyEncoded
+ *
+ * Verifies that the Attestation Application ID software enforced tag has a proper length encoding.
+ * Some implementations break strict encoding rules by encoding a length between 127 and 256 in one
+ * byte. Proper DER encoding specifies that for lengths greater than 127, one byte should be used
+ * to specify how many following bytes will be used to encode the length.
+ */
+TEST_P(NewKeyGenerationTest, AttestationApplicationIDLengthProperlyEncoded) {
+ auto challenge = "hello";
+ auto key_size = 256;
+ std::vector<uint32_t> app_id_lengths{143, 258};
+
+ for (uint32_t length : app_id_lengths) {
+ const string app_id(length, 'a');
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics));
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ sw_enforced, hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.LimitedUsageEcdsa
*
* Verifies that KeyMint can generate all required EC key sizes with limited usage, and that the
@@ -641,6 +1128,41 @@
}
/*
+ * NewKeyGenerationTest.HmacNoAttestation
+ *
+ * Verifies that for Hmac key generation, no attestation will be generated even if challenge
+ * and app id are provided.
+ */
+TEST_P(NewKeyGenerationTest, HmacNoAttestation) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ constexpr size_t key_size = 128;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(digest)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ ASSERT_EQ(cert_chain_.size(), 0);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.LimitedUsageHmac
*
* Verifies that KeyMint supports all required digests with limited usage Hmac, and that the
@@ -774,6 +1296,47 @@
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
}
+/*
+ * NewKeyGenerationTest.AesNoAttestation
+ *
+ * Verifies that attestation parameters to AES keys are ignored and generateKey
+ * will succeed.
+ */
+TEST_P(NewKeyGenerationTest, AesNoAttestation) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .EcbMode()
+ .Padding(PaddingMode::PKCS7)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)));
+
+ ASSERT_EQ(cert_chain_.size(), 0);
+}
+
+/*
+ * NewKeyGenerationTest.TripleDesNoAttestation
+ *
+ * Verifies that attesting parameters to 3DES keys are ignored and generate key
+ * will be successful. No attestation should be generated.
+ */
+TEST_P(NewKeyGenerationTest, TripleDesNoAttestation) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)));
+ ASSERT_EQ(cert_chain_.size(), 0);
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(NewKeyGenerationTest);
typedef KeyMintAidlTestBase SigningOperationsTest;
@@ -1711,16 +2274,27 @@
* Verifies that importing and using an RSA key pair works correctly.
*/
TEST_P(ImportKeyTest, RsaSuccess) {
+ uint32_t key_size;
+ string key;
+
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ key_size = 2048;
+ key = rsa_2048_key;
+ } else {
+ key_size = 1024;
+ key = rsa_key;
+ }
+
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaSigningKey(1024, 65537)
+ .RsaSigningKey(key_size, 65537)
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PSS)
.SetDefaultValidity(),
- KeyFormat::PKCS8, rsa_key));
+ KeyFormat::PKCS8, key));
CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
- CheckCryptoParam(TAG_KEY_SIZE, 1024U);
+ CheckCryptoParam(TAG_KEY_SIZE, key_size);
CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_PSS);
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 57bc27a..a2071c2 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
-#include <RemotelyProvisionedComponent.h>
+#include <AndroidRemotelyProvisionedComponentDevice.h>
#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
#include <android/binder_manager.h>
#include <cppbor_parse.h>
-#include <cppcose/cppcose.h>
#include <gmock/gmock.h>
+#include <keymaster/cppcose/cppcose.h>
#include <keymaster/keymaster_configuration.h>
#include <keymint_support/authorization_set.h>
#include <openssl/ec.h>
@@ -55,117 +55,6 @@
return bytevec(p, p + strlen(s));
}
-void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey) {
- // Extract x and y affine coordinates from the encoded Cose_Key.
- auto [parsedPayload, __, payloadParseErr] = cppbor::parse(coseKeyData);
- ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
- auto coseKey = parsedPayload->asMap();
- const std::unique_ptr<cppbor::Item>& xItem = coseKey->get(cppcose::CoseKey::PUBKEY_X);
- ASSERT_NE(xItem->asBstr(), nullptr);
- vector<uint8_t> x = xItem->asBstr()->value();
- const std::unique_ptr<cppbor::Item>& yItem = coseKey->get(cppcose::CoseKey::PUBKEY_Y);
- ASSERT_NE(yItem->asBstr(), nullptr);
- vector<uint8_t> y = yItem->asBstr()->value();
-
- // Concatenate: 0x04 (uncompressed form marker) | x | y
- vector<uint8_t> pubKeyData{0x04};
- pubKeyData.insert(pubKeyData.end(), x.begin(), x.end());
- pubKeyData.insert(pubKeyData.end(), y.begin(), y.end());
-
- EC_KEY_Ptr ecKey = EC_KEY_Ptr(EC_KEY_new());
- ASSERT_NE(ecKey, nullptr);
- EC_GROUP_Ptr group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
- ASSERT_NE(group, nullptr);
- ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
- EC_POINT_Ptr point = EC_POINT_Ptr(EC_POINT_new(group.get()));
- ASSERT_NE(point, nullptr);
- ASSERT_EQ(EC_POINT_oct2point(group.get(), point.get(), pubKeyData.data(), pubKeyData.size(),
- nullptr),
- 1);
- ASSERT_EQ(EC_KEY_set_public_key(ecKey.get(), point.get()), 1);
-
- EVP_PKEY_Ptr pubKey = EVP_PKEY_Ptr(EVP_PKEY_new());
- ASSERT_NE(pubKey, nullptr);
- EVP_PKEY_assign_EC_KEY(pubKey.get(), ecKey.release());
- *signingKey = std::move(pubKey);
-}
-
-void check_cose_key(const vector<uint8_t>& data, bool testMode) {
- auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
- ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
-
- // The following check assumes that canonical CBOR encoding is used for the COSE_Key.
- if (testMode) {
- EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
- MatchesRegex("{\n"
- " 1 : 2,\n" // kty: EC2
- " 3 : -7,\n" // alg: ES256
- " -1 : 1,\n" // EC id: P256
- // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
- // sequence of 32 hexadecimal bytes, enclosed in braces and
- // separated by commas. In this case, some Ed25519 public key.
- " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
- " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
- " -70000 : null,\n" // test marker
- "}"));
- } else {
- EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
- MatchesRegex("{\n"
- " 1 : 2,\n" // kty: EC2
- " 3 : -7,\n" // alg: ES256
- " -1 : 1,\n" // EC id: P256
- // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
- // sequence of 32 hexadecimal bytes, enclosed in braces and
- // separated by commas. In this case, some Ed25519 public key.
- " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
- " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
- "}"));
- }
-}
-
-void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
- vector<uint8_t>* payload_value) {
- auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
- ASSERT_TRUE(coseMac0) << "COSE Mac0 parse failed " << mac0ParseErr;
-
- ASSERT_NE(coseMac0->asArray(), nullptr);
- ASSERT_EQ(coseMac0->asArray()->size(), kCoseMac0EntryCount);
-
- auto protParms = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
- ASSERT_NE(protParms, nullptr);
-
- // Header label:value of 'alg': HMAC-256
- ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n 1 : 5,\n}");
-
- auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
- ASSERT_NE(unprotParms, nullptr);
- ASSERT_EQ(unprotParms->size(), 0);
-
- // The payload is a bstr holding an encoded COSE_Key
- auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
- ASSERT_NE(payload, nullptr);
- check_cose_key(payload->value(), testMode);
-
- auto coseMac0Tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
- ASSERT_TRUE(coseMac0Tag);
- auto extractedTag = coseMac0Tag->value();
- EXPECT_EQ(extractedTag.size(), 32U);
-
- // Compare with tag generated with kTestMacKey. Should only match in test mode
- auto testTag = cppcose::generateCoseMac0Mac(remote_prov::kTestMacKey, {} /* external_aad */,
- payload->value());
- ASSERT_TRUE(testTag) << "Tag calculation failed: " << testTag.message();
-
- if (testMode) {
- EXPECT_EQ(*testTag, extractedTag);
- } else {
- EXPECT_NE(*testTag, extractedTag);
- }
- if (payload_value != nullptr) {
- *payload_value = payload->value();
- }
-}
-
ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index fe04ede..718133a 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -57,29 +57,8 @@
"include",
],
shared_libs: [
- "libcppcose",
"libcppbor_external",
+ "libcppcose_rkp",
"libcrypto",
],
}
-
-cc_library {
- name: "libcppcose",
- vendor_available: true,
- srcs: [
- "cppcose.cpp",
- ],
- export_include_dirs: [
- "include",
- ],
- shared_libs: [
- "libbinder_ndk",
- "libcppbor_external",
- "libcrypto",
- "liblog",
- ],
- static_libs: [
- // TODO(swillden): Remove keymint NDK
- "android.hardware.security.keymint-V1-ndk_platform",
- ],
-}
diff --git a/security/keymint/support/cppcose.cpp b/security/keymint/support/cppcose.cpp
deleted file mode 100644
index bafb2b6..0000000
--- a/security/keymint/support/cppcose.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Copyright (C) 2020 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 <cppcose/cppcose.h>
-
-#include <stdio.h>
-#include <iostream>
-
-#include <cppbor.h>
-#include <cppbor_parse.h>
-
-#include <openssl/err.h>
-
-namespace cppcose {
-
-namespace {
-
-ErrMsgOr<bssl::UniquePtr<EVP_CIPHER_CTX>> aesGcmInitAndProcessAad(const bytevec& key,
- const bytevec& nonce,
- const bytevec& aad,
- bool encrypt) {
- if (key.size() != kAesGcmKeySize) return "Invalid key size";
-
- bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
- if (!ctx) return "Failed to allocate cipher context";
-
- if (!EVP_CipherInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, key.data(),
- nonce.data(), encrypt ? 1 : 0)) {
- return "Failed to initialize cipher";
- }
-
- int outlen;
- if (!aad.empty() && !EVP_CipherUpdate(ctx.get(), nullptr /* out; null means AAD */, &outlen,
- aad.data(), aad.size())) {
- return "Failed to process AAD";
- }
-
- return std::move(ctx);
-}
-
-} // namespace
-
-ErrMsgOr<bytevec> generateCoseMac0Mac(const bytevec& macKey, const bytevec& externalAad,
- const bytevec& payload) {
- auto macStructure = cppbor::Array()
- .add("MAC0")
- .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
- .add(externalAad)
- .add(payload)
- .encode();
-
- bytevec macTag(SHA256_DIGEST_LENGTH);
- uint8_t* out = macTag.data();
- unsigned int outLen;
- out = HMAC(EVP_sha256(), //
- macKey.data(), macKey.size(), //
- macStructure.data(), macStructure.size(), //
- out, &outLen);
-
- assert(out != nullptr && outLen == macTag.size());
- if (out == nullptr || outLen != macTag.size()) {
- return "Error computing public key MAC";
- }
-
- return macTag;
-}
-
-ErrMsgOr<cppbor::Array> constructCoseMac0(const bytevec& macKey, const bytevec& externalAad,
- const bytevec& payload) {
- auto tag = generateCoseMac0Mac(macKey, externalAad, payload);
- if (!tag) return tag.moveMessage();
-
- return cppbor::Array()
- .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
- .add(cppbor::Map() /* unprotected */)
- .add(payload)
- .add(tag.moveValue());
-}
-
-ErrMsgOr<bytevec /* payload */> parseCoseMac0(const cppbor::Item* macItem) {
- auto mac = macItem ? macItem->asArray() : nullptr;
- if (!mac || mac->size() != kCoseMac0EntryCount) {
- return "Invalid COSE_Mac0";
- }
-
- auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
- auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
- auto payload = mac->get(kCoseMac0Payload)->asBstr();
- auto tag = mac->get(kCoseMac0Tag)->asBstr();
- if (!protectedParms || !unprotectedParms || !payload || !tag) {
- return "Invalid COSE_Mac0 contents";
- }
-
- return payload->value();
-}
-
-ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macItem,
- const bytevec& macKey) {
- auto mac = macItem ? macItem->asArray() : nullptr;
- if (!mac || mac->size() != kCoseMac0EntryCount) {
- return "Invalid COSE_Mac0";
- }
-
- auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
- auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
- auto payload = mac->get(kCoseMac0Payload)->asBstr();
- auto tag = mac->get(kCoseMac0Tag)->asBstr();
- if (!protectedParms || !unprotectedParms || !payload || !tag) {
- return "Invalid COSE_Mac0 contents";
- }
-
- auto [protectedMap, _, errMsg] = cppbor::parse(protectedParms);
- if (!protectedMap || !protectedMap->asMap()) {
- return "Invalid Mac0 protected: " + errMsg;
- }
- auto& algo = protectedMap->asMap()->get(ALGORITHM);
- if (!algo || !algo->asInt() || algo->asInt()->value() != HMAC_256) {
- return "Unsupported Mac0 algorithm";
- }
-
- auto macTag = generateCoseMac0Mac(macKey, {} /* external_aad */, payload->value());
- if (!macTag) return macTag.moveMessage();
-
- if (macTag->size() != tag->value().size() ||
- CRYPTO_memcmp(macTag->data(), tag->value().data(), macTag->size()) != 0) {
- return "MAC tag mismatch";
- }
-
- return payload->value();
-}
-
-ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
- const bytevec& payload, const bytevec& aad) {
- bytevec signatureInput = cppbor::Array()
- .add("Signature1") //
- .add(protectedParams)
- .add(aad)
- .add(payload)
- .encode();
-
- if (key.size() != ED25519_PRIVATE_KEY_LEN) return "Invalid signing key";
- bytevec signature(ED25519_SIGNATURE_LEN);
- if (!ED25519_sign(signature.data(), signatureInput.data(), signatureInput.size(), key.data())) {
- return "Signing failed";
- }
-
- return signature;
-}
-
-ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map protectedParams,
- const bytevec& payload, const bytevec& aad) {
- bytevec protParms = protectedParams.add(ALGORITHM, EDDSA).canonicalize().encode();
- auto signature = createCoseSign1Signature(key, protParms, payload, aad);
- if (!signature) return signature.moveMessage();
-
- return cppbor::Array()
- .add(protParms)
- .add(cppbor::Map() /* unprotected parameters */)
- .add(payload)
- .add(*signature);
-}
-
-ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, const bytevec& payload,
- const bytevec& aad) {
- return constructCoseSign1(key, {} /* protectedParams */, payload, aad);
-}
-
-ErrMsgOr<bytevec> verifyAndParseCoseSign1(bool ignoreSignature, const cppbor::Array* coseSign1,
- const bytevec& signingCoseKey, const bytevec& aad) {
- if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) {
- return "Invalid COSE_Sign1";
- }
-
- const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
- const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
- const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
- const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
-
- if (!protectedParams || !unprotectedParams || !payload || !signature) {
- return "Invalid COSE_Sign1";
- }
-
- auto [parsedProtParams, _, errMsg] = cppbor::parse(protectedParams);
- if (!parsedProtParams) {
- return errMsg + " when parsing protected params.";
- }
- if (!parsedProtParams->asMap()) {
- return "Protected params must be a map";
- }
-
- auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
- if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) {
- return "Unsupported signature algorithm";
- }
-
- if (!ignoreSignature) {
- bool selfSigned = signingCoseKey.empty();
- auto key = CoseKey::parseEd25519(selfSigned ? payload->value() : signingCoseKey);
- if (!key) return "Bad signing key: " + key.moveMessage();
-
- bytevec signatureInput = cppbor::Array()
- .add("Signature1")
- .add(*protectedParams)
- .add(aad)
- .add(*payload)
- .encode();
-
- if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
- key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
- return "Signature verification failed";
- }
- }
-
- return payload->value();
-}
-
-ErrMsgOr<bytevec> createCoseEncryptCiphertext(const bytevec& key, const bytevec& nonce,
- const bytevec& protectedParams,
- const bytevec& plaintextPayload, const bytevec& aad) {
- auto ciphertext = aesGcmEncrypt(key, nonce,
- cppbor::Array() // Enc strucure as AAD
- .add("Encrypt") // Context
- .add(protectedParams) // Protected
- .add(aad) // External AAD
- .encode(),
- plaintextPayload);
-
- if (!ciphertext) return ciphertext.moveMessage();
- return ciphertext.moveValue();
-}
-
-ErrMsgOr<cppbor::Array> constructCoseEncrypt(const bytevec& key, const bytevec& nonce,
- const bytevec& plaintextPayload, const bytevec& aad,
- cppbor::Array recipients) {
- auto encryptProtectedHeader = cppbor::Map() //
- .add(ALGORITHM, AES_GCM_256)
- .canonicalize()
- .encode();
-
- auto ciphertext =
- createCoseEncryptCiphertext(key, nonce, encryptProtectedHeader, plaintextPayload, aad);
- if (!ciphertext) return ciphertext.moveMessage();
-
- return cppbor::Array()
- .add(encryptProtectedHeader) // Protected
- .add(cppbor::Map().add(IV, nonce).canonicalize()) // Unprotected
- .add(*ciphertext) // Payload
- .add(std::move(recipients));
-}
-
-ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>> getSenderPubKeyFromCoseEncrypt(
- const cppbor::Item* coseEncrypt) {
- if (!coseEncrypt || !coseEncrypt->asArray() ||
- coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
- return "Invalid COSE_Encrypt";
- }
-
- auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);
- if (!recipients || !recipients->asArray() || recipients->asArray()->size() != 1) {
- return "Invalid recipients list";
- }
-
- auto& recipient = recipients->asArray()->get(0);
- if (!recipient || !recipient->asArray() || recipient->asArray()->size() != 3) {
- return "Invalid COSE_recipient";
- }
-
- auto& ciphertext = recipient->asArray()->get(2);
- if (!ciphertext->asSimple() || !ciphertext->asSimple()->asNull()) {
- return "Unexpected value in recipients ciphertext field " +
- cppbor::prettyPrint(ciphertext.get());
- }
-
- auto& protParms = recipient->asArray()->get(0);
- if (!protParms || !protParms->asBstr()) return "Invalid protected params";
- auto [parsedProtParms, _, errMsg] = cppbor::parse(protParms->asBstr());
- if (!parsedProtParms) return "Failed to parse protected params: " + errMsg;
- if (!parsedProtParms->asMap()) return "Invalid protected params";
-
- auto& algorithm = parsedProtParms->asMap()->get(ALGORITHM);
- if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != ECDH_ES_HKDF_256) {
- return "Invalid algorithm";
- }
-
- auto& unprotParms = recipient->asArray()->get(1);
- if (!unprotParms || !unprotParms->asMap()) return "Invalid unprotected params";
-
- auto& senderCoseKey = unprotParms->asMap()->get(COSE_KEY);
- if (!senderCoseKey || !senderCoseKey->asMap()) return "Invalid sender COSE_Key";
-
- auto& keyType = senderCoseKey->asMap()->get(CoseKey::KEY_TYPE);
- if (!keyType || !keyType->asInt() || keyType->asInt()->value() != OCTET_KEY_PAIR) {
- return "Invalid key type";
- }
-
- auto& curve = senderCoseKey->asMap()->get(CoseKey::CURVE);
- if (!curve || !curve->asInt() || curve->asInt()->value() != X25519) {
- return "Unsupported curve";
- }
-
- auto& pubkey = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X);
- if (!pubkey || !pubkey->asBstr() ||
- pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) {
- return "Invalid X25519 public key";
- }
-
- auto& key_id = unprotParms->asMap()->get(KEY_ID);
- if (key_id && key_id->asBstr()) {
- return std::make_pair(pubkey->asBstr()->value(), key_id->asBstr()->value());
- }
-
- // If no key ID, just return an empty vector.
- return std::make_pair(pubkey->asBstr()->value(), bytevec{});
-}
-
-ErrMsgOr<bytevec> decryptCoseEncrypt(const bytevec& key, const cppbor::Item* coseEncrypt,
- const bytevec& external_aad) {
- if (!coseEncrypt || !coseEncrypt->asArray() ||
- coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
- return "Invalid COSE_Encrypt";
- }
-
- auto& protParms = coseEncrypt->asArray()->get(kCoseEncryptProtectedParams);
- auto& unprotParms = coseEncrypt->asArray()->get(kCoseEncryptUnprotectedParams);
- auto& ciphertext = coseEncrypt->asArray()->get(kCoseEncryptPayload);
- auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);
-
- if (!protParms || !protParms->asBstr() || !unprotParms || !ciphertext || !recipients) {
- return "Invalid COSE_Encrypt";
- }
-
- auto [parsedProtParams, _, errMsg] = cppbor::parse(protParms->asBstr()->value());
- if (!parsedProtParams) {
- return errMsg + " when parsing protected params.";
- }
- if (!parsedProtParams->asMap()) {
- return "Protected params must be a map";
- }
-
- auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
- if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != AES_GCM_256) {
- return "Unsupported encryption algorithm";
- }
-
- if (!unprotParms->asMap() || unprotParms->asMap()->size() != 1) {
- return "Invalid unprotected params";
- }
-
- auto& nonce = unprotParms->asMap()->get(IV);
- if (!nonce || !nonce->asBstr() || nonce->asBstr()->value().size() != kAesGcmNonceLength) {
- return "Invalid nonce";
- }
-
- if (!ciphertext->asBstr()) return "Invalid ciphertext";
-
- auto aad = cppbor::Array() // Enc strucure as AAD
- .add("Encrypt") // Context
- .add(protParms->asBstr()->value()) // Protected
- .add(external_aad) // External AAD
- .encode();
-
- return aesGcmDecrypt(key, nonce->asBstr()->value(), aad, ciphertext->asBstr()->value());
-}
-
-ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA,
- const bytevec& pubKeyB, bool senderIsA) {
- bytevec rawSharedKey(X25519_SHARED_KEY_LEN);
- if (!::X25519(rawSharedKey.data(), privKeyA.data(), pubKeyB.data())) {
- return "ECDH operation failed";
- }
-
- bytevec kdfContext = cppbor::Array()
- .add(AES_GCM_256)
- .add(cppbor::Array() // Sender Info
- .add(cppbor::Bstr("client"))
- .add(bytevec{} /* nonce */)
- .add(senderIsA ? pubKeyA : pubKeyB))
- .add(cppbor::Array() // Recipient Info
- .add(cppbor::Bstr("server"))
- .add(bytevec{} /* nonce */)
- .add(senderIsA ? pubKeyB : pubKeyA))
- .add(cppbor::Array() // SuppPubInfo
- .add(128) // output key length
- .add(bytevec{})) // protected
- .encode();
-
- bytevec retval(SHA256_DIGEST_LENGTH);
- bytevec salt{};
- if (!HKDF(retval.data(), retval.size(), //
- EVP_sha256(), //
- rawSharedKey.data(), rawSharedKey.size(), //
- salt.data(), salt.size(), //
- kdfContext.data(), kdfContext.size())) {
- return "ECDH HKDF failed";
- }
-
- return retval;
-}
-
-ErrMsgOr<bytevec> aesGcmEncrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
- const bytevec& plaintext) {
- auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, true /* encrypt */);
- if (!ctx) return ctx.moveMessage();
-
- bytevec ciphertext(plaintext.size() + kAesGcmTagSize);
- int outlen;
- if (!EVP_CipherUpdate(ctx->get(), ciphertext.data(), &outlen, plaintext.data(),
- plaintext.size())) {
- return "Failed to encrypt plaintext";
- }
- assert(plaintext.size() == outlen);
-
- if (!EVP_CipherFinal_ex(ctx->get(), ciphertext.data() + outlen, &outlen)) {
- return "Failed to finalize encryption";
- }
- assert(outlen == 0);
-
- if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize,
- ciphertext.data() + plaintext.size())) {
- return "Failed to retrieve tag";
- }
-
- return ciphertext;
-}
-
-ErrMsgOr<bytevec> aesGcmDecrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
- const bytevec& ciphertextWithTag) {
- auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, false /* encrypt */);
- if (!ctx) return ctx.moveMessage();
-
- if (ciphertextWithTag.size() < kAesGcmTagSize) return "Missing tag";
-
- bytevec plaintext(ciphertextWithTag.size() - kAesGcmTagSize);
- int outlen;
- if (!EVP_CipherUpdate(ctx->get(), plaintext.data(), &outlen, ciphertextWithTag.data(),
- ciphertextWithTag.size() - kAesGcmTagSize)) {
- return "Failed to decrypt plaintext";
- }
- assert(plaintext.size() == outlen);
-
- bytevec tag(ciphertextWithTag.end() - kAesGcmTagSize, ciphertextWithTag.end());
- if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag.data())) {
- return "Failed to set tag: " + std::to_string(ERR_peek_last_error());
- }
-
- if (!EVP_CipherFinal_ex(ctx->get(), nullptr, &outlen)) {
- return "Failed to finalize encryption";
- }
- assert(outlen == 0);
-
- return plaintext;
-}
-
-} // namespace cppcose
diff --git a/security/keymint/support/include/cppcose/cppcose.h b/security/keymint/support/include/cppcose/cppcose.h
deleted file mode 100644
index a936bfd..0000000
--- a/security/keymint/support/include/cppcose/cppcose.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-
-#include <cppbor.h>
-#include <cppbor_parse.h>
-
-#include <openssl/cipher.h>
-#include <openssl/curve25519.h>
-#include <openssl/digest.h>
-#include <openssl/hkdf.h>
-#include <openssl/hmac.h>
-#include <openssl/mem.h>
-#include <openssl/sha.h>
-
-namespace cppcose {
-
-using bytevec = std::vector<uint8_t>;
-
-constexpr int kCoseSign1EntryCount = 4;
-constexpr int kCoseSign1ProtectedParams = 0;
-constexpr int kCoseSign1UnprotectedParams = 1;
-constexpr int kCoseSign1Payload = 2;
-constexpr int kCoseSign1Signature = 3;
-
-constexpr int kCoseMac0EntryCount = 4;
-constexpr int kCoseMac0ProtectedParams = 0;
-constexpr int kCoseMac0UnprotectedParams = 1;
-constexpr int kCoseMac0Payload = 2;
-constexpr int kCoseMac0Tag = 3;
-
-constexpr int kCoseEncryptEntryCount = 4;
-constexpr int kCoseEncryptProtectedParams = 0;
-constexpr int kCoseEncryptUnprotectedParams = 1;
-constexpr int kCoseEncryptPayload = 2;
-constexpr int kCoseEncryptRecipients = 3;
-
-enum Label : int {
- ALGORITHM = 1,
- KEY_ID = 4,
- IV = 5,
- COSE_KEY = -1,
-};
-
-enum CoseKeyAlgorithm : int {
- AES_GCM_256 = 3,
- HMAC_256 = 5,
- ES256 = -7, // ECDSA with SHA-256
- EDDSA = -8,
- ECDH_ES_HKDF_256 = -25,
-};
-
-enum CoseKeyCurve : int { P256 = 1, X25519 = 4, ED25519 = 6 };
-enum CoseKeyType : int { OCTET_KEY_PAIR = 1, EC2 = 2, SYMMETRIC_KEY = 4 };
-enum CoseKeyOps : int { SIGN = 1, VERIFY = 2, ENCRYPT = 3, DECRYPT = 4 };
-
-constexpr int kAesGcmNonceLength = 12;
-constexpr int kAesGcmTagSize = 16;
-constexpr int kAesGcmKeySize = 32;
-
-template <typename T>
-class ErrMsgOr {
- public:
- ErrMsgOr(std::string errMsg) : errMsg_(std::move(errMsg)) {}
- ErrMsgOr(const char* errMsg) : errMsg_(errMsg) {}
- ErrMsgOr(T val) : value_(std::move(val)) {}
-
- operator bool() const { return value_.has_value(); }
-
- T* operator->() & {
- assert(value_);
- return &value_.value();
- }
- T& operator*() & {
- assert(value_);
- return value_.value();
- };
- T&& operator*() && {
- assert(value_);
- return std::move(value_).value();
- };
-
- const std::string& message() { return errMsg_; }
- std::string moveMessage() { return std::move(errMsg_); }
-
- T moveValue() {
- assert(value_);
- return std::move(value_).value();
- }
-
- private:
- std::string errMsg_;
- std::optional<T> value_;
-};
-
-class CoseKey {
- public:
- CoseKey() {}
- CoseKey(const CoseKey&) = delete;
- CoseKey(CoseKey&&) = default;
-
- enum Label : int {
- KEY_TYPE = 1,
- KEY_ID = 2,
- ALGORITHM = 3,
- KEY_OPS = 4,
- CURVE = -1,
- PUBKEY_X = -2,
- PUBKEY_Y = -3,
- PRIVATE_KEY = -4,
- TEST_KEY = -70000 // Application-defined
- };
-
- static ErrMsgOr<CoseKey> parse(const bytevec& coseKey) {
- auto [parsedKey, _, errMsg] = cppbor::parse(coseKey);
- if (!parsedKey) return errMsg + " when parsing key";
- if (!parsedKey->asMap()) return "CoseKey must be a map";
- return CoseKey(static_cast<cppbor::Map*>(parsedKey.release()));
- }
-
- static ErrMsgOr<CoseKey> parse(const bytevec& coseKey, CoseKeyType expectedKeyType,
- CoseKeyAlgorithm expectedAlgorithm, CoseKeyCurve expectedCurve) {
- auto key = parse(coseKey);
- if (!key) return key;
-
- if (!key->checkIntValue(CoseKey::KEY_TYPE, expectedKeyType) ||
- !key->checkIntValue(CoseKey::ALGORITHM, expectedAlgorithm) ||
- !key->checkIntValue(CoseKey::CURVE, expectedCurve)) {
- return "Unexpected key type:";
- }
-
- return key;
- }
-
- static ErrMsgOr<CoseKey> parseEd25519(const bytevec& coseKey) {
- auto key = parse(coseKey, OCTET_KEY_PAIR, EDDSA, ED25519);
- if (!key) return key;
-
- auto& pubkey = key->getMap().get(PUBKEY_X);
- if (!pubkey || !pubkey->asBstr() ||
- pubkey->asBstr()->value().size() != ED25519_PUBLIC_KEY_LEN) {
- return "Invalid Ed25519 public key";
- }
-
- return key;
- }
-
- static ErrMsgOr<CoseKey> parseX25519(const bytevec& coseKey, bool requireKid) {
- auto key = parse(coseKey, OCTET_KEY_PAIR, ECDH_ES_HKDF_256, X25519);
- if (!key) return key;
-
- auto& pubkey = key->getMap().get(PUBKEY_X);
- if (!pubkey || !pubkey->asBstr() ||
- pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) {
- return "Invalid X25519 public key";
- }
-
- auto& kid = key->getMap().get(KEY_ID);
- if (requireKid && (!kid || !kid->asBstr())) {
- return "Missing KID";
- }
-
- return key;
- }
-
- static ErrMsgOr<CoseKey> parseP256(const bytevec& coseKey) {
- auto key = parse(coseKey, EC2, ES256, P256);
- if (!key) return key;
-
- auto& pubkey_x = key->getMap().get(PUBKEY_X);
- auto& pubkey_y = key->getMap().get(PUBKEY_Y);
- if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() ||
- pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) {
- return "Invalid P256 public key";
- }
-
- return key;
- }
-
- std::optional<int> getIntValue(Label label) {
- const auto& value = key_->get(label);
- if (!value || !value->asInt()) return {};
- return value->asInt()->value();
- }
-
- std::optional<bytevec> getBstrValue(Label label) {
- const auto& value = key_->get(label);
- if (!value || !value->asBstr()) return {};
- return value->asBstr()->value();
- }
-
- const cppbor::Map& getMap() const { return *key_; }
- cppbor::Map&& moveMap() { return std::move(*key_); }
-
- bool checkIntValue(Label label, int expectedValue) {
- const auto& value = key_->get(label);
- return value && value->asInt() && value->asInt()->value() == expectedValue;
- }
-
- void add(Label label, int value) { key_->add(label, value); }
- void add(Label label, bytevec value) { key_->add(label, std::move(value)); }
-
- bytevec encode() { return key_->canonicalize().encode(); }
-
- private:
- CoseKey(cppbor::Map* parsedKey) : key_(parsedKey) {}
-
- // This is the full parsed key structure.
- std::unique_ptr<cppbor::Map> key_;
-};
-
-ErrMsgOr<bytevec> generateCoseMac0Mac(const bytevec& macKey, const bytevec& externalAad,
- const bytevec& payload);
-ErrMsgOr<cppbor::Array> constructCoseMac0(const bytevec& macKey, const bytevec& externalAad,
- const bytevec& payload);
-ErrMsgOr<bytevec /* payload */> parseCoseMac0(const cppbor::Item* macItem);
-ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macItem,
- const bytevec& macKey);
-
-ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
- const bytevec& payload, const bytevec& aad);
-ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, const bytevec& payload,
- const bytevec& aad);
-ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map extraProtectedFields,
- const bytevec& payload, const bytevec& aad);
-/**
- * Verify and parse a COSE_Sign1 message, returning the payload.
- *
- * @param ignoreSignature indicates whether signature verification should be skipped. If true, no
- * verification of the signature will be done.
- *
- * @param coseSign1 is the COSE_Sign1 to verify and parse.
- *
- * @param signingCoseKey is a CBOR-encoded COSE_Key to use to verify the signature. The bytevec may
- * be empty, in which case the function assumes that coseSign1's payload is the COSE_Key to
- * use, i.e. that coseSign1 is a self-signed "certificate".
- */
-ErrMsgOr<bytevec /* payload */> verifyAndParseCoseSign1(bool ignoreSignature,
- const cppbor::Array* coseSign1,
- const bytevec& signingCoseKey,
- const bytevec& aad);
-
-ErrMsgOr<bytevec> createCoseEncryptCiphertext(const bytevec& key, const bytevec& nonce,
- const bytevec& protectedParams, const bytevec& aad);
-ErrMsgOr<cppbor::Array> constructCoseEncrypt(const bytevec& key, const bytevec& nonce,
- const bytevec& plaintextPayload, const bytevec& aad,
- cppbor::Array recipients);
-ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>> getSenderPubKeyFromCoseEncrypt(
- const cppbor::Item* encryptItem);
-inline ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>>
-getSenderPubKeyFromCoseEncrypt(const std::unique_ptr<cppbor::Item>& encryptItem) {
- return getSenderPubKeyFromCoseEncrypt(encryptItem.get());
-}
-
-ErrMsgOr<bytevec /* plaintextPayload */> decryptCoseEncrypt(const bytevec& key,
- const cppbor::Item* encryptItem,
- const bytevec& aad);
-
-ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& senderPubKey, const bytevec& senderPrivKey,
- const bytevec& recipientPubKey, bool senderIsA);
-
-ErrMsgOr<bytevec /* ciphertextWithTag */> aesGcmEncrypt(const bytevec& key, const bytevec& nonce,
- const bytevec& aad,
- const bytevec& plaintext);
-ErrMsgOr<bytevec /* plaintext */> aesGcmDecrypt(const bytevec& key, const bytevec& nonce,
- const bytevec& aad,
- const bytevec& ciphertextWithTag);
-
-} // namespace cppcose
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index 5e205a2..e4261f3 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -18,7 +18,7 @@
#include <vector>
-#include <cppcose/cppcose.h>
+#include <keymaster/cppcose/cppcose.h>
namespace aidl::android::hardware::security::keymint::remote_prov {
diff --git a/sensors/2.1/default/SensorsV2_1.cpp b/sensors/2.1/default/SensorsV2_1.cpp
index 4c5386a..06446a2 100644
--- a/sensors/2.1/default/SensorsV2_1.cpp
+++ b/sensors/2.1/default/SensorsV2_1.cpp
@@ -46,7 +46,8 @@
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
mSensorInfo.flags = static_cast<uint32_t>(V1_0::SensorFlagBits::ON_CHANGE_MODE |
- V1_0::SensorFlagBits::WAKE_UP);
+ V1_0::SensorFlagBits::WAKE_UP |
+ V1_0::SensorFlagBits::DATA_INJECTION);
}
};
diff --git a/tetheroffload/control/1.1/Android.bp b/tetheroffload/control/1.1/Android.bp
index e87ff5c..7871c2c 100644
--- a/tetheroffload/control/1.1/Android.bp
+++ b/tetheroffload/control/1.1/Android.bp
@@ -21,5 +21,9 @@
"android.hardware.tetheroffload.control@1.0",
"android.hidl.base@1.0",
],
+ apex_available: [
+ "//apex_available:platform", // Used by InProcessTethering
+ "com.android.tethering",
+ ],
gen_java: true,
}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index a9d1ed5..4d03ebf 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -553,8 +553,6 @@
}
TEST_P(VibratorAidl, ComposeCallback) {
- constexpr std::chrono::milliseconds allowedLatency{10};
-
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
@@ -586,17 +584,16 @@
<< toString(primitive);
duration = std::chrono::milliseconds(durationMs);
+ start = high_resolution_clock::now();
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
<< toString(primitive);
- start = high_resolution_clock::now();
- EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), std::future_status::ready)
+ EXPECT_EQ(completionFuture.wait_for(duration * 2), std::future_status::ready)
<< toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
- EXPECT_LE(elapsed.count(), (duration + allowedLatency).count()) << toString(primitive);
- EXPECT_GE(elapsed.count(), (duration - allowedLatency).count()) << toString(primitive);
+ EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
}
}
}
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
index 29bd9a9..61627d9 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
@@ -12,7 +12,8 @@
* 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.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -37,6 +38,6 @@
android.hardware.weaver.WeaverReadResponse read(in int slotId, in byte[] key);
void write(in int slotId, in byte[] key, in byte[] value);
const int STATUS_FAILED = 1;
- const int INCORRECT_KEY = 2;
- const int THROTTLE = 3;
+ const int STATUS_INCORRECT_KEY = 2;
+ const int STATUS_THROTTLE = 3;
}
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
index 239cdac..7491f32 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
@@ -12,7 +12,8 @@
* 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.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -33,7 +34,7 @@
package android.hardware.weaver;
@VintfStability
parcelable WeaverConfig {
- long slots;
- long keySize;
- long valueSize;
+ int slots;
+ int keySize;
+ int valueSize;
}
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
index 7e5db59..47ee4c8 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
@@ -12,7 +12,8 @@
* 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.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/weaver/aidl/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
index ebbfabe..f51034a 100644
--- a/weaver/aidl/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
@@ -46,8 +46,8 @@
* Read binder calls may return a ServiceSpecificException with the following error codes.
*/
const int STATUS_FAILED = 1;
- const int INCORRECT_KEY = 2;
- const int THROTTLE = 3;
+ const int STATUS_INCORRECT_KEY = 2;
+ const int STATUS_THROTTLE = 3;
/**
* Attempts to retrieve the value stored in the identified slot.
diff --git a/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
index 75d961e..a156a7b 100644
--- a/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
+++ b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
@@ -21,14 +21,14 @@
/**
* The number of slots available.
*/
- long slots;
+ int slots;
/**
* The number of bytes used for a key.
*/
- long keySize;
+ int keySize;
/**
* The number of bytes used for a value.
*/
- long valueSize;
+ int valueSize;
}
diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
index 7d8daa2..878c762 100644
--- a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
+++ b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
@@ -156,7 +156,7 @@
ASSERT_FALSE(readRet.isOk());
ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
- ASSERT_EQ(IWeaver::INCORRECT_KEY, readRet.getServiceSpecificError());
+ ASSERT_EQ(IWeaver::STATUS_INCORRECT_KEY, readRet.getServiceSpecificError());
EXPECT_TRUE(readValue.empty());
}
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index e199850..8d7a36e 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -47,6 +47,15 @@
* - This will be invoked before an active wifi connection is established on the second
* interface.
* - This use-case hint is implicitly void when the second STA interface is brought down.
+ * - When there is only 1 STA interface, the must should still retain the last use case
+ * set, which must become active the next time multi STA is enabled.
+ * 1. Initialize with single STA.
+ * 2. Framework creates second STA.
+ * 3. Framework sets use case to DUAL_STA_NON_TRANSIENT_UNBIASED.
+ * 4. Framework destroys second STA. Only 1 STA remains.
+ * 5. Framework recreates second STA.
+ * 6. The active use case remains DUAL_STA_NON_TRANSIENT_UNBIASED (i.e. firmware should not
+ * automatically change it during period of single STA unless requested by framework).
*/
enum MultiStaUseCase : uint8_t {
/**
@@ -100,11 +109,14 @@
/**
* Invoked to indicate that the provided iface is the primary STA iface when there are more
* than 1 STA iface concurrently active.
- * Note: If the wifi firmware/chip cannot support multiple instances of any offload
- * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
- * offloads are at least enabled for the primary interface. If the new primary interface is
- * already connected to a network, the firmware must switch all the offloads on
- * this new interface without disconnecting.
+ * Notes:
+ * - If the wifi firmware/chip cannot support multiple instances of any offload
+ * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
+ * offloads are at least enabled for the primary interface. If the new primary interface is
+ * already connected to a network, the firmware must switch all the offloads on
+ * this new interface without disconnecting.
+ * - When there is only 1 STA interface, the firmware must still retain the last primary
+ * connection, which must become active the next time multi STA is enabled.
*
* @param ifname Name of the STA iface.
* @return status WifiStatus of the operation.
diff --git a/wifi/1.5/default/OWNERS b/wifi/1.5/default/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.5/default/OWNERS
+++ b/wifi/1.5/default/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 848fbd6..5074252 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1677,7 +1677,7 @@
}
wifi_error WifiLegacyHal::triggerSubsystemRestart() {
- return global_func_table_.wifi_trigger_subsystem_restart();
+ return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
}
void WifiLegacyHal::invalidate() {
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
index b9c7b30..bd0e8cf 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -26,6 +26,7 @@
#include "supplicant_hidl_call_util.h"
#include "supplicant_hidl_test_utils.h"
+#include <cutils/properties.h>
using ::android::sp;
using ::android::hardware::hidl_array;
@@ -62,7 +63,7 @@
constexpr uint32_t kTestRadioWorkFrequency = 2412;
constexpr uint32_t kTestRadioWorkTimeout = 8;
constexpr uint32_t kTestRadioWorkId = 16;
-constexpr int8_t kTestCountryCode[] = {'U', 'S'};
+int8_t kTestCountryCode[] = {'U', 'S'};
constexpr uint8_t kTestWpsDeviceType[] = {[0 ... 7] = 0x01};
constexpr uint16_t kTestWpsConfigMethods = 0xffff;
} // namespace
@@ -444,6 +445,10 @@
* SetCountryCode.
*/
TEST_P(SupplicantStaIfaceHidlTest, SetCountryCode) {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ property_get("ro.boot.wificountrycode", buffer.data(), "US");
+ kTestCountryCode[0] = buffer.data()[0];
+ kTestCountryCode[1] = buffer.data()[1];
sta_iface_->setCountryCode(
kTestCountryCode, [](const SupplicantStatus& status) {
EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ b/wifi/supplicant/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com
diff --git a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
index 4f95213..4dfe8e6 100644
--- a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
@@ -41,7 +41,7 @@
/**
* GCMP-128 Pairwise Cipher
*/
- GCMP_128 = 1 << 9,
+ GCMP_128 = 1 << 6,
};
/**
@@ -51,7 +51,7 @@
/**
* GCMP-128 Group Cipher
*/
- GCMP_128 = 1 << 9,
+ GCMP_128 = 1 << 6,
};
/**
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ b/wifi/supplicant/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
etancohen@google.com