Merge "Add Unix_time and STORAGE_ENCRYPTION_BINDING_SEED" into sc-dev
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index 653531d..7d2706c 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -155,6 +155,12 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
+ public enum AudioEncapsulationType {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
+ enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+ }
+
public enum AudioFormat {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC;
@@ -488,10 +494,12 @@
public class Profile {
ctor public Profile();
method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask> getChannelMasks();
+ method @Nullable public android.audio.policy.configuration.V7_0.AudioEncapsulationType getEncapsulationType();
method @Nullable public String getFormat();
method @Nullable public String getName();
method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask>);
+ method public void setEncapsulationType(@Nullable android.audio.policy.configuration.V7_0.AudioEncapsulationType);
method public void setFormat(@Nullable String);
method public void setName(@Nullable String);
method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index ee51aa8..2030921 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -551,11 +551,18 @@
<xs:simpleType name="channelMasks">
<xs:list itemType="audioChannelMask" />
</xs:simpleType>
+ <xs:simpleType name="audioEncapsulationType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+ </xs:restriction>
+ </xs:simpleType>
<xs:complexType name="profile">
<xs:attribute name="name" type="xs:token" use="optional"/>
<xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
<xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
<xs:attribute name="channelMasks" type="channelMasks" use="optional"/>
+ <xs:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/>
</xs:complexType>
<xs:simpleType name="audioGainMode">
<xs:restriction base="xs:string">
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/common/7.0/enums/OWNERS
similarity index 67%
rename from audio/effect/all-versions/default/OWNERS
rename to audio/common/7.0/enums/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/common/7.0/enums/OWNERS
@@ -1,3 +1,2 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
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 fe8eee1..7d83556 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
@@ -212,6 +212,15 @@
return isOutputDevice(stringToAudioDevice(device));
}
+static inline bool isTelephonyDevice(AudioDevice device) {
+ return device == AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX ||
+ device == AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX;
+}
+
+static inline bool isTelephonyDevice(const std::string& device) {
+ return isTelephonyDevice(stringToAudioDevice(device));
+}
+
static inline bool maybeVendorExtension(const std::string& s) {
// Only checks whether the string starts with the "vendor prefix".
static const std::string vendorPrefix = "VX_";
@@ -260,6 +269,28 @@
return stringToAudioUsage(usage) == AudioUsage::UNKNOWN;
}
+static inline bool isLinearPcm(AudioFormat format) {
+ switch (format) {
+ case AudioFormat::AUDIO_FORMAT_PCM_16_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_8_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_32_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_8_24_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_FLOAT:
+ case AudioFormat::AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool isLinearPcm(const std::string& format) {
+ return isLinearPcm(stringToAudioFormat(format));
+}
+
+static inline bool isUnknownAudioEncapsulationType(const std::string& encapsulationType) {
+ return stringToAudioEncapsulationType(encapsulationType) == AudioEncapsulationType::UNKNOWN;
+}
+
} // namespace android::audio::policy::configuration::V7_0
#endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/common/7.0/example/OWNERS
similarity index 67%
copy from audio/effect/all-versions/default/OWNERS
copy to audio/common/7.0/example/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/common/7.0/example/OWNERS
@@ -1,3 +1,2 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 4f920e4..6fca93e 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -145,6 +145,14 @@
};
/**
+ * Audio encapsulation type indicates the encapsulation type that is required
+ * for playback/capture.
+ * See 'audioEncapsulationType' in audio_policy_configuration.xsd for the list
+ * of allowed values.
+ */
+typedef string AudioEncapsulationType;
+
+/**
* Configurations supported for a certain audio format.
*/
struct AudioProfile {
@@ -156,6 +164,35 @@
};
/**
+ * AudioTransport struct describes the capability of an audio port. The
+ * capability is described via AudioProfile or raw hardware descriptors for
+ * for formats that are not supported by the platform.
+ */
+struct AudioTransport {
+ safe_union AudioCapability {
+ /**
+ * A certain audio format that is known by the platform and its
+ * corresponding configuration.
+ */
+ AudioProfile profile;
+ /**
+ * The audio descriptor that is reported from EDID. See HDMI
+ * specification 1.4b section 7 and CEA-861-G section 7.5.2 for more
+ * information. When this value is set, it indicates the standard is
+ * AUDIO_STANDARD_EDID.
+ */
+ vec<uint8_t> edid;
+ } audioCapability;
+
+ /**
+ * The encapsulation type that is required when the framework is using this
+ * format when playing or capturing to/from a stream or device exposing this
+ * audio transport.
+ */
+ AudioEncapsulationType encapsulationType;
+};
+
+/**
* Major modes for a mobile device. The current mode setting affects audio
* routing.
*/
@@ -488,8 +525,12 @@
* E.g. "telephony_tx" or "fm_tuner".
*/
string name;
- /** List of audio profiles supported by the port. */
- vec<AudioProfile> profiles;
+ /**
+ * List of audio transports supported by the audio port. This includes
+ * supported formats and raw hardware descriptors for formats not supported
+ * by the platform.
+ */
+ vec<AudioTransport> transports;
/** List of gain controls attached to the port. */
vec<AudioGain> gains;
/** Parameters that depend on the actual port role. */
diff --git a/audio/common/all-versions/OWNERS b/audio/common/all-versions/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/common/all-versions/OWNERS
+++ b/audio/common/all-versions/OWNERS
@@ -1,3 +1,2 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index 2949fac..5a5b5d2 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -715,6 +715,27 @@
return result;
}
+status_t HidlUtils::encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType,
+ AudioEncapsulationType* encapsulationType) {
+ *encapsulationType = audio_encapsulation_type_to_string(halEncapsulationType);
+ if (!encapsulationType->empty() && !xsd::isUnknownAudioEncapsulationType(*encapsulationType)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio encapsulation type value 0x%X", halEncapsulationType);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType,
+ audio_encapsulation_type_t* halEncapsulationType) {
+ if (!xsd::isUnknownAudioEncapsulationType(encapsulationType) &&
+ audio_encapsulation_type_from_string(encapsulationType.c_str(), halEncapsulationType)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio encapsulation type \"%s\"", encapsulationType.c_str());
+ *halEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE;
+ return BAD_VALUE;
+}
+
status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
struct audio_port_v7 halPortV7 = {};
audio_populate_audio_port_v7(&halPort, &halPortV7);
@@ -758,11 +779,7 @@
CONVERT_CHECKED(audioPortExtendedInfoFromHal(halPort.role, halPort.type, halDevice, halMix,
halSession, &port->ext, &isInput),
result);
- port->profiles.resize(halPort.num_audio_profiles);
- for (size_t i = 0; i < halPort.num_audio_profiles; ++i) {
- CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput, &port->profiles[i]),
- result);
- }
+ CONVERT_CHECKED(audioTransportsFromHal(halPort, isInput, &port->transports), result);
port->gains.resize(halPort.num_gains);
for (size_t i = 0; i < halPort.num_gains; ++i) {
CONVERT_CHECKED(audioGainFromHal(halPort.gains[i], isInput, &port->gains[i]), result);
@@ -780,15 +797,7 @@
ALOGE("HIDL Audio Port name is too long: %zu", port.name.size());
result = BAD_VALUE;
}
- halPort->num_audio_profiles = port.profiles.size();
- if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) {
- ALOGE("HIDL Audio Port has too many profiles: %u", halPort->num_audio_profiles);
- halPort->num_audio_profiles = AUDIO_PORT_MAX_AUDIO_PROFILES;
- result = BAD_VALUE;
- }
- for (size_t i = 0; i < halPort->num_audio_profiles; ++i) {
- CONVERT_CHECKED(audioProfileToHal(port.profiles[i], &halPort->audio_profiles[i]), result);
- }
+ CONVERT_CHECKED(audioTransportsToHal(port.transports, halPort), result);
halPort->num_gains = port.gains.size();
if (halPort->num_gains > AUDIO_PORT_MAX_GAINS) {
ALOGE("HIDL Audio Port has too many gains: %u", halPort->num_gains);
@@ -824,6 +833,110 @@
return result;
}
+status_t HidlUtils::audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput,
+ hidl_vec<AudioTransport>* transports) {
+ if (halPort.num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES ||
+ halPort.num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) {
+ ALOGE("%s, too many audio profiles(%u) or extra audio descriptors(%u)", __func__,
+ halPort.num_audio_profiles, halPort.num_extra_audio_descriptors);
+ return BAD_VALUE;
+ }
+ status_t result = NO_ERROR;
+ transports->resize(halPort.num_audio_profiles + halPort.num_extra_audio_descriptors);
+ size_t idx = 0;
+ for (size_t i = 0; i < halPort.num_audio_profiles; ++i) {
+ auto& transport = (*transports)[idx++];
+ transport.audioCapability.profile({});
+ CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput,
+ &transport.audioCapability.profile()),
+ result);
+ CONVERT_CHECKED(encapsulationTypeFromHal(halPort.audio_profiles[i].encapsulation_type,
+ &transport.encapsulationType),
+ result);
+ }
+ for (size_t i = 0; i < halPort.num_extra_audio_descriptors; ++i) {
+ switch (halPort.extra_audio_descriptors[i].standard) {
+ case AUDIO_STANDARD_EDID: {
+ const struct audio_extra_audio_descriptor* extraAudioDescriptor =
+ &halPort.extra_audio_descriptors[i];
+ if (extraAudioDescriptor->descriptor_length <= EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ auto& transport = (*transports)[idx++];
+ transport.audioCapability.edid(
+ hidl_vec<uint8_t>(extraAudioDescriptor->descriptor,
+ extraAudioDescriptor->descriptor +
+ extraAudioDescriptor->descriptor_length));
+ CONVERT_CHECKED(
+ encapsulationTypeFromHal(extraAudioDescriptor->encapsulation_type,
+ &transport.encapsulationType),
+ result);
+ } else {
+ ALOGE("%s, invalid descriptor length %u", __func__,
+ extraAudioDescriptor->descriptor_length);
+ result = BAD_VALUE;
+ }
+ } break;
+ case AUDIO_STANDARD_NONE:
+ default:
+ ALOGE("%s, invalid standard %u", __func__,
+ halPort.extra_audio_descriptors[i].standard);
+ result = BAD_VALUE;
+ break;
+ }
+ }
+ return result;
+}
+
+status_t HidlUtils::audioTransportsToHal(const hidl_vec<AudioTransport>& transports,
+ struct audio_port_v7* halPort) {
+ status_t result = NO_ERROR;
+ halPort->num_audio_profiles = 0;
+ halPort->num_extra_audio_descriptors = 0;
+ for (const auto& transport : transports) {
+ switch (transport.audioCapability.getDiscriminator()) {
+ case AudioTransport::AudioCapability::hidl_discriminator::profile:
+ if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) {
+ ALOGE("%s, too many audio profiles", __func__);
+ result = BAD_VALUE;
+ break;
+ }
+ CONVERT_CHECKED(
+ audioProfileToHal(transport.audioCapability.profile(),
+ &halPort->audio_profiles[halPort->num_audio_profiles]),
+ result);
+ CONVERT_CHECKED(encapsulationTypeToHal(
+ transport.encapsulationType,
+ &halPort->audio_profiles[halPort->num_audio_profiles++]
+ .encapsulation_type),
+ result);
+ break;
+ case AudioTransport::AudioCapability::hidl_discriminator::edid:
+ if (halPort->num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) {
+ ALOGE("%s, too many extra audio descriptors", __func__);
+ result = BAD_VALUE;
+ break;
+ }
+ if (transport.audioCapability.edid().size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ ALOGE("%s, wrong edid size %zu", __func__,
+ transport.audioCapability.edid().size());
+ result = BAD_VALUE;
+ break;
+ }
+ struct audio_extra_audio_descriptor* extraAudioDescriptor =
+ &halPort->extra_audio_descriptors[halPort->num_extra_audio_descriptors++];
+ extraAudioDescriptor->standard = AUDIO_STANDARD_EDID;
+ extraAudioDescriptor->descriptor_length = transport.audioCapability.edid().size();
+ memcpy(extraAudioDescriptor->descriptor, transport.audioCapability.edid().data(),
+ transport.audioCapability.edid().size() * sizeof(uint8_t));
+
+ CONVERT_CHECKED(encapsulationTypeToHal(transport.encapsulationType,
+ &extraAudioDescriptor->encapsulation_type),
+ result);
+ break;
+ }
+ }
+ return result;
+}
+
status_t HidlUtils::audioProfileFromHal(const struct audio_profile& halProfile, bool isInput,
AudioProfile* profile) {
status_t result = NO_ERROR;
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index dd4ca4d..98ecc07 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -126,6 +126,10 @@
static hidl_vec<AudioTag> filterOutNonVendorTags(const hidl_vec<AudioTag>& tags);
static std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags);
static std::vector<std::string> splitAudioTags(const char* halTags);
+ static status_t audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput,
+ hidl_vec<AudioTransport>* transports);
+ static status_t audioTransportsToHal(const hidl_vec<AudioTransport>& transports,
+ struct audio_port_v7* halTransport);
private:
static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
@@ -145,6 +149,10 @@
struct audio_port_config_device_ext* device,
struct audio_port_config_mix_ext* mix,
struct audio_port_config_session_ext* session);
+ static status_t encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType,
+ AudioEncapsulationType* encapsulationType);
+ static status_t encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType,
+ audio_encapsulation_type_t* halEncapsulationType);
#endif // MAJOR_VERSION >= 7
diff --git a/audio/common/all-versions/default/OWNERS b/audio/common/all-versions/default/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/common/all-versions/default/OWNERS
+++ b/audio/common/all-versions/default/OWNERS
@@ -1,3 +1,2 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index e154453..c9e6fac 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -47,6 +47,10 @@
// AUDIO_STREAM_DEFAULT is framework-only
static constexpr audio_stream_type_t kInvalidHalStreamType = static_cast<audio_stream_type_t>(-2);
static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU);
+static constexpr audio_encapsulation_type_t kInvalidEncapsulationType =
+ static_cast<audio_encapsulation_type_t>(0xFFFFFFFFU);
+static constexpr audio_standard_t kInvalidAudioStandard =
+ static_cast<audio_standard_t>(0xFFFFFFFFU);
TEST(HidlUtils, ConvertInvalidChannelMask) {
AudioChannelMask invalid;
@@ -950,6 +954,53 @@
EXPECT_TRUE(audio_port_configs_are_equal(&halConfig, &halConfigBack));
}
+TEST(HidlUtils, ConvertInvalidAudioTransports) {
+ hidl_vec<AudioTransport> invalid;
+ struct audio_port_v7 halInvalid = {};
+ halInvalid.num_audio_profiles = 1;
+ halInvalid.audio_profiles[0].format = kInvalidHalFormat;
+ halInvalid.audio_profiles[0].encapsulation_type = kInvalidEncapsulationType;
+ halInvalid.num_extra_audio_descriptors = 1;
+ halInvalid.extra_audio_descriptors[0].standard = kInvalidAudioStandard;
+ halInvalid.extra_audio_descriptors[0].descriptor_length = EXTRA_AUDIO_DESCRIPTOR_SIZE + 1;
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::audioTransportsFromHal(halInvalid, false /*isInput*/, &invalid));
+ invalid.resize(2);
+ AudioProfile invalidProfile;
+ invalidProfile.format = "random string";
+ invalid[0].audioCapability.profile(invalidProfile);
+ invalid[0].encapsulationType = "random string";
+ invalid[0].audioCapability.edid(hidl_vec<uint8_t>(EXTRA_AUDIO_DESCRIPTOR_SIZE + 1));
+ invalid[1].encapsulationType = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertAudioTransports) {
+ hidl_vec<AudioTransport> transports;
+ transports.resize(2);
+ AudioProfile profile;
+ profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ profile.sampleRates.resize(2);
+ profile.sampleRates[0] = 44100;
+ profile.sampleRates[1] = 48000;
+ profile.channelMasks.resize(2);
+ profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+ profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ transports[0].audioCapability.profile(profile);
+ hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01});
+ transports[0].encapsulationType =
+ toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE);
+ transports[1].audioCapability.edid(std::move(shortAudioDescriptor));
+ transports[1].encapsulationType =
+ toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937);
+ struct audio_port_v7 halPort;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTransportsToHal(transports, &halPort));
+ hidl_vec<AudioTransport> transportsBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioTransportsFromHal(halPort, false /*isInput*/, &transportsBack));
+ EXPECT_EQ(transports, transportsBack);
+}
+
TEST(HidlUtils, ConvertInvalidAudioPort) {
AudioPort invalid;
struct audio_port_v7 halInvalid = {};
@@ -958,8 +1009,10 @@
halInvalid.num_audio_profiles = 1;
halInvalid.audio_profiles[0].format = kInvalidHalFormat;
EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortFromHal(halInvalid, &invalid));
- invalid.profiles.resize(1);
- invalid.profiles[0].format = "random string";
+ invalid.transports.resize(1);
+ AudioProfile invalidProfile;
+ invalidProfile.format = "random string";
+ invalid.transports[0].audioCapability.profile(invalidProfile);
EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortToHal(invalid, &halInvalid));
}
@@ -967,14 +1020,22 @@
AudioPort port = {};
port.id = 42;
port.name = "test";
- port.profiles.resize(1);
- port.profiles[0].format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
- port.profiles[0].sampleRates.resize(2);
- port.profiles[0].sampleRates[0] = 44100;
- port.profiles[0].sampleRates[1] = 48000;
- port.profiles[0].channelMasks.resize(2);
- port.profiles[0].channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
- port.profiles[0].channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ port.transports.resize(2);
+ AudioProfile profile;
+ profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ profile.sampleRates.resize(2);
+ profile.sampleRates[0] = 44100;
+ profile.sampleRates[1] = 48000;
+ profile.channelMasks.resize(2);
+ profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+ profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ port.transports[0].audioCapability.profile(profile);
+ port.transports[0].encapsulationType =
+ toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE);
+ hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01});
+ port.transports[1].audioCapability.edid(std::move(shortAudioDescriptor));
+ port.transports[1].encapsulationType =
+ toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937);
port.gains.resize(1);
port.gains[0].channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
port.ext.device({});
diff --git a/audio/common/all-versions/test/OWNERS b/audio/common/all-versions/test/OWNERS
deleted file mode 100644
index 6a26ae7..0000000
--- a/audio/common/all-versions/test/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-yim@google.com
-zhuoyao@google.com
diff --git a/audio/core/all-versions/default/OWNERS b/audio/core/all-versions/OWNERS
similarity index 100%
rename from audio/core/all-versions/default/OWNERS
rename to audio/core/all-versions/OWNERS
diff --git a/audio/core/all-versions/vts/OWNERS b/audio/core/all-versions/vts/OWNERS
deleted file mode 100644
index 0ea4666..0000000
--- a/audio/core/all-versions/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
-yim@google.com
-zhuoyao@google.com
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index f87e5ed..b96cc83 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -77,7 +77,6 @@
.tags = {},
.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
#endif
- EventFlag* efGroup;
for (auto microphone : microphones) {
#if MAJOR_VERSION <= 6
if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
@@ -96,44 +95,15 @@
config, flags, initMetadata, cb);
},
config, &res, &suggestedConfig));
+ StreamReader reader(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(reader.start());
+ reader.pause(); // This ensures that at least one read has happened.
+ EXPECT_FALSE(reader.hasError());
+
hidl_vec<MicrophoneInfo> activeMicrophones;
- Result readRes;
- typedef MessageQueue<IStreamIn::ReadParameters, kSynchronizedReadWrite> CommandMQ;
- typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
- std::unique_ptr<CommandMQ> commandMQ;
- std::unique_ptr<DataMQ> dataMQ;
- size_t frameSize = stream->getFrameSize();
- size_t frameCount = stream->getBufferSize() / frameSize;
- ASSERT_OK(stream->prepareForReading(
- frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) {
- readRes = r;
- if (readRes == Result::OK) {
- commandMQ.reset(new CommandMQ(c));
- dataMQ.reset(new DataMQ(d));
- if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
- EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
- }
- }
- }));
- ASSERT_OK(readRes);
- IStreamIn::ReadParameters params;
- params.command = IStreamIn::ReadCommand::READ;
- ASSERT_TRUE(commandMQ != nullptr);
- ASSERT_TRUE(commandMQ->isValid());
- ASSERT_TRUE(commandMQ->write(¶ms));
- efGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
- uint32_t efState = 0;
- efGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
- if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
- ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
- ASSERT_OK(res);
- ASSERT_NE(0U, activeMicrophones.size());
- }
- helper.close(true /*clear*/, &res);
+ ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
ASSERT_OK(res);
- if (efGroup) {
- EventFlag::deleteEventFlag(&efGroup);
- }
+ EXPECT_NE(0U, activeMicrophones.size());
}
}
}
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index c1923f1..0b3098b 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <android-base/chrono_utils.h>
+
#include "Generators.h"
// pull in all the <= 6.0 tests
@@ -487,3 +489,353 @@
<< ::testing::PrintToString(metadata);
}
}
+
+static const std::vector<DeviceConfigParameter>& getOutputDevicePcmOnlyConfigParameters() {
+ static const std::vector<DeviceConfigParameter> parameters = [] {
+ auto allParams = getOutputDeviceConfigParameters();
+ std::vector<DeviceConfigParameter> pcmParams;
+ std::copy_if(allParams.begin(), allParams.end(), std::back_inserter(pcmParams), [](auto cfg) {
+ const auto& flags = std::get<PARAM_FLAGS>(cfg);
+ return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
+ // MMAP NOIRQ and HW A/V Sync profiles use special writing protocols.
+ &&
+ std::find_if(flags.begin(), flags.end(),
+ [](const auto& flag) {
+ return flag == toString(xsd::AudioInOutFlag::
+ AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
+ flag == toString(xsd::AudioInOutFlag::
+ AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+ }) == flags.end() &&
+ !getCachedPolicyConfig()
+ .getAttachedSinkDeviceForMixPort(
+ std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
+ std::get<PARAM_PORT_NAME>(cfg))
+ .empty();
+ });
+ return pcmParams;
+ }();
+ return parameters;
+}
+
+class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
+ public:
+ void TearDown() override {
+ releasePatchIfNeeded();
+ OutputStreamTest::TearDown();
+ }
+
+ bool canQueryPresentationPosition() const {
+ auto maybeSinkAddress =
+ getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
+ // Returning 'true' when no sink is found so the test can fail later with a more clear
+ // problem description.
+ return !maybeSinkAddress.has_value() ||
+ !xsd::isTelephonyDevice(maybeSinkAddress.value().deviceType);
+ }
+
+ void createPatchIfNeeded() {
+ auto maybeSinkAddress =
+ getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
+ ASSERT_TRUE(maybeSinkAddress.has_value())
+ << "No sink device found for mix port " << getMixPortName() << " (module "
+ << getDeviceName() << ")";
+ if (areAudioPatchesSupported()) {
+ AudioPortConfig source;
+ source.base.format.value(getConfig().base.format);
+ source.base.sampleRateHz.value(getConfig().base.sampleRateHz);
+ source.base.channelMask.value(getConfig().base.channelMask);
+ source.ext.mix({});
+ source.ext.mix().ioHandle = helper.getIoHandle();
+ source.ext.mix().useCase.stream({});
+ AudioPortConfig sink;
+ sink.ext.device(maybeSinkAddress.value());
+ EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
+ hidl_vec<AudioPortConfig>{sink},
+ returnIn(res, mPatchHandle)));
+ mHasPatch = res == Result::OK;
+ } else {
+ EXPECT_OK(stream->setDevices({maybeSinkAddress.value()}));
+ }
+ }
+
+ void releasePatchIfNeeded() {
+ if (areAudioPatchesSupported()) {
+ if (mHasPatch) {
+ EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
+ mHasPatch = false;
+ }
+ } else {
+ EXPECT_OK(stream->setDevices({address}));
+ }
+ }
+
+ const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
+
+ void waitForPresentationPositionAdvance(StreamWriter& writer, uint64_t* firstPosition = nullptr,
+ uint64_t* lastPosition = nullptr) {
+ static constexpr int kWriteDurationUs = 50 * 1000;
+ static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
+ uint64_t framesInitial;
+ TimeSpec ts;
+ // Starting / resuming of streams is asynchronous at HAL level.
+ // Sometimes HAL doesn't have enough information until the audio data actually gets
+ // consumed by the hardware.
+ bool timedOut = false;
+ res = Result::INVALID_STATE;
+ for (android::base::Timer elapsed;
+ res != Result::OK && !writer.hasError() &&
+ !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+ usleep(kWriteDurationUs);
+ ASSERT_OK(stream->getPresentationPosition(returnIn(res, framesInitial, ts)));
+ ASSERT_RESULT(okOrInvalidState, res);
+ }
+ ASSERT_FALSE(writer.hasError());
+ ASSERT_FALSE(timedOut);
+
+ uint64_t frames = framesInitial;
+ for (android::base::Timer elapsed;
+ frames <= framesInitial && !writer.hasError() &&
+ !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+ usleep(kWriteDurationUs);
+ ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, ts)));
+ ASSERT_RESULT(Result::OK, res);
+ }
+ EXPECT_FALSE(timedOut);
+ EXPECT_FALSE(writer.hasError());
+ EXPECT_GT(frames, framesInitial);
+ if (firstPosition) *firstPosition = framesInitial;
+ if (lastPosition) *lastPosition = frames;
+ }
+
+ private:
+ AudioPatchHandle mPatchHandle = {};
+ bool mHasPatch = false;
+};
+
+TEST_P(PcmOnlyConfigOutputStreamTest, Write) {
+ doc::test("Check that output streams opened for PCM output accepts audio data");
+ StreamWriter writer(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(writer.start());
+ EXPECT_TRUE(writer.waitForAtLeastOneCycle());
+}
+
+TEST_P(PcmOnlyConfigOutputStreamTest, PresentationPositionAdvancesWithWrites) {
+ doc::test("Check that the presentation position advances with writes");
+ if (!canQueryPresentationPosition()) {
+ GTEST_SKIP() << "Presentation position retrieval is not possible";
+ }
+
+ ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+ StreamWriter writer(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(writer.start());
+ ASSERT_TRUE(writer.waitForAtLeastOneCycle());
+ ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer));
+
+ writer.stop();
+ releasePatchIfNeeded();
+}
+
+TEST_P(PcmOnlyConfigOutputStreamTest, PresentationPositionPreservedOnStandby) {
+ doc::test("Check that the presentation position does not reset on standby");
+ if (!canQueryPresentationPosition()) {
+ GTEST_SKIP() << "Presentation position retrieval is not possible";
+ }
+
+ ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+ StreamWriter writer(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(writer.start());
+ ASSERT_TRUE(writer.waitForAtLeastOneCycle());
+
+ uint64_t framesInitial;
+ ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer, nullptr, &framesInitial));
+ writer.pause();
+ ASSERT_OK(stream->standby());
+ writer.resume();
+
+ uint64_t frames;
+ ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer, &frames));
+ EXPECT_GT(frames, framesInitial);
+
+ writer.stop();
+ releasePatchIfNeeded();
+}
+
+INSTANTIATE_TEST_CASE_P(PcmOnlyConfigOutputStream, PcmOnlyConfigOutputStreamTest,
+ ::testing::ValuesIn(getOutputDevicePcmOnlyConfigParameters()),
+ &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigOutputStreamTest);
+
+static const std::vector<DeviceConfigParameter>& getInputDevicePcmOnlyConfigParameters() {
+ static const std::vector<DeviceConfigParameter> parameters = [] {
+ auto allParams = getInputDeviceConfigParameters();
+ std::vector<DeviceConfigParameter> pcmParams;
+ std::copy_if(
+ allParams.begin(), allParams.end(), std::back_inserter(pcmParams), [](auto cfg) {
+ const auto& flags = std::get<PARAM_FLAGS>(cfg);
+ return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
+ // MMAP NOIRQ profiles use different reading protocol,
+ // reading h/w hotword might require Soundtrigger to be active.
+ &&
+ std::find_if(
+ flags.begin(), flags.end(),
+ [](const auto& flag) {
+ return flag == toString(
+ xsd::AudioInOutFlag::
+ AUDIO_INPUT_FLAG_MMAP_NOIRQ) ||
+ flag == toString(xsd::AudioInOutFlag::
+ AUDIO_INPUT_FLAG_HW_HOTWORD);
+ }) == flags.end() &&
+ !getCachedPolicyConfig()
+ .getAttachedSourceDeviceForMixPort(
+ std::get<PARAM_DEVICE_NAME>(
+ std::get<PARAM_DEVICE>(cfg)),
+ std::get<PARAM_PORT_NAME>(cfg))
+ .empty();
+ });
+ return pcmParams;
+ }();
+ return parameters;
+}
+
+class PcmOnlyConfigInputStreamTest : public InputStreamTest {
+ public:
+ void TearDown() override {
+ releasePatchIfNeeded();
+ InputStreamTest::TearDown();
+ }
+
+ bool canQueryCapturePosition() const {
+ auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
+ getDeviceName(), getMixPortName());
+ // Returning 'true' when no source is found so the test can fail later with a more clear
+ // problem description.
+ return !maybeSourceAddress.has_value() ||
+ !xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType);
+ }
+
+ void createPatchIfNeeded() {
+ auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
+ getDeviceName(), getMixPortName());
+ ASSERT_TRUE(maybeSourceAddress.has_value())
+ << "No source device found for mix port " << getMixPortName() << " (module "
+ << getDeviceName() << ")";
+ if (areAudioPatchesSupported()) {
+ AudioPortConfig source;
+ source.ext.device(maybeSourceAddress.value());
+ AudioPortConfig sink;
+ sink.base.format.value(getConfig().base.format);
+ sink.base.sampleRateHz.value(getConfig().base.sampleRateHz);
+ sink.base.channelMask.value(getConfig().base.channelMask);
+ sink.ext.mix({});
+ sink.ext.mix().ioHandle = helper.getIoHandle();
+ sink.ext.mix().useCase.source(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+ EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
+ hidl_vec<AudioPortConfig>{sink},
+ returnIn(res, mPatchHandle)));
+ mHasPatch = res == Result::OK;
+ } else {
+ EXPECT_OK(stream->setDevices({maybeSourceAddress.value()}));
+ }
+ }
+
+ void releasePatchIfNeeded() {
+ if (areAudioPatchesSupported()) {
+ if (mHasPatch) {
+ EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
+ mHasPatch = false;
+ }
+ } else {
+ EXPECT_OK(stream->setDevices({address}));
+ }
+ }
+
+ void waitForCapturePositionAdvance(StreamReader& reader, uint64_t* firstPosition = nullptr,
+ uint64_t* lastPosition = nullptr) {
+ static constexpr int kReadDurationUs = 50 * 1000;
+ static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
+ uint64_t framesInitial, ts;
+ // Starting / resuming of streams is asynchronous at HAL level.
+ // Sometimes HAL doesn't have enough information until the audio data actually has been
+ // produced by the hardware. Legacy HALs might return NOT_SUPPORTED when they actually
+ // mean INVALID_STATE.
+ bool timedOut = false;
+ res = Result::INVALID_STATE;
+ for (android::base::Timer elapsed;
+ res != Result::OK && !reader.hasError() &&
+ !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+ usleep(kReadDurationUs);
+ ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
+ ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
+ }
+ ASSERT_FALSE(reader.hasError());
+ ASSERT_FALSE(timedOut);
+
+ uint64_t frames = framesInitial;
+ for (android::base::Timer elapsed;
+ frames <= framesInitial && !reader.hasError() &&
+ !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+ usleep(kReadDurationUs);
+ ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
+ ASSERT_RESULT(Result::OK, res);
+ }
+ EXPECT_FALSE(timedOut);
+ EXPECT_FALSE(reader.hasError());
+ EXPECT_GT(frames, framesInitial);
+ if (firstPosition) *firstPosition = framesInitial;
+ if (lastPosition) *lastPosition = frames;
+ }
+
+ private:
+ AudioPatchHandle mPatchHandle = {};
+ bool mHasPatch = false;
+};
+
+TEST_P(PcmOnlyConfigInputStreamTest, Read) {
+ doc::test("Check that input streams opened for PCM input retrieve audio data");
+ StreamReader reader(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(reader.start());
+ EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+}
+
+TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionAdvancesWithReads) {
+ doc::test("Check that the capture position advances with reads");
+ if (!canQueryCapturePosition()) {
+ GTEST_SKIP() << "Capture position retrieval is not possible";
+ }
+
+ ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+ StreamReader reader(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(reader.start());
+ EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+ ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader));
+}
+
+TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionPreservedOnStandby) {
+ doc::test("Check that the capture position does not reset on standby");
+ if (!canQueryCapturePosition()) {
+ GTEST_SKIP() << "Capture position retrieval is not possible";
+ }
+
+ ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+ StreamReader reader(stream.get(), stream->getBufferSize());
+ ASSERT_TRUE(reader.start());
+ EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+
+ uint64_t framesInitial;
+ ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader, nullptr, &framesInitial));
+ reader.pause();
+ ASSERT_OK(stream->standby());
+ reader.resume();
+
+ uint64_t frames;
+ ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader, &frames, nullptr));
+ EXPECT_GT(frames, framesInitial);
+
+ reader.stop();
+ releasePatchIfNeeded();
+}
+
+INSTANTIATE_TEST_CASE_P(PcmOnlyConfigInputStream, PcmOnlyConfigInputStreamTest,
+ ::testing::ValuesIn(getInputDevicePcmOnlyConfigParameters()),
+ &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigInputStreamTest);
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index eafc813..d2ba339 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -110,7 +110,7 @@
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(config.base));
}
- result.emplace_back(device, config, flags);
+ result.emplace_back(device, mixPort.getName(), config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -160,7 +160,7 @@
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
{
AudioConfig config{.base = validBase};
@@ -168,7 +168,7 @@
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
@@ -176,32 +176,32 @@
config.offloadInfo.info(generateOffloadInfo(validBase));
}
std::vector<AudioInOutFlag> flags = {"random_string", ""};
- result.emplace_back(device, config, flags);
+ result.emplace_back(device, mixPort.getName(), config, flags);
}
if (isOffload) {
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.channelMask = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.format = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().streamType = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().usage = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
hasOffloadConfig = true;
} else {
@@ -234,7 +234,7 @@
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (const auto& config : configs) {
- result.emplace_back(device, config, flags);
+ result.emplace_back(device, mixPort.getName(), config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -285,17 +285,17 @@
{
AudioConfig config{.base = validBase};
config.base.channelMask = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
{
AudioConfig config{.base = validBase};
config.base.format = "random_string";
- result.emplace_back(device, config, validFlags);
+ result.emplace_back(device, mixPort.getName(), config, validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
std::vector<AudioInOutFlag> flags = {"random_string", ""};
- result.emplace_back(device, config, flags);
+ result.emplace_back(device, mixPort.getName(), config, flags);
}
hasConfig = true;
break;
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
new file mode 100644
index 0000000..2988207
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
@@ -0,0 +1,215 @@
+/*
+ * 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 <fcntl.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include <HidlUtils.h>
+#include <system/audio.h>
+#include <system/audio_config.h>
+
+#include "DeviceManager.h"
+#include "PolicyConfig.h"
+#include "common/all-versions/HidlSupport.h"
+
+using ::android::NO_ERROR;
+using ::android::OK;
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::utils::splitString;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
+using Module = Modules::Module;
+} // namespace xsd
+
+std::string PolicyConfig::getError() const {
+ if (mFilePath.empty()) {
+ return "Could not find " + mConfigFileName +
+ " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+ } else {
+ return "Invalid config file: " + mFilePath;
+ }
+}
+
+const xsd::Module* PolicyConfig::getModuleFromName(const std::string& name) const {
+ if (mConfig && mConfig->getFirstModules()) {
+ for (const auto& module : mConfig->getFirstModules()->get_module()) {
+ if (module.getName() == name) return &module;
+ }
+ }
+ return nullptr;
+}
+
+std::optional<DeviceAddress> PolicyConfig::getSinkDeviceForMixPort(
+ const std::string& moduleName, const std::string& mixPortName) const {
+ std::string device;
+ if (auto module = getModuleFromName(moduleName); module) {
+ auto possibleDevices = getSinkDevicesForMixPort(moduleName, mixPortName);
+ if (module->hasDefaultOutputDevice() &&
+ possibleDevices.count(module->getDefaultOutputDevice())) {
+ device = module->getDefaultOutputDevice();
+ } else {
+ device = getAttachedSinkDeviceForMixPort(moduleName, mixPortName);
+ }
+ }
+ if (!device.empty()) {
+ return getDeviceAddressOfDevicePort(moduleName, device);
+ }
+ ALOGE("Could not find a route for the mix port \"%s\" in module \"%s\"", mixPortName.c_str(),
+ moduleName.c_str());
+ return std::optional<DeviceAddress>{};
+}
+
+std::optional<DeviceAddress> PolicyConfig::getSourceDeviceForMixPort(
+ const std::string& moduleName, const std::string& mixPortName) const {
+ const std::string device = getAttachedSourceDeviceForMixPort(moduleName, mixPortName);
+ if (!device.empty()) {
+ return getDeviceAddressOfDevicePort(moduleName, device);
+ }
+ ALOGE("Could not find a route for the mix port \"%s\" in module \"%s\"", mixPortName.c_str(),
+ moduleName.c_str());
+ return std::optional<DeviceAddress>{};
+}
+
+bool PolicyConfig::haveInputProfilesInModule(const std::string& name) const {
+ auto module = getModuleFromName(name);
+ if (module && module->getFirstMixPorts()) {
+ for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+ if (mixPort.getRole() == xsd::Role::sink) return true;
+ }
+ }
+ return false;
+}
+
+// static
+std::string PolicyConfig::findExistingConfigurationFile(const std::string& fileName) {
+ for (const auto& location : android::audio_get_configuration_paths()) {
+ std::string path = location + '/' + fileName;
+ if (access(path.c_str(), F_OK) == 0) {
+ return path;
+ }
+ }
+ return {};
+}
+
+std::string PolicyConfig::findAttachedDevice(const std::vector<std::string>& attachedDevices,
+ const std::set<std::string>& possibleDevices) const {
+ for (const auto& device : attachedDevices) {
+ if (possibleDevices.count(device)) return device;
+ }
+ return {};
+}
+
+const std::vector<std::string>& PolicyConfig::getAttachedDevices(
+ const std::string& moduleName) const {
+ static const std::vector<std::string> empty;
+ auto module = getModuleFromName(moduleName);
+ if (module && module->getFirstAttachedDevices()) {
+ return module->getFirstAttachedDevices()->getItem();
+ }
+ return empty;
+}
+
+std::optional<DeviceAddress> PolicyConfig::getDeviceAddressOfDevicePort(
+ const std::string& moduleName, const std::string& devicePortName) const {
+ auto module = getModuleFromName(moduleName);
+ if (module->getFirstDevicePorts()) {
+ const auto& devicePorts = module->getFirstDevicePorts()->getDevicePort();
+ const auto& devicePort = std::find_if(
+ devicePorts.begin(), devicePorts.end(),
+ [&devicePortName](auto dp) { return dp.getTagName() == devicePortName; });
+ if (devicePort != devicePorts.end()) {
+ audio_devices_t halDeviceType;
+ if (HidlUtils::audioDeviceTypeToHal(devicePort->getType(), &halDeviceType) ==
+ NO_ERROR) {
+ // For AOSP device types use the standard parser for the device address.
+ const std::string address =
+ devicePort->hasAddress() ? devicePort->getAddress() : "";
+ DeviceAddress result;
+ if (HidlUtils::deviceAddressFromHal(halDeviceType, address.c_str(), &result) ==
+ NO_ERROR) {
+ return result;
+ }
+ } else if (xsd::isVendorExtension(devicePort->getType())) {
+ DeviceAddress result;
+ result.deviceType = devicePort->getType();
+ if (devicePort->hasAddress()) {
+ result.address.id(devicePort->getAddress());
+ }
+ return result;
+ }
+ } else {
+ ALOGE("Device port \"%s\" not found in module \"%s\"", devicePortName.c_str(),
+ moduleName.c_str());
+ }
+ } else {
+ ALOGE("Module \"%s\" has no device ports", moduleName.c_str());
+ }
+ return std::optional<DeviceAddress>{};
+}
+
+std::set<std::string> PolicyConfig::getSinkDevicesForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ std::set<std::string> result;
+ auto module = getModuleFromName(moduleName);
+ if (module && module->getFirstRoutes()) {
+ for (const auto& route : module->getFirstRoutes()->getRoute()) {
+ const auto sources = splitString(route.getSources(), ',');
+ if (std::find(sources.begin(), sources.end(), mixPortName) != sources.end()) {
+ result.insert(route.getSink());
+ }
+ }
+ }
+ return result;
+}
+
+std::set<std::string> PolicyConfig::getSourceDevicesForMixPort(
+ const std::string& moduleName, const std::string& mixPortName) const {
+ std::set<std::string> result;
+ auto module = getModuleFromName(moduleName);
+ if (module && module->getFirstRoutes()) {
+ const auto& routes = module->getFirstRoutes()->getRoute();
+ const auto route = std::find_if(routes.begin(), routes.end(), [&mixPortName](auto rte) {
+ return rte.getSink() == mixPortName;
+ });
+ if (route != routes.end()) {
+ const auto sources = splitString(route->getSources(), ',');
+ std::copy(sources.begin(), sources.end(), std::inserter(result, result.end()));
+ }
+ }
+ return result;
+}
+
+void PolicyConfig::init() {
+ if (mConfig) {
+ mStatus = OK;
+ mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+ if (mConfig->getFirstModules()) {
+ for (const auto& module : mConfig->getFirstModules()->get_module()) {
+ if (module.getFirstAttachedDevices()) {
+ auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+ if (!attachedDevices.empty()) {
+ mModulesWithDevicesNames.insert(module.getName());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index feb4d4b..f798839 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -16,15 +16,12 @@
#pragma once
-#include <fcntl.h>
-#include <unistd.h>
-
#include <optional>
#include <set>
#include <string>
+#include <vector>
#include <gtest/gtest.h>
-#include <system/audio_config.h>
#include <utils/Errors.h>
// clang-format off
@@ -35,12 +32,6 @@
#include <android_audio_policy_configuration_V7_0-enums.h>
#include <android_audio_policy_configuration_V7_0.h>
-#include "DeviceManager.h"
-
-using ::android::NO_INIT;
-using ::android::OK;
-using ::android::status_t;
-
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
namespace xsd {
@@ -62,69 +53,49 @@
mConfig{xsd::read(mFilePath.c_str())} {
init();
}
- status_t getStatus() const { return mStatus; }
- std::string getError() const {
- if (mFilePath.empty()) {
- return std::string{"Could not find "} + mConfigFileName +
- " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
- } else {
- return "Invalid config file: " + mFilePath;
- }
- }
+ android::status_t getStatus() const { return mStatus; }
+ std::string getError() const;
const std::string& getFilePath() const { return mFilePath; }
- const xsd::Module* getModuleFromName(const std::string& name) const {
- if (mConfig && mConfig->getFirstModules()) {
- for (const auto& module : mConfig->getFirstModules()->get_module()) {
- if (module.getName() == name) return &module;
- }
- }
- return nullptr;
- }
+ const xsd::Module* getModuleFromName(const std::string& name) const;
const xsd::Module* getPrimaryModule() const { return mPrimaryModule; }
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
- bool haveInputProfilesInModule(const std::string& name) const {
- auto module = getModuleFromName(name);
- if (module && module->getFirstMixPorts()) {
- for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
- if (mixPort.getRole() == xsd::Role::sink) return true;
- }
- }
- return false;
+ std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ return findAttachedDevice(getAttachedDevices(moduleName),
+ getSinkDevicesForMixPort(moduleName, mixPortName));
}
+ std::string getAttachedSourceDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ return findAttachedDevice(getAttachedDevices(moduleName),
+ getSourceDevicesForMixPort(moduleName, mixPortName));
+ }
+ std::optional<DeviceAddress> getSinkDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const;
+ std::optional<DeviceAddress> getSourceDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const;
+ bool haveInputProfilesInModule(const std::string& name) const;
private:
- static std::string findExistingConfigurationFile(const std::string& fileName) {
- for (const auto& location : android::audio_get_configuration_paths()) {
- std::string path = location + '/' + fileName;
- if (access(path.c_str(), F_OK) == 0) {
- return path;
- }
- }
- return std::string{};
- }
- void init() {
- if (mConfig) {
- mStatus = OK;
- mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
- if (mConfig->getFirstModules()) {
- for (const auto& module : mConfig->getFirstModules()->get_module()) {
- if (module.getFirstAttachedDevices()) {
- auto attachedDevices = module.getFirstAttachedDevices()->getItem();
- if (!attachedDevices.empty()) {
- mModulesWithDevicesNames.insert(module.getName());
- }
- }
- }
- }
- }
- }
+ static std::string findExistingConfigurationFile(const std::string& fileName);
+ std::string findAttachedDevice(const std::vector<std::string>& attachedDevices,
+ const std::set<std::string>& possibleDevices) const;
+ const std::vector<std::string>& getAttachedDevices(const std::string& moduleName) const;
+ std::optional<DeviceAddress> getDeviceAddressOfDevicePort(
+ const std::string& moduleName, const std::string& devicePortName) const;
+ std::string getDevicePortTagNameFromType(const std::string& moduleName,
+ const AudioDevice& deviceType) const;
+ std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const;
+ std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const;
+ void init();
const std::string mConfigFileName;
const std::string mFilePath;
std::optional<xsd::AudioPolicyConfiguration> mConfig;
- status_t mStatus = NO_INIT;
+ android::status_t mStatus = android::NO_INIT;
const xsd::Module* mPrimaryModule;
std::set<std::string> mModulesWithDevicesNames;
};
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 926a791..e446a7f 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -156,6 +156,7 @@
srcs: [
"7.0/AudioPrimaryHidlHalTest.cpp",
"7.0/Generators.cpp",
+ "7.0/PolicyConfig.cpp",
],
generated_headers: ["audio_policy_configuration_V7_0_parser"],
generated_sources: ["audio_policy_configuration_V7_0_parser"],
@@ -163,6 +164,7 @@
"android.hardware.audio@7.0",
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
],
cflags: [
"-DMAJOR_VERSION=7",
@@ -178,7 +180,15 @@
}
// Note: the following aren't VTS tests, but rather unit tests
-// to verify correctness of test parameter generator utilities.
+// to verify correctness of test utilities.
+cc_test {
+ name: "HalAudioStreamWorkerTest",
+ host_supported: true,
+ srcs: [
+ "tests/streamworker_tests.cpp",
+ ],
+}
+
cc_test {
name: "HalAudioV6_0GeneratorTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
@@ -210,6 +220,7 @@
defaults: ["VtsHalAudioTargetTest_defaults"],
srcs: [
"7.0/Generators.cpp",
+ "7.0/PolicyConfig.cpp",
"tests/generators_tests.cpp",
],
generated_headers: ["audio_policy_configuration_V7_0_parser"],
@@ -218,6 +229,7 @@
"android.hardware.audio@7.0",
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 56939fe..aa7fd8e 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -89,6 +89,10 @@
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
+using ReadParameters = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadStatus;
+using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
+using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
#if MAJOR_VERSION >= 7
// Make an alias for enumerations generated from the APM config XSD.
namespace xsd {
@@ -100,6 +104,7 @@
static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
static auto okOrNotSupportedOrInvalidArgs = {Result::OK, Result::NOT_SUPPORTED,
Result::INVALID_ARGUMENTS};
+static auto okOrInvalidState = {Result::OK, Result::INVALID_STATE};
static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE,
Result::NOT_SUPPORTED};
static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
@@ -115,6 +120,7 @@
#include "7.0/Generators.h"
#include "7.0/PolicyConfig.h"
#endif
+#include "StreamWorker.h"
class HidlTest : public ::testing::Test {
public:
@@ -778,6 +784,11 @@
////////////////////////// open{Output,Input}Stream //////////////////////////
//////////////////////////////////////////////////////////////////////////////
+static inline AudioIoHandle getNextIoHandle() {
+ static AudioIoHandle lastHandle{};
+ return ++lastHandle;
+}
+
// This class is also used by some device tests.
template <class Stream>
class StreamHelper {
@@ -787,16 +798,13 @@
template <class Open>
void open(Open openStream, const AudioConfig& config, Result* res,
AudioConfig* suggestedConfigPtr) {
- // FIXME: Open a stream without an IOHandle
- // This is not required to be accepted by hal implementations
- AudioIoHandle ioHandle{};
AudioConfig suggestedConfig{};
bool retryWithSuggestedConfig = true;
if (suggestedConfigPtr == nullptr) {
suggestedConfigPtr = &suggestedConfig;
retryWithSuggestedConfig = false;
}
- ASSERT_OK(openStream(ioHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
+ ASSERT_OK(openStream(mIoHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
switch (*res) {
case Result::OK:
ASSERT_TRUE(mStream != nullptr);
@@ -806,7 +814,7 @@
ASSERT_TRUE(mStream == nullptr);
if (retryWithSuggestedConfig) {
AudioConfig suggestedConfigRetry;
- ASSERT_OK(openStream(ioHandle, *suggestedConfigPtr,
+ ASSERT_OK(openStream(mIoHandle, *suggestedConfigPtr,
returnIn(*res, mStream, suggestedConfigRetry)));
ASSERT_OK(*res);
ASSERT_TRUE(mStream != nullptr);
@@ -834,8 +842,10 @@
#endif
}
}
+ AudioIoHandle getIoHandle() const { return mIoHandle; }
private:
+ const AudioIoHandle mIoHandle = getNextIoHandle();
sp<Stream>& mStream;
};
@@ -861,7 +871,6 @@
return res;
}
- private:
void TearDown() override {
if (open) {
ASSERT_OK(closeStream());
@@ -879,6 +888,116 @@
////////////////////////////// openOutputStream //////////////////////////////
+class StreamWriter : public StreamWorker<StreamWriter> {
+ public:
+ StreamWriter(IStreamOut* stream, size_t bufferSize)
+ : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
+ ~StreamWriter() {
+ stop();
+ if (mEfGroup) {
+ EventFlag::deleteEventFlag(&mEfGroup);
+ }
+ }
+
+ typedef MessageQueue<WriteCommand, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
+ typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
+ typedef MessageQueue<WriteStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
+
+ bool workerInit() {
+ std::unique_ptr<CommandMQ> tempCommandMQ;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ std::unique_ptr<StatusMQ> tempStatusMQ;
+ Result retval;
+ Return<void> ret = mStream->prepareForWriting(
+ 1, mBufferSize,
+ [&](Result r, const CommandMQ::Descriptor& commandMQ,
+ const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
+ const auto& /*halThreadInfo*/) {
+ retval = r;
+ if (retval == Result::OK) {
+ tempCommandMQ.reset(new CommandMQ(commandMQ));
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ tempStatusMQ.reset(new StatusMQ(statusMQ));
+ if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
+ EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+ }
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("Transport error while calling prepareForWriting: %s", ret.description().c_str());
+ return false;
+ }
+ if (retval != Result::OK) {
+ ALOGE("Error from prepareForWriting: %d", retval);
+ return false;
+ }
+ if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
+ !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
+ ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
+ ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+ "Command message queue for writing is invalid");
+ ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
+ ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
+ "Data message queue for writing is invalid");
+ ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
+ ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
+ "Status message queue for writing is invalid");
+ ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
+ return false;
+ }
+ mCommandMQ = std::move(tempCommandMQ);
+ mDataMQ = std::move(tempDataMQ);
+ mStatusMQ = std::move(tempStatusMQ);
+ return true;
+ }
+
+ bool workerCycle() {
+ WriteCommand cmd = WriteCommand::WRITE;
+ if (!mCommandMQ->write(&cmd)) {
+ ALOGE("command message queue write failed");
+ return false;
+ }
+ const size_t dataSize = std::min(mData.size(), mDataMQ->availableToWrite());
+ bool success = mDataMQ->write(mData.data(), dataSize);
+ ALOGE_IF(!success, "data message queue write failed");
+ mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
+
+ uint32_t efState = 0;
+ retry:
+ status_t ret =
+ mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
+ if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
+ WriteStatus writeStatus;
+ writeStatus.retval = Result::NOT_INITIALIZED;
+ if (!mStatusMQ->read(&writeStatus)) {
+ ALOGE("status message read failed");
+ success = false;
+ }
+ if (writeStatus.retval != Result::OK) {
+ ALOGE("bad write status: %d", writeStatus.retval);
+ success = false;
+ }
+ }
+ if (ret == -EAGAIN || ret == -EINTR) {
+ // Spurious wakeup. This normally retries no more than once.
+ goto retry;
+ } else if (ret) {
+ ALOGE("bad wait status: %d", ret);
+ success = false;
+ }
+ return success;
+ }
+
+ private:
+ IStreamOut* const mStream;
+ const size_t mBufferSize;
+ std::vector<uint8_t> mData;
+ std::unique_ptr<CommandMQ> mCommandMQ;
+ std::unique_ptr<DataMQ> mDataMQ;
+ std::unique_ptr<StatusMQ> mStatusMQ;
+ EventFlag* mEfGroup = nullptr;
+};
+
class OutputStreamTest : public OpenStreamTest<IStreamOut> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
@@ -954,13 +1073,138 @@
////////////////////////////// openInputStream //////////////////////////////
+class StreamReader : public StreamWorker<StreamReader> {
+ public:
+ StreamReader(IStreamIn* stream, size_t bufferSize)
+ : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
+ ~StreamReader() {
+ stop();
+ if (mEfGroup) {
+ EventFlag::deleteEventFlag(&mEfGroup);
+ }
+ }
+
+ typedef MessageQueue<ReadParameters, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
+ typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
+ typedef MessageQueue<ReadStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
+
+ bool workerInit() {
+ std::unique_ptr<CommandMQ> tempCommandMQ;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ std::unique_ptr<StatusMQ> tempStatusMQ;
+ Result retval;
+ Return<void> ret = mStream->prepareForReading(
+ 1, mBufferSize,
+ [&](Result r, const CommandMQ::Descriptor& commandMQ,
+ const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
+ const auto& /*halThreadInfo*/) {
+ retval = r;
+ if (retval == Result::OK) {
+ tempCommandMQ.reset(new CommandMQ(commandMQ));
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ tempStatusMQ.reset(new StatusMQ(statusMQ));
+ if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
+ EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+ }
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("Transport error while calling prepareForReading: %s", ret.description().c_str());
+ return false;
+ }
+ if (retval != Result::OK) {
+ ALOGE("Error from prepareForReading: %d", retval);
+ return false;
+ }
+ if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
+ !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
+ ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for reading");
+ ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+ "Command message queue for reading is invalid");
+ ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
+ ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
+ "Data message queue for reading is invalid");
+ ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
+ ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
+ "Status message queue for reading is invalid");
+ ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
+ return false;
+ }
+ mCommandMQ = std::move(tempCommandMQ);
+ mDataMQ = std::move(tempDataMQ);
+ mStatusMQ = std::move(tempStatusMQ);
+ return true;
+ }
+
+ bool workerCycle() {
+ ReadParameters params;
+ params.command = IStreamIn::ReadCommand::READ;
+ params.params.read = mBufferSize;
+ if (!mCommandMQ->write(¶ms)) {
+ ALOGE("command message queue write failed");
+ return false;
+ }
+ mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
+
+ uint32_t efState = 0;
+ bool success = true;
+ retry:
+ status_t ret =
+ mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
+ if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
+ ReadStatus readStatus;
+ readStatus.retval = Result::NOT_INITIALIZED;
+ if (!mStatusMQ->read(&readStatus)) {
+ ALOGE("status message read failed");
+ success = false;
+ }
+ if (readStatus.retval != Result::OK) {
+ ALOGE("bad read status: %d", readStatus.retval);
+ success = false;
+ }
+ const size_t dataSize = std::min(mData.size(), mDataMQ->availableToRead());
+ if (!mDataMQ->read(mData.data(), dataSize)) {
+ ALOGE("data message queue read failed");
+ success = false;
+ }
+ }
+ if (ret == -EAGAIN || ret == -EINTR) {
+ // Spurious wakeup. This normally retries no more than once.
+ goto retry;
+ } else if (ret) {
+ ALOGE("bad wait status: %d", ret);
+ success = false;
+ }
+ return success;
+ }
+
+ private:
+ IStreamIn* const mStream;
+ const size_t mBufferSize;
+ std::vector<uint8_t> mData;
+ std::unique_ptr<CommandMQ> mCommandMQ;
+ std::unique_ptr<DataMQ> mDataMQ;
+ std::unique_ptr<StatusMQ> mStatusMQ;
+ EventFlag* mEfGroup = nullptr;
+};
+
class InputStreamTest : public OpenStreamTest<IStreamIn> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
#elif MAJOR_VERSION >= 7
- address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
+ auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
+ getDeviceName(), getMixPortName());
+ if (maybeSourceAddress.has_value() &&
+ !xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
+ address = maybeSourceAddress.value();
+ auto& metadata = initMetadata.tracks[0];
+ metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
+ metadata.channelMask = getConfig().base.channelMask;
+ } else {
+ address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
+ }
#endif
const AudioConfig& config = getConfig();
auto flags = getInputFlags();
@@ -978,7 +1222,8 @@
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
#elif MAJOR_VERSION >= 7
- const SinkMetadata initMetadata = {
+ const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
+ SinkMetadata initMetadata = {
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT),
.gain = 1,
.tags = {},
@@ -1377,6 +1622,12 @@
uint64_t frames;
uint64_t time;
ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
+ // Although 'getCapturePosition' is mandatory in V7, legacy implementations
+ // may return -ENOSYS (which is translated to NOT_SUPPORTED) in cases when
+ // the capture position can't be retrieved, e.g. when the stream isn't
+ // running. Because of this, we don't fail when getting NOT_SUPPORTED
+ // in this test. Behavior of 'getCapturePosition' for running streams is
+ // tested in 'PcmOnlyConfigInputStreamTest' for V7.
ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
if (res == Result::OK) {
ASSERT_EQ(0U, frames);
@@ -1560,15 +1811,19 @@
"If supported, a stream should always succeed to retrieve the "
"presentation position");
uint64_t frames;
- TimeSpec mesureTS;
- ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS)));
+ TimeSpec measureTS;
+ ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, measureTS)));
+#if MAJOR_VERSION <= 6
if (res == Result::NOT_SUPPORTED) {
- doc::partialTest("getpresentationPosition is not supported");
+ doc::partialTest("getPresentationPosition is not supported");
return;
}
+#else
+ ASSERT_NE(Result::NOT_SUPPORTED, res) << "getPresentationPosition is mandatory in V7";
+#endif
ASSERT_EQ(0U, frames);
- if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) {
+ if (measureTS.tvNSec == 0 && measureTS.tvSec == 0) {
// As the stream has never written a frame yet,
// the timestamp does not really have a meaning, allow to return 0
return;
@@ -1580,8 +1835,8 @@
auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
- auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec);
- ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, mesureTime);
+ auto measureTime = toMicroSec(measureTS.tvSec, measureTS.tvNSec);
+ ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, measureTime);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
index 5b14a21..aa67630 100644
--- a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
+++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
@@ -31,15 +31,17 @@
// Nesting a tuple in another tuple allows to use GTest Combine function to generate
// all combinations of devices and configs.
-enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
#if MAJOR_VERSION <= 6
+enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
enum { INDEX_INPUT, INDEX_OUTPUT };
using DeviceConfigParameter =
std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
std::variant<android::hardware::audio::common::CPP_VERSION::AudioInputFlag,
android::hardware::audio::common::CPP_VERSION::AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
+enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
using DeviceConfigParameter =
- std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
+ std::tuple<DeviceParameter, std::string,
+ android::hardware::audio::common::CPP_VERSION::AudioConfig,
std::vector<android::hardware::audio::CPP_VERSION::AudioInOutFlag>>;
#endif
diff --git a/audio/core/all-versions/vts/functional/StreamWorker.h b/audio/core/all-versions/vts/functional/StreamWorker.h
new file mode 100644
index 0000000..68a8024
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/StreamWorker.h
@@ -0,0 +1,146 @@
+/*
+ * 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 <sched.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+template <typename Impl>
+class StreamWorker {
+ enum class WorkerState { STOPPED, RUNNING, PAUSE_REQUESTED, PAUSED, RESUME_REQUESTED, ERROR };
+
+ public:
+ StreamWorker() = default;
+ ~StreamWorker() { stop(); }
+ bool start() {
+ mWorker = std::thread(&StreamWorker::workerThread, this);
+ std::unique_lock<std::mutex> lock(mWorkerLock);
+ mWorkerCv.wait(lock, [&] { return mWorkerState != WorkerState::STOPPED; });
+ return mWorkerState == WorkerState::RUNNING;
+ }
+ void pause() { switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED); }
+ void resume() { switchWorkerStateSync(WorkerState::PAUSED, WorkerState::RESUME_REQUESTED); }
+ bool hasError() {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ return mWorkerState == WorkerState::ERROR;
+ }
+ void stop() {
+ {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ if (mWorkerState == WorkerState::STOPPED) return;
+ mWorkerState = WorkerState::STOPPED;
+ }
+ if (mWorker.joinable()) {
+ mWorker.join();
+ }
+ }
+ bool waitForAtLeastOneCycle() {
+ WorkerState newState;
+ switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED, &newState);
+ if (newState != WorkerState::PAUSED) return false;
+ switchWorkerStateSync(newState, WorkerState::RESUME_REQUESTED, &newState);
+ return newState == WorkerState::RUNNING;
+ }
+
+ // Methods that need to be provided by subclasses:
+ //
+ // Called once at the beginning of the thread loop. Must return
+ // 'true' to enter the thread loop, otherwise the thread loop
+ // exits and the worker switches into the 'error' state.
+ // bool workerInit();
+ //
+ // Called for each thread loop unless the thread is in 'paused' state.
+ // Must return 'true' to continue running, otherwise the thread loop
+ // exits and the worker switches into the 'error' state.
+ // bool workerCycle();
+
+ private:
+ void switchWorkerStateSync(WorkerState oldState, WorkerState newState,
+ WorkerState* finalState = nullptr) {
+ std::unique_lock<std::mutex> lock(mWorkerLock);
+ if (mWorkerState != oldState) {
+ if (finalState) *finalState = mWorkerState;
+ return;
+ }
+ mWorkerState = newState;
+ mWorkerCv.wait(lock, [&] { return mWorkerState != newState; });
+ if (finalState) *finalState = mWorkerState;
+ }
+ void workerThread() {
+ bool success = static_cast<Impl*>(this)->workerInit();
+ {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ mWorkerState = success ? WorkerState::RUNNING : WorkerState::ERROR;
+ }
+ mWorkerCv.notify_one();
+ if (!success) return;
+
+ for (WorkerState state = WorkerState::RUNNING; state != WorkerState::STOPPED;) {
+ bool needToNotify = false;
+ if (state != WorkerState::PAUSED ? static_cast<Impl*>(this)->workerCycle()
+ : (sched_yield(), true)) {
+ //
+ // Pause and resume are synchronous. One worker cycle must complete
+ // before the worker indicates a state change. This is how 'mWorkerState' and
+ // 'state' interact:
+ //
+ // mWorkerState == RUNNING
+ // client sets mWorkerState := PAUSE_REQUESTED
+ // last workerCycle gets executed, state := mWorkerState := PAUSED by us
+ // (or the workers enters the 'error' state if workerCycle fails)
+ // client gets notified about state change in any case
+ // thread is doing a busy wait while 'state == PAUSED'
+ // client sets mWorkerState := RESUME_REQUESTED
+ // state := mWorkerState (RESUME_REQUESTED)
+ // mWorkerState := RUNNING, but we don't notify the client yet
+ // first workerCycle gets executed, the code below triggers a client notification
+ // (or if workerCycle fails, worker enters 'error' state and also notifies)
+ // state := mWorkerState (RUNNING)
+ if (state == WorkerState::RESUME_REQUESTED) {
+ needToNotify = true;
+ }
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ state = mWorkerState;
+ if (mWorkerState == WorkerState::PAUSE_REQUESTED) {
+ state = mWorkerState = WorkerState::PAUSED;
+ needToNotify = true;
+ } else if (mWorkerState == WorkerState::RESUME_REQUESTED) {
+ mWorkerState = WorkerState::RUNNING;
+ }
+ } else {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ if (state == WorkerState::RESUME_REQUESTED ||
+ mWorkerState == WorkerState::PAUSE_REQUESTED) {
+ needToNotify = true;
+ }
+ mWorkerState = WorkerState::ERROR;
+ state = WorkerState::STOPPED;
+ }
+ if (needToNotify) {
+ mWorkerCv.notify_one();
+ }
+ }
+ }
+
+ std::thread mWorker;
+ std::mutex mWorkerLock;
+ std::condition_variable mWorkerCv;
+ WorkerState mWorkerState = WorkerState::STOPPED; // GUARDED_BY(mWorkerLock);
+};
diff --git a/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp b/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp
new file mode 100644
index 0000000..925fd33
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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 "StreamWorker.h"
+
+#include <sched.h>
+#include <unistd.h>
+#include <atomic>
+
+#include <gtest/gtest.h>
+#define LOG_TAG "StreamWorker_Test"
+#include <log/log.h>
+
+struct TestStream {
+ std::atomic<bool> error = false;
+};
+
+class TestWorker : public StreamWorker<TestWorker> {
+ public:
+ // Use nullptr to test error reporting from the worker thread.
+ explicit TestWorker(TestStream* stream) : mStream(stream) {}
+
+ size_t getWorkerCycles() const { return mWorkerCycles; }
+ bool hasWorkerCycleCalled() const { return mWorkerCycles != 0; }
+ bool hasNoWorkerCycleCalled(useconds_t usec) {
+ const size_t cyclesBefore = mWorkerCycles;
+ usleep(usec);
+ return mWorkerCycles == cyclesBefore;
+ }
+
+ bool workerInit() { return mStream; }
+ bool workerCycle() {
+ do {
+ mWorkerCycles++;
+ } while (mWorkerCycles == 0);
+ return !mStream->error;
+ }
+
+ private:
+ TestStream* const mStream;
+ std::atomic<size_t> mWorkerCycles = 0;
+};
+
+// The parameter specifies whether an extra call to 'stop' is made at the end.
+class StreamWorkerInvalidTest : public testing::TestWithParam<bool> {
+ public:
+ StreamWorkerInvalidTest() : StreamWorkerInvalidTest(nullptr) {}
+ void TearDown() override {
+ if (GetParam()) {
+ worker.stop();
+ }
+ }
+
+ protected:
+ StreamWorkerInvalidTest(TestStream* stream) : testing::TestWithParam<bool>(), worker(stream) {}
+ TestWorker worker;
+};
+
+TEST_P(StreamWorkerInvalidTest, Uninitialized) {
+ EXPECT_FALSE(worker.hasWorkerCycleCalled());
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
+ EXPECT_FALSE(worker.hasError());
+ worker.pause();
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedResumeIgnored) {
+ EXPECT_FALSE(worker.hasError());
+ worker.resume();
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, Start) {
+ EXPECT_FALSE(worker.start());
+ EXPECT_FALSE(worker.hasWorkerCycleCalled());
+ EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
+ EXPECT_FALSE(worker.start());
+ EXPECT_TRUE(worker.hasError());
+ worker.pause();
+ EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, ResumeIgnored) {
+ EXPECT_FALSE(worker.start());
+ EXPECT_TRUE(worker.hasError());
+ worker.resume();
+ EXPECT_TRUE(worker.hasError());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorkerInvalid, StreamWorkerInvalidTest, testing::Bool());
+
+class StreamWorkerTest : public StreamWorkerInvalidTest {
+ public:
+ StreamWorkerTest() : StreamWorkerInvalidTest(&stream) {}
+
+ protected:
+ TestStream stream;
+};
+
+static constexpr unsigned kWorkerIdleCheckTime = 50 * 1000;
+
+TEST_P(StreamWorkerTest, Uninitialized) {
+ EXPECT_FALSE(worker.hasWorkerCycleCalled());
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, Start) {
+ ASSERT_TRUE(worker.start());
+ worker.waitForAtLeastOneCycle();
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerError) {
+ ASSERT_TRUE(worker.start());
+ stream.error = true;
+ worker.waitForAtLeastOneCycle();
+ EXPECT_TRUE(worker.hasError());
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, PauseResume) {
+ ASSERT_TRUE(worker.start());
+ worker.waitForAtLeastOneCycle();
+ EXPECT_FALSE(worker.hasError());
+ worker.pause();
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+ EXPECT_FALSE(worker.hasError());
+ const size_t workerCyclesBefore = worker.getWorkerCycles();
+ worker.resume();
+ // 'resume' is synchronous and returns after the worker has looped at least once.
+ EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, StopPaused) {
+ ASSERT_TRUE(worker.start());
+ worker.waitForAtLeastOneCycle();
+ EXPECT_FALSE(worker.hasError());
+ worker.pause();
+ worker.stop();
+ EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, PauseAfterErrorIgnored) {
+ ASSERT_TRUE(worker.start());
+ stream.error = true;
+ worker.waitForAtLeastOneCycle();
+ EXPECT_TRUE(worker.hasError());
+ worker.pause();
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+ EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, ResumeAfterErrorIgnored) {
+ ASSERT_TRUE(worker.start());
+ stream.error = true;
+ worker.waitForAtLeastOneCycle();
+ EXPECT_TRUE(worker.hasError());
+ worker.resume();
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+ EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerErrorOnResume) {
+ ASSERT_TRUE(worker.start());
+ worker.waitForAtLeastOneCycle();
+ EXPECT_FALSE(worker.hasError());
+ worker.pause();
+ EXPECT_FALSE(worker.hasError());
+ stream.error = true;
+ EXPECT_FALSE(worker.hasError());
+ worker.resume();
+ worker.waitForAtLeastOneCycle();
+ EXPECT_TRUE(worker.hasError());
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycle) {
+ ASSERT_TRUE(worker.start());
+ const size_t workerCyclesBefore = worker.getWorkerCycles();
+ EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+ EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycleError) {
+ ASSERT_TRUE(worker.start());
+ stream.error = true;
+ EXPECT_FALSE(worker.waitForAtLeastOneCycle());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorker, StreamWorkerTest, testing::Bool());
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/effect/all-versions/OWNERS
similarity index 67%
copy from audio/effect/all-versions/default/OWNERS
copy to audio/effect/all-versions/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/effect/all-versions/OWNERS
@@ -1,3 +1,2 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
diff --git a/audio/effect/all-versions/vts/OWNERS b/audio/effect/all-versions/vts/OWNERS
deleted file mode 100644
index 0ea4666..0000000
--- a/audio/effect/all-versions/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
-yim@google.com
-zhuoyao@google.com
diff --git a/automotive/vehicle/2.0/vts/functional/Android.bp b/automotive/vehicle/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..e64e942
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/Android.bp
@@ -0,0 +1,30 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalAutomotiveVehicleV2_0TargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ ],
+ srcs: [
+ "VtsHalAutomotiveVehicleV2_0TargetTest.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0",
+ ],
+ test_suites: [
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
new file mode 100644
index 0000000..7f1d4d1
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "VtsHalAutomotiveVehicle"
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+using namespace android::hardware::automotive::vehicle::V2_0;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+constexpr auto kTimeout = std::chrono::milliseconds(500);
+constexpr auto kInvalidProp = 0x31600207;
+
+class VtsVehicleCallback : public IVehicleCallback {
+ private:
+ using MutexGuard = std::lock_guard<std::mutex>;
+ using HidlVecOfValues = hidl_vec<VehiclePropValue>;
+ std::mutex mLock;
+ std::condition_variable mEventCond;
+ std::vector<HidlVecOfValues> mReceivedEvents;
+
+ public:
+ Return<void> onPropertyEvent(const hidl_vec<VehiclePropValue>& values) override {
+ {
+ MutexGuard guard(mLock);
+ mReceivedEvents.push_back(values);
+ }
+ mEventCond.notify_one();
+ return Return<void>();
+ }
+
+ Return<void> onPropertySet(const VehiclePropValue& /* value */) override {
+ return Return<void>();
+ }
+ Return<void> onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */,
+ int32_t /* areaId */) override {
+ return Return<void>();
+ }
+
+ bool waitForExpectedEvents(size_t expectedEvents) {
+ std::unique_lock<std::mutex> g(mLock);
+
+ if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
+ return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
+ }
+
+ while (expectedEvents != mReceivedEvents.size()) {
+ if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void reset() { mReceivedEvents.clear(); }
+};
+
+class VehicleHalHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mVehicle = IVehicle::getService(GetParam());
+ ASSERT_NE(mVehicle.get(), nullptr);
+ }
+ virtual void TearDown() override {}
+
+ sp<IVehicle> mVehicle;
+
+ bool isBooleanGlobalProp(int32_t property) {
+ return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN &&
+ (property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL;
+ }
+
+ void invokeGet(int32_t property, int32_t areaId) {
+ VehiclePropValue requestedValue{};
+ requestedValue.prop = property;
+ requestedValue.areaId = areaId;
+
+ invokeGet(requestedValue);
+ }
+
+ void invokeGet(const VehiclePropValue& requestedPropValue) {
+ mActualValue = VehiclePropValue{}; // reset previous values
+
+ StatusCode refStatus;
+ VehiclePropValue refValue;
+ bool isCalled = false;
+ mVehicle->get(requestedPropValue,
+ [&refStatus, &refValue, &isCalled](StatusCode status,
+ const VehiclePropValue& value) {
+ refStatus = status;
+ refValue = value;
+ isCalled = true;
+ });
+ ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop;
+
+ mActualValue = refValue;
+ mActualStatusCode = refStatus;
+ }
+
+ VehiclePropValue mActualValue;
+ StatusCode mActualStatusCode;
+};
+
+// Test getAllPropConfig() returns at least 4 property configs.
+TEST_P(VehicleHalHidlTest, getAllPropConfigs) {
+ ALOGD("VehicleHalHidlTest::getAllPropConfigs");
+ bool isCalled = false;
+ hidl_vec<VehiclePropConfig> propConfigs;
+ mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) {
+ propConfigs = cfgs;
+ isCalled = true;
+ });
+ ASSERT_TRUE(isCalled);
+ ASSERT_GE(propConfigs.size(), 4);
+}
+
+// Test getPropConfig() can query all properties listed in CDD.
+TEST_P(VehicleHalHidlTest, getPropConfigs) {
+ ALOGD("VehicleHalHidlTest::getPropConfigs");
+ // Check the properties listed in CDD
+ hidl_vec<int32_t> properties = {
+ (int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE,
+ (int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED};
+ bool isCalled = false;
+ mVehicle->getPropConfigs(
+ properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
+ ASSERT_EQ(StatusCode::OK, status);
+ ASSERT_EQ(4u, cfgs.size());
+ isCalled = true;
+ });
+ ASSERT_TRUE(isCalled);
+}
+
+// Test getPropConfig() with an invalid propertyId returns an error code.
+TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) {
+ ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp");
+ hidl_vec<int32_t> properties = {kInvalidProp};
+ bool isCalled = false;
+ mVehicle->getPropConfigs(
+ properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
+ ASSERT_NE(StatusCode::OK, status);
+ ASSERT_EQ(0, cfgs.size());
+ isCalled = true;
+ });
+ ASSERT_TRUE(isCalled);
+}
+
+// Test get() return current value for properties.
+TEST_P(VehicleHalHidlTest, get) {
+ ALOGD("VehicleHalHidlTest::get");
+ invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0);
+ ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+}
+
+// Test get() with an invalid propertyId return an error codes.
+TEST_P(VehicleHalHidlTest, getInvalidProp) {
+ ALOGD("VehicleHalHidlTest::getInvalidProp");
+
+ invokeGet(kInvalidProp, 0);
+ ASSERT_NE(StatusCode::OK, mActualStatusCode);
+}
+
+// Test set() on read_write properties.
+TEST_P(VehicleHalHidlTest, setProp) {
+ ALOGD("VehicleHalHidlTest::setProp");
+ hidl_vec<VehiclePropConfig> propConfigs;
+ mVehicle->getAllPropConfigs(
+ [&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
+ for (const VehiclePropConfig& cfg : propConfigs) {
+ // test on boolean and writable property
+ if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop)) {
+ invokeGet(cfg.prop, 0);
+ int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
+ VehiclePropValue propToSet = mActualValue;
+ propToSet.value.int32Values[0] = setValue;
+ ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet));
+ // check set success
+ invokeGet(cfg.prop, 0);
+ ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+ ASSERT_EQ(setValue, mActualValue.value.int32Values[0]);
+ }
+ }
+}
+
+// Test set() on an read_only property.
+TEST_P(VehicleHalHidlTest, setNotWritableProp) {
+ ALOGD("VehicleHalHidlTest::setNotWritableProp");
+ invokeGet(static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED), 0);
+ ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+ VehiclePropValue vehicleSpeed = mActualValue;
+
+ ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed));
+}
+
+// Test subscribe() and unsubscribe().
+TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) {
+ ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe");
+ const auto prop = static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED);
+ sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
+
+ hidl_vec<SubscribeOptions> options = {
+ SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
+
+ ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options));
+ ASSERT_TRUE(cb->waitForExpectedEvents(10));
+
+ ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop));
+ cb->reset();
+ ASSERT_FALSE(cb->waitForExpectedEvents(10));
+}
+
+// Test subscribe() with an invalid property.
+TEST_P(VehicleHalHidlTest, subscribeInvalidProp) {
+ ALOGD("VehicleHalHidlTest::subscribeInvalidProp");
+
+ sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
+
+ hidl_vec<SubscribeOptions> options = {SubscribeOptions{
+ .propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
+
+ ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, VehicleHalHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
+ android::hardware::PrintInstanceNameToString);
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 205429b..9033989 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
@@ -34,17 +34,17 @@
package android.hardware.biometrics.face;
@VintfStability
interface ISession {
- void generateChallenge(in int cookie);
- void revokeChallenge(in int cookie, in long challenge);
- android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, 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 int cookie, in long operationId);
- android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
- void enumerateEnrollments(in int cookie);
- void removeEnrollments(in int cookie, in int[] enrollmentIds);
- void getFeatures(in int cookie, in int enrollmentId);
- void setFeature(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat, in int enrollmentId, in android.hardware.biometrics.face.Feature feature, boolean enabled);
- void getAuthenticatorId(in int cookie);
- void invalidateAuthenticatorId(in int cookie);
- void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
- void close(in int cookie);
+ void generateChallenge();
+ void revokeChallenge(in long challenge);
+ 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 getAuthenticatorId();
+ void invalidateAuthenticatorId();
+ void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
+ void close();
}
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 d6ebbb6..2bb053a 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
@@ -34,7 +34,6 @@
package android.hardware.biometrics.face;
@VintfStability
interface ISessionCallback {
- void onStateChanged(in int cookie, in android.hardware.biometrics.face.SessionState state);
void onChallengeGenerated(in long challenge);
void onChallengeRevoked(in long challenge);
void onAuthenticationFrame(in android.hardware.biometrics.face.AuthenticationFrame frame);
@@ -53,4 +52,5 @@
void onEnrollmentsRemoved(in int[] enrollmentIds);
void onAuthenticatorIdRetrieved(in long authenticatorId);
void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+ void onSessionClosed();
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 66c7c38..f9c13e6 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -23,11 +23,25 @@
import android.hardware.keymaster.HardwareAuthToken;
/**
- * A session is a collection of immutable state (sensorId, userId), mutable state (SessionState),
- * methods available for the framework to call, and a callback (ISessionCallback) to notify the
- * framework about the events and results. A session is used to establish communication between
- * the framework and the HAL.
+ * Operations that can be performed for unique sessions retrieved via IFace#createSession.
+ * Operations defined within this interface can be divided into the following categories:
+ * 1) Cancellable operations. These are usually the operations that can execute for several
+ * minutes. To allow for cancellation, they return an instance of ICancellationSignal that
+ * lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
+ * is cancelled, it must notify the framework by calling ISessionCallback#onError with
+ * Error::CANCELED.
+ * 2) Non-cancellable operations. Such operations cannot be cancelled once started.
+ *
+ * The lifecycle of an operation ends when one of its terminal callbacks is called. For example,
+ * ISession#authenticate is considered completed when any of the following callbacks is called:
+ * ISessionCallback#onError, ISessionCallback#onAuthenticationSucceeded,
+ * ISessionCallback#onAuthenticationFailed.
+ *
+ * ISession only supports execution of one operation at a time, regardless of whether it's
+ * cancellable or not. The framework must wait for a corresponding callback indicating the end of
+ * the current operation before a new operation can be started.
*/
+
@VintfStability
interface ISession {
/**
@@ -55,7 +69,7 @@
*
* Note that this interface allows multiple in-flight challenges. Invoking generateChallenge
* twice does not invalidate the first challenge. The challenge is invalidated only when:
- * 1) Its lifespan exceeds the HAL's internal challenge timeout
+ * 1) Its lifespan exceeds the challenge timeout defined in the TEE.
* 2) IFingerprint#revokeChallenge is invoked
*
* For example, the following is a possible table of valid challenges:
@@ -68,9 +82,8 @@
* | 0 | 10 | <Time4> | <Random4> |
* ----------------------------------------------
*
- * @param cookie A unique number identifying this operation
*/
- void generateChallenge(in int cookie);
+ void generateChallenge();
/**
* revokeChallenge:
@@ -79,10 +92,9 @@
* parameters is requested, the implementation must still notify the framework using the
* provided callback.
*
- * @param cookie A unique number identifying this operation
* @param challenge Challenge that should be revoked.
*/
- void revokeChallenge(in int cookie, in long challenge);
+ void revokeChallenge(in long challenge);
/**
* getEnrollmentConfig:
@@ -101,19 +113,13 @@
*
* A request to add a face enrollment.
*
- * Once the HAL is able to start processing the enrollment request, it must notify the framework
- * via ISessionCallback#onStateChanged with SessionState::ENROLLING.
- *
* At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
- * framework via ISessionCallback#onError with the applicable enrollment-specific error, and
- * then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
- * operation is in the queue.
+ * framework via ISessionCallback#onError with the applicable enrollment-specific error.
*
* Before capturing face data, the implementation must first verify the authenticity and
* integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
* within the provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of
- * the above checks fail, the framework must be notified via ISessionCallback#onError and the
- * HAL must notify the framework when it returns to the idle state. See
+ * the above checks fail, the framework must be notified using ISessionCallback#onError with
* Error::UNABLE_TO_PROCESS.
*
* During enrollment, the implementation may notify the framework via
@@ -121,15 +127,12 @@
* can be invoked multiple times if necessary. Similarly, the framework may be notified of
* enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
* notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
- * ISessionCallback#onEnrollmentProgress for more info. The HAL must notify the framework once
- * it returns to the idle state.
+ * ISessionCallback#onEnrollmentProgress for more info.
*
- * When a finger is successfully added and before the framework is notified of remaining=0, the
- * implementation MUST update and associate this (sensorId, userId) pair with a new new
+ * When a face is successfully added and before the framework is notified of remaining=0, the
+ * implementation MUST update and associate this (sensorId, userId) pair with a new
* entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param hat See above documentation.
* @param enrollmentType See the EnrollmentType enum.
* @param features See the Feature enum.
@@ -139,7 +142,7 @@
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
- ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat, in EnrollmentType type,
+ ICancellationSignal enroll(in HardwareAuthToken hat, in EnrollmentType type,
in Feature[] features, in NativeHandle previewSurface);
/**
@@ -147,13 +150,8 @@
*
* A request to start looking for faces to authenticate.
*
- * Once the HAL is able to start processing the authentication request, it must notify framework
- * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
- *
* At any point during authentication, if a non-recoverable error occurs, the HAL must notify
- * the framework via ISessionCallback#onError with the applicable authentication-specific error,
- * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
- * subsequent operation is in the queue.
+ * the framework via ISessionCallback#onError with the applicable authentication-specific error.
*
* During authentication, the implementation may notify the framework via
* ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
@@ -175,8 +173,6 @@
* must be set with the operationId passed in during #authenticate. If the sensor is NOT
* SensorStrength::STRONG, the HardwareAuthToken MUST be null.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
* upon successful authentication and wrapped in the HardwareAuthToken's
* "challenge" field and sent to the framework via
@@ -190,7 +186,7 @@
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
- ICancellationSignal authenticate(in int cookie, in long operationId);
+ ICancellationSignal authenticate(in long operationId);
/**
* detectInteraction:
@@ -199,17 +195,12 @@
* SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
* support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
- *
* The framework will use this method in cases where determing user presence is required, but
* identifying/authentication is not. For example, when the device is encrypted (first boot) or
* in lockdown mode.
*
* At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
- * the framework via ISessionCallback#onError with the applicable error, and then send
- * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
- * in the queue.
+ * the framework via ISessionCallback#onError with the applicable error.
*
* The implementation must only check for a face-like image was detected (e.g. to
* minimize interactions due to non-face objects), and the lockout counter must not
@@ -222,17 +213,14 @@
* 1) Any face is detected and the framework is notified via
* ISessionCallback#onInteractiondetected
* 2) The operation was cancelled by the framework (see ICancellationSignal)
- * 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one.
*
* Note that if the operation is canceled, the implementation must notify the framework via
* ISessionCallback#onError with Error::CANCELED.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
- ICancellationSignal detectInteraction(in int cookie);
+ ICancellationSignal detectInteraction();
/*
* enumerateEnrollments:
@@ -240,32 +228,22 @@
* A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
* framework typically uses this to ensure that its cache is in sync with the HAL.
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
- *
* The implementation must then notify the framework with a list of enrollments applicable
* for the current session via ISessionCallback#onEnrollmentsEnumerated.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
*/
- void enumerateEnrollments(in int cookie);
+ void enumerateEnrollments();
/**
* removeEnrollments:
*
* A request to remove the enrollments for this (sensorId, userId) pair.
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
- *
* After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
* etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
*/
- void removeEnrollments(in int cookie, in int[] enrollmentIds);
+ void removeEnrollments(in int[] enrollmentIds);
/**
* getFeatures:
@@ -273,20 +251,14 @@
* Returns a list of currently enabled features for the provided enrollmentId.
*
* If the enrollmentId is invalid, the HAL must invoke ISessionCallback#onError with
- * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
- * queue.
- *
- * Once the HAL is able to start processing this request, it must notify the framework by using
- * ISessionCallback#onStateChanged with SessionState::GETTING_FEATURES.
+ * Error::UNABLE_TO_PROCESS.
*
* The HAL must notify the framework about the result by calling
* ISessionCallback#onFeaturesRetrieved.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param enrollmentId the ID of the enrollment for which the features are requested.
*/
- void getFeatures(in int cookie, in int enrollmentId);
+ void getFeatures(in int enrollmentId);
/**
* setFeature:
@@ -296,24 +268,18 @@
* (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 and return to SessionState::IDLING if no subsequent work is in
- * the queue.
- *
- * Once the HAL is able to start processing this request, it must notify the framework by using
- * ISessionCallback#onStateChanged with SessionState::SETTING_FEATURE.
+ * with Error::UNABLE_TO_PROCESS.
*
* After the feature is successfully set, the HAL must notify the framework by calling
* ISessionCallback#onFeatureSet.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @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 int cookie, in HardwareAuthToken hat, in int enrollmentId,
- in Feature feature, boolean enabled);
+ void setFeature(
+ in HardwareAuthToken hat, in int enrollmentId, in Feature feature, boolean enabled);
/**
* getAuthenticatorId:
@@ -341,10 +307,8 @@
* 3) MUST not change if a face is deleted.
* 4) MUST be an entropy-encoded random number
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void getAuthenticatorId(in int cookie);
+ void getAuthenticatorId();
/**
* invalidateAuthenticatorId:
@@ -368,10 +332,8 @@
* for more details). As such, the framework would coordinate invalidation across multiple
* biometric HALs as necessary.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void invalidateAuthenticatorId(in int cookie);
+ void invalidateAuthenticatorId();
/**
* resetLockout:
@@ -382,8 +344,7 @@
* 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
* order of minutes, not hours).
* If either of the checks fail, the HAL must invoke ISessionCallback#onError with
- * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
- * queue.
+ * Error::UNABLE_TO_PROCESS.
*
* Upon successful verification, the HAL must clear the lockout counter and notify the framework
* via ISessionCallback#onLockoutCleared.
@@ -414,27 +375,20 @@
* See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
* requirements.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param hat HardwareAuthToken See above documentation.
*/
- void resetLockout(in int cookie, in HardwareAuthToken hat);
+ void resetLockout(in HardwareAuthToken hat);
/*
* Close this session and allow the HAL to release the resources associated with this session.
*
- * A session can only be closed when it's in SessionState::IDLING. Closing a session will
- * result in a ISessionCallback#onStateChanged call with SessionState::CLOSED.
- *
- * If a session is unresponsive or stuck in a state other than SessionState::CLOSED,
- * IFace#reset could be used as a last resort to terminate the session and recover the HAL
- * from a bad state.
+ * A session can only be closed when the HAL is idling, i.e. not performing any operations.
+ * If the HAL is busy performing a cancellable operation, the operation must be explicitly
+ * cancelled with a call to ICancellationSignal#cancel before the session can be closed.
*
* All sessions must be explicitly closed. Calling IFace#createSession while there is an active
* session is considered an error.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void close(in int cookie);
+ void close();
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index 2e3cd95..a2601e7 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -21,17 +21,11 @@
import android.hardware.biometrics.face.EnrollmentFrame;
import android.hardware.biometrics.face.Error;
import android.hardware.biometrics.face.Feature;
-import android.hardware.biometrics.face.SessionState;
import android.hardware.keymaster.HardwareAuthToken;
@VintfStability
interface ISessionCallback {
/**
- * Used to notify the framework of session state changes. See ISession for more information.
- */
- void onStateChanged(in int cookie, in SessionState state);
-
- /**
* Notifies the framework when a challenge is successfully generated.
*/
void onChallengeGenerated(in long challenge);
@@ -42,9 +36,9 @@
void onChallengeRevoked(in long challenge);
/**
- * This method must only be used to notify the framework during the following states:
- * 1) SessionState::AUTHENTICATING
- * 2) SessionState::DETECTING_INTERACTION
+ * This method must only be used to notify the framework during the following operations:
+ * 1) ISession#authenticate
+ * 2) ISession#detectInteraction
*
* These messages may be used to provide user guidance multiple times if necessary per
* operation.
@@ -54,8 +48,8 @@
void onAuthenticationFrame(in AuthenticationFrame frame);
/**
- * This method must only be used to notify the framework during the SessionState::ENROLLING
- * state.
+ * This method must only be used to notify the framework during the ISession#enroll
+ * operation.
*
* These messages may be used to provide user guidance multiple times if necessary per
* operation.
@@ -65,18 +59,18 @@
void onEnrollmentFrame(in EnrollmentFrame frame);
/**
- * This method must only be used to notify the framework during the following states:
- * 1) SessionState::ENROLLING
- * 2) SessionState::AUTHENTICATING
- * 3) SessionState::DETECTING_INTERACTION
- * 4) SessionState::INVALIDATING_AUTHENTICATOR_ID
- * 5) SessionState::RESETTING_LOCKOUT
+ * This method must only be used to notify the framework during the following operations:
+ * 1) ISession#enroll
+ * 2) ISession#authenticate
+ * 3) ISession#detectInteraction
+ * 4) ISession#invalidateAuthenticatorId
+ * 5) ISession#resetLockout
*
* These messages may be used to notify the framework or user that a non-recoverable error
* has occurred. The operation is finished, and the HAL must proceed with the next operation
- * or return to SessionState::IDLING if the queue is empty.
+ * or return to the idling state.
*
- * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
+ * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
* an Error::CANCELED message.
*
* @param error See the Error enum.
@@ -88,8 +82,7 @@
void onError(in Error error, in int vendorCode);
/**
- * This method must only be used to notify the framework during the following state:
- * 1) SessionState::ENROLLING
+ * This method must only be used to notify the framework during the ISession#enroll operation.
*
* @param enrollmentId Unique stable identifier for the enrollment that's being added by this
* ISession#enroll invocation.
@@ -98,7 +91,7 @@
void onEnrollmentProgress(in int enrollmentId, int remaining);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Used to notify the framework about a successful authentication. This ends the authentication
* lifecycle.
@@ -112,7 +105,7 @@
void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Used to notify the framework about a failed authentication. This ends the authentication
* lifecycle.
@@ -120,7 +113,7 @@
void onAuthenticationFailed();
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
* lockout, and authentication can be restarted after a period of time. See
@@ -133,7 +126,7 @@
void onLockoutTimed(in long durationMillis);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Authentication is disabled until the user unlocks with their device credential
* (PIN/Pattern/Password). See ISession#resetLockout.
@@ -160,7 +153,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::DETECTING_INTERACTION
+ * ISession#detectInteraction
*
* Notifies the framework that user interaction occurred. See ISession#detectInteraction.
*/
@@ -168,7 +161,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::ENUMERATING_ENROLLMENTS.
+ * ISession#enumerateEnrollments.
*
* Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
*
@@ -177,7 +170,7 @@
void onEnrollmentsEnumerated(in int[] enrollmentIds);
/**
- * This method must only be used to notify the framework during SessionState::GETTING_FEATURES.
+ * 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.
*
@@ -187,7 +180,7 @@
void onFeaturesRetrieved(in Feature[] features, in int enrollmentId);
/**
- * This method must only be used to notify the framework during SessionState::SETTING_FEATURE.
+ * This method must only be used to notify the framework during ISession#setFeature.
*
* Notifies the framework that ISession#setFeature has completed.
*
@@ -198,7 +191,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::REMOVING_ENROLLMENTS.
+ * ISession#removeEnrollments.
*
* Notifies the framework that the specified enrollments are removed.
*
@@ -208,7 +201,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::GETTING_AUTHENTICATOR_ID.
+ * ISession#getAuthenticatorId.
*
* Notifies the framework with the authenticatorId corresponding to this session's
* (userId, sensorId) pair.
@@ -219,7 +212,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::INVALIDATING_AUTHENTICATOR_ID.
+ * ISession#invalidateAuthenticatorId.
*
* See ISession#invalidateAuthenticatorId for more information.
*
@@ -227,4 +220,10 @@
* current set of enrollments.
*/
void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+
+ /**
+ * This method notifes the client that this session has closed.
+ * The client must not make any more calls to this session.
+ */
+ void onSessionClosed();
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
deleted file mode 100644
index afde4eb..0000000
--- a/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
+++ /dev/null
@@ -1,91 +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.
- */
-
-package android.hardware.biometrics.face;
-
-@VintfStability
-@Backing(type="byte")
-enum SessionState {
- /**
- * The HAL is not processing any session requests.
- */
- IDLING,
-
- /**
- * The session has been closed by the client.
- */
- CLOSED,
-
- /**
- * The HAL is processing the ISession#generateChallenge request.
- */
- GENERATING_CHALLENGE,
-
- /**
- * The HAL is processing the ISession#revokeChallenge request.
- */
- REVOKING_CHALLENGE,
-
- /**
- * The HAL is processing the ISession#enroll request.
- */
- ENROLLING,
-
- /**
- * The HAL is processing the ISession#authenticate request.
- */
- AUTHENTICATING,
-
- /**
- * The HAL is processing the ISession#detectInteraction request.
- */
- DETECTING_INTERACTION,
-
- /**
- * The HAL is processing the ISession#enumerateEnrollments request.
- */
- ENUMERATING_ENROLLMENTS,
-
- /**
- * The HAL is processing the ISession#removeEnrollments request.
- */
- REMOVING_ENROLLMENTS,
-
- /**
- * The HAL is processing the ISession#getFeatures request.
- */
- GETTING_FEATURES,
-
- /**
- * The HAL is processing the ISession#setFeature request.
- */
- SETTING_FEATURE,
-
- /**
- * The HAL is processing the ISession#getAuthenticatorId request.
- */
- GETTING_AUTHENTICATOR_ID,
-
- /**
- * The HAL is processing the ISession#invalidateAuthenticatorId request.
- */
- INVALIDATING_AUTHENTICATOR_ID,
-
- /**
- * The HAL is processing the ISession#resetLockout request.
- */
- RESETTING_LOCKOUT
-}
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index ce6c557..b5eb717 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -30,119 +30,105 @@
ndk::ScopedAStatus cancel() override {
cb_->onError(Error::CANCELED, 0 /* vendorCode */);
- cb_->onStateChanged(0, SessionState::IDLING);
return ndk::ScopedAStatus::ok();
}
};
Session::Session(std::shared_ptr<ISessionCallback> cb) : cb_(std::move(cb)) {}
-ndk::ScopedAStatus Session::generateChallenge(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::generateChallenge() {
LOG(INFO) << "generateChallenge";
if (cb_) {
- cb_->onStateChanged(0, SessionState::GENERATING_CHALLENGE);
cb_->onChallengeGenerated(0);
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::revokeChallenge(int32_t /*cookie*/, int64_t challenge) {
+ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
LOG(INFO) << "revokeChallenge";
if (cb_) {
- cb_->onStateChanged(0, SessionState::REVOKING_CHALLENGE);
cb_->onChallengeRevoked(challenge);
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::enroll(
- int32_t /*cookie*/, const keymaster::HardwareAuthToken& /*hat*/,
- EnrollmentType /*enrollmentType*/, const std::vector<Feature>& /*features*/,
- const NativeHandle& /*previewSurface*/,
+ const keymaster::HardwareAuthToken& /*hat*/, EnrollmentType /*enrollmentType*/,
+ const std::vector<Feature>& /*features*/, const NativeHandle& /*previewSurface*/,
std::shared_ptr<biometrics::common::ICancellationSignal>* /*return_val*/) {
LOG(INFO) << "enroll";
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::authenticate(int32_t /*cookie*/, int64_t /*keystoreOperationId*/,
+ndk::ScopedAStatus Session::authenticate(int64_t /*keystoreOperationId*/,
std::shared_ptr<common::ICancellationSignal>* return_val) {
LOG(INFO) << "authenticate";
if (cb_) {
- cb_->onStateChanged(0, SessionState::AUTHENTICATING);
+ cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
}
*return_val = SharedRefBase::make<CancellationSignal>(cb_);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::detectInteraction(
- int32_t /*cookie*/, std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
+ std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
LOG(INFO) << "detectInteraction";
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::enumerateEnrollments(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::enumerateEnrollments() {
LOG(INFO) << "enumerateEnrollments";
if (cb_) {
- cb_->onStateChanged(0, SessionState::ENUMERATING_ENROLLMENTS);
cb_->onEnrollmentsEnumerated(std::vector<int32_t>());
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::removeEnrollments(int32_t /*cookie*/,
- const std::vector<int32_t>& /*enrollmentIds*/) {
+ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& /*enrollmentIds*/) {
LOG(INFO) << "removeEnrollments";
if (cb_) {
- cb_->onStateChanged(0, SessionState::REMOVING_ENROLLMENTS);
cb_->onEnrollmentsRemoved(std::vector<int32_t>());
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::getFeatures(int32_t /*cookie*/, int32_t /*enrollmentId*/) {
+ndk::ScopedAStatus Session::getFeatures(int32_t /*enrollmentId*/) {
LOG(INFO) << "getFeatures";
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::setFeature(int32_t /*cookie*/,
- const keymaster::HardwareAuthToken& /*hat*/,
+ndk::ScopedAStatus Session::setFeature(const keymaster::HardwareAuthToken& /*hat*/,
int32_t /*enrollmentId*/, Feature /*feature*/,
bool /*enabled*/) {
LOG(INFO) << "setFeature";
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::getAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::getAuthenticatorId() {
LOG(INFO) << "getAuthenticatorId";
if (cb_) {
- cb_->onStateChanged(0, SessionState::GETTING_AUTHENTICATOR_ID);
cb_->onAuthenticatorIdRetrieved(0 /* authenticatorId */);
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
LOG(INFO) << "invalidateAuthenticatorId";
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::resetLockout(int32_t /*cookie*/,
- const keymaster::HardwareAuthToken& /*hat*/) {
+ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& /*hat*/) {
LOG(INFO) << "resetLockout";
if (cb_) {
- cb_->onStateChanged(0, SessionState::RESETTING_LOCKOUT);
cb_->onLockoutCleared();
- cb_->onStateChanged(0, SessionState::IDLING);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::close(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::close() {
+ if (cb_) {
+ cb_->onSessionClosed();
+ }
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index eb9ae83..73cdf08 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -30,40 +30,38 @@
public:
explicit Session(std::shared_ptr<ISessionCallback> cb);
- ndk::ScopedAStatus generateChallenge(int32_t cookie) override;
+ ndk::ScopedAStatus generateChallenge() override;
- ndk::ScopedAStatus revokeChallenge(int32_t cookie, int64_t challenge) override;
+ ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
- ndk::ScopedAStatus enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+ ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat,
EnrollmentType enrollmentType, const std::vector<Feature>& features,
const NativeHandle& previewSurface,
std::shared_ptr<common::ICancellationSignal>* return_val) override;
ndk::ScopedAStatus authenticate(
- int32_t cookie, int64_t keystoreOperationId,
+ int64_t keystoreOperationId,
std::shared_ptr<common::ICancellationSignal>* returnVal) override;
ndk::ScopedAStatus detectInteraction(
- int32_t cookie, std::shared_ptr<common::ICancellationSignal>* returnVal) override;
+ std::shared_ptr<common::ICancellationSignal>* returnVal) override;
- ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
+ ndk::ScopedAStatus enumerateEnrollments() override;
- ndk::ScopedAStatus removeEnrollments(int32_t cookie,
- const std::vector<int32_t>& enrollmentIds) override;
+ ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
- ndk::ScopedAStatus getFeatures(int32_t cookie, int32_t enrollmentId) override;
+ ndk::ScopedAStatus getFeatures(int32_t enrollmentId) override;
- ndk::ScopedAStatus setFeature(int32_t cookie, const keymaster::HardwareAuthToken& hat,
- int32_t enrollmentId, Feature feature, bool enabled) override;
+ ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, int32_t enrollmentId,
+ Feature feature, bool enabled) override;
- ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
+ ndk::ScopedAStatus getAuthenticatorId() override;
- ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
+ ndk::ScopedAStatus invalidateAuthenticatorId() override;
- ndk::ScopedAStatus resetLockout(int32_t cookie,
- const keymaster::HardwareAuthToken& hat) override;
+ ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override;
- ndk::ScopedAStatus close(int32_t cookie) override;
+ ndk::ScopedAStatus close() override;
private:
std::shared_ptr<ISessionCallback> cb_;
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 4cc8b4a..60e0a2a 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -21,35 +21,31 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <chrono>
#include <future>
namespace aidl::android::hardware::biometrics::face {
namespace {
+using namespace std::literals::chrono_literals;
+
constexpr int kSensorId = 0;
constexpr int kUserId = 0;
-constexpr auto kCallbackTimeout = std::chrono::seconds(1);
-enum class SessionCallbackMethodName {
- kOnStateChanged,
+enum class MethodName {
+ kOnError,
+ kOnSessionClosed,
};
-struct SessionCallbackInvocation {
- SessionCallbackMethodName method_name;
- SessionState state;
+struct Invocation {
+ MethodName methodName;
+ Error error;
+ int32_t vendorCode;
};
class SessionCallback : public BnSessionCallback {
public:
- explicit SessionCallback(std::promise<SessionCallbackInvocation> invocation_promise)
- : invocation_promise_(std::move(invocation_promise)) {}
- ndk::ScopedAStatus onStateChanged(int32_t /*cookie*/, SessionState state) override {
- SessionCallbackInvocation invocation = {};
- invocation.method_name = SessionCallbackMethodName::kOnStateChanged;
- invocation.state = state;
- invocation_promise_.set_value(invocation);
- return ndk::ScopedAStatus::ok();
- }
+ explicit SessionCallback(Invocation* inv) : mInv(inv) {}
ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
return ndk::ScopedAStatus::ok();
@@ -67,7 +63,12 @@
return ndk::ScopedAStatus::ok();
}
- ndk::ScopedAStatus onError(Error /*error*/, int32_t /*vendorCode*/) override {
+ ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override {
+ *mInv = {};
+ mInv->methodName = MethodName::kOnError;
+ mInv->error = error;
+ mInv->vendorCode = vendorCode;
+
return ndk::ScopedAStatus::ok();
}
@@ -120,8 +121,15 @@
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus onSessionClosed() override {
+ *mInv = {};
+ mInv->methodName = MethodName::kOnSessionClosed;
+
+ return ndk::ScopedAStatus::ok();
+ }
+
private:
- std::promise<SessionCallbackInvocation> invocation_promise_;
+ Invocation* mInv;
};
class Face : public testing::TestWithParam<std::string> {
@@ -129,28 +137,34 @@
void SetUp() override {
AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
ASSERT_NE(binder, nullptr);
- hal_ = IFace::fromBinder(ndk::SpAIBinder(binder));
+ mHal = IFace::fromBinder(ndk::SpAIBinder(binder));
}
- std::shared_ptr<IFace> hal_;
+ std::shared_ptr<IFace> mHal;
+ Invocation mInv;
};
TEST_P(Face, AuthenticateTest) {
- std::promise<SessionCallbackInvocation> invocation_promise;
- std::future<SessionCallbackInvocation> invocation_future = invocation_promise.get_future();
- std::shared_ptr<SessionCallback> session_cb =
- ndk::SharedRefBase::make<SessionCallback>(std::move(invocation_promise));
+ // Prepare the callback.
+ auto cb = ndk::SharedRefBase::make<SessionCallback>(&mInv);
+ // Create a session
std::shared_ptr<ISession> session;
- ASSERT_TRUE(hal_->createSession(kSensorId, kUserId, session_cb, &session).isOk());
+ ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
- std::shared_ptr<common::ICancellationSignal> cancel_cb;
- ASSERT_TRUE(session->authenticate(0, 0, &cancel_cb).isOk());
- ASSERT_EQ(invocation_future.wait_for(kCallbackTimeout), std::future_status::ready);
+ // Call authenticate
+ std::shared_ptr<common::ICancellationSignal> cancellationSignal;
+ ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).isOk());
- SessionCallbackInvocation invocation = invocation_future.get();
- EXPECT_EQ(invocation.method_name, SessionCallbackMethodName::kOnStateChanged);
- EXPECT_EQ(invocation.state, SessionState::AUTHENTICATING);
+ // Get the results
+ EXPECT_EQ(mInv.methodName, MethodName::kOnError);
+ EXPECT_EQ(mInv.error, Error::UNABLE_TO_PROCESS);
+ EXPECT_EQ(mInv.vendorCode, 0);
+
+ // Close the session
+ ASSERT_TRUE(session->close().isOk());
+
+ EXPECT_EQ(mInv.methodName, MethodName::kOnSessionClosed);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
@@ -159,6 +173,7 @@
::android::PrintInstanceNameToString);
} // namespace
+} // namespace aidl::android::hardware::biometrics::face
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
@@ -167,4 +182,3 @@
return RUN_ALL_TESTS();
}
-} // namespace aidl::android::hardware::biometrics::face
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 a8e73fc..2c2011a 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
@@ -45,4 +45,5 @@
TOO_DARK = 8,
TOO_BRIGHT = 9,
IMMOBILE = 10,
+ RETRYING_CAPTURE = 11,
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
index 87eaf96..9934a76 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -34,17 +34,17 @@
package android.hardware.biometrics.fingerprint;
@VintfStability
interface ISession {
- void generateChallenge(in int cookie);
- void revokeChallenge(in int cookie, in long challenge);
- android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
- android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId);
- android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
- void enumerateEnrollments(in int cookie);
- void removeEnrollments(in int cookie, in int[] enrollmentIds);
- void getAuthenticatorId(in int cookie);
- void invalidateAuthenticatorId(in int cookie);
- void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
- void close(in int cookie);
+ void generateChallenge();
+ void revokeChallenge(in long challenge);
+ android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat);
+ android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
+ android.hardware.biometrics.common.ICancellationSignal detectInteraction();
+ void enumerateEnrollments();
+ void removeEnrollments(in int[] enrollmentIds);
+ void getAuthenticatorId();
+ void invalidateAuthenticatorId();
+ void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
+ void close();
void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major);
void onPointerUp(in int pointerId);
void onUiReady();
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 13c2b05..3c40ad6 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -34,7 +34,6 @@
package android.hardware.biometrics.fingerprint;
@VintfStability
interface ISessionCallback {
- void onStateChanged(in int cookie, in android.hardware.biometrics.fingerprint.SessionState state);
void onChallengeGenerated(in long challenge);
void onChallengeRevoked(in long challenge);
void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode);
@@ -50,4 +49,5 @@
void onEnrollmentsRemoved(in int[] enrollmentIds);
void onAuthenticatorIdRetrieved(in long authenticatorId);
void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+ void onSessionClosed();
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
deleted file mode 100644
index 9b0b6f6..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
+++ /dev/null
@@ -1,49 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_AUTHENTICATOR_ID = 9,
- INVALIDATING_AUTHENTICATOR_ID = 10,
- RESETTING_LOCKOUT = 11,
-}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index bf11daa..b406947 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -82,5 +82,11 @@
* same finger can help against false rejections.
*/
IMMOBILE,
-}
+ /**
+ * This message may be sent to notify the framework that an additional image capture is taking
+ * place. Multiple RETRYING_CAPTURE may be sent before an ACQUIRED_GOOD message is sent.
+ * However, RETRYING_CAPTURE must not be sent after ACQUIRED_GOOD is sent.
+ */
+ RETRYING_CAPTURE,
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 98a4530..271a9bf 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -32,27 +32,14 @@
/**
* createSession:
*
- * Creates a session which can then be used by the framework to perform operations such as
- * enroll, authenticate, etc for the given sensorId and userId.
+ * Creates a instance of ISession which can be used by the framework to perform operations
+ * such as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId.
*
- * Calling this method while there is an active session is considered an error. If the
- * framework is in a bad state and for some reason cannot close its session, it should use
- * the reset method below.
- *
- * A physical sensor identified by sensorId typically supports only a single in-flight session
- * at a time. As such, if a session is currently in a state other than SessionState::IDLING, the
- * HAL MUST finish or cancel the current operation and return to SessionState::IDLING before the
- * new session is created. For example:
- * 1) If a session for sensorId=0, userId=0 is currently in a cancellable state (see
- * ICancellationSignal) such as SessionState::AUTHENTICATING and the framework requests a
- * new session for sensorId=0, userId=10, the HAL must end the current session with
- * Error::CANCELED, invoke ISessionCallback#onStateChanged with SessionState::IDLING, and
- * then return a new session for sensorId=0, userId=10.
- * 2) If a session for sensorId=0, userId=0 is currently in a non-cancellable state such as
- * SessionState::REMOVING_ENROLLMENTS, and the framework requests a new session for
- * sensorId=0, userId=10, the HAL must finish the current operation before invoking
- * ISessionCallback#onStateChanged with SessionState::IDLING, and return a new session for
- * sensorId=0, userId=10.
+ * Calling this method while there is an active session is considered an error. If the framework
+ * wants to create a new session when it already has an active session, it must first cancel the
+ * current operation if it's cancellable, or wait until it completes. Then, the framework must
+ * explicitly close the session with ISession#close. Once the framework receives
+ * ISessionCallback#onSessionClosed, a new session can be created.
*
* Implementations must store user-specific state or metadata in /data/vendor_de/<user>/fpdata
* as specified by the SeLinux policy. This directory is created/removed by vold (see
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index ef2e6fc..940548b 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -22,23 +22,28 @@
/**
* Operations that can be performed for unique sessions retrieved via IFingerprint#createSession.
* Methods defined within this interface can be split into the following categories:
- * 1) Methods associated with a state (see the SessionState enum). State-based operations are
- * handled by the HAL in FIFO order.
- * 1a) Cancellable state-based operations. If a cancellable operation is in-progress and the
- * framework requests a subsequent state-based operation, the implementation should finish
- * the operation via ISessionCallback#onError with Error::CANCELED.
- * 1b) Non-cancellable state-based operations. These operations should fully complete before the
- * next state-based operation can be started.
- * 2) Methods without a state. These methods may be invoked by the framework depending on its
- * use case. For example on devices with sensors of FingerprintSensorType::UNDER_DISPLAY_*,
- * ISession#onFingerDown may be invoked while the HAL is in SessionState::ENROLLING,
- * SessionState::AUTHENTICATING, or SessionState::DETECTING_INTERACTION.
+ * 1) Non-interrupting operations. These operations are handled by the HAL in FIFO order.
+ * 1a) Cancellable operations. These are usually the operations that can execute for several
+ * minutes. To allow for cancellation, they return an instance of ICancellationSignal that
+ * lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
+ * is cancelled, it must notify the framework by calling ISessionCallback#onError with
+ * Error::CANCELED.
+ * 1b) Non-cancellable operations. Such operations cannot be cancelled once started.
+ * 2) Interrupting operations. These operations may be invoked by the framework immediately,
+ * regardless of whether another operation is executing. For example, on devices with sensors
+ * of FingerprintSensorType::UNDER_DISPLAY_*, ISession#onFingerDown may be invoked while the
+ * HAL is executing ISession#enroll, ISession#authenticate or ISession#detectInteraction.
*
- * If the HAL has multiple operations in its queue, it is not required to notify the framework
- * of SessionState::IDLING between each operation. However, it must notify the framework when all
- * work is completed. See ISessionCallback#onStateChanged. For example, the following is a valid
- * sequence of ISessionCallback#onStateChanged invocations: SessionState::IDLING -->
- * SessionState::ENROLLING --> SessionState::ENUMERATING_ENROLLMENTS --> SessionState::IDLING.
+ * The lifecycle of a non-interrupting operation ends when one of its terminal callbacks is called.
+ * For example, ISession#authenticate is considered completed when either of the following callbacks
+ * is called: ISessionCallback#onError or ISessionCallback#onAuthenticationSucceeded.
+ *
+ * The lifecycle of an interrupting operation ends when it returns. Interrupting operations do not
+ * 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.
*/
@VintfStability
interface ISession {
@@ -84,9 +89,8 @@
* | 0 | 10 | <Time4> | <Random4> |
* ----------------------------------------------
*
- * @param cookie A unique number identifying this operation
*/
- void generateChallenge(in int cookie);
+ void generateChallenge();
/**
* revokeChallenge:
@@ -95,23 +99,17 @@
* parameters is requested, the implementation must still notify the framework using the
* provided callback.
*
- * @param cookie A unique number identifying this operation
* @param challenge Challenge that should be revoked.
*/
- void revokeChallenge(in int cookie, in long challenge);
+ void revokeChallenge(in long challenge);
/**
* enroll:
*
* A request to add a fingerprint enrollment.
*
- * Once the HAL is able to start processing the enrollment request, it must notify the framework
- * via ISessionCallback#onStateChanged with SessionState::ENROLLING.
- *
* At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
- * framework via ISessionCallback#onError with the applicable enrollment-specific error, and
- * then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
- * operation is in the queue.
+ * framework via ISessionCallback#onError with the applicable enrollment-specific error.
*
* Before capturing fingerprint data, the implementation must first verify the authenticity and
* integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
@@ -132,24 +130,17 @@
* implementation MUST update and associate this (sensorId, userId) pair with a new new
* entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param hat See above documentation.
*/
- ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat);
+ ICancellationSignal enroll(in HardwareAuthToken hat);
/**
* authenticate:
*
* A request to start looking for fingerprints to authenticate.
*
- * Once the HAL is able to start processing the authentication request, it must notify framework
- * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
- *
* At any point during authentication, if a non-recoverable error occurs, the HAL must notify
- * the framework via ISessionCallback#onError with the applicable authentication-specific error,
- * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
- * subsequent operation is in the queue.
+ * the framework via ISessionCallback#onError with the applicable authentication-specific error.
*
* During authentication, the implementation may notify the framework via
* ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
@@ -171,8 +162,6 @@
* must be set with the operationId passed in during #authenticate. If the sensor is NOT
* SensorStrength::STRONG, the HardwareAuthToken MUST be null.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
* upon successful authentication and wrapped in the HardwareAuthToken's
* "challenge" field and sent to the framework via
@@ -184,7 +173,7 @@
* setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
* KeyProtection.Builder.
*/
- ICancellationSignal authenticate(in int cookie, in long operationId);
+ ICancellationSignal authenticate(in long operationId);
/**
* detectInteraction:
@@ -193,17 +182,12 @@
* if SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
* support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
- *
* The framework will use this method in cases where determing user presence is required, but
* identifying/authentication is not. For example, when the device is encrypted (first boot) or
* in lockdown mode.
*
* At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
- * the framework via ISessionCallback#onError with the applicable error, and then send
- * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
- * in the queue.
+ * the framework via ISessionCallback#onError with the applicable error.
*
* The implementation must only check for a fingerprint-like image was detected (e.g. to
* minimize interactions due to non-fingerprint objects), and the lockout counter must not
@@ -221,10 +205,8 @@
* Note that if the operation is canceled, the implementation must notify the framework via
* ISessionCallback#onError with Error::CANCELED.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
*/
- ICancellationSignal detectInteraction(in int cookie);
+ ICancellationSignal detectInteraction();
/*
* enumerateEnrollments:
@@ -232,32 +214,22 @@
* A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
* framework typically uses this to ensure that its cache is in sync with the HAL.
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
- *
* The implementation must then notify the framework with a list of enrollments applicable
* for the current session via ISessionCallback#onEnrollmentsEnumerated.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
*/
- void enumerateEnrollments(in int cookie);
+ void enumerateEnrollments();
/**
* removeEnrollments:
*
* A request to remove the enrollments for this (sensorId, userId) pair.
*
- * Once the HAL is able to start processing this request, it must notify the framework via
- * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
- *
* After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
* etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
*
- * @param cookie An identifier used to track subsystem operations related to this call path.
- * The framework will guarantee that it is unique per ISession.
*/
- void removeEnrollments(in int cookie, in int[] enrollmentIds);
+ void removeEnrollments(in int[] enrollmentIds);
/**
* getAuthenticatorId:
@@ -285,10 +257,8 @@
* 3) MUST not change if a fingerprint is deleted.
* 4) MUST be an entropy-encoded random number
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void getAuthenticatorId(in int cookie);
+ void getAuthenticatorId();
/**
* invalidateAuthenticatorId:
@@ -312,10 +282,8 @@
* for more details). As such, the framework would coordinate invalidation across multiple
* biometric HALs as necessary.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void invalidateAuthenticatorId(in int cookie);
+ void invalidateAuthenticatorId();
/**
* resetLockout:
@@ -326,8 +294,7 @@
* 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
* order of minutes, not hours).
* If either of the checks fail, the HAL must invoke ISessionCallback#onError with
- * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
- * queue.
+ * Error::UNABLE_TO_PROCESS and return to the idling state.
*
* Upon successful verification, the HAL must clear the lockout counter and notify the framework
* via ISessionCallback#onLockoutCleared.
@@ -358,29 +325,26 @@
* See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
* requirements.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
* @param hat HardwareAuthToken See above documentation.
*/
- void resetLockout(in int cookie, in HardwareAuthToken hat);
+ void resetLockout(in HardwareAuthToken hat);
/*
* Close this session and allow the HAL to release the resources associated with this session.
*
- * A session can only be closed when it's in SessionState::IDLING. Closing a session will
- * result in a ISessionCallback#onStateChanged call with SessionState::CLOSED.
+ * A session can only be closed when the HAL is idling, i.e. not performing any of the
+ * non-interruptable operations. If the HAL is busy performing a cancellable operation, the
+ * operation must be explicitly cancelled with a call to ICancellationSignal#cancel before
+ * the session can be closed.
*
- * If a session is unresponsive or stuck in a state other than SessionState::CLOSED,
- * IFingerprint#reset could be used as a last resort to terminate the session and recover the
- * HAL from a bad state.
+ * After a session is closed, the HAL must notify the framework by calling
+ * ISessionCallback#onSessionClosed.
*
* All sessions must be explicitly closed. Calling IFingerprint#createSession while there is an
* active session is considered an error.
*
- * @param cookie An identifier used to track subsystem operations related to this call path. The
- * client must guarantee that it is unique per ISession.
*/
- void close(in int cookie);
+ void close();
/**
* Methods for notifying the under-display fingerprint sensor about external events.
@@ -394,9 +358,8 @@
* of other types, the HAL must treat this as a no-op and return immediately.
*
* For sensors of type FingerprintSensorType::UNDER_DISPLAY_*, this method is used to notify the
- * HAL of display touches. This method can be invoked when the session is in one of the
- * following states: SessionState::ENROLLING, SessionState::AUTHENTICATING, or
- * SessionState::DETECTING_INTERACTION.
+ * HAL of display touches. This method can be invoked when the HAL is performing any one of:
+ * ISession#authenticate, ISession#enroll, ISession#detectInteraction.
*
* Note that the framework will only invoke this method if the event occurred on the display on
* which this sensor is located.
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index fde1df7..95657b3 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -18,17 +18,11 @@
import android.hardware.biometrics.fingerprint.AcquiredInfo;
import android.hardware.biometrics.fingerprint.Error;
-import android.hardware.biometrics.fingerprint.SessionState;
import android.hardware.keymaster.HardwareAuthToken;
@VintfStability
interface ISessionCallback {
/**
- * Used to notify the framework of session state changes. See ISession for more information.
- */
- void onStateChanged(in int cookie, in SessionState state);
-
- /**
* Notifies the framework when a challenge is successfully generated.
*/
void onChallengeGenerated(in long challenge);
@@ -39,10 +33,10 @@
void onChallengeRevoked(in long challenge);
/**
- * This method must only be used to notify the framework during the following states:
- * 1) SessionState::ENROLLING
- * 2) SessionState::AUTHENTICATING
- * 3) SessionState::DETECTING_INTERACTION
+ * This method must only be used to notify the framework during the following operations:
+ * 1) ISession#enroll
+ * 2) ISession#authenticate
+ * 3) ISession#detectInteraction
*
* These messages may be used to provide user guidance multiple times if necessary per
* operation.
@@ -56,18 +50,18 @@
void onAcquired(in AcquiredInfo info, in int vendorCode);
/**
- * This method must only be used to notify the framework during the following states:
- * 1) SessionState::ENROLLING
- * 2) SessionState::AUTHENTICATING
- * 3) SessionState::DETECTING_INTERACTION
- * 4) SessionState::INVALIDATING_AUTHENTICATOR_ID
- * 5) SessionState::RESETTING_LOCKOUT
+ * This method must only be used to notify the framework during the following operations:
+ * 1) ISession#enroll
+ * 2) ISession#authenticate
+ * 3) ISession#detectInteraction
+ * 4) ISession#invalidateAuthenticatorId
+ * 5) ISession#resetLockout
*
* These messages may be used to notify the framework or user that a non-recoverable error
- * has occurred. The operation is finished, and the HAL must proceed with the next operation
- * or return to SessionState::IDLING if the queue is empty.
+ * has occurred. The operation is finished, and the HAL can proceed with the next operation
+ * or return to the idling state.
*
- * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
+ * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
* an Error::CANCELED message.
*
* @param error See the Error enum.
@@ -79,8 +73,7 @@
void onError(in Error error, in int vendorCode);
/**
- * This method must only be used to notify the framework during the following state:
- * 1) SessionState::ENROLLING
+ * This method must only be used to notify the framework during the ISession#enroll operation.
*
* @param enrollmentId Unique stable identifier for the enrollment that's being added by this
* ISession#enroll invocation.
@@ -89,7 +82,7 @@
void onEnrollmentProgress(in int enrollmentId, int remaining);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Used to notify the framework upon successful authentication. Note that the authentication
* lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred. The
@@ -104,7 +97,7 @@
void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Used to notify the framework upon rejected attempts. Note that the authentication
* lifecycle ends when either 1) a fingerprint is accepted, or 2) an occurred. The
@@ -113,7 +106,7 @@
void onAuthenticationFailed();
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
* lockout, and authentication can be restarted after a period of time. See
@@ -126,7 +119,7 @@
void onLockoutTimed(in long durationMillis);
/**
- * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+ * This method must only be used to notify the framework during ISession#authenticate.
*
* Authentication is disabled until the user unlocks with their device credential
* (PIN/Pattern/Password). See ISession#resetLockout.
@@ -153,7 +146,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::DETECTING_INTERACTION
+ * ISession#detectInteraction
*
* Notifies the framework that user interaction occurred. See ISession#detectInteraction.
*/
@@ -161,7 +154,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::ENUMERATING_ENROLLMENTS.
+ * ISession#enumerateEnrollments.
*
* Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
*
@@ -171,7 +164,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::REMOVING_ENROLLMENTS.
+ * ISession#removeEnrollments.
*
* Notifies the framework that the specified enrollments are removed.
*
@@ -181,7 +174,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::GETTING_AUTHENTICATOR_ID.
+ * ISession#getAuthenticatorId.
*
* Notifies the framework with the authenticatorId corresponding to this session's
* (userId, sensorId) pair.
@@ -192,7 +185,7 @@
/**
* This method must only be used to notify the framework during
- * SessionState::INVALIDATING_AUTHENTICATOR_ID.
+ * ISession#invalidateAuthenticatorId.
*
* See ISession#invalidateAuthenticatorId for more information.
*
@@ -200,4 +193,10 @@
* current set of enrollments.
*/
void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+
+ /**
+ * This method notifes the client that this session has closed.
+ * The client must not make any more calls to this session.
+ */
+ void onSessionClosed();
}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl
deleted file mode 100644
index 19a6ce3..0000000
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl
+++ /dev/null
@@ -1,81 +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.biometrics.fingerprint;
-
-@VintfStability
-@Backing(type="byte")
-enum SessionState {
- /**
- * The HAL is not processing any session requests.
- */
- IDLING,
-
- /**
- * The session has been closed by the client.
- */
- CLOSED,
-
- /**
- * The HAL is processing the ISession#generateChallenge request.
- */
- GENERATING_CHALLENGE,
-
- /**
- * The HAL is processing the ISession#revokeChallenge request.
- */
- REVOKING_CHALLENGE,
-
- /**
- * The HAL is processing the ISession#enroll request.
- */
- ENROLLING,
-
- /**
- * The HAL is processing the ISession#authenticate request.
- */
- AUTHENTICATING,
-
- /**
- * The HAL is processing the ISession#detectInteraction request.
- */
- DETECTING_INTERACTION,
-
- /**
- * The HAL is processing the ISession#enumerateEnrollments request.
- */
- ENUMERATING_ENROLLMENTS,
-
- /**
- * The HAL is processing the ISession#removeEnrollments request.
- */
- REMOVING_ENROLLMENTS,
-
- /**
- * The HAL is processing the ISession#getAuthenticatorId request.
- */
- GETTING_AUTHENTICATOR_ID,
-
- /**
- * The HAL is processing the ISession#invalidateAuthenticatorId request.
- */
- INVALIDATING_AUTHENTICATOR_ID,
-
- /**
- * The HAL is processing the ISession#resetLockout request.
- */
- RESETTING_LOCKOUT
-}
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index c035407..ca481e7 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -39,54 +39,56 @@
}
void Session::scheduleStateOrCrash(SessionState state) {
- CHECK(mScheduledState == SessionState::IDLING);
- CHECK(mCurrentState == SessionState::IDLING);
+ // TODO(b/166800618): call enterIdling from the terminal callbacks and restore these checks.
+ // CHECK(mScheduledState == SessionState::IDLING);
+ // CHECK(mCurrentState == SessionState::IDLING);
mScheduledState = state;
}
-void Session::enterStateOrCrash(int cookie, SessionState state) {
+void Session::enterStateOrCrash(SessionState state) {
CHECK(mScheduledState == state);
mCurrentState = state;
mScheduledState = SessionState::IDLING;
- mCb->onStateChanged(cookie, mCurrentState);
}
-void Session::enterIdling(int cookie) {
- mCurrentState = SessionState::IDLING;
- mCb->onStateChanged(cookie, mCurrentState);
+void Session::enterIdling() {
+ // TODO(b/166800618): call enterIdling from the terminal callbacks and rethink this conditional.
+ if (mCurrentState != SessionState::CLOSED) {
+ mCurrentState = SessionState::IDLING;
+ }
}
bool Session::isClosed() {
return mCurrentState == SessionState::CLOSED;
}
-ndk::ScopedAStatus Session::generateChallenge(int32_t cookie) {
+ndk::ScopedAStatus Session::generateChallenge() {
LOG(INFO) << "generateChallenge";
scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE);
- mWorker->schedule(Callable::from([this, cookie] {
- enterStateOrCrash(cookie, SessionState::GENERATING_CHALLENGE);
+ mWorker->schedule(Callable::from([this] {
+ enterStateOrCrash(SessionState::GENERATING_CHALLENGE);
mEngine->generateChallengeImpl(mCb.get());
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::revokeChallenge(int32_t cookie, int64_t challenge) {
+ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
LOG(INFO) << "revokeChallenge";
scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE);
- mWorker->schedule(Callable::from([this, cookie, challenge] {
- enterStateOrCrash(cookie, SessionState::REVOKING_CHALLENGE);
+ mWorker->schedule(Callable::from([this, challenge] {
+ enterStateOrCrash(SessionState::REVOKING_CHALLENGE);
mEngine->revokeChallengeImpl(mCb.get(), challenge);
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat,
std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "enroll";
scheduleStateOrCrash(SessionState::ENROLLING);
@@ -94,21 +96,21 @@
std::promise<void> cancellationPromise;
auto cancFuture = cancellationPromise.get_future();
- mWorker->schedule(Callable::from([this, cookie, hat, cancFuture = std::move(cancFuture)] {
- enterStateOrCrash(cookie, SessionState::ENROLLING);
+ mWorker->schedule(Callable::from([this, hat, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(SessionState::ENROLLING);
if (shouldCancel(cancFuture)) {
mCb->onError(Error::CANCELED, 0 /* vendorCode */);
} else {
mEngine->enrollImpl(mCb.get(), hat);
}
- enterIdling(cookie);
+ enterIdling();
}));
*out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::authenticate(int32_t cookie, int64_t operationId,
+ndk::ScopedAStatus Session::authenticate(int64_t operationId,
std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "authenticate";
scheduleStateOrCrash(SessionState::AUTHENTICATING);
@@ -116,114 +118,113 @@
std::promise<void> cancPromise;
auto cancFuture = cancPromise.get_future();
- mWorker->schedule(
- Callable::from([this, cookie, operationId, cancFuture = std::move(cancFuture)] {
- enterStateOrCrash(cookie, SessionState::AUTHENTICATING);
- if (shouldCancel(cancFuture)) {
- mCb->onError(Error::CANCELED, 0 /* vendorCode */);
- } else {
- mEngine->authenticateImpl(mCb.get(), operationId);
- }
- enterIdling(cookie);
- }));
+ mWorker->schedule(Callable::from([this, operationId, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(SessionState::AUTHENTICATING);
+ if (shouldCancel(cancFuture)) {
+ mCb->onError(Error::CANCELED, 0 /* vendorCode */);
+ } else {
+ mEngine->authenticateImpl(mCb.get(), operationId);
+ }
+ enterIdling();
+ }));
*out = SharedRefBase::make<CancellationSignal>(std::move(cancPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::detectInteraction(int32_t cookie,
- std::shared_ptr<common::ICancellationSignal>* out) {
+ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "detectInteraction";
scheduleStateOrCrash(SessionState::DETECTING_INTERACTION);
std::promise<void> cancellationPromise;
auto cancFuture = cancellationPromise.get_future();
- mWorker->schedule(Callable::from([this, cookie, cancFuture = std::move(cancFuture)] {
- enterStateOrCrash(cookie, SessionState::DETECTING_INTERACTION);
+ mWorker->schedule(Callable::from([this, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(SessionState::DETECTING_INTERACTION);
if (shouldCancel(cancFuture)) {
mCb->onError(Error::CANCELED, 0 /* vendorCode */);
} else {
mEngine->detectInteractionImpl(mCb.get());
}
- enterIdling(cookie);
+ enterIdling();
}));
*out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::enumerateEnrollments(int32_t cookie) {
+ndk::ScopedAStatus Session::enumerateEnrollments() {
LOG(INFO) << "enumerateEnrollments";
scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
- mWorker->schedule(Callable::from([this, cookie] {
- enterStateOrCrash(cookie, SessionState::ENUMERATING_ENROLLMENTS);
+ mWorker->schedule(Callable::from([this] {
+ enterStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
mEngine->enumerateEnrollmentsImpl(mCb.get());
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::removeEnrollments(int32_t cookie,
- const std::vector<int32_t>& enrollmentIds) {
+ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
LOG(INFO) << "removeEnrollments";
scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
- mWorker->schedule(Callable::from([this, cookie, enrollmentIds] {
- enterStateOrCrash(cookie, SessionState::REMOVING_ENROLLMENTS);
+ mWorker->schedule(Callable::from([this, enrollmentIds] {
+ enterStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds);
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::getAuthenticatorId(int32_t cookie) {
+ndk::ScopedAStatus Session::getAuthenticatorId() {
LOG(INFO) << "getAuthenticatorId";
scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
- mWorker->schedule(Callable::from([this, cookie] {
- enterStateOrCrash(cookie, SessionState::GETTING_AUTHENTICATOR_ID);
+ mWorker->schedule(Callable::from([this] {
+ enterStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
mEngine->getAuthenticatorIdImpl(mCb.get());
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t cookie) {
+ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
LOG(INFO) << "invalidateAuthenticatorId";
scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
- mWorker->schedule(Callable::from([this, cookie] {
- enterStateOrCrash(cookie, SessionState::INVALIDATING_AUTHENTICATOR_ID);
+ mWorker->schedule(Callable::from([this] {
+ enterStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
mEngine->invalidateAuthenticatorIdImpl(mCb.get());
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::resetLockout(int32_t cookie, const keymaster::HardwareAuthToken& hat) {
+ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) {
LOG(INFO) << "resetLockout";
scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT);
- mWorker->schedule(Callable::from([this, cookie, hat] {
- enterStateOrCrash(cookie, SessionState::RESETTING_LOCKOUT);
+ mWorker->schedule(Callable::from([this, hat] {
+ enterStateOrCrash(SessionState::RESETTING_LOCKOUT);
mEngine->resetLockoutImpl(mCb.get(), hat);
- enterIdling(cookie);
+ enterIdling();
}));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::close(int32_t cookie) {
+ndk::ScopedAStatus Session::close() {
LOG(INFO) << "close";
- CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session. Crashing.";
+ // TODO(b/166800618): call enterIdling from the terminal callbacks and restore this check.
+ // CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session.
+ // Crashing.";
mCurrentState = SessionState::CLOSED;
- mCb->onStateChanged(cookie, mCurrentState);
+ mCb->onSessionClosed();
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 42e1aa5..6667f7a 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -37,7 +37,7 @@
cb->onEnrollmentProgress(0 /* enrollmentId */, 0 /* remaining */);
}
- void authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/) {
+ void authenticateImpl(ISessionCallback* cb, int64_t /* operationId */) {
LOG(INFO) << "authenticateImpl";
cb->onAuthenticationSucceeded(0 /* enrollmentId */, {} /* hat */);
}
diff --git a/biometrics/fingerprint/aidl/default/include/Session.h b/biometrics/fingerprint/aidl/default/include/Session.h
index 97d5645..9e46422 100644
--- a/biometrics/fingerprint/aidl/default/include/Session.h
+++ b/biometrics/fingerprint/aidl/default/include/Session.h
@@ -27,37 +27,50 @@
namespace common = aidl::android::hardware::biometrics::common;
namespace keymaster = aidl::android::hardware::keymaster;
+enum class SessionState {
+ IDLING,
+ CLOSED,
+ GENERATING_CHALLENGE,
+ REVOKING_CHALLENGE,
+ ENROLLING,
+ AUTHENTICATING,
+ DETECTING_INTERACTION,
+ ENUMERATING_ENROLLMENTS,
+ REMOVING_ENROLLMENTS,
+ GETTING_AUTHENTICATOR_ID,
+ INVALIDATING_AUTHENTICATOR_ID,
+ RESETTING_LOCKOUT,
+};
+
class Session : public BnSession {
public:
Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
FakeFingerprintEngine* engine, WorkerThread* worker);
- ndk::ScopedAStatus generateChallenge(int32_t cookie) override;
+ ndk::ScopedAStatus generateChallenge() override;
- ndk::ScopedAStatus revokeChallenge(int32_t cookie, int64_t challenge) override;
+ ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
- ndk::ScopedAStatus enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+ ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat,
std::shared_ptr<common::ICancellationSignal>* out) override;
- ndk::ScopedAStatus authenticate(int32_t cookie, int64_t operationId,
+ ndk::ScopedAStatus authenticate(int64_t operationId,
std::shared_ptr<common::ICancellationSignal>* out) override;
ndk::ScopedAStatus detectInteraction(
- int32_t cookie, std::shared_ptr<common::ICancellationSignal>* out) override;
+ std::shared_ptr<common::ICancellationSignal>* out) override;
- ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
+ ndk::ScopedAStatus enumerateEnrollments() override;
- ndk::ScopedAStatus removeEnrollments(int32_t cookie,
- const std::vector<int32_t>& enrollmentIds) override;
+ ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
- ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
+ ndk::ScopedAStatus getAuthenticatorId() override;
- ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
+ ndk::ScopedAStatus invalidateAuthenticatorId() override;
- ndk::ScopedAStatus resetLockout(int32_t cookie,
- const keymaster::HardwareAuthToken& hat) override;
+ ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override;
- ndk::ScopedAStatus close(int32_t cookie) override;
+ ndk::ScopedAStatus close() override;
ndk::ScopedAStatus onPointerDown(int32_t pointerId, int32_t x, int32_t y, float minor,
float major) override;
@@ -76,11 +89,11 @@
// Crashes the HAL if the provided state doesn't match the previously scheduled state.
// Otherwise, transitions into the provided state, clears the scheduled state, and notifies
// the client about the transition by calling ISessionCallback#onStateChanged.
- void enterStateOrCrash(int cookie, SessionState state);
+ void enterStateOrCrash(SessionState state);
// Sets the current state to SessionState::IDLING and notifies the client about the transition
// by calling ISessionCallback#onStateChanged.
- void enterIdling(int cookie);
+ void enterIdling();
// The sensor and user IDs for which this session was created.
int32_t mSensorId;
diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
index 0d5014bb..c548fe5 100644
--- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
@@ -32,23 +32,41 @@
TEST(WorkerThreadTest, ScheduleReturnsTrueWhenQueueHasSpace) {
WorkerThread worker(1 /*maxQueueSize*/);
for (int i = 0; i < 100; ++i) {
- EXPECT_TRUE(worker.schedule(Callable::from([] {})));
- // Allow enough time for the previous task to be processed.
- std::this_thread::sleep_for(2ms);
+ std::promise<void> promise;
+ auto future = promise.get_future();
+
+ ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable {
+ // Notify that the task has started.
+ promise.set_value();
+ })));
+
+ auto status = future.wait_for(1s);
+ EXPECT_EQ(status, std::future_status::ready);
}
}
TEST(WorkerThreadTest, ScheduleReturnsFalseWhenQueueIsFull) {
WorkerThread worker(2 /*maxQueueSize*/);
- // Add a long-running task.
- worker.schedule(Callable::from([] { std::this_thread::sleep_for(1s); }));
- // Allow enough time for the worker to start working on the previous task.
- std::this_thread::sleep_for(2ms);
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ // Schedule a long-running task.
+ ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable {
+ // Notify that the task has started.
+ promise.set_value();
+ // Block for a "very long" time.
+ std::this_thread::sleep_for(2s);
+ })));
+
+ // Make sure the long-running task began executing.
+ auto status = future.wait_for(1s);
+ ASSERT_EQ(status, std::future_status::ready);
+
+ // The first task is already being worked on, which means the queue must be empty.
// Fill the worker's queue to the maximum.
- worker.schedule(Callable::from([] {}));
- worker.schedule(Callable::from([] {}));
+ ASSERT_TRUE(worker.schedule(Callable::from([] {})));
+ ASSERT_TRUE(worker.schedule(Callable::from([] {})));
EXPECT_FALSE(worker.schedule(Callable::from([] {})));
}
@@ -71,7 +89,8 @@
auto future = promise.get_future();
// Schedule a special task to signal when all of the tasks are finished.
- worker.schedule(Callable::from([&promise] { promise.set_value(); }));
+ worker.schedule(
+ Callable::from([promise = std::move(promise)]() mutable { promise.set_value(); }));
auto status = future.wait_for(1s);
ASSERT_EQ(status, std::future_status::ready);
@@ -84,23 +103,37 @@
std::promise<void> promise2;
auto future1 = promise1.get_future();
auto future2 = promise2.get_future();
+ std::atomic<bool> value;
+ // Local scope for the worker to test its destructor when it goes out of scope.
{
WorkerThread worker(2 /*maxQueueSize*/);
- worker.schedule(Callable::from([&promise1] {
- promise1.set_value();
- std::this_thread::sleep_for(200ms);
- }));
- worker.schedule(Callable::from([&promise2] { promise2.set_value(); }));
- // Make sure the first task is executing.
- auto status1 = future1.wait_for(1s);
- ASSERT_EQ(status1, std::future_status::ready);
+ ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise1)]() mutable {
+ promise.set_value();
+ std::this_thread::sleep_for(200ms);
+ })));
+
+ // The first task should start executing.
+ auto status = future1.wait_for(1s);
+ ASSERT_EQ(status, std::future_status::ready);
+
+ // The second task should schedule successfully.
+ ASSERT_TRUE(
+ worker.schedule(Callable::from([promise = std::move(promise2), &value]() mutable {
+ // The worker should destruct before it gets a chance to execute this.
+ value = true;
+ promise.set_value();
+ })));
}
// The second task should never execute.
- auto status2 = future2.wait_for(1s);
- EXPECT_EQ(status2, std::future_status::timeout);
+ auto status = future2.wait_for(1s);
+ ASSERT_EQ(status, std::future_status::ready);
+ // The future is expected to be ready but contain an exception.
+ // Cannot use ASSERT_THROW because exceptions are disabled in this codebase.
+ // ASSERT_THROW(future2.get(), std::future_error);
+ EXPECT_FALSE(value);
}
} // namespace
diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
index 894fdfe..f1cfb17 100644
--- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
+++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
@@ -22,46 +22,20 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <chrono>
#include <future>
namespace aidl::android::hardware::biometrics::fingerprint {
namespace {
+using namespace std::literals::chrono_literals;
+
constexpr int kSensorId = 0;
constexpr int kUserId = 0;
-constexpr auto kCallbackTimeout = std::chrono::seconds(1);
-
-enum class MethodName {
- kOnStateChanged,
-};
-
-struct Invocation {
- MethodName methodName;
- int32_t cookie;
- SessionState state;
-};
class SessionCallback : public BnSessionCallback {
public:
- explicit SessionCallback() : mIsPromiseValid(false) {}
-
- void setPromise(std::promise<std::vector<Invocation>>&& promise) {
- mPromise = std::move(promise);
- mIsPromiseValid = true;
- }
-
- ndk::ScopedAStatus onStateChanged(int32_t cookie, SessionState state) override {
- Invocation invocation = {};
- invocation.methodName = MethodName::kOnStateChanged;
- invocation.cookie = cookie;
- invocation.state = state;
- mInvocations.push_back(invocation);
- if (state == SessionState::IDLING) {
- assert(mIsPromiseValid);
- mPromise.set_value(mInvocations);
- }
- return ndk::ScopedAStatus::ok();
- }
+ explicit SessionCallback(std::promise<void>&& promise) : mPromise(std::move(promise)) {}
ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
return ndk::ScopedAStatus::ok();
@@ -119,10 +93,13 @@
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus onSessionClosed() override {
+ mPromise.set_value();
+ return ndk::ScopedAStatus::ok();
+ }
+
private:
- bool mIsPromiseValid;
- std::vector<Invocation> mInvocations;
- std::promise<std::vector<Invocation>> mPromise;
+ std::promise<void> mPromise;
};
class Fingerprint : public testing::TestWithParam<std::string> {
@@ -137,33 +114,26 @@
};
TEST_P(Fingerprint, AuthenticateTest) {
- // Prepare the callback
- std::promise<std::vector<Invocation>> promise;
+ auto promise = std::promise<void>{};
auto future = promise.get_future();
- std::shared_ptr<SessionCallback> cb = ndk::SharedRefBase::make<SessionCallback>();
- cb->setPromise(std::move(promise));
+ // Prepare the callback.
+ auto cb = ndk::SharedRefBase::make<SessionCallback>(std::move(promise));
// Create a session
std::shared_ptr<ISession> session;
ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
// Call authenticate
- int32_t cookie = 123;
std::shared_ptr<common::ICancellationSignal> cancellationSignal;
- ASSERT_TRUE(session->authenticate(cookie, 0, &cancellationSignal).isOk());
+ ASSERT_TRUE(session->authenticate(-1 /* operationId */, &cancellationSignal).isOk());
// Get the results
- ASSERT_TRUE(future.wait_for(kCallbackTimeout) == std::future_status::ready);
- std::vector<Invocation> invocations = future.get();
+ // TODO(b/166799066): test authenticate.
// Close the session
- ASSERT_TRUE(session->close(0).isOk());
-
- ASSERT_FALSE(invocations.empty());
- EXPECT_EQ(invocations.front().methodName, MethodName::kOnStateChanged);
- EXPECT_EQ(invocations.front().state, SessionState::AUTHENTICATING);
- EXPECT_EQ(invocations.back().methodName, MethodName::kOnStateChanged);
- EXPECT_EQ(invocations.back().state, SessionState::IDLING);
+ ASSERT_TRUE(session->close().isOk());
+ auto status = future.wait_for(1s);
+ ASSERT_EQ(status, std::future_status::ready);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint);
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
index b159083..57e6592 100644
--- a/broadcastradio/1.0/default/OWNERS
+++ b/broadcastradio/1.0/default/OWNERS
@@ -1,4 +1,3 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
twasilczyk@google.com
diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp
index 42782f2..15c1b5c 100644
--- a/camera/device/3.7/Android.bp
+++ b/camera/device/3.7/Android.bp
@@ -1,5 +1,14 @@
// This file is autogenerated by hidl-gen -Landroidbp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
hidl_interface {
name: "android.hardware.camera.device@3.7",
root: "android.hardware",
@@ -15,6 +24,11 @@
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
"android.hardware.camera.device@3.6",
+ "android.hardware.camera.metadata@3.2",
+ "android.hardware.camera.metadata@3.3",
+ "android.hardware.camera.metadata@3.4",
+ "android.hardware.camera.metadata@3.5",
+ "android.hardware.camera.metadata@3.6",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/camera/device/3.7/types.hal b/camera/device/3.7/types.hal
index 9450c2f..6910e65 100644
--- a/camera/device/3.7/types.hal
+++ b/camera/device/3.7/types.hal
@@ -21,6 +21,8 @@
import @3.4::CaptureRequest;
import @3.4::Stream;
+import android.hardware.camera.metadata@3.6::CameraMetadataEnumAndroidSensorPixelMode;
+
/**
* Stream:
*
@@ -57,6 +59,14 @@
* usage flag.
*/
int32_t groupId;
+
+ /**
+ * The sensor pixel modes used by this stream. This can assist the camera
+ * HAL in decision making about stream combination support.
+ * If this is empty, the HAL must assume that this stream will only be used
+ * with ANDROID_SENSOR_PIXEL_MODE set to ANDROID_SENSOR_PIXEL_MODE_DEFAULT.
+ */
+ vec<CameraMetadataEnumAndroidSensorPixelMode> sensorPixelModesUsed;
};
/**
diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal
index 3472ae9..709cfb3 100644
--- a/camera/metadata/3.6/types.hal
+++ b/camera/metadata/3.6/types.hal
@@ -36,6 +36,43 @@
* '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
*/
enum CameraMetadataTag : @3.5::CameraMetadataTag {
+ /** android.control.availableHighSpeedVideoConfigurationsMaximumResolution [static, int32[], hidden]
+ *
+ * <p>List of available high speed video size, fps range and max batch size configurations
+ * supported by the camera device, in the format of
+ * (width, height, fps_min, fps_max, batch_size_max),
+ * when ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.5::CameraMetadataTag:ANDROID_CONTROL_END_3_5,
+
+ ANDROID_CONTROL_END_3_6,
+
+ /** android.lens.distortionMaximumResolution [static, float[], public]
+ *
+ * <p>The correction coefficients to correct for this camera device's
+ * radial and tangential lens distortion for a
+ * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_LENS_END_3_3,
+
+ /** android.lens.intrinsicCalibrationMaximumResolution [static, float[], public]
+ *
+ * <p>The parameters for this camera device's intrinsic
+ * calibration when ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION,
+
+ ANDROID_LENS_END_3_6,
+
/** android.scaler.defaultSecureImageSize [static, int32[], public]
*
* <p>Default YUV/PRIVATE size to use for requesting secure image buffers.</p>
@@ -50,14 +87,237 @@
*/
ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS,
+ /** android.scaler.availableStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+ *
+ * <p>The available stream configurations that this
+ * camera device supports (i.e. format, width, height, output/input stream) for a
+ * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.scaler.availableMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination when the camera device is sent a CaptureRequest with
+ * ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.scaler.availableStallDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination when CaptureRequests are submitted with
+ * ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a></p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.scaler.availableInputOutputFormatsMapMaximumResolution [static, int32, hidden]
+ *
+ * <p>The mapping of image formats that are supported by this
+ * camera device for input streams, to their corresponding output formats, when
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP_MAXIMUM_RESOLUTION,
+
ANDROID_SCALER_END_3_6,
+ /** android.sensor.opaqueRawSizeMaximumResolution [static, int32[], system]
+ *
+ * <p>Size in bytes for all the listed opaque RAW buffer sizes when
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_END,
+
+ /** android.sensor.pixelMode [dynamic, enum, public]
+ *
+ * <p>Switches sensor pixel mode between maximum resolution mode and default mode.</p>
+ */
+ ANDROID_SENSOR_PIXEL_MODE,
+
+ /** android.sensor.rawBinningFactorUsed [dynamic, enum, public]
+ *
+ * <p>Whether <code>RAW</code> images requested have their bayer pattern as described by
+ * ANDROID_SENSOR_INFO_BINNING_FACTOR.</p>
+ *
+ * @see ANDROID_SENSOR_INFO_BINNING_FACTOR
+ */
+ ANDROID_SENSOR_RAW_BINNING_FACTOR_USED,
+
+ ANDROID_SENSOR_END_3_6,
+
+ /** android.sensor.info.activeArraySizeMaximumResolution [static, int32[], public]
+ *
+ * <p>The area of the image sensor which corresponds to active pixels after any geometric
+ * distortion correction has been applied, when the sensor runs in maximum resolution mode.</p>
+ */
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_INFO_END,
+
+ /** android.sensor.info.pixelArraySizeMaximumResolution [static, int32[], public]
+ *
+ * <p>Dimensions of the full pixel array, possibly
+ * including black calibration pixels, when the sensor runs in maximum resolution mode.
+ * Analogous to ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, when ANDROID_SENSOR_PIXEL_MODE is
+ * set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+
+ /** android.sensor.info.preCorrectionActiveArraySizeMaximumResolution [static, int32[], public]
+ *
+ * <p>The area of the image sensor which corresponds to active pixels prior to the
+ * application of any geometric distortion correction, when the sensor runs in maximum
+ * resolution mode. This key must be used for crop / metering regions, only when
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+
+ /** android.sensor.info.binningFactor [static, int32[], public]
+ *
+ * <p>Dimensions of the group of pixels which are under the same color filter.
+ * This specifies the width and height (pair of integers) of the group of pixels which fall
+ * under the same color filter for ULTRA_HIGH_RESOLUTION sensors.</p>
+ */
+ ANDROID_SENSOR_INFO_BINNING_FACTOR,
+
+ ANDROID_SENSOR_INFO_END_3_6,
+
+ /** android.depth.availableDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+ *
+ * <p>The available depth dataspace stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream) when a CaptureRequest is submitted with
+ * ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_DEPTH_END_3_4,
+
+ /** android.depth.availableDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for depth output formats when a CaptureRequest is submitted with
+ * ANDROID_SENSOR_PIXEL_MODE set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.depth.availableDepthStallDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination for depth streams for CaptureRequests where
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+ *
+ * <p>The available dynamic depth dataspace stream
+ * configurations that this camera device supports (i.e. format, width, height,
+ * output/input stream) for CaptureRequests where ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.depth.availableDynamicDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for dynamic depth output streams for CaptureRequests where
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.depth.availableDynamicDepthStallDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination for dynamic depth streams for CaptureRequests where
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+ ANDROID_DEPTH_END_3_6,
+
+ /** android.heic.availableHeicStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+ *
+ * <p>The available HEIC (ISO/IEC 23008-12) stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).</p>
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_HEIC_END_3_4,
+
+ /** android.heic.availableHeicMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for HEIC output formats for CaptureRequests where
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+ /** android.heic.availableHeicStallDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination for HEIC streams for CaptureRequests where
+ * ANDROID_SENSOR_PIXEL_MODE is set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+ ANDROID_HEIC_END_3_6,
+
};
/*
* Enumeration definitions for the various entries that need them
*/
+/** android.request.availableCapabilities enumeration values added since v3.5
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
+ @3.5::CameraMetadataEnumAndroidRequestAvailableCapabilities {
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
+};
+
/** android.scaler.physicalCameraMultiResolutionStreamConfigurations enumeration values
* @see ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS
*/
@@ -65,3 +325,51 @@
ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_OUTPUT,
ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_INPUT,
};
+
+/** android.scaler.availableStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurationsMaximumResolution : uint32_t {
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.sensor.pixelMode enumeration values
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+enum CameraMetadataEnumAndroidSensorPixelMode : uint32_t {
+ ANDROID_SENSOR_PIXEL_MODE_DEFAULT,
+ ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION,
+};
+
+/** android.sensor.rawBinningFactorUsed enumeration values
+ * @see ANDROID_SENSOR_RAW_BINNING_FACTOR_USED
+ */
+enum CameraMetadataEnumAndroidSensorRawBinningFactorUsed : uint32_t {
+ ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_TRUE,
+ ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_FALSE,
+};
+
+/** android.depth.availableDepthStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurationsMaximumResolution : uint32_t {
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurationsMaximumResolution : uint32_t {
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+ ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.heic.availableHeicStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurationsMaximumResolution : uint32_t {
+ ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+ ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
diff --git a/camera/provider/2.7/Android.bp b/camera/provider/2.7/Android.bp
index 094dd9d..ba59b38 100644
--- a/camera/provider/2.7/Android.bp
+++ b/camera/provider/2.7/Android.bp
@@ -1,5 +1,14 @@
// This file is autogenerated by hidl-gen -Landroidbp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
hidl_interface {
name: "android.hardware.camera.provider@2.7",
root: "android.hardware",
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9e99c48..c656af2 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -359,7 +359,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.media.c2</name>
- <version>1.0-1</version>
+ <version>1.0-2</version>
<interface>
<name>IComponentStore</name>
<regex-instance>default[0-9]*</regex-instance>
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
index 5033ce8..75122bc 100644
--- a/contexthub/1.2/types.hal
+++ b/contexthub/1.2/types.hal
@@ -35,10 +35,12 @@
AIRPLANE_MODE,
/**
- * Indicates if the microphone access was turned off globally by the user,
- * in which case audio data cannot be used and propagated by CHRE.
+ * Indicates if the microphone access is available for CHRE. Microphone
+ * access is disabled if the user has turned off the microphone as a
+ * privacy setting, in which case audio data cannot be used and propagated
+ * by CHRE.
*/
- GLOBAL_MIC_DISABLE,
+ MICROPHONE,
};
struct ContextHubMsg {
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
index 3510c23..9ee40ed 100644
--- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -131,10 +131,10 @@
ASSERT_OK(registerCallback_1_2(nullptr));
}
-TEST_P(ContexthubHidlTest, TestOnGlobalMicDisableSettingChanged) {
+TEST_P(ContexthubHidlTest, TestOnMicrophoneSettingChanged) {
ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2()));
- hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::DISABLED);
- hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::ENABLED);
+ hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::DISABLED);
+ hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::ENABLED);
ASSERT_OK(registerCallback_1_2(nullptr));
}
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 9a44eb5..609f59e 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -33,6 +33,7 @@
"service.cpp",
],
shared_libs: [
+ "libcutils",
"libhidlbase",
"libutils",
"liblog",
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
index 1a2feb7..a4f0097 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
index 9c9a241..b0848bb 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
index fbcc8a3..7d3baa4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
index 15fe2e9..c54cc2c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
index f873b87..c1fcfcc 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
index 9e05db7..ebb5d0b 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
index bc73bb1..948c540 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
index b9db343..24f45c4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
index 6676e2e..670244f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
index ba02f72..c2a5b51 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 10b05a7..f93b496 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index 9ad9159..fb0931c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.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,4 +38,5 @@
const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
const int CAPABILITY_CORRELATION_VECTOR = 4096;
const int CAPABILITY_SATELLITE_PVT = 8192;
+ const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
index 20dd781..54cd022 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
index 93894bf..6e62617 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 07a51ae..24d6f9c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
index 1cc7f71..fbf1f6f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
index 01f91dc..bfa787e 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
index 1758792..526ecc8 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
index a1af105..2205bc4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
index b387121..727bb69 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
index 4dd45b2..ed23e63 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
index c96b2e5..e1a20c3 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
index 95af152..747ee90 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.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/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
index 558aec9..a571048 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.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/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
index f20cd25..336e927 100644
--- a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
@@ -17,8 +17,8 @@
package android.hardware.gnss;
import android.hardware.gnss.CorrelationVector;
-import android.hardware.gnss.GnssSignalType;
import android.hardware.gnss.GnssMultipathIndicator;
+import android.hardware.gnss.GnssSignalType;
import android.hardware.gnss.SatellitePvt;
/**
@@ -32,41 +32,41 @@
@VintfStability
parcelable GnssMeasurement {
/** Bit mask indicating a valid 'snr' is stored in the GnssMeasurement. */
- const int HAS_SNR = 1 << 0;
+ const int HAS_SNR = 1 << 0;
/** Bit mask indicating a valid 'carrier frequency' is stored in the GnssMeasurement. */
- const int HAS_CARRIER_FREQUENCY = 1 << 9;
+ const int HAS_CARRIER_FREQUENCY = 1 << 9;
/** Bit mask indicating a valid 'carrier cycles' is stored in the GnssMeasurement. */
- const int HAS_CARRIER_CYCLES = 1 << 10;
+ const int HAS_CARRIER_CYCLES = 1 << 10;
/** Bit mask indicating a valid 'carrier phase' is stored in the GnssMeasurement. */
- const int HAS_CARRIER_PHASE = 1 << 11;
+ const int HAS_CARRIER_PHASE = 1 << 11;
/** Bit mask indicating a valid 'carrier phase uncertainty' is stored in the GnssMeasurement. */
- const int HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12;
+ const int HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12;
/** Bit mask indicating a valid automatic gain control is stored in the GnssMeasurement. */
- const int HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13;
+ const int HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13;
/** Bit mask indicating a valid full inter-signal bias is stored in the GnssMeasurement. */
- const int HAS_FULL_ISB = 1 << 16;
+ const int HAS_FULL_ISB = 1 << 16;
/**
* Bit mask indicating a valid full inter-signal bias uncertainty is stored in the
* GnssMeasurement.
*/
- const int HAS_FULL_ISB_UNCERTAINTY = 1 << 17;
+ const int HAS_FULL_ISB_UNCERTAINTY = 1 << 17;
/**
* Bit mask indicating a valid satellite inter-signal bias is stored in the GnssMeasurement.
*/
- const int HAS_SATELLITE_ISB = 1 << 18;
+ const int HAS_SATELLITE_ISB = 1 << 18;
/**
* Bit mask indicating a valid satellite inter-signal bias uncertainty is stored in the
* GnssMeasurement.
*/
- const int HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19;
+ const int HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19;
/**
* Bit mask indicating a valid satellite PVT is stored in the GnssMeasurement.
*/
- const int HAS_SATELLITE_PVT = 1 << 20;
+ const int HAS_SATELLITE_PVT = 1 << 20;
/**
* Bit mask indicating valid correlation vectors are stored in the GnssMeasurement.
*/
- const int HAS_CORRELATION_VECTOR = 1 << 21;
+ const int HAS_CORRELATION_VECTOR = 1 << 21;
/**
* A bitfield of flags indicating the validity of the fields in this GnssMeasurement. The bit
@@ -132,17 +132,17 @@
* the received GNSS satellite time value.
*
* +---------------------------+--------------------+-----+-----------+--------------------+------+
- * | |GPS/QZSS |GLNS |BDS |GAL |SBAS |
+ * | |GPS/QZSS |GLNS |BDS |GAL |SBAS |
* +---------------------------+------+------+------+-----+------+----+------+------+------+------+
* |State Flag |L1 |L5I |L5Q |L1OF |B1I |B1I |E1B |E1C |E5AQ |L1 |
- * | |C/A | | | |(D1) |(D2)| | | |C/A |
+ * | |C/A | | | |(D1) |(D2)| | | |C/A |
* |---------------------------+------+------+------+-----+------+----+------+------+------+------+
- * |STATE_UNKNOWN |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ * |STATE_UNKNOWN |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
* |---------------------------+------+------+------+-----+------+----+------+------+------+------+
* |STATE_CODE_LOCK |1ms |1 ms |1 ms |1 ms |1 ms |1 ms|- |- |1 ms |1 ms |
* |---------------------------+------+------+------+-----+------+----+------+------+------+------+
* |STATE_SYMBOL_SYNC |20ms |10 ms |1 ms |10 ms|20 ms |2 ms|4 ms |4 ms |1 ms |2 ms |
- * | |(opt.)| |(opt.)| |(opt.)| |(opt.)|(opt.)|(opt.)| |
+ * | |(opt.)| |(opt.)| |(opt.)| |(opt.)|(opt.)|(opt.)| |
* |---------------------------+------+------+------+-----+------+----+------+------+------+------+
* |STATE_BIT_SYNC |20 ms |20 ms |1 ms |20 ms|20 ms |- |8 ms |- |1 ms |4 ms |
* | | | |(opt.)| | | | | |(opt.)| |
@@ -194,24 +194,24 @@
* - For E1B and E1C, STATE_SYMBOL_SYNC is optional, because it is implied by
* STATE_GAL_E1BC_CODE_LOCK.
*/
- const int STATE_UNKNOWN = 0;
- const int STATE_CODE_LOCK = 1 << 0;
- const int STATE_BIT_SYNC = 1 << 1;
- const int STATE_SUBFRAME_SYNC = 1 << 2;
- const int STATE_TOW_DECODED = 1 << 3;
- const int STATE_MSEC_AMBIGUOUS = 1 << 4;
- const int STATE_SYMBOL_SYNC = 1 << 5;
- const int STATE_GLO_STRING_SYNC = 1 << 6;
- const int STATE_GLO_TOD_DECODED = 1 << 7;
- const int STATE_BDS_D2_BIT_SYNC = 1 << 8;
- const int STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9;
- const int STATE_GAL_E1BC_CODE_LOCK = 1 << 10;
- const int STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11;
- const int STATE_GAL_E1B_PAGE_SYNC = 1 << 12;
- const int STATE_SBAS_SYNC = 1 << 13;
- const int STATE_TOW_KNOWN = 1 << 14;
- const int STATE_GLO_TOD_KNOWN = 1 << 15;
- const int STATE_2ND_CODE_LOCK = 1 << 16;
+ const int STATE_UNKNOWN = 0;
+ const int STATE_CODE_LOCK = 1 << 0;
+ const int STATE_BIT_SYNC = 1 << 1;
+ const int STATE_SUBFRAME_SYNC = 1 << 2;
+ const int STATE_TOW_DECODED = 1 << 3;
+ const int STATE_MSEC_AMBIGUOUS = 1 << 4;
+ const int STATE_SYMBOL_SYNC = 1 << 5;
+ const int STATE_GLO_STRING_SYNC = 1 << 6;
+ const int STATE_GLO_TOD_DECODED = 1 << 7;
+ const int STATE_BDS_D2_BIT_SYNC = 1 << 8;
+ const int STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9;
+ const int STATE_GAL_E1BC_CODE_LOCK = 1 << 10;
+ const int STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11;
+ const int STATE_GAL_E1B_PAGE_SYNC = 1 << 12;
+ const int STATE_SBAS_SYNC = 1 << 13;
+ const int STATE_TOW_KNOWN = 1 << 14;
+ const int STATE_GLO_TOD_KNOWN = 1 << 15;
+ const int STATE_2ND_CODE_LOCK = 1 << 16;
/**
* A bitfield of flags indicating the GnssMeasurementState per satellite sync state. It
@@ -380,7 +380,6 @@
*/
double pseudorangeRateUncertaintyMps;
-
/**
* Flags indicating the Accumulated Delta Range's states.
*
@@ -620,8 +619,10 @@
double satelliteInterSignalBiasUncertaintyNs;
/**
- * The GNSS satellite position, velocity and time information at the signal transmission time
- * receivedSvTimeInNs.
+ * The GNSS satellite position, velocity and time information at the same signal transmission
+ * time receivedSvTimeInNs.
+ *
+ * The position and velocity must be in ECEF coordinates.
*
* If the data is available, gnssMeasurementFlags must contain HAS_SATELLITE_PVT.
*/
@@ -635,4 +636,4 @@
* at equally spaced spatial offsets.
*/
CorrelationVector[] correlationVectors;
-}
\ No newline at end of file
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index 8881ea7..aad09ef 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -16,8 +16,8 @@
package android.hardware.gnss;
-import android.hardware.gnss.IGnssPsds;
import android.hardware.gnss.IGnssConfiguration;
+import android.hardware.gnss.IGnssPsds;
/**
* This interface is required for the HAL to communicate certain information
@@ -26,15 +26,17 @@
*/
@VintfStability
interface IGnssCallback {
-
/** Capability bit mask indicating that GNSS supports blocklisting satellites */
const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9;
/** Capability bit mask indicating that GNSS supports correlation vector */
- const int CAPABILITY_CORRELATION_VECTOR = 1 << 12;
+ const int CAPABILITY_CORRELATION_VECTOR = 1 << 12;
/** Capability bit mask indicating that GNSS supports satellite PVT */
- const int CAPABILITY_SATELLITE_PVT = 1 << 13;
+ const int CAPABILITY_SATELLITE_PVT = 1 << 13;
+
+ /** Capability bit mask indicating that GNSS supports measurement corrections for driving */
+ const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 1 << 14;
/**
* Callback to inform framework of the GNSS HAL implementation's capabilities.
diff --git a/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl
index 4b3615e..febe623 100644
--- a/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl
+++ b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl
@@ -18,6 +18,9 @@
/**
* Contains estimates of the satellite position fields in ECEF coordinate frame.
+ *
+ * The satellite position must be defined at the time of transmission of the
+ * signal receivedSvTimeNs.
*/
@VintfStability
parcelable SatellitePositionEcef {
@@ -36,4 +39,4 @@
* It covers satellite position and clock errors projected to the pseudorange measurements.
*/
double ureMeters;
-}
\ No newline at end of file
+}
diff --git a/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl
index 25ece3a..f2d7ab6 100644
--- a/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl
+++ b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl
@@ -18,6 +18,9 @@
/**
* Contains estimates of the satellite velocity fields in the ECEF coordinate frame.
+ *
+ * The satellite velocity must be defined at the time of transmission of the
+ * signal receivedSvTimeNs.
*/
@VintfStability
parcelable SatelliteVelocityEcef {
@@ -37,4 +40,4 @@
* projected to the pseudorange rate measurements.
*/
double ureRateMps;
-}
\ No newline at end of file
+}
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index d363a9f..4cc2b6e 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -40,6 +40,7 @@
],
shared_libs: [
"libbase",
+ "libcutils",
"libbinder_ndk",
"libhidlbase",
"libutils",
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index a330c5a..43db873 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -44,6 +44,7 @@
],
export_include_dirs: ["include"],
shared_libs: [
+ "libcutils",
"libhidlbase",
"libutils",
"android.hardware.gnss@1.0",
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 4d4ec93..79c78c3 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -28,6 +28,8 @@
#include <string>
#include <thread>
+#include <cutils/properties.h>
+
#include "GnssAntennaInfo.h"
#include "GnssConfiguration.h"
#include "GnssDebug.h"
@@ -157,9 +159,17 @@
std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
char inputBuffer[INPUT_BUFFER_SIZE];
if (!mHardwareModeChecked) {
- mGnssFd = open(GNSS_PATH, O_RDWR | O_NONBLOCK);
+ // default using gnss0
+ const char * gnss_dev_path = GNSS_PATH;
+ char devname_value[PROPERTY_VALUE_MAX] = "";
+ if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
+ gnss_dev_path = devname_value;
+ ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
+ }
+
+ mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
if (mGnssFd == -1) {
- ALOGW("Failed to open /dev/gnss0 errno: %d", errno);
+ ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
}
mHardwareModeChecked = true;
}
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
index 3e2289a..6ec1fae 100644
--- a/keymaster/4.1/default/Android.bp
+++ b/keymaster/4.1/default/Android.bp
@@ -45,5 +45,14 @@
"liblog",
"libutils",
],
+ required: [
+ "android.hardware.hardware_keystore.km41.xml",
+ ],
+}
+prebuilt_etc {
+ name: "android.hardware.hardware_keystore.km41.xml",
+ sub_dir: "permissions",
+ vendor: true,
+ src: "android.hardware.hardware_keystore.km41.xml",
}
diff --git a/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml b/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml
new file mode 100644
index 0000000..0dbeed8
--- /dev/null
+++ b/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<permissions>
+ <feature name="android.hardware.hardware_keystore" version="41" />
+</permissions>
diff --git a/media/c2/1.2/Android.bp b/media/c2/1.2/Android.bp
new file mode 100644
index 0000000..6d3e74d
--- /dev/null
+++ b/media/c2/1.2/Android.bp
@@ -0,0 +1,40 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+hidl_interface {
+ name: "android.hardware.media.c2@1.2",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IComponent.hal",
+ "IComponentStore.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "android.hardware.media.omx@1.0",
+ "android.hardware.media@1.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+}
diff --git a/media/c2/1.2/IComponent.hal b/media/c2/1.2/IComponent.hal
new file mode 100644
index 0000000..088d810
--- /dev/null
+++ b/media/c2/1.2/IComponent.hal
@@ -0,0 +1,61 @@
+/*
+ * 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.media.c2@1.2;
+
+import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
+import android.hardware.media.c2@1.1::IComponent;
+import android.hardware.media.c2@1.0::Status;
+
+
+/**
+ * Interface for a Codec2 component corresponding to API level 1.2 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
+ *
+ * @note This is an extension of version 1.1 of `IComponent`. The purpose of the
+ * extension is to add blocking allocation of output buffer from surface.
+ */
+interface IComponent extends @1.1::IComponent {
+ /**
+ * Starts using a surface for output with a synchronization object
+ *
+ * This method must not block.
+ *
+ * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+ * output surface.
+ * @param surface Output surface.
+ * @param syncObject synchronization object for buffer allocation between
+ * Framework and Component.
+ * @return status Status of the call, which may be
+ * - `OK` - The operation completed successfully.
+ * - `CANNOT_DO` - The component does not support an output surface.
+ * - `REFUSED` - The output surface cannot be accessed.
+ * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `CORRUPTED` - Some unknown error occurred.
+ */
+ setOutputSurfaceWithSyncObj(
+ uint64_t blockPoolId,
+ @2.0::IGraphicBufferProducer surface,
+ SurfaceSyncObj syncObject
+ ) generates (
+ Status status
+ );
+};
diff --git a/media/c2/1.2/IComponentStore.hal b/media/c2/1.2/IComponentStore.hal
new file mode 100644
index 0000000..c38fc7a
--- /dev/null
+++ b/media/c2/1.2/IComponentStore.hal
@@ -0,0 +1,64 @@
+/*
+ * 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.media.c2@1.2;
+
+import android.hardware.media.bufferpool@2.0::IClientManager;
+import android.hardware.media.c2@1.0::IComponentListener;
+import android.hardware.media.c2@1.1::IComponentStore;
+import android.hardware.media.c2@1.0::Status;
+
+import IComponent;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ *
+ * @note This is an extension of version 1.1 of `IComponentStore`. The purpose
+ * of the extension is to add support for blocking output buffer allocator.
+ */
+interface IComponentStore extends @1.1::IComponentStore {
+ /**
+ * Creates a component by name.
+ *
+ * @param name Name of the component to create. This must match one of the
+ * names returned by listComponents().
+ * @param listener Callback receiver.
+ * @param pool `IClientManager` object of the BufferPool in the client
+ * process. This may be null if the client does not own a BufferPool.
+ * @return status Status of the call, which may be
+ * - `OK` - The component was created successfully.
+ * - `NOT_FOUND` - There is no component with the given name.
+ * - `NO_MEMORY` - Not enough memory to create the component.
+ * - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `CORRUPTED` - Some unknown error occurred.
+ * @return comp The created component if @p status is `OK`.
+ *
+ * @sa IComponentListener.
+ */
+ createComponent_1_2(
+ string name,
+ IComponentListener listener,
+ IClientManager pool
+ ) generates (
+ Status status,
+ IComponent comp
+ );
+};
diff --git a/media/c2/1.2/types.hal b/media/c2/1.2/types.hal
new file mode 100644
index 0000000..096edbd
--- /dev/null
+++ b/media/c2/1.2/types.hal
@@ -0,0 +1,52 @@
+/*
+ * 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.media.c2@1.2;
+
+/**
+ * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
+ * output buffers. This keeps # of dequeued buffers from Surface less than
+ * configured max # of dequeued buffers all the time.
+ */
+struct SurfaceSyncObj {
+ /**
+ * ASharedMemory for synchronization data. Layout is below
+ *
+ * |lock(futex) 4bytes|
+ * |conditional_variable(futex) 4bytes|
+ * |# of max dequeable buffer 4bytes|
+ * |# of dequeued buffer 4bytes|
+ * |Status of the surface 4bytes|
+ * INIT = 0, Configuring surface is not finished.
+ * ACTIVE = 1, Surface is ready to allocate(dequeue).
+ * SWITCHING = 2, Switching to the new surface. It is blocked
+ * to allocate(dequeue) a buffer until switching
+ * completes.
+ */
+ handle syncMemory;
+
+ // Read-only.
+ // The values which are tied and not changed with respect to Surface
+ // which is currently set up.
+ /** BufferQueue id. */
+ uint64_t bqId;
+ /** Generation id. */
+ uint32_t generationId;
+ /** Consumer usage flags. See +ndk
+ * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+ */
+ uint64_t consumerUsage;
+};
diff --git a/neuralnetworks/1.0/types.t b/neuralnetworks/1.0/types.t
index d7b26aa..be1ee07 100644
--- a/neuralnetworks/1.0/types.t
+++ b/neuralnetworks/1.0/types.t
@@ -63,361 +63,25 @@
RELU6 = 3,
};
-/**
- * How an operand is used.
- */
-enum OperandLifeTime : int32_t {
- /**
- * The operand is internal to the model. It's created by an operation and
- * consumed by other operations. It must be an output operand of
- * exactly one operation.
- */
- TEMPORARY_VARIABLE,
+%insert OperandLifeTime
- /**
- * The operand is an input of the model. It must not be an output
- * operand of any operation.
- *
- * An operand can't be both input and output of a model.
- */
- MODEL_INPUT,
+%insert DeviceStatus
- /**
- * The operand is an output of the model. It must be an output
- * operand of exactly one operation.
- *
- * An operand can't be both input and output of a model.
- */
- MODEL_OUTPUT,
+%insert PerformanceInfo
- /**
- * The operand is a constant found in Model.operandValues. It must
- * not be an output operand of any operation.
- */
- CONSTANT_COPY,
+%insert Capabilities
- /**
- * The operand is a constant that was specified via a Memory
- * object. It must not be an output operand of any operation.
- */
- CONSTANT_REFERENCE,
+%insert DataLocation
- /**
- * The operand does not have a value. This is valid only for optional
- * arguments of operations.
- */
- NO_VALUE,
-};
+%insert Operand
-/**
- * Status of a device.
- */
-enum DeviceStatus : int32_t {
- AVAILABLE,
- BUSY,
- OFFLINE,
- UNKNOWN,
-};
+%insert Operation
-/**
- * Performance information for the reference workload.
- *
- * Used by a driver to report its performance characteristics.
- */
-struct PerformanceInfo {
- /**
- * Ratio of the time taken by the driver to execute the
- * workload compared to the time the CPU would take for the
- * same workload. A lower number is better.
- */
- float execTime;
+%insert Model
- /**
- * Ratio of the energy used by the driver compared to what
- * the CPU would use for doing the same workload. A lower number
- * is better.
- */
- float powerUsage;
-};
+%insert RequestArgument
-/**
- * The capabilities of a driver.
- */
-struct Capabilities {
- /**
- * Driver performance when operating on float32 data.
- */
- PerformanceInfo float32Performance;
-
- /**
- * Driver performance when operating on asymmetric 8-bit quantized data.
- */
- PerformanceInfo quantized8Performance;
-};
-
-/**
- * Describes the location of a data object.
- */
-struct DataLocation {
- /**
- * The index of the memory pool where this location is found.
- */
- uint32_t poolIndex;
-
- /**
- * Offset in bytes from the start of the pool.
- */
- uint32_t offset;
-
- /**
- * The length of the data in bytes.
- */
- uint32_t length;
-};
-
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
- /**
- * Data type of the operand.
- */
- OperandType type;
-
- /**
- * Dimensions of the operand.
- *
- * For a scalar operand, dimensions.size() must be 0.
- *
- * For a tensor operand, dimensions.size() must be at least 1;
- * however, any of the dimensions may be unspecified.
- *
- * A tensor operand with all dimensions specified has "fully
- * specified" dimensions. Whenever possible (i.e., whenever the
- * dimensions are known at model construction time), a tensor
- * operand should have (but is not required to have) fully
- * specified dimensions, in order to enable the best possible
- * performance.
- *
- * If a tensor operand's dimensions are not fully specified, the
- * dimensions of the operand are deduced from the operand
- * dimensions and values of the operation for which that operand
- * is an output.
- *
- * In the following situations, a tensor operand's dimensions must
- * be fully specified:
- *
- * . The operand has lifetime CONSTANT_COPY or
- * CONSTANT_REFERENCE.
- *
- * . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
- * specified dimensions must either be present in the
- * Operand or they must be provided in the corresponding
- * RequestArgument.
- * EXCEPTION: If the input or output is optional and omitted
- * (by setting the hasNoValue field of the corresponding
- * RequestArgument to true) then it need not have fully
- * specified dimensions.
- *
- * A tensor operand with some number of unspecified dimensions is
- * represented by setting each unspecified dimension to 0.
- */
- vec<uint32_t> dimensions;
-
- /**
- * The number of times this operand appears as an operation input.
- *
- * (For example, if this operand appears once in one operation's
- * input list, and three times in another operation's input list,
- * then numberOfConsumers = 4.)
- */
- uint32_t numberOfConsumers;
-
- /**
- * Quantized scale of the operand.
- *
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
- * TENSOR_INT32.
- */
- float scale;
-
- /**
- * Quantized zero-point offset of the operand.
- *
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
- */
- int32_t zeroPoint;
-
- /**
- * How the operand is used.
- */
- OperandLifeTime lifetime;
-
- /**
- * Where to find the data for this operand.
- * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
- * NO_VALUE:
- * - All the fields must be 0.
- * If the lifetime is CONSTANT_COPY:
- * - location.poolIndex is 0.
- * - location.offset is the offset in bytes into Model.operandValues.
- * - location.length is set.
- * If the lifetime is CONSTANT_REFERENCE:
- * - location.poolIndex is set.
- * - location.offset is the offset in bytes into the specified pool.
- * - location.length is set.
- */
- DataLocation location;
-};
-
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
- /**
- * The operation type.
- */
- OperationType type;
-
- /**
- * Describes the table that contains the indexes of the inputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> inputs;
-
- /**
- * Describes the table that contains the indexes of the outputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> outputs;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * might not be known is the shape of the input tensors.
- */
-struct Model {
- /**
- * All operands included in the model.
- */
- vec<Operand> operands;
-
- /**
- * All operations included in the model.
- *
- * The operations are sorted into execution order. Every operand
- * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
- * written before it is read.
- */
- vec<Operation> operations;
-
- /**
- * Input indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> inputIndexes;
-
- /**
- * Output indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> outputIndexes;
-
- /**
- * A byte buffer containing operand data that were copied into the model.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_COPY.
- */
- vec<uint8_t> operandValues;
-
- /**
- * A collection of shared memory pools containing operand values.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_REFERENCE.
- */
- vec<memory> pools;
-};
-
-/**
- * Metadata information specifying the location of the input or output data and
- * any updates to the input or output operand.
- */
-struct RequestArgument {
- /**
- * If true, the argument does not have a value. This can be used for
- * operations that take optional arguments. If true, the fields of location
- * are set to 0 and the dimensions vector is left empty.
- */
- bool hasNoValue;
-
- /**
- * The location within one of the memory pools passed in the Request.
- */
- DataLocation location;
-
- /**
- * Updated dimension information.
- *
- * If dimensions.size() > 0, dimension information was provided
- * along with the argument. This can be the case for models that
- * accept inputs of varying size. This can't change the rank, just
- * the value of the dimensions that were unspecified in the
- * model. If dimensions.size() > 0, then all dimensions must be
- * specified here; and any dimension that was specified in the
- * model must have the same value here.
- *
- * If the dimensions in the model are not fully specified, then
- * they must be fully specified here, unless hasNoValue is set to
- * true. If the dimensions in the model are fully specified, then
- * either dimensions.size() may be 0, or the dimensions in the
- * model must be identical to the dimensions here.
- */
- vec<uint32_t> dimensions;
-};
-
-/**
- * Inputs to be sent to and outputs to be retrieved from a prepared model.
- *
- * A Request serves two primary tasks:
- * 1) Provides the input and output data to be used when executing the model.
- * 2) Specifies any updates to the input operand metadata that were left
- * unspecified at model preparation time.
- *
- * An output must not overlap with any other output, with an input, or
- * with an operand of lifetime CONSTANT_REFERENCE.
- */
-struct Request {
- /**
- * Input data and information to be used in the execution of a prepared
- * model.
- *
- * The index of the input corresponds to the index in Model.inputIndexes.
- * E.g., input[i] corresponds to Model.inputIndexes[i].
- */
- vec<RequestArgument> inputs;
-
- /**
- * Output data and information to be used in the execution of a prepared
- * model.
- *
- * The index of the output corresponds to the index in Model.outputIndexes.
- * E.g., output[i] corresponds to Model.outputIndexes[i].
- */
- vec<RequestArgument> outputs;
-
- /**
- * A collection of shared memory pools containing operand data for both the
- * inputs and the outputs to a model.
- */
- vec<memory> pools;
-};
+%insert Request
/**
* Return status of a function.
diff --git a/neuralnetworks/1.1/types.t b/neuralnetworks/1.1/types.t
index 75ac2e7..8c22b30 100644
--- a/neuralnetworks/1.1/types.t
+++ b/neuralnetworks/1.1/types.t
@@ -31,128 +31,10 @@
%insert Operation_1.1
};
-/**
- * The capabilities of a driver.
- */
-struct Capabilities {
- /**
- * Driver performance when operating on float32 data.
- */
- PerformanceInfo float32Performance;
+%insert Capabilities
- /**
- * Driver performance when operating on asymmetric 8-bit quantized data.
- */
- PerformanceInfo quantized8Performance;
+%insert Operation
- /**
- * Driver performance when operating on float32 data but performing
- * calculations with range and/or precision as low as that of the IEEE
- * 754 16-bit floating-point format.
- */
- PerformanceInfo relaxedFloat32toFloat16Performance;
-};
+%insert Model
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
- /**
- * The operation type.
- */
- OperationType type;
-
- /**
- * Describes the table that contains the indexes of the inputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> inputs;
-
- /**
- * Describes the table that contains the indexes of the outputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> outputs;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
- /**
- * All operands included in the model.
- */
- vec<Operand> operands;
-
- /**
- * All operations included in the model.
- *
- * The operations are sorted into execution order. Every operand
- * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
- * written before it is read.
- */
- vec<Operation> operations;
-
- /**
- * Input indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> inputIndexes;
-
- /**
- * Output indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> outputIndexes;
-
- /**
- * A byte buffer containing operand data that were copied into the model.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_COPY.
- */
- vec<uint8_t> operandValues;
-
- /**
- * A collection of shared memory pools containing operand values.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_REFERENCE.
- */
- vec<memory> pools;
-
- /**
- * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
- * precision as low as that of the IEEE 754 16-bit floating-point format.
- * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
- * range and precision of the IEEE 754 32-bit floating-point format.
- */
- bool relaxComputationFloat32toFloat16;
-};
-
-/**
- * Execution preferences.
- */
-enum ExecutionPreference : int32_t {
- /**
- * Prefer executing in a way that minimizes battery drain.
- * This is desirable for compilations that will be executed often.
- */
- LOW_POWER = 0,
- /**
- * Prefer returning a single answer as fast as possible, even if this causes
- * more power consumption.
- */
- FAST_SINGLE_ANSWER = 1,
- /**
- * Prefer maximizing the throughput of successive frames, for example when
- * processing successive frames coming from the camera.
- */
- SUSTAINED_SPEED = 2,
-};
+%insert ExecutionPreference
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
index 4c9fd02..b490f7f 100644
--- a/neuralnetworks/1.2/types.t
+++ b/neuralnetworks/1.2/types.t
@@ -97,379 +97,23 @@
BASE_MAX = 0xFFFF,
};
-/**
- * Device types.
- *
- * The type of NNAPI device.
- */
-enum DeviceType : int32_t {
- // Leaving 0 unused as it means unknown type in NDK NNAPI. There is no
- // HAL equivalent of unknown type and a 1.2 HAL implementation must belong
- // to one of the categories below.
- /** The device does not fall into any category below. */
- OTHER = 1,
- /** The device runs NNAPI models on single or multi-core CPU. */
- CPU = 2,
- /** The device can run NNAPI models and also accelerate graphics APIs such
- * as OpenGL ES and Vulkan. */
- GPU = 3,
- /** Dedicated accelerator for Machine Learning workloads. */
- ACCELERATOR = 4,
-};
+%insert DeviceType
-/**
- * The capabilities of a driver.
- *
- * Performance of an operation comes from the type of its first operand.
- * This represents performance for non extension operand types.
- */
-struct Capabilities {
- /**
- * Driver performance when operating on float32 data but performing
- * calculations with range and/or precision as low as that of the IEEE
- * 754 16-bit floating-point format.
- */
- PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
- PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+%insert Capabilities
- /**
- * Driver performance when operating on a particular data type.
- * In the case of float32 data, this is used when the calculations
- * are not relaxed.
- */
- struct OperandPerformance {
- OperandType type;
- PerformanceInfo info;
- };
+%insert Operation
- /**
- * Performance by operand type. Must be sorted by OperandType.
- * If a particular OperandType is not present in operandPerformance,
- * its performance is treated as { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
- */
- vec<OperandPerformance> operandPerformance;
-};
+%insert SymmPerChannelQuantParams
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
- /**
- * The operation type.
- *
- * Besides the values listed in {@link OperationType}, any value above
- * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
- * as an extension type according to {@link Model::extensionNameToPrefix}.
- */
- OperationType type;
+%insert Operand
- /**
- * Describes the table that contains the indexes of the inputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> inputs;
+%insert Model
- /**
- * Describes the table that contains the indexes of the outputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> outputs;
-};
+%insert OutputShape
-/**
- * Parameters for TENSOR_QUANT8_SYMM_PER_CHANNEL operand.
- */
-struct SymmPerChannelQuantParams {
- /** Array of scaling values for each channel. Each value must be greater than zero. */
- vec<float> scales;
- /** Index of the channel dimension */
- uint32_t channelDim;
-};
+%insert MeasureTiming
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
- /**
- * The data type.
- *
- * Besides the values listed in {@link OperandType}, any value above
- * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
- * as an extension type according to {@link Model::extensionNameToPrefix}.
- */
- OperandType type;
-
- /**
- * Dimensions of the operand.
- *
- * For a scalar operand, dimensions.size() must be 0.
- *
- * A tensor operand with all dimensions specified has "fully
- * specified" dimensions. Whenever possible (i.e., whenever the
- * dimensions are known at model construction time), a tensor
- * operand should have (but is not required to have) fully
- * specified dimensions, in order to enable the best possible
- * performance.
- *
- * If a tensor operand's dimensions are not fully specified, the
- * dimensions of the operand are deduced from the operand
- * dimensions and values of the operation for which that operand
- * is an output.
- *
- * In the following situations, a tensor operand's dimensions must
- * be fully specified:
- *
- * . The operand has lifetime CONSTANT_COPY or
- * CONSTANT_REFERENCE.
- *
- * . The operand has lifetime MODEL_INPUT. Fully
- * specified dimensions must either be present in the
- * Operand or they must be provided in the corresponding
- * RequestArgument.
- * EXCEPTION: If the input is optional and omitted
- * (by setting the hasNoValue field of the corresponding
- * RequestArgument to true) then it need not have fully
- * specified dimensions.
- *
- * A tensor operand with some number of unspecified dimensions is
- * represented by setting each unspecified dimension to 0.
- *
- * A tensor operand with unspecified rank is represented by providing
- * an empty dimensions vector.
- */
- vec<uint32_t> dimensions;
-
- /**
- * The number of times this operand appears as an operation input.
- *
- * (For example, if this operand appears once in one operation's
- * input list, and three times in another operation's input list,
- * then numberOfConsumers = 4.)
- */
- uint32_t numberOfConsumers;
-
- /**
- * Quantized scale of the operand.
- *
- * Must be 0 when not applicable to an operand type.
- *
- * See {@link OperandType}.
- */
- float scale;
-
- /**
- * Quantized zero-point offset of the operand.
- *
- * Must be 0 when not applicable to an operand type.
- *
- * See {@link OperandType}.
- */
- int32_t zeroPoint;
-
- /**
- * How the operand is used.
- */
- OperandLifeTime lifetime;
-
- /**
- * Where to find the data for this operand.
- * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
- * NO_VALUE:
- * - All the fields must be 0.
- * If the lifetime is CONSTANT_COPY:
- * - location.poolIndex is 0.
- * - location.offset is the offset in bytes into Model.operandValues.
- * - location.length is set.
- * If the lifetime is CONSTANT_REFERENCE:
- * - location.poolIndex is set.
- * - location.offset is the offset in bytes into the specified pool.
- * - location.length is set.
- */
- DataLocation location;
-
- /**
- * Additional parameters specific to a particular operand type.
- */
- safe_union ExtraParams {
- /**
- * No additional parameters.
- */
- Monostate none;
-
- /**
- * Symmetric per-channel quantization parameters.
- *
- * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
- */
- SymmPerChannelQuantParams channelQuant;
-
- /**
- * Extension operand parameters.
- *
- * The framework treats this as an opaque data blob.
- * The format is up to individual extensions.
- */
- vec<uint8_t> extension;
- } extraParams;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
- /**
- * All operands included in the model.
- */
- vec<Operand> operands;
-
- /**
- * All operations included in the model.
- *
- * The operations are sorted into execution order. Every operand
- * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
- * written before it is read.
- */
- vec<Operation> operations;
-
- /**
- * Input indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> inputIndexes;
-
- /**
- * Output indexes of the model. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> outputIndexes;
-
- /**
- * A byte buffer containing operand data that were copied into the model.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_COPY.
- */
- vec<uint8_t> operandValues;
-
- /**
- * A collection of shared memory pools containing operand values.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_REFERENCE.
- */
- vec<memory> pools;
-
- /**
- * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
- * precision as low as that of the IEEE 754 16-bit floating-point format.
- * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
- * range and precision of the IEEE 754 32-bit floating-point format.
- */
- bool relaxComputationFloat32toFloat16;
-
- /**
- * The mapping between extension names and prefixes of operand and
- * operation type values.
- *
- * An operand or operation whose numeric type value is above
- * {@link OperandTypeRange::BASE_MAX} or
- * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
- * as an extension operand. The low
- * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
- * correspond to the type ID within the extension and the high
- * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
- * the "prefix", which maps uniquely to the extension name.
- *
- * For example, if a model contains an operation whose value is
- * 0xAAAABBBB and extensionNameToPrefix contains an entry with
- * prefix=0xAAAA and name="vendor.test.test_extension", then
- * the operation should be interpreted as the operation 0xBBBB
- * of the extension named vendor.test.test_extension.
- *
- * This is a one-to-one correspondence. That is, there must be at most one
- * prefix corresponding to each extension name and at most one extension
- * name corresponding to each prefix.
- */
- vec<ExtensionNameAndPrefix> extensionNameToPrefix;
-
- /**
- * A correspondence between an extension name and a prefix of operand and
- * operation type values.
- */
- struct ExtensionNameAndPrefix {
- /**
- * The extension name.
- *
- * See {@link Extension::name} for the format specification.
- */
- string name;
-
- /**
- * The unique extension identifier within the model.
- *
- * See {@link Model::extensionNameToPrefix}.
- */
- uint16_t prefix;
- };
-
- /**
- * Numeric values of extension operand and operation types have the
- * following structure:
- * - 16 high bits represent the "prefix", which corresponds uniquely to the
- * extension name.
- * - 16 low bits represent the type ID within the extension.
- */
- enum ExtensionTypeEncoding : uint8_t {
- HIGH_BITS_PREFIX = 16,
- LOW_BITS_TYPE = 16,
- };
-};
-
-/**
- * Describes the shape information of an output operand after execution.
- */
-struct OutputShape {
- /**
- * Dimensions of the operand.
- */
- vec<uint32_t> dimensions;
-
- /**
- * Whether the provided buffer size is sufficient for the output.
- */
- bool isSufficient;
-};
-
-/**
- * Specifies whether or not to measure timing information during execution.
- */
-enum MeasureTiming : int32_t {
- NO = 0,
- YES = 1,
-};
-
-/**
-
- * Timing information measured during execution. Each time is a duration from
- * the beginning of some task to the end of that task, including time when that
- * task is not active (for example, preempted by some other task, or
- * waiting for some resource to become available).
- *
- * Times are measured in microseconds.
- * When a time is not available, it must be reported as UINT64_MAX.
- */
-struct Timing {
- /** Execution time on device (not driver, which runs on host processor). */
- uint64_t timeOnDevice;
- /** Execution time in driver (including time on device). */
- uint64_t timeInDriver;
-};
+%insert Timing
/**
* FmqRequestDatum is a single element of a serialized representation of an
@@ -683,46 +327,4 @@
Timing executionTiming;
};
-/**
- * Information about an extension.
- */
-struct Extension {
- /**
- * The extension name.
- *
- * The name must consist of lowercase latin letters, numbers, periods, and
- * underscore signs. The name must contain at least one period.
- *
- * The name must start with the reverse domain name of the vendor.
- *
- * Example: com.google.test_extension
- */
- string name;
-
- /**
- * Information about an extension operand type.
- */
- struct OperandTypeInformation {
- /**
- * The extension operand type.
- */
- uint16_t type;
-
- /**
- * Indicates whether the extension operand type represents a tensor or
- * a scalar.
- */
- bool isTensor;
-
- /**
- * The byte size of the operand (if scalar) or of a single element (if
- * tensor).
- */
- uint32_t byteSize;
- };
-
- /**
- * Information about operand types defined by the extension.
- */
- vec<OperandTypeInformation> operandTypes;
-};
+%insert Extension
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 9f69c9e..96d1a1b 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -90,459 +90,25 @@
BASE_MAX = 0xFFFF,
};
-/**
- * Priority given to a prepared model for execution.
- */
-enum Priority : int32_t {
- LOW,
- MEDIUM,
- HIGH,
-};
+%insert Priority
-/**
- * The capabilities of a driver.
- *
- * This represents performance of non-extension operations.
- *
- * Performance of an operation other than {@link OperationType::IF} and
- * {@link OperationType::WHILE} comes from the type of its first operand.
- */
-struct Capabilities {
- /**
- * Driver performance when operating on float32 data but performing
- * calculations with range and/or precision as low as that of the IEEE
- * 754 16-bit floating-point format.
- */
- PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
- PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+%insert Capabilities
- /**
- * Driver performance when operating on a particular data type.
- * In the case of float32 data, this is used when the calculations
- * are not relaxed.
- */
- struct OperandPerformance {
- OperandType type;
- PerformanceInfo info;
- };
+%insert Operation
- /**
- * Performance by operand type. Must be sorted by OperandType.
- *
- * If a particular {@link OperandType} is not present in operandPerformance,
- * its performance is treated as
- * { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
- *
- * Performance does not apply to {@link OperandType::SUBGRAPH}, and a driver
- * must not report operand performance for {@link OperandType::SUBGRAPH}.
- */
- vec<OperandPerformance> operandPerformance;
+%insert OperandLifeTime
- /**
- * Performance of an {@link OperationType::IF} operation is the sum of
- * {@link Capabilities::ifPerformance} and the mean of performance for the
- * two branch subgraphs, where performance for a subgraph is the sum of the
- * performance of all operations within the subgraph.
- */
- PerformanceInfo ifPerformance;
+%insert Operand
- /**
- * Performance of a {@link OperationType::WHILE} operation is the sum of
- * {@link Capabilities::whilePerformance}, performance for the condition
- * subgraph and performance for the body subgraph, where performance for a
- * subgraph is the sum of the performance of all operations within the
- * subgraph.
- */
- PerformanceInfo whilePerformance;
-};
+%insert Model
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
- /**
- * The operation type.
- *
- * Besides the values listed in {@link OperationType}, any value above
- * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
- * as an extension type according to {@link Model::extensionNameToPrefix}.
- */
- OperationType type;
+%insert Subgraph
- /**
- * Describes the table that contains the indexes of the inputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> inputs;
+%insert BufferDesc
- /**
- * Describes the table that contains the indexes of the outputs of the
- * operation. The offset is the index in the operandIndexes table.
- */
- vec<uint32_t> outputs;
-};
+%insert BufferRole
-/**
- * How an operand is used.
- */
-enum OperandLifeTime : int32_t {
- /**
- * The operand is internal to the model. It's created by an operation and
- * consumed by other operations. It must be an output operand of
- * exactly one operation.
- */
- TEMPORARY_VARIABLE,
-
- /**
- * The operand is an input of a subgraph. It must not be an output
- * operand of any operation.
- *
- * An operand can't be both input and output of a subgraph.
- */
- SUBGRAPH_INPUT,
-
- /**
- * The operand is an output of a subgraph. It must be an output
- * operand of exactly one operation.
- *
- * An operand can't be both input and output of a subgraph.
- */
- SUBGRAPH_OUTPUT,
-
- /**
- * The operand is a constant found in Model.operandValues. It must
- * not be an output operand of any operation.
- */
- CONSTANT_COPY,
-
- /**
- * The operand is a constant that was specified via a Memory
- * object. It must not be an output operand of any operation.
- */
- CONSTANT_REFERENCE,
-
- /**
- * The operand does not have a value. This is valid only for optional
- * arguments of operations.
- */
- NO_VALUE,
-
- /**
- * The operand is a reference to a subgraph. It must be an input to one
- * or more {@link OperationType::IF} or {@link OperationType::WHILE}
- * operations.
- */
- SUBGRAPH,
-};
-
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
- /**
- * The data type.
- *
- * Besides the values listed in {@link OperandType}, any value above
- * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
- * as an extension type according to {@link Model::extensionNameToPrefix}.
- */
- OperandType type;
-
- /**
- * Dimensions of the operand.
- *
- * For a scalar operand, dimensions.size() must be 0.
- *
- * A tensor operand with all dimensions specified has "fully
- * specified" dimensions. Whenever possible (i.e., whenever the
- * dimensions are known at model construction time), a tensor
- * operand should have (but is not required to have) fully
- * specified dimensions, in order to enable the best possible
- * performance.
- *
- * If a tensor operand's dimensions are not fully specified, the
- * dimensions of the operand are deduced from the operand
- * dimensions and values of the operation for which that operand
- * is an output or from the corresponding {@link OperationType::IF} or
- * {@link OperationType::WHILE} operation input operand dimensions in the
- * case of referenced subgraph input operands.
- *
- * In the following situations, a tensor operand's dimensions must
- * be fully specified:
- *
- * . The operand has lifetime CONSTANT_COPY or
- * CONSTANT_REFERENCE.
- *
- * . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
- * subgraph. Fully specified dimensions must either be present in the
- * Operand or they must be provided in the corresponding
- * RequestArgument.
- * EXCEPTION: If the input is optional and omitted
- * (by setting the hasNoValue field of the corresponding
- * RequestArgument to true) then it need not have fully
- * specified dimensions.
- *
- * A tensor operand with some number of unspecified dimensions is
- * represented by setting each unspecified dimension to 0.
- *
- * A tensor operand with unspecified rank is represented by providing
- * an empty dimensions vector.
- */
- vec<uint32_t> dimensions;
-
- /**
- * The number of times this operand appears as an operation input.
- *
- * (For example, if this operand appears once in one operation's
- * input list, and three times in another operation's input list,
- * then numberOfConsumers = 4.)
- */
- uint32_t numberOfConsumers;
-
- /**
- * Quantized scale of the operand.
- *
- * Must be 0 when not applicable to an operand type.
- *
- * See {@link OperandType}.
- */
- float scale;
-
- /**
- * Quantized zero-point offset of the operand.
- *
- * Must be 0 when not applicable to an operand type.
- *
- * See {@link OperandType}.
- */
- int32_t zeroPoint;
-
- /**
- * How the operand is used.
- */
- OperandLifeTime lifetime;
-
- /**
- * Where to find the data for this operand.
- * If the lifetime is TEMPORARY_VARIABLE, SUBGRAPH_INPUT, SUBGRAPH_OUTPUT,
- * or NO_VALUE:
- * - All the fields must be 0.
- * If the lifetime is CONSTANT_COPY:
- * - location.poolIndex is 0.
- * - location.offset is the offset in bytes into Model.operandValues.
- * - location.length is set.
- * If the lifetime is CONSTANT_REFERENCE:
- * - location.poolIndex is set.
- * - location.offset is the offset in bytes into the specified pool.
- * - location.length is set.
- * If the lifetime is SUBGRAPH:
- * - location.poolIndex is 0.
- * - location.offset is the index of the referenced subgraph in
- * {@link Model::referenced}.
- * - location.length is 0.
- */
- DataLocation location;
-
- /**
- * Additional parameters specific to a particular operand type.
- */
- @1.2::Operand.ExtraParams extraParams;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
- /**
- * The top-level subgraph.
- */
- Subgraph main;
-
- /**
- * Referenced subgraphs.
- *
- * Each subgraph is referenced by the main subgraph or at least one other
- * referenced subgraph.
- *
- * There must be no reference cycles.
- */
- vec<Subgraph> referenced;
-
- /**
- * A byte buffer containing operand data that were copied into the model.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_COPY.
- */
- vec<uint8_t> operandValues;
-
- /**
- * A collection of shared memory pools containing operand values.
- *
- * An operand's value must be located here if and only if Operand::lifetime
- * equals OperandLifeTime::CONSTANT_REFERENCE.
- */
- vec<memory> pools;
-
- /**
- * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
- * precision as low as that of the IEEE 754 16-bit floating-point format.
- * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
- * range and precision of the IEEE 754 32-bit floating-point format.
- */
- bool relaxComputationFloat32toFloat16;
-
- /**
- * The mapping between extension names and prefixes of operand and
- * operation type values.
- *
- * An operand or operation whose numeric type value is above
- * {@link OperandTypeRange::BASE_MAX} or
- * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
- * as an extension operand. The low
- * {@link @1.2::Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the
- * value correspond to the type ID within the extension and the high
- * {@link @1.2::Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
- * the "prefix", which maps uniquely to the extension name.
- *
- * For example, if a model contains an operation whose value is
- * 0xAAAABBBB and extensionNameToPrefix contains an entry with
- * prefix=0xAAAA and name="vendor.test.test_extension", then
- * the operation should be interpreted as the operation 0xBBBB
- * of the extension named vendor.test.test_extension.
- *
- * This is a one-to-one correspondence. That is, there must be at most one
- * prefix corresponding to each extension name and at most one extension
- * name corresponding to each prefix.
- */
- vec<@1.2::Model.ExtensionNameAndPrefix> extensionNameToPrefix;
-};
-
-/**
- * An excerpt of the execution graph.
- */
-struct Subgraph {
- /**
- * All operands included in the subgraph.
- */
- vec<Operand> operands;
-
- /**
- * All operations included in the subgraph.
- *
- * The operations are sorted into execution order. Every operand
- * with lifetime SUBGRAPH_OUTPUT or TEMPORARY_VARIABLE must be
- * written before it is read.
- */
- vec<Operation> operations;
-
- /**
- * Input indexes of the subgraph. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> inputIndexes;
-
- /**
- * Output indexes of the subgraph. There must be at least one.
- *
- * Each value corresponds to the index of the operand in "operands".
- */
- vec<uint32_t> outputIndexes;
-};
-
-/**
- * A buffer descriptor. Describes the properties of a buffer.
- */
-struct BufferDesc {
- /**
- * Dimensions of the buffer. May have unknown dimensions or rank. A buffer with some number
- * of unspecified dimensions is represented by setting each unspecified dimension to 0. A
- * buffer with unspecified rank is represented by providing an empty dimensions vector.
- */
- vec<uint32_t> dimensions;
-};
-
-/**
- * Describes a role of an input or output to a prepared model.
- */
-struct BufferRole {
- /**
- * The index of the IPreparedModel within the "preparedModel" argument passed in
- * IDevice::allocate.
- */
- uint32_t modelIndex;
-
- /**
- * The index of the input or output operand.
- */
- uint32_t ioIndex;
-
- /**
- * A floating-point value within the range (0.0, 1.0]. Describes how likely the
- * buffer is to be used in the specified role. This is provided as a hint to
- * optimize the case when multiple roles prefer different buffer locations or data
- * layouts.
- */
- float frequency;
-};
-
-/**
- * Inputs to be sent to and outputs to be retrieved from a prepared model.
- *
- * A Request serves two primary tasks:
- * 1) Provides the input and output data to be used when executing the model.
- * 2) Specifies any updates to the input operand metadata that were left
- * unspecified at model preparation time.
- *
- * An output must not overlap with any other output, with an input, or
- * with an operand of lifetime CONSTANT_REFERENCE.
- */
-struct Request {
- /**
- * Input data and information to be used in the execution of a prepared
- * model.
- *
- * The index of the input corresponds to the index in Model.main.inputIndexes.
- * E.g., input[i] corresponds to Model.main.inputIndexes[i].
- */
- vec<RequestArgument> inputs;
-
- /**
- * Output data and information to be used in the execution of a prepared
- * model.
- *
- * The index of the output corresponds to the index in Model.main.outputIndexes.
- * E.g., output[i] corresponds to Model.main.outputIndexes[i].
- */
- vec<RequestArgument> outputs;
-
- /**
- * A memory pool.
- */
- safe_union MemoryPool {
- /**
- * Specifies a client-managed shared memory pool.
- */
- memory hidlMemory;
-
- /**
- * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
- * and is specific to the IDevice object.
- */
- uint32_t token;
- };
-
- /**
- * A collection of memory pools containing operand data for both the
- * inputs and the outputs to a model.
- */
- vec<MemoryPool> pools;
-};
+%insert Request
/**
* Optional time point of the steady clock (as from std::chrono::steady_clock)
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index 9788fe1..8b45f71 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -244,7 +244,7 @@
return BufferRole{
.modelIndex = bufferRole.modelIndex,
.ioIndex = bufferRole.ioIndex,
- .frequency = bufferRole.frequency,
+ .probability = bufferRole.frequency,
};
}
@@ -577,7 +577,7 @@
return BufferRole{
.modelIndex = bufferRole.modelIndex,
.ioIndex = bufferRole.ioIndex,
- .frequency = bufferRole.frequency,
+ .frequency = bufferRole.probability,
};
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl
index 71b7758..05cec76 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl
index c2d636c..10a6b75 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.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. //
///////////////////////////////////////////////////////////////////////////////
@@ -35,5 +36,5 @@
parcelable BufferRole {
int modelIndex;
int ioIndex;
- float frequency;
+ float probability;
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl
index 01cc753..30877c0 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl
index e836dae..db49a38 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl
index 7bc8aa7..7cdd6db 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl
index 1abacc8..82fe8ae 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl
index 873c584..57d5d6e 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl
index c4badc0..4352d8f 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl
index b99bb31..44e9922 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl
index a7ae942..c47028d 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
index 4c25538..6c287fd 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
index b32b217..a3680aa 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl
index 2fee136..7e61bbb 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl
index 2860692..f10e7e2 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.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/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
index 4db47c9..634f39e 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
@@ -31,21 +31,9 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+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);
+ 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 4c5fd2f..b328b29 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
@@ -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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
index abe67b8..0bfb80a 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.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/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 1f7cbe0..52882cd 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
@@ -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. //
///////////////////////////////////////////////////////////////////////////////
@@ -35,6 +36,7 @@
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.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/IPreparedModelCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
index 8eaaab6..e0c763b 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
index 8388fda..dbedf12 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.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/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 3b2f240..8207b25 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
@@ -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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl
index 9d12e58..30d8dda 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
index c1e87da..9314760 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl
index bb78caa..5a9f4ff 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl
index 3f6d93b..14792cf 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl
index d581ced..40adfb1 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl
index 87fd3a6..de93d8b 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl
index 186c13d..9f2c759 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl
index fec83a8..33fcd60 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
index ad42b02..de3b438 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl
index 09a43f7..f733505 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl
index 178946c..04910f5 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl
index d9b77fa..8f35709 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl
index 599b3f4..39ec7a9 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl
index 91b9aa7..e3541c0 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl
index 3813b51..312f581 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl
index dec976f..b7d4451 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.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/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
index 66fdfe7..02d68f9 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.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/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 d0de34a..9690e01 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
@@ -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/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl
index 0d7f678..c444851 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl
@@ -35,5 +35,5 @@
* used in the specified role. This is provided as a hint to optimize the case when multiple
* roles prefer different buffer locations or data layouts.
*/
- float frequency;
+ float probability;
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
new file mode 100644
index 0000000..85d2a03
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
@@ -0,0 +1,120 @@
+/*
+ * 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.neuralnetworks;
+
+import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionResult;
+import android.hardware.neuralnetworks.Request;
+
+/**
+ * IBurst represents a burst execution object.
+ *
+ * Burst executions are a sequence of executions of the same prepared model that occur in rapid
+ * succession, such as frames of a camera capture or successive audio samples. A burst object is
+ * used to control a set of burst executions, and to preserve resources between executions, enabling
+ * executions to have lower overhead. Burst objects enable some optimizations:
+ * (1) A burst object is created before a sequence of executions, and freed when the sequence has
+ * ended. Because of this, the lifetime of the burst object hints to a driver how long it should
+ * remain in a high performance state.
+ * (2) A burst object can preserve resources between executions. For example, a driver can map a
+ * memory object on the first execution and cache the mapping in the burst object for reuse in
+ * subsequent executions. Any cached resource can be released when the burst object is destroyed
+ * or when the NNAPI runtime notifies the burst object that the resource is no longer required.
+ * (3) A burst object may be used for at most one execution at a time. This enables any transient
+ * execution resources such as intermediate tensors to be allocated once when the burst object
+ * is created and freed when the burst object is destroyed.
+ */
+@VintfStability
+interface IBurst {
+ /**
+ * Performs a synchronous execution on a burst object.
+ *
+ * The execution is performed synchronously with respect to the caller. executeSynchronously
+ * must verify the inputs to the function are correct, and the usages of memory pools allocated
+ * by IDevice::allocate are valid. If there is an error, executeSynchronously must immediately
+ * return a service specific exception with the appropriate ErrorStatus value. If the inputs to
+ * the function are valid and there is no error, executeSynchronously must perform the
+ * execution, and must not return until the execution is complete.
+ *
+ * The caller must not change the content of any data object referenced by 'request' (described
+ * by the {@link DataLocation} of a {@link RequestArgument}) until executeSynchronously returns.
+ * executeSynchronously must not change the content of any of the data objects corresponding to
+ * 'request' inputs.
+ *
+ * If the burst object was configured from a prepared model wherein all tensor operands have
+ * fully specified dimensions, and the inputs to the function are valid, and at execution time
+ * every operation's input operands have legal values, then the execution should complete
+ * successfully: there must be no failure unless the device itself is in a bad state.
+ *
+ * executeSynchronously may be called with an optional deadline. If the execution is not able to
+ * be completed before the provided deadline, the execution may be aborted, and either
+ * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+ * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+ * sent the same way as other errors, described above.
+ *
+ * Only a single execution on a given burst object may be active at any time.
+ *
+ * @param request The input and output information on which the prepared model is to be
+ * executed.
+ * @param memoryIdentifierTokens A list of tokens where each token is a non-negative number
+ * that uniquely identifies a memory object. Each memory
+ * identifier token corresponds to an element of request.pools. A
+ * value of -1 indicates no identity.
+ * @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}.
+ * @return ExecutionResult parcelable, containing the status of the execution, output shapes and
+ * timing information.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid
+ * - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+ * deadline
+ * - 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);
+
+ /**
+ * releaseMemoryResource is used by the client to signal to the service that a memory buffer
+ * corresponding to a slot number is no longer needed by the client, and any cached resources
+ * associated with that memory object may be released.
+ *
+ * The identifier tokens are unique to the burst object.
+ *
+ * @param memoryIdentifierToken Value uniquely identifying a memory object that is no longer
+ * used.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid
+ */
+ void releaseMemoryResource(in long memoryIdentifierToken);
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index 0240e3c..2a9757b 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -20,6 +20,7 @@
import android.hardware.neuralnetworks.ErrorStatus;
import android.hardware.neuralnetworks.ExecutionResult;
import android.hardware.neuralnetworks.FencedExecutionResult;
+import android.hardware.neuralnetworks.IBurst;
import android.hardware.neuralnetworks.Request;
/**
@@ -166,4 +167,22 @@
FencedExecutionResult executeFenced(in Request request, in ParcelFileDescriptor[] waitFor,
in boolean measureTiming, in long deadline, in long loopTimeoutDuration,
in long duration);
+
+ /**
+ * Configure a Burst object used to execute multiple inferences on a prepared model in rapid
+ * succession.
+ *
+ * If the prepared model was prepared from a model wherein all tensor operands have fully
+ * specified dimensions, and a valid serialized Request is sent to the Burst for execution, and
+ * at execution time every operation's input operands have legal values, then the execution
+ * should complete successfully (ErrorStatus::NONE): There must be no failure unless the device
+ * itself is in a bad state.
+ *
+ * @return burst Execution burst controller object.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ IBurst configureExecutionBurst();
}
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index c47ba0e..45bc005 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -472,7 +472,7 @@
return BufferRole{
.modelIndex = static_cast<uint32_t>(bufferRole.modelIndex),
.ioIndex = static_cast<uint32_t>(bufferRole.ioIndex),
- .frequency = bufferRole.frequency,
+ .probability = bufferRole.probability,
};
}
@@ -718,7 +718,7 @@
return BufferRole{
.modelIndex = static_cast<int32_t>(bufferRole.modelIndex),
.ioIndex = static_cast<int32_t>(bufferRole.ioIndex),
- .frequency = bufferRole.frequency,
+ .probability = bufferRole.probability,
};
}
diff --git a/neuralnetworks/aidl/utils/test/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
index 545b491..36e0ec3 100644
--- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h
+++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
@@ -39,6 +39,8 @@
bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
int64_t duration, FencedExecutionResult* fencedExecutionResult),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, configureExecutionBurst, (std::shared_ptr<IBurst> * burst),
+ (override));
};
inline std::shared_ptr<MockPreparedModel> MockPreparedModel::create() {
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index 4eb704b..1440429 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -17,6 +17,7 @@
#include "GeneratedTestHarness.h"
#include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
#include <android/sync.h>
@@ -101,7 +102,7 @@
ASSERT_NE(result, nullptr);
// Prepare arguments.
- BufferRole role = {.modelIndex = 0, .ioIndex = index, .frequency = 1.0f};
+ BufferRole role = {.modelIndex = 0, .ioIndex = index, .probability = 1.0f};
std::vector<BufferRole> inputRoles, outputRoles;
if constexpr (ioType == IOType::INPUT) {
inputRoles = {role};
@@ -299,9 +300,11 @@
}
static void makeOutputInsufficientSize(uint32_t outputIndex, Request* request) {
- auto& length = request->outputs[outputIndex].location.length;
- ASSERT_GT(length, 1u);
- length -= 1u;
+ auto& loc = request->outputs[outputIndex].location;
+ ASSERT_GT(loc.length, 1u);
+ loc.length -= 1u;
+ // Test that the padding is not used for output data.
+ loc.padding += 1u;
}
static void makeOutputDimensionsUnspecified(Model* model) {
@@ -336,6 +339,12 @@
std::vector<std::shared_ptr<IBuffer>> mBuffers;
};
+// Returns the number of bytes needed to round up "size" to the nearest multiple of "multiple".
+static uint32_t roundUpBytesNeeded(uint32_t size, uint32_t multiple) {
+ CHECK(multiple != 0);
+ return ((size + multiple - 1) / multiple) * multiple - size;
+}
+
std::optional<Request> ExecutionContext::createRequest(const TestModel& testModel,
MemoryType memoryType) {
// Memory pools are organized as:
@@ -370,10 +379,13 @@
}
// Reserve shared memory for input.
+ inputSize += roundUpBytesNeeded(inputSize, nn::kDefaultRequestMemoryAlignment);
+ const auto padding = roundUpBytesNeeded(op.data.size(), nn::kDefaultRequestMemoryPadding);
DataLocation loc = {.poolIndex = kInputPoolIndex,
.offset = static_cast<int64_t>(inputSize),
- .length = static_cast<int64_t>(op.data.size())};
- inputSize += op.data.alignedSize();
+ .length = static_cast<int64_t>(op.data.size()),
+ .padding = static_cast<int64_t>(padding)};
+ inputSize += (op.data.size() + padding);
inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
}
@@ -404,10 +416,13 @@
size_t bufferSize = std::max<size_t>(op.data.size(), 1);
// Reserve shared memory for output.
+ outputSize += roundUpBytesNeeded(outputSize, nn::kDefaultRequestMemoryAlignment);
+ const auto padding = roundUpBytesNeeded(bufferSize, nn::kDefaultRequestMemoryPadding);
DataLocation loc = {.poolIndex = kOutputPoolIndex,
.offset = static_cast<int64_t>(outputSize),
- .length = static_cast<int64_t>(bufferSize)};
- outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
+ .length = static_cast<int64_t>(bufferSize),
+ .padding = static_cast<int64_t>(padding)};
+ outputSize += (bufferSize + padding);
outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
}
@@ -568,6 +583,53 @@
}
break;
}
+ case Executor::BURST: {
+ SCOPED_TRACE("burst");
+
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ ASSERT_NE(nullptr, burst.get());
+
+ // associate a unique slot with each memory pool
+ int64_t currentSlot = 0;
+ std::vector<int64_t> slots;
+ slots.reserve(request.pools.size());
+ for (const auto& pool : request.pools) {
+ if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+ slots.push_back(currentSlot++);
+ } else {
+ EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
+ slots.push_back(-1);
+ }
+ }
+
+ ExecutionResult executionResult;
+ // execute
+ ret = burst->executeSynchronously(request, slots, testConfig.measureTiming, kNoDeadline,
+ loopTimeoutDuration, &executionResult);
+ ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << ret.getDescription();
+ if (ret.isOk()) {
+ executionStatus = executionResult.outputSufficientSize
+ ? ErrorStatus::NONE
+ : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+ outputShapes = std::move(executionResult.outputShapes);
+ timing = executionResult.timing;
+ } else {
+ executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+ }
+
+ // Mark each slot as unused after the execution. This is unnecessary because the burst
+ // is freed after this scope ends, but this is here to test the functionality.
+ for (int64_t slot : slots) {
+ ret = burst->releaseMemoryResource(slot);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ }
+
+ break;
+ }
case Executor::FENCED: {
SCOPED_TRACE("fenced");
ErrorStatus result = ErrorStatus::NONE;
@@ -713,19 +775,19 @@
case TestKind::GENERAL: {
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {false, true};
- executorList = {Executor::SYNC};
+ executorList = {Executor::SYNC, Executor::BURST};
memoryTypeList = {MemoryType::ASHMEM};
} break;
case TestKind::DYNAMIC_SHAPE: {
outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
measureTimingList = {false, true};
- executorList = {Executor::SYNC, Executor::FENCED};
+ executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
memoryTypeList = {MemoryType::ASHMEM};
} break;
case TestKind::MEMORY_DOMAIN: {
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {false};
- executorList = {Executor::SYNC, Executor::FENCED};
+ executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
} break;
case TestKind::FENCED_COMPUTE: {
@@ -741,7 +803,7 @@
case TestKind::INTINITE_LOOP_TIMEOUT: {
outputTypesList = {OutputType::MISSED_DEADLINE};
measureTimingList = {false, true};
- executorList = {Executor::SYNC, Executor::FENCED};
+ executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
memoryTypeList = {MemoryType::ASHMEM};
} break;
}
@@ -765,7 +827,7 @@
const TestModel& coupledModel) {
const std::vector<OutputType> outputTypesList = {OutputType::FULLY_SPECIFIED};
const std::vector<bool> measureTimingList = {false, true};
- const std::vector<Executor> executorList = {Executor::SYNC, Executor::FENCED};
+ const std::vector<Executor> executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
for (const OutputType outputType : outputTypesList) {
for (const bool measureTiming : measureTimingList) {
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 57bc1ae..596f8ae 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -203,6 +203,10 @@
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
}
+ ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>*) override {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
};
template <typename... Args>
@@ -333,18 +337,18 @@
const std::shared_ptr<IPreparedModel>& model2) {
validateAllocate({
.preparedModels = {model1, model2},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.preparedModels = {model1, model2},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
- .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
+ .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.preparedModels = {model1, model2},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
}
};
@@ -366,13 +370,13 @@
// Test with nullptr prepared model as input role.
validateAllocate({
.preparedModels = {nullptr},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
// Test with nullptr prepared model as output role.
validateAllocate({
.preparedModels = {nullptr},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -383,13 +387,13 @@
// Test with invalid prepared model as input role.
validateAllocate({
.preparedModels = {invalidPreparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
// Test with invalid prepared model as output role.
validateAllocate({
.preparedModels = {invalidPreparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -400,13 +404,13 @@
// This should fail, because the model index is out of bound.
validateAllocate({
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
// This should fail, because the model index is out of bound.
validateAllocate({
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -417,30 +421,30 @@
// This should fail, because the model only has one input.
validateAllocate({
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 1, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 1, .probability = 1.0f}},
});
// This should fail, because the model only has one output.
validateAllocate({
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 1, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 1, .probability = 1.0f}},
});
}
-TEST_P(MemoryDomainAllocateTest, InvalidFrequency) {
+TEST_P(MemoryDomainAllocateTest, InvalidProbability) {
auto preparedModel = createConvPreparedModel(kTestOperand);
if (preparedModel == nullptr) return;
for (float invalidFreq : {10.0f, 0.0f, -0.5f}) {
- // Test with invalid frequency for input roles.
+ // Test with invalid probability for input roles.
validateAllocate({
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = invalidFreq}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = invalidFreq}},
});
- // Test with invalid frequency for output roles.
+ // Test with invalid probability for output roles.
validateAllocate({
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = invalidFreq}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = invalidFreq}},
});
}
}
@@ -452,25 +456,25 @@
// Same role with same model index.
validateAllocate({
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
// Different model indexes, but logically referring to the same role.
validateAllocate({
.preparedModels = {preparedModel, preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.preparedModels = {preparedModel, preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
- {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f},
+ {.modelIndex = 1, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -549,12 +553,12 @@
validateAllocate({
.dimensions = badDimensions,
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.dimensions = badDimensions,
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -568,12 +572,12 @@
validateAllocate({
.dimensions = badDimensions,
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
validateAllocate({
.dimensions = badDimensions,
.preparedModels = {preparedModel},
- .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+ .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .probability = 1.0f}},
});
}
@@ -586,7 +590,7 @@
validateAllocate({
.dimensions = {1},
.preparedModels = {preparedModel},
- .inputRoles = {{.modelIndex = 0, .ioIndex = 2, .frequency = 1.0f}},
+ .inputRoles = {{.modelIndex = 0, .ioIndex = 2, .probability = 1.0f}},
});
}
@@ -620,7 +624,7 @@
std::vector<BufferRole> inputRoles(inputIndexes.size()), outputRoles(outputIndexes.size());
auto trans = [](int32_t ind) -> BufferRole {
- return {.modelIndex = 0, .ioIndex = ind, .frequency = 1.0f};
+ return {.modelIndex = 0, .ioIndex = ind, .probability = 1.0f};
};
std::transform(inputIndexes.begin(), inputIndexes.end(), inputRoles.begin(), trans);
std::transform(outputIndexes.begin(), outputIndexes.end(), outputRoles.begin(), trans);
@@ -866,6 +870,9 @@
case Executor::SYNC:
EXPECT_EQ(executeSync(preparedModel, request), expectedStatus);
break;
+ case Executor::BURST:
+ EXPECT_EQ(executeBurst(preparedModel, request), expectedStatus);
+ break;
case Executor::FENCED:
EXPECT_EQ(executeFenced(preparedModel, request), expectedStatus);
break;
@@ -916,6 +923,35 @@
return executionStatus;
}
+ ErrorStatus executeBurst(const std::shared_ptr<IPreparedModel>& preparedModel,
+ const Request& request) {
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ EXPECT_TRUE(ret.isOk()) << ret.getDescription();
+ EXPECT_NE(nullptr, burst.get());
+ if (!ret.isOk() || burst.get() == nullptr) {
+ return ErrorStatus::GENERAL_FAILURE;
+ }
+
+ // use -1 for all memory identifier tokens
+ const std::vector<int64_t> slots(request.pools.size(), -1);
+
+ ExecutionResult executionResult;
+ ret = burst->executeSynchronously(request, slots, false, kNoDeadline,
+ kOmittedTimeoutDuration, &executionResult);
+
+ if (!ret.isOk()) {
+ EXPECT_EQ(ret.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ return static_cast<ErrorStatus>(ret.getServiceSpecificError());
+ }
+ const ErrorStatus executionStatus = executionResult.outputSufficientSize
+ ? ErrorStatus::NONE
+ : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+ EXPECT_EQ(executionResult.timing, kNoTiming);
+ return executionStatus;
+ }
+
const Executor kExecutor = std::get<Executor>(GetParam());
};
@@ -1159,7 +1195,7 @@
ErrorStatus::GENERAL_FAILURE);
}
-const auto kExecutorChoices = testing::Values(Executor::SYNC, Executor::FENCED);
+const auto kExecutorChoices = testing::Values(Executor::SYNC, Executor::BURST, Executor::FENCED);
std::string printMemoryDomainExecutionTest(
const testing::TestParamInfo<MemoryDomainExecutionTestParam>& info) {
diff --git a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
index 58db98f..9ace1a9 100644
--- a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
@@ -51,6 +51,10 @@
using Results = std::tuple<ErrorStatus, std::vector<OutputShape>, Timing>;
using MaybeResults = std::optional<Results>;
+using ExecutionFunction =
+ std::function<MaybeResults(const std::shared_ptr<IPreparedModel>& preparedModel,
+ const Request& request, int64_t deadline)>;
+
static int64_t makeDeadline(DeadlineBoundType deadlineBoundType) {
const auto getNanosecondsSinceEpoch = [](const auto& time) -> int64_t {
const auto timeSinceEpoch = time.time_since_epoch();
@@ -177,13 +181,53 @@
std::move(executionResult.outputShapes), executionResult.timing});
}
+static MaybeResults executeBurst(const std::shared_ptr<IPreparedModel>& preparedModel,
+ const Request& request, int64_t deadline) {
+ SCOPED_TRACE("burst");
+ const bool measure = false;
+
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ EXPECT_TRUE(ret.isOk()) << ret.getDescription();
+ EXPECT_NE(nullptr, burst.get());
+ if (!ret.isOk() || burst.get() == nullptr) {
+ return std::nullopt;
+ }
+
+ // use -1 for all memory identifier tokens
+ const std::vector<int64_t> slots(request.pools.size(), -1);
+
+ // run execution
+ ExecutionResult executionResult;
+ ret = burst->executeSynchronously(request, slots, measure, deadline, kOmittedTimeoutDuration,
+ &executionResult);
+ EXPECT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << ret.getDescription();
+ if (!ret.isOk()) {
+ if (ret.getExceptionCode() != EX_SERVICE_SPECIFIC) {
+ return std::nullopt;
+ }
+ return MaybeResults(
+ {static_cast<ErrorStatus>(ret.getServiceSpecificError()), {}, kNoTiming});
+ }
+
+ // return results
+ return MaybeResults({executionResult.outputSufficientSize
+ ? ErrorStatus::NONE
+ : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE,
+ std::move(executionResult.outputShapes), executionResult.timing});
+}
+
void runExecutionTest(const std::shared_ptr<IPreparedModel>& preparedModel,
const TestModel& testModel, const Request& request,
- const ExecutionContext& context, DeadlineBoundType deadlineBound) {
+ const ExecutionContext& context, bool synchronous,
+ DeadlineBoundType deadlineBound) {
+ const ExecutionFunction execute = synchronous ? executeSynchronously : executeBurst;
const auto deadline = makeDeadline(deadlineBound);
// Perform execution and unpack results.
- const auto results = executeSynchronously(preparedModel, request, deadline);
+ const auto results = execute(preparedModel, request, deadline);
if (!results.has_value()) return;
const auto& [status, outputShapes, timing] = results.value();
@@ -235,8 +279,11 @@
void runExecutionTests(const std::shared_ptr<IPreparedModel>& preparedModel,
const TestModel& testModel, const Request& request,
const ExecutionContext& context) {
- for (auto deadlineBound : deadlineBounds) {
- runExecutionTest(preparedModel, testModel, request, context, deadlineBound);
+ for (bool synchronous : {false, true}) {
+ for (auto deadlineBound : deadlineBounds) {
+ runExecutionTest(preparedModel, testModel, request, context, synchronous,
+ deadlineBound);
+ }
}
}
diff --git a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
index 3be4c1b..29e2471 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
@@ -16,7 +16,9 @@
#define LOG_TAG "neuralnetworks_aidl_hal_test"
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
#include <android/binder_auto_utils.h>
+#include <variant>
#include <chrono>
@@ -77,6 +79,35 @@
ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
ErrorStatus::INVALID_ARGUMENT);
}
+
+ // burst
+ {
+ SCOPED_TRACE(message + " [burst]");
+
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ ASSERT_NE(nullptr, burst.get());
+
+ // use -1 for all memory identifier tokens
+ const std::vector<int64_t> slots(request.pools.size(), -1);
+
+ ExecutionResult executionResult;
+ const auto executeStatus = burst->executeSynchronously(
+ request, slots, measure, kNoDeadline, kOmittedTimeoutDuration, &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
+}
+
+std::shared_ptr<IBurst> createBurst(const std::shared_ptr<IPreparedModel>& preparedModel) {
+ std::shared_ptr<IBurst> burst;
+ const auto ret = preparedModel->configureExecutionBurst(&burst);
+ if (!ret.isOk()) return nullptr;
+ return burst;
}
///////////////////////// REMOVE INPUT ////////////////////////////////////
@@ -110,6 +141,65 @@
removeOutputTest(preparedModel, request);
}
+void validateBurst(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request) {
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ ASSERT_NE(nullptr, burst.get());
+
+ const auto test = [&burst, &request](const std::vector<int64_t>& slots) {
+ ExecutionResult executionResult;
+ const auto executeStatus =
+ burst->executeSynchronously(request, slots, /*measure=*/false, kNoDeadline,
+ kOmittedTimeoutDuration, &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ };
+
+ int64_t currentSlot = 0;
+ std::vector<int64_t> slots;
+ slots.reserve(request.pools.size());
+ for (const auto& pool : request.pools) {
+ if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+ slots.push_back(currentSlot++);
+ } else {
+ slots.push_back(-1);
+ }
+ }
+
+ constexpr int64_t invalidSlot = -2;
+
+ // validate failure when invalid memory identifier token value
+ for (size_t i = 0; i < request.pools.size(); ++i) {
+ const int64_t oldSlotValue = slots[i];
+
+ slots[i] = invalidSlot;
+ test(slots);
+
+ slots[i] = oldSlotValue;
+ }
+
+ // validate failure when request.pools.size() != memoryIdentifierTokens.size()
+ if (request.pools.size() > 0) {
+ slots = std::vector<int64_t>(request.pools.size() - 1, -1);
+ test(slots);
+ }
+
+ // validate failure when request.pools.size() != memoryIdentifierTokens.size()
+ slots = std::vector<int64_t>(request.pools.size() + 1, -1);
+ test(slots);
+
+ // validate failure when invalid memory identifier token value
+ const auto freeStatus = burst->releaseMemoryResource(invalidSlot);
+ ASSERT_FALSE(freeStatus.isOk());
+ ASSERT_EQ(freeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(freeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+}
+
void validateRequestFailure(const std::shared_ptr<IPreparedModel>& preparedModel,
const Request& request) {
SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index 2d91b8e..0c3a196 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -127,6 +127,8 @@
// Forward declaration from ValidateRequest.cpp
void validateRequest(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request);
// Forward declaration from ValidateRequest.cpp
+void validateBurst(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request);
+// Forward declaration from ValidateRequest.cpp
void validateRequestFailure(const std::shared_ptr<IPreparedModel>& preparedModel,
const Request& request);
@@ -140,6 +142,7 @@
if (preparedModel == nullptr) return;
validateRequest(preparedModel, request);
+ validateBurst(preparedModel, request);
// HIDL also had test that expected executeFenced to fail on received null fd (-1). This is not
// allowed in AIDL and will result in EX_TRANSACTION_FAILED.
}
@@ -178,8 +181,6 @@
std::string toString(Executor executor) {
switch (executor) {
- case Executor::ASYNC:
- return "ASYNC";
case Executor::SYNC:
return "SYNC";
case Executor::BURST:
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
index 9b81ee1..4312d3a 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
@@ -52,7 +52,7 @@
std::shared_ptr<IPreparedModel>* preparedModel,
bool reportSkipping = true);
-enum class Executor { ASYNC, SYNC, BURST, FENCED };
+enum class Executor { SYNC, BURST, FENCED };
std::string toString(Executor executor);
diff --git a/power/stats/aidl/Android.bp b/power/stats/aidl/Android.bp
index 454c69a..0dbf9b4 100644
--- a/power/stats/aidl/Android.bp
+++ b/power/stats/aidl/Android.bp
@@ -41,4 +41,5 @@
enabled: true,
},
},
+ host_supported: true,
}
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index d201332..a4e8811 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -544,4 +544,43 @@
* as the input param.
*/
oneway setCarrierInfoForImsiEncryption_1_6(int32_t serial, @1.6::ImsiEncryptionInfo imsiEncryptionInfo);
+
+ /**
+ * Get the local and global phonebook records from the SIM card.
+ * This should be called again after a simPhonebookChanged notification is received.
+ *
+ * The phonebook records are received via IRadioIndication.simPhonebookRecordsReceived()
+ *
+ * @param serial Serial number of request.
+ *
+ * Response callback is IRadioResponse.getSimPhonebookRecordsResponse()
+ */
+ oneway getSimPhonebookRecords(int32_t serial);
+
+ /**
+ * Get the phone book capacity
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is defined from IRadioResponse.getSimPhonebookCapacityResponse()
+ */
+ oneway getSimPhonebookCapacity(int32_t serial);
+
+ /**
+ * Insert, delete or update a phonebook record on the SIM card.
+ * If the index of recordInfo is 0, the phonebook record will be added to global or
+ * local phonebook, and global phonebook has higher priority than local phonebook.
+ *
+ * If the fields in the recordInfo are all empty except for the index, the phonebook
+ * record specified by the index will be deleted.
+ *
+ * The indication simPhonebookChanged will be called after every successful call of
+ * updateSimPhonebookRecords.
+ *
+ * @param serial Serial number of request.
+ * @param recordInfo Details of the record to insert, delete or update.
+ *
+ * Response callback is IRadioResponse.updateSimPhonebookRecordsResponse()
+ */
+ oneway updateSimPhonebookRecords(int32_t serial, PhonebookRecordInfo recordInfo);
};
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index a53d7c1..9788345 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -23,7 +23,9 @@
import @1.6::NetworkScanResult;
import @1.6::SignalStrength;
import @1.6::SetupDataCallResult;
+import @1.6::PbReceivedStatus;
import @1.6::PhysicalChannelConfig;
+import @1.6::PhonebookRecordInfo;
/**
* Interface declaring unsolicited radio indications.
@@ -72,7 +74,6 @@
*/
oneway currentLinkCapacityEstimate_1_6(RadioIndicationType type, LinkCapacityEstimate lce);
-
/**
* Indicates current signal strength of the radio.
*
@@ -113,4 +114,27 @@
*/
oneway currentPhysicalChannelConfigs_1_6(RadioIndicationType type,
vec<PhysicalChannelConfig> configs);
+
+ /**
+ * Indicates whether SIM phonebook is changed.
+ *
+ * This indication is sent whenever the SIM phonebook is changed, including SIM is
+ * inserted or removed and updated by IRadio.updateSimPhonebookRecords.
+ *
+ * @param type Type of radio indication
+ */
+ oneway simPhonebookChanged(RadioIndicationType type);
+
+ /**
+ * Indicates the content of all the used records in the SIM phonebook.
+ *
+ * This indication is associated with the API getSimPhonebookRecords and
+ * might be received more than once that is replying on the record count.
+ *
+ * @param type Type of radio indication
+ * @param status Status of PbReceivedStatus
+ * @param records Vector of PhonebookRecordInfo
+ */
+ oneway simPhonebookRecordsReceived(RadioIndicationType type,
+ PbReceivedStatus status, vec<PhonebookRecordInfo> records);
};
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index d65c6d0..33fe94f 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -27,6 +27,7 @@
import @1.6::SetupDataCallResult;
import @1.6::SignalStrength;
import @1.6::SlicingConfig;
+import @1.6::PhonebookCapacity;
/**
* Interface declaring response functions to solicited radio requests.
@@ -342,6 +343,7 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
+ * RadioError:REQUEST_NOT_SUPPORTED
*/
oneway setDataThrottlingResponse(RadioResponseInfo info);
@@ -432,7 +434,61 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:MODEM_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
*/
oneway getSlicingConfigResponse(RadioResponseInfo info,
SlicingConfig slicingConfig);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INVALID_SIM_STATE
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+ * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+ */
+ oneway getSimPhonebookRecordsResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param capacity Response capacity enum indicating response processing status
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INVALID_SIM_STATE
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+ * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+ */
+ oneway getSimPhonebookCapacityResponse(RadioResponseInfo info, PhonebookCapacity capacity);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param updatedRecordIndex The index of the updated or inserted record in the phonebook and
+ * the minimum value is 1
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INVALID_SIM_STATE
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:SIM_ERR
+ * RadioError:NO_SUCH_ENTRY
+ * RadioError:NO_RESOURCES
+ * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+ * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+ */
+ oneway updateSimPhonebookRecordsResponse(RadioResponseInfo info, int32_t updatedRecordIndex);
};
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 95eba69..3fd31cc 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -1027,18 +1027,6 @@
*/
uint8_t precedence;
/**
- * Parameters defining this RouteSelectionDescriptor. The length of the vector
- * must be >= 1.
- */
- vec<RouteSelectionDescriptorParams> routeSelectionDescriptorParams;
-};
-
-/**
- * This struct represents a route selection descriptor. A valid struct must have
- * at least one of the vectors non-empty.
- */
-struct RouteSelectionDescriptorParams {
- /**
* Valid values are IP, IPV6 and IPV4V6.
*/
OptionalPdpProtocolType sessionType;
@@ -1106,3 +1094,106 @@
@1.1::ImsiEncryptionInfo base;
PublicKeyType keyType; // Public key type
};
+
+/**
+ * Phonebook-record-information specified by EF_ADN(Abbreviated dialing numbers)
+ * record of SIM as per 3GPP spec 31.102 v15 Section-4.4.2.3.
+ */
+struct PhonebookRecordInfo {
+ /** Record index. 0 is used to insert a record */
+ uint32_t recordId;
+
+ /** Alpha identifier, empty string if no value */
+ string name;
+
+ /** Dialling number, empty string if no value */
+ string number;
+
+ /** Email addresses */
+ vec<string> emails;
+
+ /** Additional numbers */
+ vec<string> additionalNumbers;
+};
+
+struct PhonebookCapacity {
+ /**
+ * Maximum number of ADN records possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxAdnRecords;
+
+ /**
+ * Used ADN records in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t usedAdnRecords;
+
+ /**
+ * Maximum email records possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxEmailRecords;
+
+ /**
+ * Used email records in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t usedEmailRecords;
+
+ /**
+ * Maximum additional number records possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxAdditionalNumberRecords;
+
+ /**
+ * Used additional number records in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t usedAdditionalNumberRecords;
+
+ /**
+ * Maximum name length possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxNameLen;
+
+ /**
+ * Maximum number length possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxNumberLen;
+
+ /**
+ * Maximum email length possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxEmailLen;
+
+ /**
+ * Maximum additional number length possible in the SIM phonebook
+ * Needs to be non-negative
+ */
+ int32_t maxAdditionalNumberLen;
+};
+
+/**
+ * Enum representing the status of the received PB indication,
+ * PB_RECEIVED_OK indicates this retrieval is fine
+ * PB_RECEIVED_ERROR indicates one error happens, in general, the process
+ * can't be restored soon.
+ * PB_RECEIVED_ABORT indicates the process is interrupted, in this case,
+ * modem might need resources and interrupt the current process, or it is
+ * timed out to receive all indications, and client can retry soon.
+ * PB_RECEIVED_FINAL indicates the whole process is finished with a full
+ * chunk of phonebook data, means this is a last indication with the left
+ * data.
+ */
+enum PbReceivedStatus : int32_t {
+ PB_RECEIVED_OK = 1,
+ PB_RECEIVED_ERROR = 2,
+ PB_RECEIVED_ABORT = 3,
+ PB_RECEIVED_FINAL = 4,
+};
+
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 91d98cb..c21b2fc 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -172,7 +172,13 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
- EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+ if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+ 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);
+ }
}
/*
@@ -420,13 +426,18 @@
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);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+ if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+ }
serial = GetRandomSerialNumber();
res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
@@ -435,13 +446,18 @@
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);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+ if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+ }
serial = GetRandomSerialNumber();
res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
@@ -450,13 +466,18 @@
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);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+ if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+ }
serial = GetRandomSerialNumber();
res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
@@ -464,12 +485,18 @@
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);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+ if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+ }
}
/*
@@ -706,8 +733,8 @@
radio_v1_6->setCarrierInfoForImsiEncryption_1_6(serial, imsiInfo);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
- EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo_v1_0.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo_v1_0.serial);
if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(
@@ -716,3 +743,141 @@
::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
}
}
+
+/*
+ * Test IRadio.getSimPhonebookRecords() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_6, getSimPhonebookRecords) {
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getSimPhonebookRecords(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadio.getSimPhonebookCapacity for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getSimPhonebookCapacity) {
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getSimPhonebookCapacity(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+
+ ::android::hardware::radio::V1_6::PhonebookCapacity pbCapacity =
+ radioRsp_v1_6->capacity;
+ if(pbCapacity.maxAdnRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxNameLen > 0 && pbCapacity.maxNumberLen > 0);
+ EXPECT_TRUE(pbCapacity.usedAdnRecords <= pbCapacity.maxAdnRecords);
+ }
+
+ if(pbCapacity.maxEmailRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxEmailLen > 0);
+ EXPECT_TRUE(pbCapacity.usedEmailRecords <= pbCapacity.maxEmailRecords);
+ }
+
+ if(pbCapacity.maxAdditionalNumberRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxAdditionalNumberLen > 0);
+ EXPECT_TRUE(pbCapacity.usedAdditionalNumberRecords <= pbCapacity.maxAdditionalNumberRecords);
+ }
+ }
+}
+
+/*
+ * Test IRadio.updateSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, updateSimPhonebookRecords) {
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getSimPhonebookCapacity(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ ::android::hardware::radio::V1_6::PhonebookCapacity pbCapacity =
+ radioRsp_v1_6->capacity;
+
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getSimPhonebookRecords(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+
+ if(pbCapacity.maxAdnRecords > 0
+ && pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
+ // Add a phonebook record
+ PhonebookRecordInfo recordInfo;
+ recordInfo.recordId = 0;
+ recordInfo.name = "ABC";
+ recordInfo.number = "1234567890";
+ serial = GetRandomSerialNumber();
+ radio_v1_6->updateSimPhonebookRecords(serial, recordInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+ int index = radioRsp_v1_6->updatedRecordIndex;
+ EXPECT_TRUE(index > 0);
+
+ // Deleted a phonebook record
+ recordInfo.recordId = index;
+ recordInfo.name = "";
+ recordInfo.number = "";
+ serial = GetRandomSerialNumber();
+ radio_v1_6->updateSimPhonebookRecords(serial, recordInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+ }
+ }
+}
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 23378b5..4fc17e5 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
@@ -103,6 +103,11 @@
::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos;
RadioResponse_v1_6(RadioResponseWaiter& parent_v1_6);
+
+ // Phone Book
+ ::android::hardware::radio::V1_6::PhonebookCapacity capacity;
+ int32_t updatedRecordIndex;
+
virtual ~RadioResponse_v1_6() = default;
Return<void> getIccCardStatusResponse(
@@ -829,6 +834,17 @@
Return<void> getSlicingConfigResponse(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const ::android::hardware::radio::V1_6::SlicingConfig& slicingConfig);
+
+ Return<void> getSimPhonebookRecordsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> getSimPhonebookCapacityResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::PhonebookCapacity& capacity);
+
+ Return<void> updateSimPhonebookRecordsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ int32_t updatedRecordIndex);
};
/* Callback class for radio indication */
@@ -1073,6 +1089,14 @@
const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
/*barringInfos*/);
+
+ Return<void> simPhonebookChanged(RadioIndicationType type);
+
+ Return<void> simPhonebookRecordsReceived(
+ RadioIndicationType type,
+ ::android::hardware::radio::V1_6::PbReceivedStatus status,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_6::PhonebookRecordInfo>&
+ records);
};
// The main test class for Radio HIDL.
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
index e7a9680..8292131 100644
--- a/radio/1.6/vts/functional/radio_indication.cpp
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -412,3 +412,16 @@
::android::hardware::radio::V1_6::CellInfo>& /*records*/) {
return Void();
}
+
+Return<void> RadioIndication_v1_6::simPhonebookChanged(
+ RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::simPhonebookRecordsReceived(
+ RadioIndicationType /*type*/,
+ ::android::hardware::radio::V1_6::PbReceivedStatus /*status*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_6::PhonebookRecordInfo>& /*records*/) {
+ return Void();
+}
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index d0c2984..2b6d1bb 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -87,7 +87,9 @@
}
Return<void> RadioResponse_v1_6::hangupConnectionResponse(
- const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info) {
+ rspInfo_v1_0 = info;
+ parent_v1_6.notify(info.serial);
return Void();
}
@@ -749,7 +751,9 @@
/* 1.1 Apis */
Return<void> RadioResponse_v1_6::setCarrierInfoForImsiEncryptionResponse(
- const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info) {
+ rspInfo_v1_0 = info;
+ parent_v1_6.notify(info.serial);
return Void();
}
@@ -1232,3 +1236,28 @@
parent_v1_6.notify(info.serial);
return Void();
}
+
+Return<void> RadioResponse_v1_6::getSimPhonebookRecordsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSimPhonebookCapacityResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::PhonebookCapacity& capacity) {
+ rspInfo = info;
+ this->capacity = capacity;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::updateSimPhonebookRecordsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ int32_t updatedRecordIndex) {
+ rspInfo = info;
+ this->updatedRecordIndex = updatedRecordIndex;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
index 117abf3..8667f0a 100644
--- a/radio/config/1.3/types.hal
+++ b/radio/config/1.3/types.hal
@@ -31,6 +31,11 @@
* <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 895ae08..50038eb 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
@@ -37,7 +37,7 @@
#include "vts_test_util.h"
-using namespace ::android::hardware::radio::config::V1_2;
+using namespace ::android::hardware::radio::config::V1_3;
using ::android::sp;
using ::android::hardware::hidl_string;
@@ -46,9 +46,11 @@
using ::android::hardware::Void;
using ::android::hardware::radio::config::V1_1::ModemsConfig;
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;
#define RADIO_SERVICE_NAME "slot1"
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 11e3cce..5501ae2 100644
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -64,8 +64,9 @@
}
Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
- const ::android::hardware::radio::V1_6::RadioResponseInfo& /* info */,
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const ::android::hardware::radio::config::V1_3::HalDeviceCapabilities& capabilities) {
halDeviceCapabilities = capabilities;
+ parent.notify(info.serial);
return Void();
}
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 54cb4b8..6766d99 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -19,7 +19,8 @@
stability: "vintf",
backend: {
java: {
- sdk_version: "module_current",
+ platform_apis: true,
+ srcs_available: true,
},
ndk: {
vndk: {
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
index 5adbdc1..6da124f 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum Algorithm {
RSA = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
index 21721bf..90f2e6e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
@@ -32,6 +32,7 @@
// 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 AttestationKey {
byte[] keyBlob;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
index d9d9c13..c952a31 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable BeginResult {
long challenge;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
index feba9d0..0049883 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum BlockMode {
ECB = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
index 470d534..645f0a7 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable Certificate {
byte[] encodedCertificate;
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
index 4db47c9..d04d49c 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
@@ -31,21 +31,9 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+package android.hardware.security.keymint;
+/* @hide */
+@VintfStability
+parcelable DeviceInfo {
+ byte[] deviceInfo;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
index 5a15aad..0df7096 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum Digest {
NONE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
index d7ec006..6b4a9ae 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum EcCurve {
P_224 = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index 91e2899..69ec4ce 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum ErrorCode {
OK = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
index 3205a46..2e07924 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -32,6 +32,7 @@
// 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 HardwareAuthToken {
long challenge;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index 926f2ec..dfc98f0 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum HardwareAuthenticatorType {
NONE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index bb18669..4f6fb28 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
interface IKeyMintDevice {
android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo();
@@ -46,6 +47,7 @@
android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in android.hardware.security.keymint.HardwareAuthToken authToken);
void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken);
void earlyBootEnded();
+ byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
byte[] performOperation(in byte[] request);
const int AUTH_TOKEN_MAC_LENGTH = 32;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
index 28a83da..5ac2b4a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
interface IKeyMintOperation {
void updateAad(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken);
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 8387ecc..88c479c 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
@@ -32,10 +32,11 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
interface IRemotelyProvisionedComponent {
byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
- void generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac, out android.hardware.security.keymint.ProtectedData protectedData);
+ 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;
const int STATUS_INVALID_MAC = 2;
const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
index 91ac7be..008381f 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable KeyCharacteristics {
android.hardware.security.keymint.SecurityLevel securityLevel = android.hardware.security.keymint.SecurityLevel.SOFTWARE;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
index b85203f..9f77d3e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable KeyCreationResult {
byte[] keyBlob;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
index 4500288..9560d8d 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum KeyFormat {
X509 = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index d959ac4..2113e42a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -32,6 +32,7 @@
// 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 KeyMintHardwareInfo {
int versionNumber;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
index 2b65567..4b3c659 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum KeyOrigin {
GENERATED = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index ee8abda..c5a1e01 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -32,6 +32,7 @@
// 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 KeyParameter {
android.hardware.security.keymint.Tag tag = android.hardware.security.keymint.Tag.INVALID;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
index fc57cd2..7a0b074 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -32,6 +32,7 @@
// 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
union KeyParameterValue {
int invalid;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
index f891de6..b84bec1 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum KeyPurpose {
ENCRYPT = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
index 30b38e1..8095e8c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable MacedPublicKey {
byte[] macedKey;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
index bfb6ea1..dba4a8a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum PaddingMode {
NONE = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
index 64cce78..d1610b4 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@VintfStability
parcelable ProtectedData {
byte[] protectedData;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
index 628476d..0d278e0 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum SecurityLevel {
SOFTWARE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index ccb0404..7591318 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum Tag {
INVALID = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
index 58f8bd3..a7d1de5 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
+/* @hide */
@Backing(type="int") @VintfStability
enum TagType {
INVALID = 0,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
index 8300b0d..1820893 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
@@ -18,6 +18,7 @@
/**
* Algorithms provided by IKeyMintDevice implementations.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
index 8167ceb..b4bc60c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
@@ -22,6 +22,7 @@
* Contains a key blob with Tag::ATTEST_KEY that can be used to sign an attestation certificate,
* and the DER-encoded X.501 Subject Name that will be placed in the Issuer field of the attestation
* certificate.
+ * @hide
*/
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
index aaf9f3c..2304a58 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
@@ -21,6 +21,7 @@
/**
* This is all the results returned by the IKeyMintDevice begin() function.
+ * @hide
*/
@VintfStability
parcelable BeginResult {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
index 629c89f..749da81 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
@@ -18,6 +18,7 @@
/**
* Symmetric block cipher modes provided by IKeyMintDevice implementations.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
index 0e5d898..21dfdd5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
@@ -18,6 +18,7 @@
/**
* This encodes an IKeyMintDevice certificate, generated for a KeyMint asymmetric public key.
+ * @hide
*/
@VintfStability
parcelable Certificate {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
new file mode 100644
index 0000000..3ea14a1
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.security.keymint;
+
+/**
+ * DeviceInfo contains information about the device that's fed in as AAD in the signature of the
+ * device private key over the MAC key used for the bundle of public keys. These values are intended
+ * to be checked by the server to verify that the certificate signing request crafted by
+ * an IRemotelyProvisionedComponent HAL instance is coming from the expected device based
+ * on values initially uploaded during device manufacture in the factory.
+ * @hide
+ */
+@VintfStability
+parcelable DeviceInfo {
+ /**
+ * DeviceInfo is a CBOR Map structure described by the following CDDL.
+ *
+ * DeviceInfo = {
+ * ? "brand" : tstr,
+ * ? "manufacturer" : tstr,
+ * ? "product" : tstr,
+ * ? "model" : tstr,
+ * ? "board" : tstr,
+ * ? "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values
+ * ? "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values
+ * ? "os_version" : tstr, // Same as android.os.Build.VERSION.release
+ * ? "system_patch_level" : uint, // YYYYMMDD
+ * ? "boot_patch_level" : uint, // YYYYMMDD
+ * ? "vendor_patch_level" : uint, // YYYYMMDD
+ * }
+ */
+ byte[] deviceInfo;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
index b44da5a..a8768c3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
@@ -18,6 +18,7 @@
/**
* Digests provided by keyMint implementations.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
index b9d1646..5b1c10c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
@@ -18,6 +18,7 @@
/**
* Supported EC curves, used in ECDSA
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
index 95b38f2..0e2c5f2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
@@ -19,6 +19,7 @@
/**
* KeyMint error codes. Aidl will return these error codes as service specific
* errors in EX_SERVICE_SPECIFIC.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
index 57150d5..0933bd5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -27,6 +27,7 @@
* passed to begin(), update(), and finish() to prove that authentication occurred. See those
* methods for more details. It is up to the caller to determine which of the generated auth tokens
* is appropriate for a given key operation.
+ * @hide
*/
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index 33f71b8..2d9d0ff 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -20,6 +20,7 @@
* Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
* authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
* authenticating to activate a key.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 384416e..17aab25 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -211,6 +211,7 @@
* hardwareEnforced authorization list. Tag::OS_VERSION, Tag::OS_PATCHLEVEL,
* Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
* IKeyMintDevice key, as described in the Key Access Control section above.
+ * @hide
*/
@VintfStability
interface IKeyMintDevice {
@@ -761,6 +762,27 @@
*/
void earlyBootEnded();
+ /*
+ * Called by the client to get a wrapped per-boot ephemeral key from a wrapped storage key.
+ * Clients will then use the returned per-boot ephemeral key in place of the wrapped storage
+ * key. Whenever the hardware is presented with a per-boot ephemeral key for an operation, it
+ * must use the storage key associated with that ephemeral key to perform the requested
+ * operation.
+ *
+ * Implementations should return ErrorCode::UNIMPLEMENTED if they don't support wrapped storage
+ * keys.
+ *
+ * Implementations should return ErrorCode::INVALID_ARGUMENT (as a ServiceSpecificException)
+ * if the input key blob doesn't represent a valid long-lived wrapped storage key.
+ *
+ * @param storageKeyBlob is the wrapped storage key for which the client wants a per-boot
+ * ephemeral key
+ *
+ * @return a buffer containing the per-boot ephemeral keyblob that should henceforth be used in
+ * place of the input storageKeyBlob
+ */
+ byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
+
/**
* Called by the client to perform a KeyMint operation.
*
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 1c2511b..5ad54cd 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -20,6 +20,7 @@
import android.hardware.security.keymint.KeyParameter;
import android.hardware.security.secureclock.TimeStampToken;
+/** @hide */
@VintfStability
interface IKeyMintOperation {
/**
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 327e4a1..1cb50ba 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -16,6 +16,7 @@
package android.hardware.security.keymint;
+import android.hardware.security.keymint.DeviceInfo;
import android.hardware.security.keymint.MacedPublicKey;
import android.hardware.security.keymint.ProtectedData;
@@ -109,6 +110,7 @@
* The IRemotelyProvisionedComponent supports a test mode, allowing the generation of test key pairs
* and test CertificateRequests. Test keys/requests are annotated as such, and the BCC used for test
* CertificateRequests must contain freshly-generated keys, not the real BCC key pairs.
+ * @hide
*/
@VintfStability
interface IRemotelyProvisionedComponent {
@@ -256,7 +258,7 @@
* @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
* authenticate the keysToSign (see keysToSignMac output argument).
*/
- void generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
- in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac,
+ byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
+ in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
out ProtectedData protectedData);
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
index 3a32e4d..25fdee3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -28,6 +28,7 @@
* enforced. Note that enforcement at a given security level means that the semantics of the tag
* and value are fully enforced. See the definition of individual tags for specifications of what
* must be enforced.
+ * @hide
*/
@VintfStability
parcelable KeyCharacteristics {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 69bec2d7..f3c5477 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -22,6 +22,7 @@
/**
* This structure is returned when a new key is created with generateKey(), importKey() or
* importWrappedKey().
+ * @hide
*/
@VintfStability
parcelable KeyCreationResult {
@@ -52,13 +53,36 @@
/**
* If the generated/imported key is an asymmetric key, `certificateChain` will contain a chain
- * of one or more certificates. If the key parameters provided to the generate/import method
- * contains Tag::ATTESTATION_CHALLENGE the first certificate will contain an attestation
- * extension, and will be signed by a factory-installed attestation key and followed by a chain
- * of certificates leading to an authoritative root. If there is no attestation challenge, only
- * one certificate will be returned, and it will be self-signed or contain a fake signature,
- * depending on whether the key has KeyPurpose::SIGN. If the generated key is symmetric,
- * certificateChain will be empty.
+ * of one or more certificates.
+ *
+ * There are a few variations in what is contained in `certificateChain`, depending on whether
+ * the caller requested attestation, whether they provided an attestation key (via the
+ * `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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 5. Symmetric key. If the generated/imported key is symmetric, the certificate chain must be
+ * empty.
*/
Certificate[] certificateChain;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
index 6ad8e3d..da3d521 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
@@ -18,6 +18,7 @@
/**
* Formats for key import and export.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index ae0d152..8da7578 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -20,6 +20,7 @@
/**
* KeyMintHardwareInfo is the hardware information returned by calling KeyMint getHardwareInfo()
+ * @hide
*/
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
index 0cd53c2..f896125 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
@@ -21,6 +21,7 @@
* either the hardware-enforced or software-enforced list for a key, indicating whether the key is
* hardware or software-based. Specifically, a key with GENERATED in the hardware-enforced list
* must be guaranteed never to have existed outide the secure hardware.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
index bf6c9b2..b69e678 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
@@ -22,6 +22,7 @@
/**
* Identifies the key authorization parameters to be used with keyMint. This is usually
* provided as an array of KeyParameters to IKeyMintDevice or Operation.
+ * @hide
*/
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
index a4f5154..59016f2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -26,10 +26,10 @@
import android.hardware.security.keymint.PaddingMode;
import android.hardware.security.keymint.SecurityLevel;
+/** @hide */
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
union KeyParameterValue {
-
/* Represents an invalid value type. */
int invalid;
@@ -45,7 +45,7 @@
SecurityLevel securityLevel;
/* Other types */
- boolean boolValue; // Always true, if present.
+ boolean boolValue; // Always true, if present.
int integer;
long longInteger;
long dateTime;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
index 978a027..c874fc3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
@@ -18,6 +18,7 @@
/**
* Possible purposes of a key (or pair).
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index cb5492d..a26094c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -19,6 +19,7 @@
/**
* MacedPublicKey contains a CBOR-encoded public key, MACed by an IRemotelyProvisionedComponent, to
* prove that the key pair was generated by that component.
+ * @hide
*/
@VintfStability
parcelable MacedPublicKey {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
index 80b73bd..fbb373b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
@@ -23,6 +23,7 @@
* padding modes for both symmetric and asymmetric algorithms. Note that implementations should not
* provide all possible combinations of algorithm and padding, only the
* cryptographically-appropriate pairs.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 438505e..44f316f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -19,6 +19,7 @@
/**
* ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
* authenticate the keysToSign (see keysToSignMac output argument).
+ * @hide
*/
@VintfStability
parcelable ProtectedData {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
index ecbde8c..80c63b2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
@@ -27,6 +27,7 @@
* certificates. This specifies the security level of the weakest environment involved in
* enforcing that particular tag, i.e. the sort of security environment an attacker would have
* to subvert in order to break the enforcement of that tag.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index aa9aa6f..6243bb9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -25,6 +25,7 @@
/**
* Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
* data are stored in KeyParameter.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
index a273af3..1ba6ede 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
@@ -18,6 +18,7 @@
/**
* TagType classifies Tags in Tag.aidl into various groups of data.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 63b91fe..ebdc9b7 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -39,6 +39,17 @@
srcs: [
"service.cpp",
],
+ required: [
+ "RemoteProvisioner",
+ "android.hardware.hardware_keystore.xml",
+ ],
+}
+
+prebuilt_etc {
+ name: "android.hardware.hardware_keystore.xml",
+ sub_dir: "permissions",
+ vendor: true,
+ src: "android.hardware.hardware_keystore.xml",
}
cc_library {
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
index 749f0bc..4dbaa05 100644
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
+++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
@@ -322,8 +322,8 @@
ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest(
bool testMode, const vector<MacedPublicKey>& keysToSign,
- const bytevec& endpointEncCertChain, const bytevec& challenge, bytevec* keysToSignMac,
- ProtectedData* protectedData) {
+ 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();
@@ -343,11 +343,12 @@
bcc = bcc_.clone();
}
+ deviceInfo->deviceInfo = createDeviceInfo();
auto signedMac = constructCoseSign1(devicePrivKey /* Signing key */, //
ephemeralMacKey /* Payload */,
cppbor::Array() /* AAD */
.add(challenge)
- .add(createDeviceInfo())
+ .add(deviceInfo->deviceInfo)
.encode());
if (!signedMac) return Status(signedMac.moveMessage());
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.h b/security/keymint/aidl/default/RemotelyProvisionedComponent.h
index e8d2343..65b1bbc 100644
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.h
+++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.h
@@ -39,8 +39,8 @@
const std::vector<MacedPublicKey>& keysToSign,
const std::vector<uint8_t>& endpointEncCertChain,
const std::vector<uint8_t>& challenge,
- std::vector<uint8_t>* keysToSignMac,
- ProtectedData* protectedData) override;
+ DeviceInfo* deviceInfo, ProtectedData* protectedData,
+ std::vector<uint8_t>* keysToSignMac) override;
private:
// TODO(swillden): Move these into an appropriate Context class.
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
new file mode 100644
index 0000000..e5a9345
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<permissions>
+ <feature name="android.hardware.hardware_keystore" version="100" />
+</permissions>
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 50e6cce..9b797de 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -227,11 +227,12 @@
TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
bool testMode = true;
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
- auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
- eekChain_.chain, challenge,
- &keysToSignMac, &protectedData);
+ auto status = provisionable_->generateCertificateRequest(
+ testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
+ &keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -297,11 +298,12 @@
TEST_P(CertificateRequestTest, EmptyRequest_prodMode) {
bool testMode = false;
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
- auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
- eekChain_.chain, challenge,
- &keysToSignMac, &protectedData);
+ auto status = provisionable_->generateCertificateRequest(
+ testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
+ &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
}
@@ -314,10 +316,12 @@
generateKeys(testMode, 4 /* numKeys */);
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
- auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
+ auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
+ challenge, &deviceInfo, &protectedData,
+ &keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -384,10 +388,12 @@
generateKeys(testMode, 4 /* numKeys */);
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
- auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
+ auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
+ challenge, &deviceInfo, &protectedData,
+ &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
}
@@ -400,11 +406,12 @@
generateKeys(false /* testMode */, 2 /* numKeys */);
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
- auto status = provisionable_->generateCertificateRequest(true /* testMode */, keysToSign_,
- eekChain_.chain, challenge,
- &keysToSignMac, &protectedData);
+ auto status = provisionable_->generateCertificateRequest(
+ true /* testMode */, keysToSign_, eekChain_.chain, challenge, &deviceInfo,
+ &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
@@ -418,10 +425,11 @@
generateKeys(true /* testMode */, 2 /* numKeys */);
bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
false /* testMode */, keysToSign_, eekChain_.chain, randomBytes(32) /* challenge */,
- &keysToSignMac, &protectedData);
+ &deviceInfo, &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index c8e5c02..c78be3b 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -16,7 +16,8 @@
stability: "vintf",
backend: {
java: {
- sdk_version: "module_current",
+ platform_apis: true,
+ srcs_available: true,
},
ndk: {
vndk: {
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
index 3778897..4ecc1e4 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
@@ -11,7 +11,8 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -30,6 +31,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.secureclock;
+/* @hide */
@VintfStability
interface ISecureClock {
android.hardware.security.secureclock.TimeStampToken generateTimeStamp(in long challenge);
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
index 00a8bb2..d105ac8 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.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. //
///////////////////////////////////////////////////////////////////////////////
@@ -31,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.secureclock;
+/* @hide */
@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
parcelable TimeStampToken {
long challenge;
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
index bebeb5c..2e0e389 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.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. //
///////////////////////////////////////////////////////////////////////////////
@@ -31,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.secureclock;
+/* @hide */
@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
parcelable Timestamp {
long milliSeconds;
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
index 577dd8f..a742ff0 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
@@ -25,8 +25,8 @@
* secret. The shared secret must be available to secure clock service by implementing
* ISharedSecret aidl. Note: ISecureClock depends on the shared secret, without which the secure
* time stamp token cannot be generated.
+ * @hide
*/
-
@VintfStability
interface ISecureClock {
/**
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
index dd95732..71b4278 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -20,8 +20,8 @@
/**
* TimeStampToken instances are used for secure environments that requires secure time information.
+ * @hide
*/
-
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
parcelable TimeStampToken {
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
index 27758e1..5061aa4 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
@@ -21,6 +21,7 @@
* and a secure environment's notion of "current time" must not repeat until the Android device
* reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
* by setting the clock to zero during each boot, and then counting time accurately).
+ * @hide
*/
@VintfStability
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index 6dfa417..56c8e1d 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -39,11 +39,11 @@
shared_libs: [
"libbinder_ndk",
"libcrypto",
- "libkeymint",
],
static_libs: [
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
+ "libkeymint",
],
test_suites: [
"general-tests",
diff --git a/security/secureclock/aidl/vts/functional/AndroidTest.xml b/security/secureclock/aidl/vts/functional/AndroidTest.xml
deleted file mode 100644
index 4861c7c..0000000
--- a/security/secureclock/aidl/vts/functional/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs VtsAidlSecureClockTargetTest.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push"
- value="VtsAidlSecureClockTargetTest->/data/local/tmp/VtsAidlSecureClockTargetTest" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsAidlSecureClockTargetTest" />
- <option name="native-test-timeout" value="900000"/>
- </test>
-</configuration>
diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
index 2509936..e76efe7 100644
--- a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -1,3 +1,17 @@
+/*
+ * 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.
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -17,6 +31,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.sharedsecret;
+/* @hide */
@VintfStability
interface ISharedSecret {
android.hardware.security.sharedsecret.SharedSecretParameters getSharedSecretParameters();
diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
index 9b65046..e15fd49 100644
--- a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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. //
///////////////////////////////////////////////////////////////////////////////
@@ -17,7 +32,8 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.sharedsecret;
-@VintfStability
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
parcelable SharedSecretParameters {
byte[] seed;
byte[] nonce;
diff --git a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
index 906303f..eca8d87 100644
--- a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -22,8 +22,8 @@
* An ISharedSecret enables any service that implements this interface to establish a shared secret
* with one or more other services such as ISecureClock, TEE IKeymintDevice, StrongBox
* IKeymintDevice, etc. The shared secret is a 256-bit HMAC key and it is further used to generate
- * secure tokens with integrity protection. There are two steps to establish a shared secret between
- * the collaborating services:
+ * secure tokens with integrity protection. There are three steps to establish a shared secret
+ * between the collaborating services:
*
* Step 1: During Android startup the system calls each service that implements this interface to
* get the shared secret parameters. This is done using getSharedSecretParameters method defined
@@ -35,8 +35,8 @@
* Step 3: The system collects sharing check hash values from each service and evaluates them. If
* they are all equal, then the shared secret generation is considered to be successful else it is
* considered to have failed.
+ * @hide
*/
-
@VintfStability
interface ISharedSecret {
/**
@@ -64,11 +64,11 @@
/**
* This method is the second and final step in the process for agreeing on a shared key. It is
- * called by Android during startup. The system calls it on each of the keymint services, and
- * sends to it all of the SharedSecretParameters returned by all keymint services.
+ * called by Android during startup. The system calls it on each of the HAL instances, and
+ * sends to it all of the SharedSecretParameters returned by all HAL instances.
*
- * This method computes the shared 32-byte HMAC key ``H'' as follows (all keymint services
- * instances perform the same computation to arrive at the same result):
+ * This method computes the shared 32-byte HMAC key ``H'' as follows (all HAL instances perform
+ * the same computation to arrive at the same result):
*
* H = CKDF(key = K,
* context = P1 || P2 || ... || Pn,
@@ -98,16 +98,16 @@
* Note that the label "KeymasterSharedMac" is the 18-byte UTF-8 encoding of the string.
*
* @param params is an array of SharedSecretParameters The lexicographically sorted
- * SharedSecretParameters data returned by all keymint services when getSharedSecretParameters
+ * SharedSecretParameters data returned by all HAL instances when getSharedSecretParameters
* was called.
*
- * @return sharingCheck A 32-byte value used to verify that all the keymint services have
+ * @return sharingCheck A 32-byte value used to verify that all the HAL instances have
* computed the same shared HMAC key. The sharingCheck value is computed as follows:
*
* sharingCheck = HMAC(H, KEY_CHECK_LABEL)
*
* The string is UTF-8 encoded, 27 bytes in length. If the returned values of all
- * keymint services don't match, clients must assume that HMAC agreement
+ * HAL instances don't match, clients must assume that HMAC agreement
* failed.
*/
byte[] computeSharedSecret(in SharedSecretParameters[] params);
diff --git a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
index 691b3f1..8144699 100644
--- a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -21,9 +21,10 @@
* HMAC key between multiple keymint services. These parameters are returned in by
* getSharedSecretParameters() and send to computeShareSecret(). See the named methods in
* ISharedSecret for details of usage.
+ * @hide
*/
-
@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
parcelable SharedSecretParameters {
/**
* Either empty or contains a non zero persistent value that is associated with the pre-shared
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index 1bc5beb..d3747fc 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -39,11 +39,11 @@
shared_libs: [
"libbinder_ndk",
"libcrypto",
- "libkeymint",
],
static_libs: [
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.sharedsecret-V1-ndk_platform",
+ "libkeymint",
],
test_suites: [
"general-tests",
diff --git a/security/sharedsecret/aidl/vts/functional/AndroidTest.xml b/security/sharedsecret/aidl/vts/functional/AndroidTest.xml
deleted file mode 100644
index c6697bc..0000000
--- a/security/sharedsecret/aidl/vts/functional/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs VtsAidlSharedSecretTargetTest.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push"
- value="VtsAidlSharedSecretTargetTest->/data/local/tmp/VtsAidlSharedSecretTargetTest" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsAidlSharedSecretTargetTest" />
- <option name="native-test-timeout" value="900000"/>
- </test>
-</configuration>
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 83f6ef3..8426120 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -114,14 +114,14 @@
const vector<shared_ptr<ISharedSecret>>& allSharedSecrets() { return allSharedSecrets_; }
static void SetUpTestCase() {
- if (allSharedSecrets_.empty()) {
- auto names = ::android::getAidlHalInstanceNames(ISharedSecret::descriptor);
- for (const auto& name : names) {
- auto servicePtr = getSharedSecretService(name.c_str());
- if (servicePtr != nullptr) allSharedSecrets_.push_back(std::move(servicePtr));
- }
+ ASSERT_TRUE(allSharedSecrets_.empty()) << "The Shared Secret vector is not empty.";
+ auto names = ::android::getAidlHalInstanceNames(ISharedSecret::descriptor);
+ for (const auto& name : names) {
+ auto servicePtr = getSharedSecretService(name.c_str());
+ if (servicePtr != nullptr) allSharedSecrets_.push_back(std::move(servicePtr));
}
}
+
static void TearDownTestCase() {}
void SetUp() override {}
void TearDown() override {}
@@ -134,6 +134,9 @@
TEST_F(SharedSecretAidlTest, GetParameters) {
auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test because no shared secret service is found.";
+ }
for (auto sharedSecret : sharedSecrets) {
auto result1 = getSharedSecretParameters(sharedSecret);
EXPECT_EQ(ErrorCode::OK, result1.error);
@@ -148,14 +151,18 @@
}
TEST_F(SharedSecretAidlTest, ComputeSharedSecret) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
auto params = getAllSharedSecretParameters();
- ASSERT_EQ(allSharedSecrets().size(), params.size())
+ ASSERT_EQ(sharedSecrets.size(), params.size())
<< "One or more shared secret services failed to provide parameters.";
auto nonces = copyNonces(params);
- EXPECT_EQ(allSharedSecrets().size(), nonces.size());
+ EXPECT_EQ(sharedSecrets.size(), nonces.size());
std::sort(nonces.begin(), nonces.end());
std::unique(nonces.begin(), nonces.end());
- EXPECT_EQ(allSharedSecrets().size(), nonces.size());
+ EXPECT_EQ(sharedSecrets.size(), nonces.size());
auto responses = computeAllSharedSecrets(params);
ASSERT_GT(responses.size(), 0U);
@@ -163,7 +170,7 @@
// Do it a second time. Should get the same answers.
params = getAllSharedSecretParameters();
- ASSERT_EQ(allSharedSecrets().size(), params.size())
+ ASSERT_EQ(sharedSecrets.size(), params.size())
<< "One or more shared secret services failed to provide parameters.";
responses = computeAllSharedSecrets(params);
@@ -188,10 +195,14 @@
}
TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptNonce) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
auto params = getAllSharedSecretParameters();
- ASSERT_EQ(allSharedSecrets().size(), params.size())
+ ASSERT_EQ(sharedSecrets.size(), params.size())
<< "One or more shared secret services failed to provide parameters.";
// All should be well in the normal case
@@ -224,9 +235,13 @@
}
TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptSeed) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
auto params = getAllSharedSecretParameters();
- ASSERT_EQ(allSharedSecrets().size(), params.size())
+ ASSERT_EQ(sharedSecrets.size(), params.size())
<< "One or more shared secret service failed to provide parameters.";
// All should be well in the normal case
diff --git a/sensors/common/utils/EventMessageQueueWrapper.h b/sensors/common/utils/EventMessageQueueWrapper.h
index c4f92c8..63e4eb0 100644
--- a/sensors/common/utils/EventMessageQueueWrapper.h
+++ b/sensors/common/utils/EventMessageQueueWrapper.h
@@ -33,7 +33,7 @@
namespace V2_1 {
namespace implementation {
-class EventMessageQueueWrapperBase : public RefBase {
+class EventMessageQueueWrapperBase {
public:
virtual ~EventMessageQueueWrapperBase() {}
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 8cf5003..47a8cc0 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -462,6 +462,7 @@
// Wait for events to be written back to the Event FMQ
callback.waitForEvents(sensors, milliseconds(1000) /* timeout */);
+ getEnvironment()->unregisterCallback();
for (const auto& s : sensors) {
auto events = callback.getEvents(s.sensorHandle);
@@ -485,7 +486,6 @@
ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status);
}
- getEnvironment()->unregisterCallback();
ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
}
@@ -603,7 +603,7 @@
<< " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name);
Result flushResult = flush(sensor.sensorHandle);
- ASSERT_EQ(flushResult, expectedResponse);
+ EXPECT_EQ(flushResult, expectedResponse);
}
}
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
index 6fdc97c..ed739cf 100644
--- a/soundtrigger/2.0/default/OWNERS
+++ b/soundtrigger/2.0/default/OWNERS
@@ -1,3 +1,3 @@
elaurent@google.com
-krocard@google.com
mnaganov@google.com
+ytai@google.com
diff --git a/tv/cec/1.0/vts/functional/Android.bp b/tv/cec/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..4d82da3
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalTvCecV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalTvCecV1_0TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.tv.cec@1.0",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ disable_framework: true,
+}
diff --git a/tv/cec/1.0/vts/functional/README.md b/tv/cec/1.0/vts/functional/README.md
new file mode 100644
index 0000000..aecd6a6
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/README.md
@@ -0,0 +1,30 @@
+# CEC VTS testing for Android TV devices
+
+Validate HDMI CEC VTS (android.hardware.tv.cec@1.0) functionality.
+
+### Setup:
+
+Running these CEC VTS tests requires an Android playback, TV or audio device connected to the host machine.
+
+
+
+### Building
+
+From the Android root folder, after choosing the lunch combo, use `make vts` to build VTS.
+
+### Automation
+
+On the host machine, ensure that the [software requirements](https://codelabs.developers.google.com/codelabs/android-lab/#2) for python SDK are met.
+
+Given the setup described above you can run tests with any of the following commands:
+
+1. Using vts-tradefed :
+```
+cd $ANDROID_BUILD_TOP/out/host/linux-x86/vts/android-vts/tools
+./vts-tradefed run commandAndExit vts -m VtsHalTvCecV1_0TargetTest
+```
+2. Using atest
+```
+atest VtsHalTvCecV1_0TargetTest
+```
+Note : atest internally handles building as well. To update the test use '-c' (clear cache) option
diff --git a/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp b/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp
new file mode 100644
index 0000000..7b42689
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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 "HdmiCec_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <android/hardware/tv/cec/1.0/types.h>
+#include <utils/Log.h>
+#include <sstream>
+#include <vector>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::tv::cec::V1_0::CecDeviceType;
+using ::android::hardware::tv::cec::V1_0::CecLogicalAddress;
+using ::android::hardware::tv::cec::V1_0::CecMessage;
+using ::android::hardware::tv::cec::V1_0::HdmiPortInfo;
+using ::android::hardware::tv::cec::V1_0::HdmiPortType;
+using ::android::hardware::tv::cec::V1_0::IHdmiCec;
+using ::android::hardware::tv::cec::V1_0::OptionKey;
+using ::android::hardware::tv::cec::V1_0::Result;
+using ::android::hardware::tv::cec::V1_0::SendMessageResult;
+
+#define CEC_VERSION 0x05
+#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
+
+// The main test class for TV CEC HAL.
+class HdmiCecTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ hdmiCec = IHdmiCec::getService(GetParam());
+ ASSERT_NE(hdmiCec, nullptr);
+ ALOGI("%s: getService() for hdmiCec is %s", __func__,
+ hdmiCec->isRemote() ? "remote" : "local");
+
+ hdmiCec_death_recipient = new HdmiCecDeathRecipient();
+ ASSERT_NE(hdmiCec_death_recipient, nullptr);
+ ASSERT_TRUE(hdmiCec->linkToDeath(hdmiCec_death_recipient, 0).isOk());
+ }
+
+ std::vector<int> getDeviceTypes() {
+ std::vector<int> deviceTypes;
+ FILE* p = popen("getprop ro.hdmi.device_type", "re");
+ if (p) {
+ char* line = NULL;
+ size_t len = 0;
+ if (getline(&line, &len, p) > 0) {
+ std::istringstream stream(line);
+ std::string number{};
+ while (std::getline(stream, number, ',')) {
+ deviceTypes.push_back(stoi(number));
+ }
+ }
+ pclose(p);
+ }
+ return deviceTypes;
+ }
+
+ bool hasDeviceType(CecDeviceType type) {
+ std::vector<int> deviceTypes = getDeviceTypes();
+ for (auto deviceType = deviceTypes.begin(); deviceType != deviceTypes.end(); ++deviceType) {
+ if (*deviceType == (int)type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ class HdmiCecDeathRecipient : public hidl_death_recipient {
+ public:
+ void serviceDied(uint64_t /*cookie*/,
+ const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) override {
+ FAIL();
+ }
+ };
+
+ sp<IHdmiCec> hdmiCec;
+ sp<HdmiCecDeathRecipient> hdmiCec_death_recipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiCecTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, HdmiCecTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHdmiCec::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+TEST_P(HdmiCecTest, ClearAddLogicalAddress) {
+ hdmiCec->clearLogicalAddress();
+ Return<Result> ret = hdmiCec->addLogicalAddress(CecLogicalAddress::PLAYBACK_3);
+ EXPECT_EQ(ret, Result::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, PhysicalAddress) {
+ Result result;
+ uint16_t addr;
+ Return<void> ret = hdmiCec->getPhysicalAddress([&result, &addr](Result res, uint16_t paddr) {
+ result = res;
+ addr = paddr;
+ });
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(result, Result::SUCCESS);
+ if (!hasDeviceType(CecDeviceType::TV)) {
+ EXPECT_NE(addr, TV_PHYSICAL_ADDRESS);
+ }
+}
+
+TEST_P(HdmiCecTest, SendMessage) {
+ CecMessage message;
+ message.initiator = CecLogicalAddress::PLAYBACK_1;
+ message.destination = CecLogicalAddress::BROADCAST;
+ message.body.resize(1);
+ message.body[0] = 131;
+ SendMessageResult ret = hdmiCec->sendMessage(message);
+ EXPECT_EQ(ret, SendMessageResult::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, CecVersion) {
+ Return<int32_t> ret = hdmiCec->getCecVersion();
+ EXPECT_GE(ret, CEC_VERSION);
+}
+
+TEST_P(HdmiCecTest, VendorId) {
+ Return<uint32_t> ret = hdmiCec->getVendorId();
+ EXPECT_NE(ret, INCORRECT_VENDOR_ID);
+}
+
+TEST_P(HdmiCecTest, GetPortInfo) {
+ hidl_vec<HdmiPortInfo> ports;
+ Return<void> ret =
+ hdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) { ports = list; });
+ EXPECT_TRUE(ret.isOk());
+ bool cecSupportedOnDevice = false;
+ for (size_t i = 0; i < ports.size(); ++i) {
+ EXPECT_TRUE((ports[i].type == HdmiPortType::OUTPUT) ||
+ (ports[i].type == HdmiPortType::INPUT));
+ if (ports[i].portId == 0) {
+ ALOGW("%s: Port id should start from 1", __func__);
+ }
+ cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported;
+ }
+ EXPECT_NE(cecSupportedOnDevice, false) << "At least one port should support CEC";
+}
+
+TEST_P(HdmiCecTest, SetOption) {
+ Return<void> ret;
+ ret = hdmiCec->setOption(OptionKey::WAKEUP, false);
+ EXPECT_TRUE(ret.isOk());
+ ret = hdmiCec->setOption(OptionKey::ENABLE_CEC, false);
+ EXPECT_TRUE(ret.isOk());
+ ret = hdmiCec->setOption(OptionKey::SYSTEM_CEC_CONTROL, true);
+ EXPECT_TRUE(ret.isOk());
+ // Restore option keys to their default values
+ ret = hdmiCec->setOption(OptionKey::WAKEUP, true);
+ EXPECT_TRUE(ret.isOk());
+ ret = hdmiCec->setOption(OptionKey::ENABLE_CEC, true);
+ EXPECT_TRUE(ret.isOk());
+ ret = hdmiCec->setOption(OptionKey::SYSTEM_CEC_CONTROL, false);
+ EXPECT_TRUE(ret.isOk());
+}
+
+TEST_P(HdmiCecTest, SetLanguage) {
+ Return<void> ret = hdmiCec->setLanguage("eng");
+ EXPECT_TRUE(ret.isOk());
+}
+
+TEST_P(HdmiCecTest, EnableAudioReturnChannel) {
+ hidl_vec<HdmiPortInfo> ports;
+ Return<void> ret =
+ hdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) { ports = list; });
+ EXPECT_TRUE(ret.isOk());
+ for (size_t i = 0; i < ports.size(); ++i) {
+ if (ports[i].arcSupported) {
+ ret = hdmiCec->enableAudioReturnChannel(ports[i].portId, true);
+ EXPECT_TRUE(ret.isOk());
+ }
+ }
+}
+
+TEST_P(HdmiCecTest, IsConnected) {
+ hidl_vec<HdmiPortInfo> ports;
+ Return<void> ret =
+ hdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) { ports = list; });
+ EXPECT_TRUE(ret.isOk());
+ for (size_t i = 0; i < ports.size(); ++i) {
+ Return<bool> ret = hdmiCec->isConnected(ports[i].portId);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
diff --git a/tv/cec/1.0/vts/functional/setup.png b/tv/cec/1.0/vts/functional/setup.png
new file mode 100644
index 0000000..a64b86c
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/setup.png
Binary files differ
diff --git a/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp b/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp
index 1eb4643..c5b4b2f 100644
--- a/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp
+++ b/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp
@@ -46,6 +46,7 @@
#define CEC_VERSION 0x05
#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
// The main test class for TV CEC HAL.
class HdmiCecTest : public ::testing::TestWithParam<std::string> {
@@ -126,6 +127,19 @@
EXPECT_EQ(ret, Result::SUCCESS);
}
+TEST_P(HdmiCecTest, PhysicalAddress) {
+ Result result;
+ uint16_t addr;
+ Return<void> ret = hdmiCec->getPhysicalAddress([&result, &addr](Result res, uint16_t paddr) {
+ result = res;
+ addr = paddr;
+ });
+ EXPECT_EQ(result, Result::SUCCESS);
+ if (!hasDeviceType(CecDeviceType::TV)) {
+ EXPECT_NE(addr, TV_PHYSICAL_ADDRESS);
+ }
+}
+
TEST_P(HdmiCecTest, SendMessage) {
CecMessage message;
message.initiator = CecLogicalAddress::PLAYBACK_1;
@@ -196,4 +210,14 @@
ASSERT_TRUE(ret.isOk());
}
}
-}
\ No newline at end of file
+}
+
+TEST_P(HdmiCecTest, IsConnected) {
+ hidl_vec<HdmiPortInfo> ports;
+ Return<void> ret =
+ hdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) { ports = list; });
+ for (size_t i = 0; i < ports.size(); ++i) {
+ Return<bool> ret = hdmiCec->isConnected(ports[i].portId);
+ EXPECT_TRUE(ret.isOk());
+ }
+}
diff --git a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
index 8092d5e..15ea3e9 100644
--- a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
+++ b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
@@ -313,6 +313,9 @@
tv_input_->openStream(device_id, stream_id,
[&result](Result res, const native_handle_t*) { result = res; });
EXPECT_EQ(Result::INVALID_STATE, result);
+
+ // close stream as subsequent tests assume no open streams
+ EXPECT_EQ(Result::OK, tv_input_->closeStream(device_id, stream_id));
}
/*
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
index 4db47c9..de3ad3c 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
@@ -31,21 +31,12 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+parcelable ActivePwle {
+ float startAmplitude;
+ float startFrequency;
+ float endAmplitude;
+ float endFrequency;
+ int duration;
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
similarity index 78%
rename from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
index 4db47c9..d38c584 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
@@ -31,21 +31,9 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum Braking {
+ NONE = 0,
+ CLAB = 1,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
index 4db47c9..fa7b43a 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
@@ -31,21 +31,9 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+parcelable BrakingPwle {
+ android.hardware.vibrator.Braking braking;
+ int duration;
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
index 0995d2d..3be58a1 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
index 0b4b527..50de13f 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
index 0d2b340..adf0f20 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
index 808644a..af5e158 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
index 1f2d946..b7afb66 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.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. //
///////////////////////////////////////////////////////////////////////////////
@@ -50,6 +51,13 @@
void alwaysOnDisable(in int id);
float getResonantFrequency();
float getQFactor();
+ float getFrequencyResolution();
+ float getFrequencyMinimum();
+ float[] getBandwidthAmplitudeMap();
+ int getPwlePrimitiveDurationMax();
+ int getPwleCompositionSizeMax();
+ android.hardware.vibrator.Braking[] getSupportedBraking();
+ void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback);
const int CAP_ON_CALLBACK = 1;
const int CAP_PERFORM_CALLBACK = 2;
const int CAP_AMPLITUDE_CONTROL = 4;
@@ -59,4 +67,6 @@
const int CAP_ALWAYS_ON_CONTROL = 64;
const int CAP_GET_RESONANT_FREQUENCY = 128;
const int CAP_GET_Q_FACTOR = 256;
+ const int CAP_FREQUENCY_CONTROL = 512;
+ const int CAP_COMPOSE_PWLE_EFFECTS = 1024;
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
index f99ecc1..99d6d22 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
index 8e3ac88..290c68d 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.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/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
index 4db47c9..584bcf4 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
@@ -31,21 +31,9 @@
// 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
- IDLING = 0,
- CLOSED = 1,
- GENERATING_CHALLENGE = 2,
- REVOKING_CHALLENGE = 3,
- ENROLLING = 4,
- AUTHENTICATING = 5,
- DETECTING_INTERACTION = 6,
- ENUMERATING_ENROLLMENTS = 7,
- REMOVING_ENROLLMENTS = 8,
- GETTING_FEATURES = 9,
- SETTING_FEATURE = 10,
- GETTING_AUTHENTICATOR_ID = 11,
- INVALIDATING_AUTHENTICATOR_ID = 12,
- RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+union PrimitivePwle {
+ android.hardware.vibrator.ActivePwle active;
+ android.hardware.vibrator.BrakingPwle braking;
}
diff --git a/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
new file mode 100644
index 0000000..fd5f8d1
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.vibrator;
+
+@VintfStability
+parcelable ActivePwle {
+ /**
+ * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
+ * in units of output acceleration amplitude, not voltage amplitude.
+ *
+ * 0.0 represents no output acceleration amplitude
+ * 1.0 represents maximum output acceleration amplitude at resonant frequency
+ */
+ float startAmplitude;
+ /**
+ * Absolute frequency point in the units of hertz
+ */
+ float startFrequency;
+ /**
+ * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
+ * in units of output acceleration amplitude, not voltage amplitude.
+ *
+ * 0.0 represents no output acceleration amplitude
+ * 1.0 represents maximum output acceleration amplitude at resonant frequency
+ */
+ float endAmplitude;
+ /**
+ * Absolute frequency point in the units of hertz
+ */
+ float endFrequency;
+ /**
+ * Total duration from start point to end point in the units of milliseconds
+ */
+ int duration;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
new file mode 100644
index 0000000..2bc51db
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.vibrator;
+
+@VintfStability
+@Backing(type="int")
+enum Braking {
+ /**
+ * No braking mechanism used.
+ * This is the default if the hardware does not support any braking mechanism.
+ */
+ NONE,
+ /**
+ * Closed-loop active braking.
+ *
+ * This effect should produce a sharp, crisp end to the waveform
+ * Support is optional.
+ */
+ CLAB,
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl
new file mode 100644
index 0000000..00675ed
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.vibrator;
+
+import android.hardware.vibrator.Braking;
+
+/**
+ * BrakingPwle is defined as a segment of zero output acceleration amplitude of duration length.
+ *
+ * There should be no output acceleration and the vibrator should be off for the entire duration.
+ * If the hardware supports braking mechanism(s), they can be set here.
+ */
+@VintfStability
+parcelable BrakingPwle {
+ /**
+ * Braking mechanism applied to adjacent segments
+ */
+ Braking braking;
+ /**
+ * Total duration of zero output acceleration in the units of milliseconds.
+ */
+ int duration;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index cba76dc..592d151 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -17,10 +17,12 @@
package android.hardware.vibrator;
import android.hardware.vibrator.IVibratorCallback;
+import android.hardware.vibrator.Braking;
import android.hardware.vibrator.Effect;
import android.hardware.vibrator.EffectStrength;
import android.hardware.vibrator.CompositeEffect;
import android.hardware.vibrator.CompositePrimitive;
+import android.hardware.vibrator.PrimitivePwle;
@VintfStability
interface IVibrator {
@@ -60,6 +62,14 @@
* Whether getQFactor is supported.
*/
const int CAP_GET_Q_FACTOR = 1 << 8;
+ /**
+ * Whether frequency control is supported.
+ */
+ const int CAP_FREQUENCY_CONTROL = 1 << 9;
+ /**
+ * Whether composePwle is supported.
+ */
+ const int CAP_COMPOSE_PWLE_EFFECTS = 1 << 10;
/**
* Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -240,18 +250,109 @@
void alwaysOnDisable(in int id);
/**
- * Retrieve the measured resonant frequency of the actuator. This may not be supported
- * and this support is reflected in getCapabilities (CAP_GET_RESONANT_FREQUENCY)
+ * Retrieve the measured resonant frequency of the actuator.
*
- * @return Measured resonant frequency in Hz.
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_GET_RESONANT_FREQUENCY)
+ *
+ * @return Measured resonant frequency in Hz. Non-zero value if supported,
+ * or value should be ignored if not supported.
*/
float getResonantFrequency();
/**
- * Retrieve the measured Q factor. This may not be supported
- * and this support is reflected in getCapabilities (CAP_GET_Q_FACTOR)
+ * Retrieve the measured Q factor.
*
- * @return Measured Q factor.
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_GET_Q_FACTOR)
+ *
+ * @return Measured Q factor. Non-zero value if supported, or value should be
+ * ignored if not supported.
*/
float getQFactor();
+
+ /**
+ * Retrieve the frequency resolution used in getBandwidthAmplitudeMap() in units of hertz
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_FREQUENCY_CONTROL).
+ *
+ * @return The frequency resolution of the bandwidth amplitude map.
+ * Non-zero value if supported, or value should be ignored if not supported.
+ */
+ float getFrequencyResolution();
+
+ /**
+ * Retrieve the minimum allowed frequency in units of hertz
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_FREQUENCY_CONTROL).
+ *
+ * @return The minimum frequency allowed. Non-zero value if supported,
+ * or value should be ignored if not supported.
+ */
+ float getFrequencyMinimum();
+
+ /**
+ * Retrieve the output acceleration amplitude values per frequency supported
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_FREQUENCY_CONTROL).
+ *
+ * The mapping is represented as a list of amplitude values in the inclusive range [0.0, 1.0].
+ * The first value represents the amplitude at the frequency returned by getFrequencyMinimum().
+ * Each subsequent element is the amplitude at the next supported frequency, in increments
+ * of getFrequencyResolution(). The value returned by getResonantFrequency() must be
+ * represented in the returned list.
+ *
+ * @return The maximum output acceleration amplitude for each supported frequency,
+ * starting at getMinimumFrequency()
+ */
+ float[] getBandwidthAmplitudeMap();
+
+ /**
+ * Retrieve the maximum duration allowed for any primitive PWLE in units of milliseconds.
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+ *
+ * @return The maximum duration allowed for a single PrimitivePwle.
+ * Non-zero value if supported, or value should be ignored if not supported.
+ */
+ int getPwlePrimitiveDurationMax();
+
+ /**
+ * Retrieve the maximum count for allowed PWLEs in one composition.
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+ *
+ * @return The maximum count allowed. Non-zero value if supported,
+ * or value should be ignored if not supported.
+ */
+ int getPwleCompositionSizeMax();
+
+ /**
+ * List of supported braking mechanism.
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+ * Implementations are optional but encouraged if available.
+ *
+ * @return The braking mechanisms which are supported by the composePwle API.
+ */
+ Braking[] getSupportedBraking();
+
+ /**
+ * Fire off a string of PWLEs.
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+ *
+ * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+ * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
+ *
+ * @param composite Array of PWLEs.
+ */
+ void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback);
}
diff --git a/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl
new file mode 100644
index 0000000..813c7dc
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.vibrator;
+
+import android.hardware.vibrator.ActivePwle;
+import android.hardware.vibrator.BrakingPwle;
+
+@VintfStability
+union PrimitivePwle {
+ ActivePwle active;
+ BrakingPwle braking;
+}
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index bf61bfe..c6682b3 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -26,9 +26,16 @@
static constexpr int32_t kComposeDelayMaxMs = 1000;
static constexpr int32_t kComposeSizeMax = 256;
+static constexpr int32_t kComposePwleSizeMax = 127;
static constexpr float kResonantFrequency = 150.0;
static constexpr float kQFactor = 11.0;
+static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
+static constexpr float PWLE_LEVEL_MIN = 0.0;
+static constexpr float PWLE_LEVEL_MAX = 0.98256;
+static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0;
+static constexpr float PWLE_FREQUENCY_MIN_HZ = 140.0;
+static constexpr float PWLE_FREQUENCY_MAX_HZ = 160.0;
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
LOG(INFO) << "Vibrator reporting capabilities";
@@ -36,7 +43,8 @@
IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
- IVibrator::CAP_GET_Q_FACTOR;
+ IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
+ IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
return ndk::ScopedAStatus::ok();
}
@@ -215,6 +223,169 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
+ *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
+ *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
+ // A valid array should be of size:
+ // (PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ
+ *_aidl_return = {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10,
+ 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20};
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
+ *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
+ *maxSize = kComposePwleSizeMax;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
+ *supported = {
+ Braking::NONE,
+ Braking::CLAB,
+ };
+ return ndk::ScopedAStatus::ok();
+}
+
+void resetPreviousEndAmplitudeEndFrequency(float &prevEndAmplitude, float &prevEndFrequency) {
+ const float reset = -1.0;
+ prevEndAmplitude = reset;
+ prevEndFrequency = reset;
+}
+
+void incrementIndex(int &index) {
+ index += 1;
+}
+
+void constructActiveDefaults(std::ostringstream &pwleBuilder, const int &segmentIdx) {
+ pwleBuilder << ",C" << segmentIdx << ":1";
+ pwleBuilder << ",B" << segmentIdx << ":0";
+ pwleBuilder << ",AR" << segmentIdx << ":0";
+ pwleBuilder << ",V" << segmentIdx << ":0";
+}
+
+void constructActiveSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
+ float amplitude, float frequency) {
+ pwleBuilder << ",T" << segmentIdx << ":" << duration;
+ pwleBuilder << ",L" << segmentIdx << ":" << amplitude;
+ pwleBuilder << ",F" << segmentIdx << ":" << frequency;
+ constructActiveDefaults(pwleBuilder, segmentIdx);
+}
+
+void constructBrakingSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
+ Braking brakingType) {
+ pwleBuilder << ",T" << segmentIdx << ":" << duration;
+ pwleBuilder << ",L" << segmentIdx << ":" << 0;
+ pwleBuilder << ",F" << segmentIdx << ":" << 0;
+ pwleBuilder << ",C" << segmentIdx << ":0";
+ pwleBuilder << ",B" << segmentIdx << ":"
+ << static_cast<std::underlying_type<Braking>::type>(brakingType);
+ pwleBuilder << ",AR" << segmentIdx << ":0";
+ pwleBuilder << ",V" << segmentIdx << ":0";
+}
+
+ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
+ const std::shared_ptr<IVibratorCallback> &callback) {
+ std::ostringstream pwleBuilder;
+ std::string pwleQueue;
+
+ int compositionSizeMax;
+ getPwleCompositionSizeMax(&compositionSizeMax);
+ if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ float prevEndAmplitude;
+ float prevEndFrequency;
+ resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
+
+ int segmentIdx = 0;
+ uint32_t totalDuration = 0;
+
+ pwleBuilder << "S:0,WF:4,RP:0,WT:0";
+
+ for (auto &e : composite) {
+ switch (e.getTag()) {
+ case PrimitivePwle::active: {
+ auto active = e.get<PrimitivePwle::active>();
+ if (active.duration < 0 ||
+ active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (active.startAmplitude < PWLE_LEVEL_MIN ||
+ active.startAmplitude > PWLE_LEVEL_MAX ||
+ active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
+ active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
+ active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
+ active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ if (!((active.startAmplitude == prevEndAmplitude) &&
+ (active.startFrequency == prevEndFrequency))) {
+ constructActiveSegment(pwleBuilder, segmentIdx, 0, active.startAmplitude,
+ active.startFrequency);
+ incrementIndex(segmentIdx);
+ }
+
+ constructActiveSegment(pwleBuilder, segmentIdx, active.duration,
+ active.endAmplitude, active.endFrequency);
+ incrementIndex(segmentIdx);
+
+ prevEndAmplitude = active.endAmplitude;
+ prevEndFrequency = active.endFrequency;
+ totalDuration += active.duration;
+ break;
+ }
+ case PrimitivePwle::braking: {
+ auto braking = e.get<PrimitivePwle::braking>();
+ if (braking.braking > Braking::CLAB) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ constructBrakingSegment(pwleBuilder, segmentIdx, 0, braking.braking);
+ incrementIndex(segmentIdx);
+
+ constructBrakingSegment(pwleBuilder, segmentIdx, braking.duration, braking.braking);
+ incrementIndex(segmentIdx);
+
+ resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
+ totalDuration += braking.duration;
+ break;
+ }
+ }
+ }
+
+ std::thread([=] {
+ LOG(INFO) << "Starting composePwle on another thread";
+ usleep(totalDuration * 1000);
+ if (callback != nullptr) {
+ LOG(INFO) << "Notifying compose PWLE complete";
+ callback->onComplete();
+ }
+ }).detach();
+
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace vibrator
} // namespace hardware
} // namespace android
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index a2af963..4203bf2 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -46,6 +46,15 @@
ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
ndk::ScopedAStatus getResonantFrequency(float *resonantFreqHz) override;
ndk::ScopedAStatus getQFactor(float *qFactor) override;
+ ndk::ScopedAStatus getFrequencyResolution(float *freqResolutionHz) override;
+ ndk::ScopedAStatus getFrequencyMinimum(float *freqMinimumHz) override;
+ ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) override;
+ ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t *durationMs) override;
+ ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t *maxSize) override;
+ ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
+ ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
+ const std::shared_ptr<IVibratorCallback> &callback) override;
+
};
} // namespace vibrator
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 2540d0b..a9d1ed5 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,7 +15,6 @@
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
-
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <android/hardware/vibrator/IVibratorManager.h>
@@ -29,13 +28,17 @@
using android::sp;
using android::String16;
using android::binder::Status;
+using android::hardware::vibrator::ActivePwle;
using android::hardware::vibrator::BnVibratorCallback;
+using android::hardware::vibrator::Braking;
+using android::hardware::vibrator::BrakingPwle;
using android::hardware::vibrator::CompositeEffect;
using android::hardware::vibrator::CompositePrimitive;
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::IVibrator;
using android::hardware::vibrator::IVibratorManager;
+using android::hardware::vibrator::PrimitivePwle;
using std::chrono::high_resolution_clock;
const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
@@ -44,32 +47,32 @@
android::enum_range<EffectStrength>().end()};
const std::vector<Effect> kInvalidEffects = {
- static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
- static_cast<Effect>(static_cast<int32_t>(kEffects.back()) + 1),
+ static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
+ static_cast<Effect>(static_cast<int32_t>(kEffects.back()) + 1),
};
const std::vector<EffectStrength> kInvalidEffectStrengths = {
- static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.front()) - 1),
- static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
+ static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.front()) - 1),
+ static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
};
const std::vector<CompositePrimitive> kCompositePrimitives{
- android::enum_range<CompositePrimitive>().begin(),
- android::enum_range<CompositePrimitive>().end()};
+ android::enum_range<CompositePrimitive>().begin(),
+ android::enum_range<CompositePrimitive>().end()};
const std::vector<CompositePrimitive> kOptionalPrimitives = {
- CompositePrimitive::THUD,
- CompositePrimitive::SPIN,
+ CompositePrimitive::THUD,
+ CompositePrimitive::SPIN,
};
const std::vector<CompositePrimitive> kInvalidPrimitives = {
- static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
- static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
+ static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
+ static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
};
class CompletionCallback : public BnVibratorCallback {
public:
- CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
+ CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
Status onComplete() override {
mCallback();
return Status::ok();
@@ -109,6 +112,89 @@
int32_t capabilities;
};
+static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
+ float resonantFrequencyHz;
+ Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
+ if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+ EXPECT_GT(resonantFrequencyHz, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+ return resonantFrequencyHz;
+}
+
+static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
+ float freqResolutionHz;
+ Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
+ if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ EXPECT_GT(freqResolutionHz, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+ return freqResolutionHz;
+}
+
+static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+ float freqMinimumHz;
+ Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
+ if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+
+ float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
+
+ EXPECT_GT(freqMinimumHz, 0);
+ EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+ return freqMinimumHz;
+}
+
+static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+ std::vector<float> bandwidthAmplitudeMap;
+ Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+ if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+
+ float freqMaximumHz =
+ (bandwidthAmplitudeMap.size() * getFrequencyResolutionHz(vibrator, capabilities)) +
+ getFrequencyMinimumHz(vibrator, capabilities);
+ return freqMaximumHz;
+}
+
+static float getAmplitudeMin() {
+ return 0.0;
+}
+
+static float getAmplitudeMax() {
+ return 1.0;
+}
+
+static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
+ float frequencyHz;
+ if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+ frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
+ } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ frequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
+ } else {
+ frequencyHz = 150.0; // default value commonly used
+ }
+
+ ActivePwle active;
+ active.startAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
+ active.startFrequency = frequencyHz;
+ active.endAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
+ active.endFrequency = frequencyHz;
+ active.duration = 1000;
+
+ return active;
+}
+
TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
sleep(1);
@@ -116,12 +202,13 @@
}
TEST_P(VibratorAidl, OnWithCallback) {
- if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK))
+ return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
std::chrono::milliseconds timeout{durationMs * 2};
EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
@@ -142,7 +229,7 @@
for (Effect effect : kEffects) {
bool isEffectSupported =
- std::find(supported.begin(), supported.end(), effect) != supported.end();
+ std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs = 0;
@@ -154,27 +241,28 @@
usleep(lengthMs * 1000);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
}
TEST_P(VibratorAidl, ValidateEffectWithCallback) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+ if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK))
+ return;
std::vector<Effect> supported;
ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
for (Effect effect : kEffects) {
bool isEffectSupported =
- std::find(supported.begin(), supported.end(), effect) != supported.end();
+ std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
int lengthMs = 0;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
@@ -185,7 +273,8 @@
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
- if (!status.isOk()) continue;
+ if (!status.isOk())
+ continue;
std::chrono::milliseconds timeout{lengthMs * 2};
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
@@ -194,7 +283,8 @@
}
TEST_P(VibratorAidl, ValidateEffectWithCallbackNotSupported) {
- if (capabilities & IVibrator::CAP_PERFORM_CALLBACK) return;
+ if (capabilities & IVibrator::CAP_PERFORM_CALLBACK)
+ return;
for (Effect effect : kEffects) {
for (EffectStrength strength : kEffectStrengths) {
@@ -212,7 +302,7 @@
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
for (Effect effect : kEffects) {
@@ -220,7 +310,7 @@
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
@@ -261,7 +351,7 @@
TEST_P(VibratorAidl, ExternalAmplitudeControl) {
const bool supportsExternalAmplitudeControl =
- (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
+ (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
@@ -293,10 +383,10 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
bool isPrimitiveOptional =
- std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
- kOptionalPrimitives.end();
+ std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
+ kOptionalPrimitives.end();
EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
}
@@ -310,7 +400,7 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
int32_t duration;
Status status = vibrator->getPrimitiveDuration(primitive, &duration);
@@ -366,7 +456,7 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
if (!isPrimitiveSupported) {
unsupported.push_back(primitive);
@@ -376,7 +466,7 @@
for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
- for (auto& effect : composite) {
+ for (auto &effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
@@ -391,7 +481,7 @@
TEST_P(VibratorAidl, ComposeScaleBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositeEffect> composite(1);
- CompositeEffect& effect = composite[0];
+ CompositeEffect &effect = composite[0];
effect.delayMs = 0;
effect.primitive = CompositePrimitive::CLICK;
@@ -478,7 +568,7 @@
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
CompositeEffect effect;
std::vector<CompositeEffect> composite;
int32_t durationMs;
@@ -493,16 +583,15 @@
EXPECT_EQ(Status::EX_NONE,
vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
- << toString(primitive);
+ << toString(primitive);
duration = std::chrono::milliseconds(durationMs);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
- << toString(primitive);
+ << toString(primitive);
start = high_resolution_clock::now();
- EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency),
- std::future_status::ready)
- << toString(primitive);
+ EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), std::future_status::ready)
+ << toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
@@ -519,17 +608,17 @@
for (Effect effect : kEffects) {
bool isEffectSupported =
- std::find(supported.begin(), supported.end(), effect) != supported.end();
+ std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
Status status = vibrator->alwaysOnEnable(0, effect, strength);
if (isEffectSupported) {
EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
} else {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
@@ -539,27 +628,253 @@
}
TEST_P(VibratorAidl, GetResonantFrequency) {
- float resonantFrequency;
- Status status = vibrator->getResonantFrequency(&resonantFrequency);
- if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
- ASSERT_NE(resonantFrequency, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
- } else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
- }
+ getResonantFrequencyHz(vibrator, capabilities);
}
TEST_P(VibratorAidl, GetQFactor) {
float qFactor;
Status status = vibrator->getQFactor(&qFactor);
if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
- ASSERT_NE(qFactor, 0);
+ ASSERT_GT(qFactor, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
+TEST_P(VibratorAidl, GetFrequencyResolution) {
+ getFrequencyResolutionHz(vibrator, capabilities);
+}
+
+TEST_P(VibratorAidl, GetFrequencyMinimum) {
+ getFrequencyMinimumHz(vibrator, capabilities);
+}
+
+TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
+ std::vector<float> bandwidthAmplitudeMap;
+ Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+ if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ ASSERT_FALSE(bandwidthAmplitudeMap.empty());
+
+ int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
+ getFrequencyMinimumHz(vibrator, capabilities)) /
+ getFrequencyResolutionHz(vibrator, capabilities);
+ ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize);
+
+ for (float e : bandwidthAmplitudeMap) {
+ ASSERT_GE(e, 0.0);
+ ASSERT_LE(e, 1.0);
+ }
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
+ int32_t durationMs;
+ Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ ASSERT_NE(durationMs, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
+ int32_t maxSize;
+ Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ ASSERT_NE(maxSize, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(VibratorAidl, GetSupportedBraking) {
+ std::vector<Braking> supported;
+ Status status = vibrator->getSupportedBraking(&supported);
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ bool isDefaultNoneSupported =
+ std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
+ ASSERT_TRUE(isDefaultNoneSupported);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(VibratorAidl, ComposeValidPwle) {
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+ std::vector<Braking> supported;
+ ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+ bool isClabSupported =
+ std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
+ BrakingPwle braking;
+ braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
+ braking.duration = 100;
+
+ std::vector<PrimitivePwle> pwleQueue;
+ PrimitivePwle pwle;
+ pwle = active;
+ pwleQueue.emplace_back(std::move(pwle));
+ pwle = braking;
+ pwleQueue.emplace_back(std::move(pwle));
+ pwle = active;
+ pwleQueue.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+ vibrator->off();
+ }
+}
+
+TEST_P(VibratorAidl, ComposeValidPwleWithCallback) {
+ if (!((capabilities & IVibrator::CAP_ON_CALLBACK) &&
+ (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS)))
+ return;
+
+ std::promise<void> completionPromise;
+ std::future<void> completionFuture{completionPromise.get_future()};
+ sp<CompletionCallback> callback =
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ uint32_t durationMs = 2100; // Sum of 2 active and 1 braking below
+ std::chrono::milliseconds timeout{durationMs * 2};
+
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+ std::vector<Braking> supported;
+ ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+ bool isClabSupported =
+ std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
+ BrakingPwle braking;
+ braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
+ braking.duration = 100;
+
+ std::vector<PrimitivePwle> pwleQueue;
+ PrimitivePwle pwle;
+ pwle = active;
+ pwleQueue.emplace_back(std::move(pwle));
+ pwle = braking;
+ pwleQueue.emplace_back(std::move(pwle));
+ pwle = active;
+ pwleQueue.emplace_back(std::move(pwle));
+
+ EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
+ EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
+ EXPECT_TRUE(vibrator->off().isOk());
+}
+
+TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ std::vector<PrimitivePwle> pwleQueue;
+ // test empty queue
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+ vibrator->off();
+
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+ PrimitivePwle pwle;
+ pwle = active;
+ int segmentCountMax;
+ vibrator->getPwleCompositionSizeMax(&segmentCountMax);
+
+ // Create PWLE queue with more segments than allowed
+ for (int i = 0; i < segmentCountMax + 10; i++) {
+ pwleQueue.emplace_back(std::move(pwle));
+ }
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+ vibrator->off();
+ }
+}
+
+TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) {
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+ active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
+ active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
+
+ std::vector<PrimitivePwle> pwleQueueGreater;
+ PrimitivePwle pwle;
+ pwle = active;
+ pwleQueueGreater.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
+ vibrator->off();
+
+ active.startAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
+ active.endAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
+
+ std::vector<PrimitivePwle> pwleQueueLess;
+ pwle = active;
+ pwleQueueLess.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
+ vibrator->off();
+ }
+}
+
+TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) {
+ if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) &&
+ (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
+ float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities);
+ float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities);
+ float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
+
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+ active.startFrequency =
+ freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
+ active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
+
+ std::vector<PrimitivePwle> pwleQueueGreater;
+ PrimitivePwle pwle;
+ pwle = active;
+ pwleQueueGreater.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
+ vibrator->off();
+
+ active.startFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
+ active.endFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
+
+ std::vector<PrimitivePwle> pwleQueueLess;
+ pwle = active;
+ pwleQueueLess.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
+ vibrator->off();
+ }
+}
+
+TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) {
+ if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+ int segmentDurationMaxMs;
+ vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
+ active.duration = segmentDurationMaxMs + 10; // Segment duration greater than allowed
+
+ std::vector<PrimitivePwle> pwleQueue;
+ PrimitivePwle pwle;
+ pwle = active;
+ pwleQueue.emplace_back(std::move(pwle));
+
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+ vibrator->off();
+ }
+}
+
std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
std::vector<std::tuple<int32_t, int32_t>> tuples;
auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
@@ -569,7 +884,7 @@
auto managerName = String16(managerAidlNames[i].c_str());
auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
- for (auto& vibratorId : vibratorIds) {
+ for (auto &vibratorId : vibratorIds) {
tuples.push_back(std::make_tuple(i, vibratorId));
}
}
@@ -583,8 +898,8 @@
return tuples;
}
-std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType>& info) {
- const auto& [managerIdx, vibratorId] = info.param;
+std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType> &info) {
+ const auto &[managerIdx, vibratorId] = info.param;
if (managerIdx < 0) {
return std::string("TOP_LEVEL_VIBRATOR_") + std::to_string(vibratorId);
}
@@ -596,7 +911,7 @@
INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()),
PrintGeneratedTest);
-int main(int argc, char** argv) {
+int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
ProcessState::self()->setThreadPoolMaxThreadCount(1);
ProcessState::self()->startThreadPool();
diff --git a/wifi/1.5/Android.bp b/wifi/1.5/Android.bp
index 7c04c69..0887c6b 100644
--- a/wifi/1.5/Android.bp
+++ b/wifi/1.5/Android.bp
@@ -20,6 +20,7 @@
"IWifiNanIface.hal",
"IWifiNanIfaceEventCallback.hal",
"IWifiStaIface.hal",
+ "IWifiEventCallback.hal",
],
interfaces: [
"android.hardware.wifi@1.0",
diff --git a/wifi/1.5/IWifi.hal b/wifi/1.5/IWifi.hal
index 66d0a9c..28b808e 100644
--- a/wifi/1.5/IWifi.hal
+++ b/wifi/1.5/IWifi.hal
@@ -17,6 +17,8 @@
package android.hardware.wifi@1.5;
import @1.4::IWifi;
+import IWifiEventCallback;
+import @1.0::WifiStatus;
/**
* This is the root of the HAL module and is the interface returned when
@@ -24,4 +26,21 @@
* module loaded in the system.
* IWifi.getChip() must return @1.5::IWifiChip
*/
-interface IWifi extends @1.4::IWifi {};
+interface IWifi extends @1.4::IWifi {
+ /**
+ * Requests notifications of significant events for the HAL. Multiple calls to
+ * this must register multiple callbacks each of which must receive all
+ * events. |IWifiEventCallback| object registration must be independent of the
+ * state of the rest of the HAL and must persist though stops/starts. These
+ * objects must be deleted when the corresponding client process is dead.
+ *
+ * @param callback An instance of the |IWifiEventCallback| HIDL interface
+ * object.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.UNKNOWN|
+ */
+ registerEventCallback_1_5(IWifiEventCallback callback)
+ generates (WifiStatus status);
+};
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index 5a3e288..e199850 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -303,4 +303,25 @@
getUsableChannels(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask,
bitfield<UsableChannelFilter> filterMask)
generates (WifiStatus status, vec<WifiUsableChannel> channels);
+
+ /**
+ * Trigger subsystem restart
+ *
+ * If the framework detects a problem (e.g. connection failure),
+ * it must call this function to attempt recovery.
+ *
+ * When the wifi HAL receiveds triggerSubsystemRestart(), it must restart
+ * the wlan subsystem, especially the wlan firmware.
+ *
+ * Regarding the callback function for subsystem restart, refer to documentation of
+ * |IWifiEventCallback.onSubsystemRestart| for details.
+ *
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ triggerSubsystemRestart() generates (WifiStatus status);
};
diff --git a/wifi/1.5/IWifiEventCallback.hal b/wifi/1.5/IWifiEventCallback.hal
new file mode 100644
index 0000000..ff27630
--- /dev/null
+++ b/wifi/1.5/IWifiEventCallback.hal
@@ -0,0 +1,28 @@
+/*
+ * 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.wifi@1.5;
+
+import @1.0::IWifiEventCallback;
+import @1.0::WifiStatus;
+
+interface IWifiEventCallback extends @1.0::IWifiEventCallback {
+ /**
+ * Must be called when the Wi-Fi subsystem restart completes.
+ * Once this event is received, framework must fully reset the Wi-Fi stack state.
+ */
+ oneway onSubsystemRestart(WifiStatus status);
+};
diff --git a/wifi/1.5/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp
index 125a50f..338a8f1 100644
--- a/wifi/1.5/default/hidl_struct_util.cpp
+++ b/wifi/1.5/default/hidl_struct_util.cpp
@@ -954,27 +954,29 @@
bool convertLegacyLinkLayerRadioStatsToHidl(
const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
- V1_3::StaLinkLayerRadioStats* hidl_radio_stat) {
+ V1_5::StaLinkLayerRadioStats* hidl_radio_stat) {
if (!hidl_radio_stat) {
return false;
}
*hidl_radio_stat = {};
- hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
- hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
- hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
- hidl_radio_stat->V1_0.onTimeInMsForScan =
+ hidl_radio_stat->radioId = legacy_radio_stat.stats.radio;
+ hidl_radio_stat->V1_3.V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
+ hidl_radio_stat->V1_3.V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
+ hidl_radio_stat->V1_3.V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
+ hidl_radio_stat->V1_3.V1_0.onTimeInMsForScan =
legacy_radio_stat.stats.on_time_scan;
- hidl_radio_stat->V1_0.txTimeInMsPerLevel =
+ hidl_radio_stat->V1_3.V1_0.txTimeInMsPerLevel =
legacy_radio_stat.tx_time_per_levels;
- hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd;
- hidl_radio_stat->onTimeInMsForBgScan =
+ hidl_radio_stat->V1_3.onTimeInMsForNanScan =
+ legacy_radio_stat.stats.on_time_nbd;
+ hidl_radio_stat->V1_3.onTimeInMsForBgScan =
legacy_radio_stat.stats.on_time_gscan;
- hidl_radio_stat->onTimeInMsForRoamScan =
+ hidl_radio_stat->V1_3.onTimeInMsForRoamScan =
legacy_radio_stat.stats.on_time_roam_scan;
- hidl_radio_stat->onTimeInMsForPnoScan =
+ hidl_radio_stat->V1_3.onTimeInMsForPnoScan =
legacy_radio_stat.stats.on_time_pno_scan;
- hidl_radio_stat->onTimeInMsForHs20Scan =
+ hidl_radio_stat->V1_3.onTimeInMsForHs20Scan =
legacy_radio_stat.stats.on_time_hs20;
std::vector<V1_3::WifiChannelStats> hidl_channel_stats;
@@ -996,7 +998,7 @@
hidl_channel_stats.push_back(hidl_channel_stat);
}
- hidl_radio_stat->channelStats = hidl_channel_stats;
+ hidl_radio_stat->V1_3.channelStats = hidl_channel_stats;
return true;
}
@@ -1089,9 +1091,9 @@
}
hidl_stats->iface.peers = hidl_peers_info_stats;
// radio legacy_stats conversion.
- std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
+ std::vector<V1_5::StaLinkLayerRadioStats> hidl_radios_stats;
for (const auto& legacy_radio_stats : legacy_stats.radios) {
- V1_3::StaLinkLayerRadioStats hidl_radio_stats;
+ V1_5::StaLinkLayerRadioStats hidl_radio_stats;
if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats,
&hidl_radio_stats)) {
return false;
diff --git a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
index e70d7ba..4b4ebd6 100644
--- a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
@@ -180,6 +180,7 @@
legacy_stats.iface.num_peers = 1;
for (auto& radio : legacy_stats.radios) {
+ radio.stats.radio = rand();
radio.stats.on_time = rand();
radio.stats.tx_time = rand();
radio.stats.rx_time = rand();
@@ -314,48 +315,53 @@
EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
+ EXPECT_EQ(legacy_stats.radios[i].stats.radio,
+ converted.radios[i].radioId);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
- converted.radios[i].V1_0.onTimeInMs);
+ converted.radios[i].V1_3.V1_0.onTimeInMs);
EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
- converted.radios[i].V1_0.txTimeInMs);
+ converted.radios[i].V1_3.V1_0.txTimeInMs);
EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
- converted.radios[i].V1_0.rxTimeInMs);
+ converted.radios[i].V1_3.V1_0.rxTimeInMs);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
- converted.radios[i].V1_0.onTimeInMsForScan);
+ converted.radios[i].V1_3.V1_0.onTimeInMsForScan);
EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
- converted.radios[i].V1_0.txTimeInMsPerLevel.size());
+ converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel.size());
for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
j++) {
EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
- converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
+ converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel[j]);
}
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
- converted.radios[i].onTimeInMsForNanScan);
+ converted.radios[i].V1_3.onTimeInMsForNanScan);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
- converted.radios[i].onTimeInMsForBgScan);
+ converted.radios[i].V1_3.onTimeInMsForBgScan);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
- converted.radios[i].onTimeInMsForRoamScan);
+ converted.radios[i].V1_3.onTimeInMsForRoamScan);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
- converted.radios[i].onTimeInMsForPnoScan);
+ converted.radios[i].V1_3.onTimeInMsForPnoScan);
EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
- converted.radios[i].onTimeInMsForHs20Scan);
+ converted.radios[i].V1_3.onTimeInMsForHs20Scan);
EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(),
- converted.radios[i].channelStats.size());
+ converted.radios[i].V1_3.channelStats.size());
for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size();
k++) {
auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k];
EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
- converted.radios[i].channelStats[k].channel.width);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq),
- converted.radios[i].channelStats[k].channel.centerFreq);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
- converted.radios[i].channelStats[k].channel.centerFreq0);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
- converted.radios[i].channelStats[k].channel.centerFreq1);
+ converted.radios[i].V1_3.channelStats[k].channel.width);
+ EXPECT_EQ(
+ WifiChannelInMhz(legacy_channel_st.channel.center_freq),
+ converted.radios[i].V1_3.channelStats[k].channel.centerFreq);
+ EXPECT_EQ(
+ WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
+ converted.radios[i].V1_3.channelStats[k].channel.centerFreq0);
+ EXPECT_EQ(
+ WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
+ converted.radios[i].V1_3.channelStats[k].channel.centerFreq1);
EXPECT_EQ(legacy_channel_st.cca_busy_time,
- converted.radios[i].channelStats[k].ccaBusyTimeInMs);
+ converted.radios[i].V1_3.channelStats[k].ccaBusyTimeInMs);
EXPECT_EQ(legacy_channel_st.on_time,
- converted.radios[i].channelStats[k].onTimeInMs);
+ converted.radios[i].V1_3.channelStats[k].onTimeInMs);
}
}
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
index da98db8..b9f20a4 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -50,13 +50,21 @@
}
Return<void> Wifi::registerEventCallback(
- const sp<IWifiEventCallback>& event_callback,
+ const sp<V1_0::IWifiEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
&Wifi::registerEventCallbackInternal, hidl_status_cb,
event_callback);
}
+Return<void> Wifi::registerEventCallback_1_5(
+ const sp<V1_5::IWifiEventCallback>& event_callback,
+ registerEventCallback_1_5_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+ &Wifi::registerEventCallbackInternal_1_5,
+ hidl_status_cb, event_callback);
+}
+
Return<bool> Wifi::isStarted() { return run_state_ != RunState::STOPPED; }
Return<void> Wifi::start(start_cb hidl_status_cb) {
@@ -95,7 +103,13 @@
}
WifiStatus Wifi::registerEventCallbackInternal(
- const sp<IWifiEventCallback>& event_callback) {
+ const sp<V1_0::IWifiEventCallback>& event_callback __unused) {
+ // Deprecated support for this callback.
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus Wifi::registerEventCallbackInternal_1_5(
+ const sp<V1_5::IWifiEventCallback>& event_callback) {
if (!event_cb_handler_.addCallback(event_callback)) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
@@ -117,7 +131,7 @@
WifiStatus wifi_status =
createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onFailure(wifi_status).isOk()) {
+ if (!callback->onSubsystemRestart(wifi_status).isOk()) {
LOG(ERROR) << "Failed to invoke onFailure callback";
}
}
diff --git a/wifi/1.5/default/wifi.h b/wifi/1.5/default/wifi.h
index 825c0bc..840bdfd 100644
--- a/wifi/1.5/default/wifi.h
+++ b/wifi/1.5/default/wifi.h
@@ -52,8 +52,11 @@
// HIDL methods exposed.
Return<void> registerEventCallback(
- const sp<IWifiEventCallback>& event_callback,
+ const sp<V1_0::IWifiEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) override;
+ Return<void> registerEventCallback_1_5(
+ const sp<V1_5::IWifiEventCallback>& event_callback,
+ registerEventCallback_1_5_cb hidl_status_cb) override;
Return<bool> isStarted() override;
Return<void> start(start_cb hidl_status_cb) override;
Return<void> stop(stop_cb hidl_status_cb) override;
@@ -67,7 +70,9 @@
// Corresponding worker functions for the HIDL methods.
WifiStatus registerEventCallbackInternal(
- const sp<IWifiEventCallback>& event_callback);
+ const sp<V1_0::IWifiEventCallback>& event_callback __unused);
+ WifiStatus registerEventCallbackInternal_1_5(
+ const sp<V1_5::IWifiEventCallback>& event_callback);
WifiStatus startInternal();
WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
@@ -87,7 +92,7 @@
std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
RunState run_state_;
std::vector<sp<WifiChip>> chips_;
- hidl_callback_util::HidlCallbackHandler<IWifiEventCallback>
+ hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback>
event_cb_handler_;
DISALLOW_COPY_AND_ASSIGN(Wifi);
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 0499f45..961f9da 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -747,6 +747,13 @@
ifaceModeMask, filterMask);
}
+Return<void> WifiChip::triggerSubsystemRestart(
+ triggerSubsystemRestart_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::triggerSubsystemRestartInternal,
+ hidl_status_cb);
+}
+
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
@@ -1522,6 +1529,11 @@
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
}
+WifiStatus WifiChip::triggerSubsystemRestartInternal() {
+ auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
WifiStatus WifiChip::handleChipConfiguration(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
ChipModeId mode_id) {
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 92d639f..bd40ead 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -184,6 +184,8 @@
WifiBand band, hidl_bitfield<WifiIfaceMode> ifaceModeMask,
hidl_bitfield<UsableChannelFilter> filterMask,
getUsableChannels_cb _hidl_cb) override;
+ Return<void> triggerSubsystemRestart(
+ triggerSubsystemRestart_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -303,6 +305,7 @@
void invalidateAndClearBridgedApAll();
void invalidateAndClearBridgedAp(const std::string& br_name);
bool findUsingNameFromBridgedApInstances(const std::string& name);
+ WifiStatus triggerSubsystemRestartInternal();
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 45ad84b..848fbd6 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1676,6 +1676,10 @@
return {status, std::move(channels)};
}
+wifi_error WifiLegacyHal::triggerSubsystemRestart() {
+ return global_func_table_.wifi_trigger_subsystem_restart();
+}
+
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index 8ebc66a..2bb7631 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -716,6 +716,8 @@
std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
+ wifi_error triggerSubsystemRestart();
+
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 6212960..dd860d6 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -160,6 +160,7 @@
populateStubFor(&hal_fn->wifi_twt_clear_stats);
populateStubFor(&hal_fn->wifi_set_dtim_config);
populateStubFor(&hal_fn->wifi_get_usable_channels);
+ populateStubFor(&hal_fn->wifi_trigger_subsystem_restart);
return true;
}
} // namespace legacy_hal
diff --git a/wifi/1.5/types.hal b/wifi/1.5/types.hal
index 0543004..3c19791 100644
--- a/wifi/1.5/types.hal
+++ b/wifi/1.5/types.hal
@@ -253,6 +253,21 @@
vec<StaPeerInfo> peers;
};
+struct StaLinkLayerRadioStats {
+ /**
+ * Baseline information as defined in HAL 1.3.
+ */
+ @1.3::StaLinkLayerRadioStats V1_3;
+
+ /**
+ * Radio ID: An implementation specific value identifying the radio interface for which the
+ * stats are produced. Framework must not interpret this value. It must use this value for
+ * persistently identifying the statistics between calls,
+ * e.g. if the HAL provides them in different order.
+ */
+ int32_t radioId;
+};
+
/**
* Link layer stats retrieved via |getLinkLayerStats|.
*/
diff --git a/wifi/hostapd/1.3/types.hal b/wifi/hostapd/1.3/types.hal
index f453df7..2230da8 100644
--- a/wifi/hostapd/1.3/types.hal
+++ b/wifi/hostapd/1.3/types.hal
@@ -25,7 +25,7 @@
* WIFI_STANDARD_11N = [hw_mode is HOSTAPD_MODE_IEEE80211G and (HT is 1 or HT40 is 1)] or
* [hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 0].
* WIFI_STANDARD_11AC = hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 1.
- * WIFI_STANDARD_11AX = hw_mode is HOSTAPD_MODE_IEEE80211AX.
+ * WIFI_STANDARD_11AX = hw_mode is HOSTAPD_MODE_IEEE80211A and HE supported.
* WIFI_STANDARD_11AD = hw_mode is HOSTAPD_MODE_IEEE80211AD.
*/
enum Generation : uint32_t {