diff options
295 files changed, 5686 insertions, 2794 deletions
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt index 653531d1f1..7d2706cbe9 100644 --- a/audio/7.0/config/api/current.txt +++ b/audio/7.0/config/api/current.txt @@ -155,6 +155,12 @@ package android.audio.policy.configuration.V7_0 { 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 @@ package android.audio.policy.configuration.V7_0 { 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 ee51aa88c5..2030921453 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 index 6fdc97ca29..24071af220 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 fe8eee1d53..7d83556895 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 @@ static inline bool isOutputDevice(const std::string& device) { 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 @@ static inline bool isUnknownAudioUsage(const std::string& usage) { 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/common/7.0/example/OWNERS b/audio/common/7.0/example/OWNERS new file mode 100644 index 0000000000..24071af220 --- /dev/null +++ b/audio/common/7.0/example/OWNERS @@ -0,0 +1,2 @@ +elaurent@google.com +mnaganov@google.com diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal index 4f920e47cc..6fca93e85b 100644 --- a/audio/common/7.0/types.hal +++ b/audio/common/7.0/types.hal @@ -145,6 +145,14 @@ struct AudioConfigBaseOptional { }; /** + * 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 @@ struct AudioProfile { }; /** + * 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 @@ struct AudioPort { * 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 6fdc97ca29..24071af220 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 2949fac293..5a5b5d276a 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 @@ status_t HidlUtils::audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext, 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 @@ status_t HidlUtils::audioPortFromHal(const struct audio_port_v7& halPort, AudioP 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 @@ status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* 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 @@ status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* 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 dd4ca4d8ca..98ecc0754e 100644 --- a/audio/common/all-versions/default/HidlUtils.h +++ b/audio/common/all-versions/default/HidlUtils.h @@ -126,6 +126,10 @@ struct HidlUtils { 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 HidlUtils { 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 6fdc97ca29..24071af220 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 e154453e2b..c9e6fac7b2 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 @@ static constexpr audio_source_t kInvalidHalSource = static_cast<audio_source_t>( // 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 @@ TEST(HidlUtils, ConvertAudioPortConfig) { 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 @@ TEST(HidlUtils, ConvertInvalidAudioPort) { 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 @@ TEST(HidlUtils, ConvertAudioPort) { 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 6a26ae72cd..0000000000 --- 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 index 6fdc97ca29..6fdc97ca29 100644 --- a/audio/core/all-versions/default/OWNERS +++ b/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 0ea4666443..0000000000 --- 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 f87e5ed565..b96cc83673 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 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { .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 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { 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 c1923f1230..0b3098b872 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 @@ TEST_P(SingleConfigInputStreamTest, UpdateInvalidSinkMetadata) { << ::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 eafc813cf9..d2ba3397af 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 @@ std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool one 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 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters 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 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters 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 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters 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 @@ std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneP 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 @@ const std::vector<DeviceConfigParameter>& getInputDeviceInvalidConfigParameters( { 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 0000000000..29882077d1 --- /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 feb4d4b3aa..f798839cb8 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 @@ class PolicyConfig { 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 926a791ba8..e446a7f2cf 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -156,6 +156,7 @@ cc_test { 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 @@ cc_test { "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 @@ cc_test { } // 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 @@ cc_test { 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 @@ cc_test { "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 56939fe6e6..aa7fd8e857 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -89,6 +89,10 @@ using ::android::hardware::details::toHexString; 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 @@ using namespace ::android::audio::policy::configuration::CPP_VERSION; 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 @@ static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUP #include "7.0/Generators.h" #include "7.0/PolicyConfig.h" #endif +#include "StreamWorker.h" class HidlTest : public ::testing::Test { public: @@ -778,6 +784,11 @@ TEST_P(AudioHidlDeviceTest, DebugDumpInvalidArguments) { ////////////////////////// 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 @@ class StreamHelper { 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 @@ class StreamHelper { 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 @@ class StreamHelper { #endif } } + AudioIoHandle getIoHandle() const { return mIoHandle; } private: + const AudioIoHandle mIoHandle = getNextIoHandle(); sp<Stream>& mStream; }; @@ -861,7 +871,6 @@ class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter { return res; } - private: void TearDown() override { if (open) { ASSERT_OK(closeStream()); @@ -879,6 +888,116 @@ class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter { ////////////////////////////// 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 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest); ////////////////////////////// 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 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> { #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 @@ TEST_P(InputStreamTest, getCapturePosition) { 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 @@ TEST_P(OutputStreamTest, GetPresentationPositionStop) { "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 @@ TEST_P(OutputStreamTest, GetPresentationPositionStop) { 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 5b14a216c9..aa676308cb 100644 --- a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h +++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h @@ -31,15 +31,17 @@ using DeviceParameter = std::tuple<std::string, std::string>; // 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 0000000000..68a8024b1e --- /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 0000000000..75116affc2 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp @@ -0,0 +1,216 @@ +/* + * 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) {} + + void ensureWorkerCycled() { + const size_t cyclesBefore = mWorkerCycles; + while (mWorkerCycles == cyclesBefore && !hasError()) { + sched_yield(); + } + } + 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.ensureWorkerCycled(); + EXPECT_FALSE(worker.hasError()); +} + +TEST_P(StreamWorkerTest, WorkerError) { + ASSERT_TRUE(worker.start()); + stream.error = true; + worker.ensureWorkerCycled(); + EXPECT_TRUE(worker.hasError()); + EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime)); +} + +TEST_P(StreamWorkerTest, PauseResume) { + ASSERT_TRUE(worker.start()); + worker.ensureWorkerCycled(); + 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.ensureWorkerCycled(); + EXPECT_FALSE(worker.hasError()); + worker.pause(); + worker.stop(); + EXPECT_FALSE(worker.hasError()); +} + +TEST_P(StreamWorkerTest, PauseAfterErrorIgnored) { + ASSERT_TRUE(worker.start()); + stream.error = true; + worker.ensureWorkerCycled(); + 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.ensureWorkerCycled(); + EXPECT_TRUE(worker.hasError()); + worker.resume(); + EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime)); + EXPECT_TRUE(worker.hasError()); +} + +TEST_P(StreamWorkerTest, WorkerErrorOnResume) { + ASSERT_TRUE(worker.start()); + worker.ensureWorkerCycled(); + EXPECT_FALSE(worker.hasError()); + worker.pause(); + EXPECT_FALSE(worker.hasError()); + stream.error = true; + EXPECT_FALSE(worker.hasError()); + worker.resume(); + worker.ensureWorkerCycled(); + 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/OWNERS b/audio/effect/all-versions/OWNERS new file mode 100644 index 0000000000..24071af220 --- /dev/null +++ b/audio/effect/all-versions/OWNERS @@ -0,0 +1,2 @@ +elaurent@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 0ea4666443..0000000000 --- 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 0000000000..e64e942a0e --- /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 0000000000..7f1d4d10b6 --- /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/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl index 4b4e7df146..d4433c5bde 100644 --- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl @@ -37,6 +37,5 @@ parcelable CommonProps { int sensorId; android.hardware.biometrics.common.SensorStrength sensorStrength = android.hardware.biometrics.common.SensorStrength.CONVENIENCE; int maxEnrollmentsPerUser; - android.hardware.biometrics.common.HardwareInfo[] hardwareInfo; - String softwareInfo; + android.hardware.biometrics.common.ComponentInfo[] componentInfo; } diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl index c5288fdae5..ad11ddaa6d 100644 --- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl @@ -33,8 +33,10 @@ package android.hardware.biometrics.common; @VintfStability -parcelable HardwareInfo { - String deviceName; +parcelable ComponentInfo { + String componentId; String hardwareVersion; + String firmwareVersion; String serialNumber; + String softwareVersion; } diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl index 7c3d511360..2f5af5dbc9 100644 --- a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl +++ b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl @@ -16,7 +16,7 @@ package android.hardware.biometrics.common; -import android.hardware.biometrics.common.HardwareInfo; +import android.hardware.biometrics.common.ComponentInfo; import android.hardware.biometrics.common.SensorStrength; @VintfStability @@ -41,16 +41,7 @@ parcelable CommonProps { int maxEnrollmentsPerUser; /** - * A list of hardware information for subsystems that pertain to this biometric sensor. + * A list of component information for subsystems that pertain to this biometric sensor. */ - HardwareInfo[] hardwareInfo; - - /** - * Software information for subsystems that pertain to this biometric sensor. - * This may include information for the matching algorithm, the PAD (Presentation Attack - * Detection) algorithm, and any other algorithm(s) used by this biometric sensor. - * For example, <algorithm_1_info>;<algorithm_2_info>;<algorithm_3_info>. - * The format of each algorithm's info can be <vendor>/<algorithm>/<version>. - */ - String softwareInfo; + ComponentInfo[] componentInfo; } diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/HardwareInfo.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl index ce9e354dd3..b268eef976 100644 --- a/biometrics/common/aidl/android/hardware/biometrics/common/HardwareInfo.aidl +++ b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl @@ -17,19 +17,34 @@ package android.hardware.biometrics.common; @VintfStability -parcelable HardwareInfo { +parcelable ComponentInfo { /** * An identifier uniquely identifying a subsystem. + * It must not be an empty string. */ - String deviceName; + String componentId; /** * The hardware version. For example, <vendor>/<model>/<revision>. + * If there's no hardware version for this component, it must be empty. */ String hardwareVersion; /** + * The firmware version. + * If there's no firmware version for this component, it must be empty. + */ + String firmwareVersion; + + /** * The sensor's serial number. + * If there's no serial number for this component, it must be empty. */ String serialNumber; + + /** + * The software version. For example, <vendor>/<version>/<revision>. + * If there's no software version for this component, it must be empty. + */ + String softwareVersion; } 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 205429bd7a..9033989563 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 d6ebbb6208..2bb053a31c 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 @@ interface ISessionCallback { 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 66c7c38710..f9c13e6801 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.common.NativeHandle; 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 @@ interface ISession { * * 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 @@ interface ISession { * | 0 | 10 | <Time4> | <Random4> | * ---------------------------------------------- * - * @param cookie A unique number identifying this operation */ - void generateChallenge(in int cookie); + void generateChallenge(); /** * revokeChallenge: @@ -79,10 +92,9 @@ interface ISession { * 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 @@ interface ISession { * * 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 @@ interface ISession { * 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 @@ interface ISession { * @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 @@ interface ISession { * * 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 @@ interface ISession { * 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 @@ interface ISession { * @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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * (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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 2e3cd950f6..a2601e7360 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.AuthenticationFrame; 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { * 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 afde4eb2d5..0000000000 --- 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/Face.cpp b/biometrics/face/aidl/default/Face.cpp index a4520deb47..aca3e135f6 100644 --- a/biometrics/face/aidl/default/Face.cpp +++ b/biometrics/face/aidl/default/Face.cpp @@ -24,23 +24,33 @@ const common::SensorStrength kSensorStrength = common::SensorStrength::STRONG; const int kMaxEnrollmentsPerUser = 5; const FaceSensorType kSensorType = FaceSensorType::RGB; const bool kHalControlsPreview = true; -const std::string kHwDeviceName = "faceSensor"; +const std::string kHwComponentId = "faceSensor"; const std::string kHardwareVersion = "vendor/model/revision"; +const std::string kFirmwareVersion = "1.01"; const std::string kSerialNumber = "00000001"; -const std::string kSoftwareVersion = "vendor1/algorithm1/version;vendor2/algorithm2/version"; +const std::string kSwComponentId = "matchingAlgorithm"; +const std::string kSoftwareVersion = "vendor/version/revision"; ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) { - common::HardwareInfo hardware_info; - hardware_info.deviceName = kHwDeviceName; - hardware_info.hardwareVersion = kHardwareVersion; - hardware_info.serialNumber = kSerialNumber; + common::ComponentInfo hw_component_info; + hw_component_info.componentId = kHwComponentId; + hw_component_info.hardwareVersion = kHardwareVersion; + hw_component_info.firmwareVersion = kFirmwareVersion; + hw_component_info.serialNumber = kSerialNumber; + hw_component_info.softwareVersion = ""; + + common::ComponentInfo sw_component_info; + sw_component_info.componentId = kSwComponentId; + sw_component_info.hardwareVersion = ""; + sw_component_info.firmwareVersion = ""; + sw_component_info.serialNumber = ""; + sw_component_info.softwareVersion = kSoftwareVersion; common::CommonProps commonProps; commonProps.sensorId = kSensorId; commonProps.sensorStrength = kSensorStrength; commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser; - commonProps.hardwareInfo = {std::move(hardware_info)}; - commonProps.softwareInfo = kSoftwareVersion; + commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)}; SensorProps props; props.commonProps = std::move(commonProps); diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp index ce6c5572e6..b5eb717351 100644 --- a/biometrics/face/aidl/default/Session.cpp +++ b/biometrics/face/aidl/default/Session.cpp @@ -30,119 +30,105 @@ class CancellationSignal : public common::BnCancellationSignal { 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 eb9ae83342..73cdf08625 100644 --- a/biometrics/face/aidl/default/Session.h +++ b/biometrics/face/aidl/default/Session.h @@ -30,40 +30,38 @@ class Session : public BnSession { 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 4cc8b4afa0..60e0a2a41f 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 @@ class SessionCallback : public BnSessionCallback { 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 @@ class SessionCallback : public BnSessionCallback { 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 @@ class Face : public testing::TestWithParam<std::string> { 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()); + + // Call authenticate + std::shared_ptr<common::ICancellationSignal> cancellationSignal; + ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).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); + // Get the results + EXPECT_EQ(mInv.methodName, MethodName::kOnError); + EXPECT_EQ(mInv.error, Error::UNABLE_TO_PROCESS); + EXPECT_EQ(mInv.vendorCode, 0); - SessionCallbackInvocation invocation = invocation_future.get(); - EXPECT_EQ(invocation.method_name, SessionCallbackMethodName::kOnStateChanged); - EXPECT_EQ(invocation.state, SessionState::AUTHENTICATING); + // Close the session + ASSERT_TRUE(session->close().isOk()); + + EXPECT_EQ(mInv.methodName, MethodName::kOnSessionClosed); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face); @@ -159,6 +173,7 @@ INSTANTIATE_TEST_SUITE_P(IFace, Face, ::android::PrintInstanceNameToString); } // namespace +} // namespace aidl::android::hardware::biometrics::face int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); @@ -167,4 +182,3 @@ int main(int argc, char** argv) { 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 a8e73fc82c..2c2011a034 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 @@ enum AcquiredInfo { 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 87eaf96a41..9934a763e7 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 13c2b05081..3c40ad63bf 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 @@ interface ISessionCallback { void onEnrollmentsRemoved(in int[] enrollmentIds); void onAuthenticatorIdRetrieved(in long authenticatorId); void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + void onSessionClosed(); } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl index bf11daa817..b406947be5 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 @@ enum AcquiredInfo { * 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 98a45307b9..271a9bf1cf 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 @@ interface IFingerprint { /** * 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 ef2e6fc499..940548ba88 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 @@ import android.hardware.keymaster.HardwareAuthToken; /** * 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 @@ interface ISession { * | 0 | 10 | <Time4> | <Random4> | * ---------------------------------------------- * - * @param cookie A unique number identifying this operation */ - void generateChallenge(in int cookie); + void generateChallenge(); /** * revokeChallenge: @@ -95,23 +99,17 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 @@ interface ISession { * 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 fde1df753d..95657b3d7b 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 @@ package android.hardware.biometrics.fingerprint; 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { /** * 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 @@ interface ISessionCallback { * 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 19a6ce3682..0000000000 --- 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/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp index 79f48fe195..fbfa52f0e7 100644 --- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp +++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp @@ -26,10 +26,12 @@ constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::STRON constexpr int MAX_ENROLLMENTS_PER_USER = 5; constexpr FingerprintSensorType SENSOR_TYPE = FingerprintSensorType::REAR; constexpr bool SUPPORTS_NAVIGATION_GESTURES = true; -constexpr char HW_DEVICE_NAME[] = "fingerprintSensor"; +constexpr char HW_COMPONENT_ID[] = "fingerprintSensor"; constexpr char HW_VERSION[] = "vendor/model/revision"; +constexpr char FW_VERSION[] = "1.01"; constexpr char SERIAL_NUMBER[] = "00000001"; -constexpr char SW_VERSION[] = "vendor1/algorithm1/version;vendor2/algorithm2/version"; +constexpr char SW_COMPONENT_ID[] = "matchingAlgorithm"; +constexpr char SW_VERSION[] = "vendor/version/revision"; } // namespace @@ -37,10 +39,13 @@ Fingerprint::Fingerprint() : mEngine(std::make_unique<FakeFingerprintEngine>()), mWorker(MAX_WORKER_QUEUE_SIZE) {} ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) { - std::vector<common::HardwareInfo> hardwareInfos = {{HW_DEVICE_NAME, HW_VERSION, SERIAL_NUMBER}}; + std::vector<common::ComponentInfo> componentInfo = { + {HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */}, + {SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */, + "" /* serialNumber */, SW_VERSION}}; common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER, - hardwareInfos, SW_VERSION}; + componentInfo}; SensorLocation sensorLocation = {0 /* displayId */, 0 /* sensorLocationX */, 0 /* sensorLocationY */, 0 /* sensorRadius */}; diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp index c035407c7e..ca481e7cf0 100644 --- a/biometrics/fingerprint/aidl/default/Session.cpp +++ b/biometrics/fingerprint/aidl/default/Session.cpp @@ -39,54 +39,56 @@ Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb, } 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 @@ ndk::ScopedAStatus Session::enroll(int32_t cookie, const keymaster::HardwareAuth 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 @@ ndk::ScopedAStatus Session::authenticate(int32_t cookie, int64_t operationId, 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 42e1aa5357..6667f7a7f0 100644 --- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h +++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h @@ -37,7 +37,7 @@ class FakeFingerprintEngine { 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 97d5645c92..9e464229e1 100644 --- a/biometrics/fingerprint/aidl/default/include/Session.h +++ b/biometrics/fingerprint/aidl/default/include/Session.h @@ -27,37 +27,50 @@ namespace aidl::android::hardware::biometrics::fingerprint { 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 @@ class Session : public BnSession { // 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 0d5014bb84..c548fe5bfb 100644 --- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp +++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp @@ -32,23 +32,41 @@ using namespace std::chrono_literals; 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 @@ TEST(WorkerThreadTest, TasksExecuteInOrder) { 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 @@ TEST(WorkerThreadTest, ExecutionStopsAfterWorkerIsDestroyed) { 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 894fdfe362..f1cfb17837 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 @@ class SessionCallback : public BnSessionCallback { 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 @@ class Fingerprint : public testing::TestWithParam<std::string> { }; 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/bluetooth/audio/2.1/types.hal b/bluetooth/audio/2.1/types.hal index 5604c386d2..e0dcc02cc0 100644 --- a/bluetooth/audio/2.1/types.hal +++ b/bluetooth/audio/2.1/types.hal @@ -16,13 +16,14 @@ package android.hardware.bluetooth.audio@2.1; -import @2.0::PcmParameters; -import @2.0::SessionType; -import @2.0::SampleRate; -import @2.0::ChannelMode; import @2.0::BitsPerSample; -import @2.0::CodecConfiguration; +import @2.0::ChannelMode; import @2.0::CodecCapabilities; +import @2.0::CodecConfiguration; +import @2.0::CodecType; +import @2.0::PcmParameters; +import @2.0::SampleRate; +import @2.0::SessionType; enum SessionType : @2.0::SessionType { /** Used when encoded by Bluetooth Stack and streaming to LE Audio device */ @@ -35,6 +36,10 @@ enum SessionType : @2.0::SessionType { LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH, }; +enum CodecType : @2.0::CodecType { + LC3 = 0x20, +}; + enum SampleRate : @2.0::SampleRate { RATE_8000 = 0x100, RATE_32000 = 0x200, @@ -49,14 +54,57 @@ struct PcmParameters { uint32_t dataIntervalUs; }; -/** Used to configure either a Hardware or Software Encoding session based on session type */ -safe_union AudioConfiguration { - PcmParameters pcmConfig; - CodecConfiguration codecConfig; +enum Lc3FrameDuration : uint8_t { + DURATION_10000US = 0x00, + DURATION_7500US = 0x01, +}; + +/** + * Used for Hardware Encoding/Decoding LC3 codec parameters. + */ +struct Lc3Parameters { + /* PCM is Input for encoder, Output for decoder */ + BitsPerSample pcmBitDepth; + + /* codec-specific parameters */ + SampleRate samplingFrequency; + Lc3FrameDuration frameDuration; + /* length in octets of a codec frame */ + uint32_t octetsPerFrame; + /* Number of blocks of codec frames per single SDU (Service Data Unit) */ + uint8_t blocksPerSdu; +}; + +/** + * Used to specify the capabilities of the LC3 codecs supported by Hardware Encoding. + */ +struct Lc3CodecCapabilities { + /* This is bitfield, if bit N is set, HW Offloader supports N+1 channels at the same time. + * Example: 0x27 = 0b00100111: One, two, three or six channels supported.*/ + uint8_t supportedChannelCounts; + Lc3Parameters lc3Capabilities; }; /** Used to specify the capabilities of the different session types */ safe_union AudioCapabilities { PcmParameters pcmCapabilities; CodecCapabilities codecCapabilities; + Lc3CodecCapabilities leAudioCapabilities; }; + +/** + * Used to configure a LC3 Hardware Encoding session. + */ +struct Lc3CodecConfiguration { + /* This is also bitfield, specifying how the channels are ordered in the outgoing media packet. + * Bit meaning is defined in Bluetooth Assigned Numbers. */ + uint32_t audioChannelAllocation; + Lc3Parameters lc3Config; +}; + +/** Used to configure either a Hardware or Software Encoding session based on session type */ +safe_union AudioConfiguration { + PcmParameters pcmConfig; + CodecConfiguration codecConfig; + Lc3CodecConfiguration leAudioCodecConfig; +};
\ No newline at end of file diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS index b159083944..57e659265a 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 42782f29a9..15c1b5ced5 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 @@ hidl_interface { "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 9450c2f5a7..6910e6574c 100644 --- a/camera/device/3.7/types.hal +++ b/camera/device/3.7/types.hal @@ -21,6 +21,8 @@ import @3.2::StreamConfigurationMode; import @3.4::CaptureRequest; import @3.4::Stream; +import android.hardware.camera.metadata@3.6::CameraMetadataEnumAndroidSensorPixelMode; + /** * Stream: * @@ -57,6 +59,14 @@ struct Stream { * 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 3472ae9668..709cfb3ec5 100644 --- a/camera/metadata/3.6/types.hal +++ b/camera/metadata/3.6/types.hal @@ -36,6 +36,43 @@ import android.hardware.camera.metadata@3.5; * '/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 @@ enum CameraMetadataTag : @3.5::CameraMetadataTag { */ 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 @@ enum CameraMetadataEnumAndroidScalerPhysicalCameraMultiResolutionStreamConfigura 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 094dd9d4cd..ba59b380f5 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 9e99c48f7c..c656af2b21 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/IContexthub.hal b/contexthub/1.2/IContexthub.hal index 4bb9361bc1..04a8cb29cc 100644 --- a/contexthub/1.2/IContexthub.hal +++ b/contexthub/1.2/IContexthub.hal @@ -51,18 +51,6 @@ interface IContexthub extends @1.1::IContexthub { registerCallback_1_2(uint32_t hubId, IContexthubCallback cb) generates (Result result); /** - * Send a message to a hub - * - * @param hubId identifier for hub to send message to - * @param msg message to be sent - * - * @return result OK if successful, error code otherwise - * BAD_VALUE if parameters are not valid - * TRANSACTION_FAILED if message send failed - */ - sendMessageToHub_1_2(uint32_t hubId, ContextHubMsg msg) generates (Result result); - - /** * Notification sent by the framework to indicate that the user * has changed a setting. * diff --git a/contexthub/1.2/default/Contexthub.cpp b/contexthub/1.2/default/Contexthub.cpp index 601eccd399..57145fc64f 100644 --- a/contexthub/1.2/default/Contexthub.cpp +++ b/contexthub/1.2/default/Contexthub.cpp @@ -80,12 +80,6 @@ Return<Result> Contexthub::registerCallback_1_2(uint32_t hubId, return Result::BAD_PARAMS; } -// We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS -Return<Result> Contexthub::sendMessageToHub_1_2(uint32_t /* hubId */, - const ContextHubMsg& /* msg */) { - return Result::BAD_PARAMS; -} - Return<void> Contexthub::onSettingChanged(SettingV1_1 /*setting*/, SettingValue /*newValue*/) { return Void(); } diff --git a/contexthub/1.2/default/Contexthub.h b/contexthub/1.2/default/Contexthub.h index 32b862dc3f..305544d5f4 100644 --- a/contexthub/1.2/default/Contexthub.h +++ b/contexthub/1.2/default/Contexthub.h @@ -55,8 +55,6 @@ class Contexthub Return<Result> registerCallback_1_2(uint32_t hubId, const sp<V1_2::IContexthubCallback>& cb) override; - Return<Result> sendMessageToHub_1_2(uint32_t hubId, const ContextHubMsg& msg) override; - private: sp<IContextHubCallbackWrapperBase> mCallback; }; diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal index 5a11efea46..75122bc898 100644 --- a/contexthub/1.2/types.hal +++ b/contexthub/1.2/types.hal @@ -35,21 +35,20 @@ enum Setting : @1.1::Setting { 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 { @1.0::ContextHubMsg msg_1_0; /** - * The list of Android permissions that the sender of this message has at - * the time the message was sent. - * - * The HAL MUST drop messages to nanoapps if this list of permissions is not - * a superset of those of the receiving nanoapp(s). + * The list of Android permissions held by the sending nanoapp at the time + * the message was sent. * * The framework MUST drop messages to host apps that don't have a superset * of the permissions that the sending nanoapp is using. diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp index c50d43c137..9ee40ede01 100644 --- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp +++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp @@ -131,10 +131,10 @@ TEST_P(ContexthubHidlTest, TestOnAirplaneModeSettingChanged) { 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)); } @@ -195,39 +195,8 @@ class TxnResultCallback : public ContexthubCallbackV1_2 { std::promise<TransactionResult> promise; }; -// Parameterized fixture that sets the callback to TxnResultCallback -class ContexthubTxnTest : public ContexthubHidlTest { - public: - virtual void SetUp() override { - ContexthubHidlTest::SetUp(); - ASSERT_OK(registerCallback_1_2(cb)); - } - - sp<TxnResultCallback> cb = new TxnResultCallback(); -}; - -TEST_P(ContexthubTxnTest, TestSendMessageToNonExistentNanoApp) { - ContextHubMsg msg; - msg.msg_1_0.appName = kNonExistentAppId; - msg.msg_1_0.msgType = 1; - msg.msg_1_0.msg.resize(4); - std::fill(msg.msg_1_0.msg.begin(), msg.msg_1_0.msg.end(), 0); - - ALOGD("Sending message to non-existent nanoapp"); - Result result = hubApi->sendMessageToHub_1_2(getHubId(), msg); - if (result != Result::OK && result != Result::BAD_PARAMS && - result != Result::TRANSACTION_FAILED) { - FAIL() << "Got result " << asBaseType(result) << ", expected OK, BAD_PARAMS" - << ", or TRANSACTION_FAILED"; - } -} - GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest); INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters), android::hardware::PrintInstanceTupleNameToString<>); -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubTxnTest); -INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubTxnTest, testing::ValuesIn(kTestParameters), - android::hardware::PrintInstanceTupleNameToString<>); - } // anonymous namespace diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp index 9a44eb5607..609f59e60f 100644 --- a/gnss/2.1/default/Android.bp +++ b/gnss/2.1/default/Android.bp @@ -33,6 +33,7 @@ cc_binary { "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 1a2feb776a..a4f00971c5 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 9c9a2414a6..b0848bb9c4 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 fbcc8a3ac7..7d3baa41f2 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 15fe2e9b57..c54cc2c500 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 f873b87d7f..c1fcfcc741 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 9e05db7bd1..ebb5d0bdff 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 bc73bb19eb..948c540fc3 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 b9db34382e..24f45c42fa 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 6676e2eb7c..670244fd1f 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 ba02f72961..c2a5b51e15 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 10b05a7ff1..f93b496cdd 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 9ad9159d67..fb0931c59a 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 @@ interface IGnssCallback { 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 20dd781466..54cd022f66 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 93894bfd6a..6e626172b9 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 07a51aeb5d..24d6f9c4cf 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 1cc7f7114a..fbf1f6ffb6 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 01f91dc3de..bfa787e3e2 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 175879245a..526ecc8fcd 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 a1af1057ef..2205bc46dd 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 b387121d5b..727bb6912b 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 4dd45b2af7..ed23e639a8 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 c96b2e5344..e1a20c378e 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 95af1524b3..747ee90933 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 558aec992d..a571048c20 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 f20cd25cd7..336e9272a6 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 @@ import android.hardware.gnss.SatellitePvt; @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 @@ parcelable GnssMeasurement { * 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 @@ parcelable GnssMeasurement { * - 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 @@ parcelable GnssMeasurement { */ double pseudorangeRateUncertaintyMps; - /** * Flags indicating the Accumulated Delta Range's states. * @@ -620,8 +619,10 @@ parcelable GnssMeasurement { 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 @@ parcelable GnssMeasurement { * 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 8881ea7486..aad09ef98b 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 @@ import android.hardware.gnss.IGnssConfiguration; */ @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 4b3615e29a..febe62333f 100644 --- a/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl +++ b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl @@ -18,6 +18,9 @@ package android.hardware.gnss; /** * 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 @@ parcelable SatellitePositionEcef { * 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 25ece3a3a7..f2d7ab6030 100644 --- a/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl +++ b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl @@ -18,6 +18,9 @@ package android.hardware.gnss; /** * 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 @@ parcelable SatelliteVelocityEcef { * 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 d363a9f832..4cc2b6e251 100644 --- a/gnss/aidl/default/Android.bp +++ b/gnss/aidl/default/Android.bp @@ -40,6 +40,7 @@ cc_binary { ], 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 a330c5a3b0..43db8739d1 100644 --- a/gnss/common/utils/default/Android.bp +++ b/gnss/common/utils/default/Android.bp @@ -44,6 +44,7 @@ cc_library_static { ], 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 4d4ec93593..79c78c3f07 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 @@ template <class T_IGnss> 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 3e2289a701..6ec1faef0e 100644 --- a/keymaster/4.1/default/Android.bp +++ b/keymaster/4.1/default/Android.bp @@ -45,5 +45,14 @@ cc_binary { "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 0000000000..0dbeed8f2b --- /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 0000000000..6d3e74d2b1 --- /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 0000000000..088d810492 --- /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 0000000000..c38fc7a499 --- /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 0000000000..096edbdf8c --- /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 d7b26aab35..be1ee07d57 100644 --- a/neuralnetworks/1.0/types.t +++ b/neuralnetworks/1.0/types.t @@ -63,361 +63,25 @@ enum FusedActivationFunc : int32_t { 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, - - /** - * 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, - - /** - * 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, - - /** - * 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, -}; - -/** - * Status of a device. - */ -enum DeviceStatus : int32_t { - AVAILABLE, - BUSY, - OFFLINE, - UNKNOWN, -}; - -/** - * 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; - - /** - * 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; -}; - -/** - * 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; +%insert OperandLifeTime - /** - * 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; +%insert DeviceStatus - /** - * 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; +%insert PerformanceInfo - /** - * 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; +%insert Capabilities - /** - * 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; -}; +%insert DataLocation -/** - * 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; +%insert Operand - /** - * 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; -}; +%insert Operation -/** - * 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; +%insert Model - /** - * 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; +%insert RequestArgument - /** - * 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 75ac2e7be8..8c22b302a5 100644 --- a/neuralnetworks/1.1/types.t +++ b/neuralnetworks/1.1/types.t @@ -31,128 +31,10 @@ enum OperationType : @1.0::OperationType { %insert Operation_1.1 }; -/** - * 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; - - /** - * 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; -}; - -/** - * Describes one operation of the model's graph. - */ -struct Operation { - /** - * The operation type. - */ - OperationType type; +%insert Capabilities - /** - * 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 Operation - /** - * 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 Model -/** - * 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 4c9fd02403..b490f7f932 100644 --- a/neuralnetworks/1.2/types.t +++ b/neuralnetworks/1.2/types.t @@ -97,379 +97,23 @@ enum OperationTypeRange : uint32_t { 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, -}; - -/** - * 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; - - /** - * 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; - }; - - /** - * 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; -}; - -/** - * 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; - - /** - * 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; -}; - -/** - * 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; -}; - -/** - * 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; +%insert DeviceType - /** - * 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; +%insert Capabilities - /** - * Quantized scale of the operand. - * - * Must be 0 when not applicable to an operand type. - * - * See {@link OperandType}. - */ - float scale; +%insert Operation - /** - * Quantized zero-point offset of the operand. - * - * Must be 0 when not applicable to an operand type. - * - * See {@link OperandType}. - */ - int32_t zeroPoint; +%insert SymmPerChannelQuantParams - /** - * How the operand is used. - */ - OperandLifeTime lifetime; +%insert Operand - /** - * 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; +%insert Model - /** - * Additional parameters specific to a particular operand type. - */ - safe_union ExtraParams { - /** - * No additional parameters. - */ - Monostate none; +%insert OutputShape - /** - * Symmetric per-channel quantization parameters. - * - * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL. - */ - SymmPerChannelQuantParams channelQuant; +%insert MeasureTiming - /** - * 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 @@ safe_union FmqResultDatum { 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 9f69c9e070..96d1a1b975 100644 --- a/neuralnetworks/1.3/types.t +++ b/neuralnetworks/1.3/types.t @@ -90,459 +90,25 @@ enum OperationTypeRange : uint32_t { BASE_MAX = 0xFFFF, }; -/** - * Priority given to a prepared model for execution. - */ -enum Priority : int32_t { - LOW, - MEDIUM, - HIGH, -}; - -/** - * 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 Priority - /** - * 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; - }; - - /** - * 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; - - /** - * 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; - - /** - * 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 Capabilities -/** - * 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 Operation - /** - * 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 OperandLifeTime - /** - * 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 Operand -/** - * 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 Model - /** - * 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, +%insert Subgraph - /** - * 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, +%insert BufferDesc - /** - * The operand is a constant found in Model.operandValues. It must - * not be an output operand of any operation. - */ - CONSTANT_COPY, +%insert BufferRole - /** - * 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 9788fe1b9d..8b45f715ab 100644 --- a/neuralnetworks/1.3/utils/src/Conversions.cpp +++ b/neuralnetworks/1.3/utils/src/Conversions.cpp @@ -244,7 +244,7 @@ GeneralResult<BufferRole> unvalidatedConvert(const hal::V1_3::BufferRole& buffer return BufferRole{ .modelIndex = bufferRole.modelIndex, .ioIndex = bufferRole.ioIndex, - .frequency = bufferRole.frequency, + .probability = bufferRole.frequency, }; } @@ -577,7 +577,7 @@ nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRol 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 71b7758f20..05cec76c88 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 c2d636c53d..10a6b75ac7 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 @@ package android.hardware.neuralnetworks; 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 01cc753b58..30877c0294 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 e836daec96..db49a38979 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 7bc8aa739a..7cdd6db742 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 1abacc8a6f..82fe8ae3e7 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 873c584f7c..57d5d6e4cd 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 c4badc0ad9..4352d8f334 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 b99bb3131e..44e9922f52 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 a7ae9421e9..c47028d99f 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 4c255387d1..6c287fd460 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 b32b217960..a3680aa9dd 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 2fee136e19..7e61bbbdb1 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 2860692378..f10e7e24ca 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 index 4db47c9c67..634f39e670 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 4c5fd2fa47..b328b29eab 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 abe67b8801..0bfb80ac78 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 1f7cbe0e4b..52882cd0ab 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 @@ package android.hardware.neuralnetworks; 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 8eaaab68e4..e0c763bc2a 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 8388fdabb4..dbedf12772 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 3b2f240b48..8207b25570 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 9d12e58f98..30d8dda55d 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 c1e87da229..9314760a43 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 bb78caaa17..5a9f4ffc72 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 3f6d93b3bf..14792cff08 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 d581cedf54..40adfb1dd8 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 87fd3a64bd..de93d8b444 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 186c13dfe9..9f2c759d38 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 fec83a89a8..33fcd60abc 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 ad42b02055..de3b438115 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 09a43f7b6b..f7335054cf 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 178946c217..04910f5410 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 d9b77fa917..8f357097ab 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 599b3f4bfa..39ec7a9acd 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 91b9aa7751..e3541c0ece 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 3813b51578..312f5813bc 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 dec976f8e8..b7d44515f4 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 66fdfe7d82..02d68f9ed1 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 d0de34a123..9690e01db3 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 0d7f678006..c444851b1e 100644 --- a/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl +++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/BufferRole.aidl @@ -35,5 +35,5 @@ parcelable BufferRole { * 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 0000000000..85d2a03a48 --- /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 0240e3c0df..2a9757b323 100644 --- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl +++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl @@ -20,6 +20,7 @@ import android.hardware.common.NativeHandle; 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 @@ interface IPreparedModel { 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/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h index b4587acbf7..cb6ff4b1cd 100644 --- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h +++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h @@ -20,13 +20,12 @@ #include <nnapi/IDevice.h> #include <nnapi/Result.h> #include <nnapi/Types.h> -#include <nnapi/hal/CommonUtils.h> #include <string> namespace aidl::android::hardware::neuralnetworks::utils { -nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name); +::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name); } // namespace aidl::android::hardware::neuralnetworks::utils diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp index c47ba0ec1c..45bc005e9f 100644 --- a/neuralnetworks/aidl/utils/src/Conversions.cpp +++ b/neuralnetworks/aidl/utils/src/Conversions.cpp @@ -472,7 +472,7 @@ GeneralResult<BufferRole> unvalidatedConvert(const aidl_hal::BufferRole& bufferR 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 @@ nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRol 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/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp index 5ec6ded5e5..511de559a6 100644 --- a/neuralnetworks/aidl/utils/src/Service.cpp +++ b/neuralnetworks/aidl/utils/src/Service.cpp @@ -18,6 +18,7 @@ #include <android/binder_auto_utils.h> #include <android/binder_manager.h> +#include <android/binder_process.h> #include <nnapi/IDevice.h> #include <nnapi/Result.h> @@ -29,19 +30,21 @@ namespace aidl::android::hardware::neuralnetworks::utils { -nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) { +nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) { + auto fullName = std::string(IDevice::descriptor) + "/" + instanceName; hal::utils::ResilientDevice::Factory makeDevice = - [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> { - auto service = blocking ? IDevice::fromBinder( - ndk::SpAIBinder(AServiceManager_getService(name.c_str()))) - : IDevice::fromBinder(ndk::SpAIBinder( - AServiceManager_checkService(name.c_str()))); + [instanceName, + name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> { + const auto& getService = + blocking ? AServiceManager_getService : AServiceManager_checkService; + auto service = IDevice::fromBinder(ndk::SpAIBinder(getService(name.c_str()))); if (service == nullptr) { return NN_ERROR() << (blocking ? "AServiceManager_getService" : "AServiceManager_checkService") << " returned nullptr"; } - return Device::create(name, std::move(service)); + ABinderProcess_startThreadPool(); + return Device::create(instanceName, std::move(service)); }; return hal::utils::ResilientDevice::create(std::move(makeDevice)); diff --git a/neuralnetworks/aidl/utils/test/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h index 545b491f1d..36e0ec392d 100644 --- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h +++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h @@ -39,6 +39,8 @@ class MockPreparedModel final : public BnPreparedModel { 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 4eb704b6e0..14404292c9 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 @@ class DeviceMemoryAllocator { 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 bool isOutputSizeGreaterThanOne(const TestModel& testModel, uint32_t inde } 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 @@ class ExecutionContext { 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 @@ std::optional<Request> ExecutionContext::createRequest(const TestModel& testMode } // 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 @@ std::optional<Request> ExecutionContext::createRequest(const TestModel& testMode 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 @@ void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device, } 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 @@ void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device, 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 @@ void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device, 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 @@ void EvaluatePreparedCoupledModels(const std::shared_ptr<IDevice>& device, 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 57bc1aed54..596f8ae58e 100644 --- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp +++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp @@ -203,6 +203,10 @@ class InvalidPreparedModel : public BnPreparedModel { 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 @@ class MemoryDomainAllocateTest : public MemoryDomainTestBase, 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_P(MemoryDomainAllocateTest, NullptrPreparedModel) { // 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_P(MemoryDomainAllocateTest, InvalidPreparedModel) { // 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 @@ TEST_P(MemoryDomainAllocateTest, InvalidModelIndex) { // 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 @@ TEST_P(MemoryDomainAllocateTest, InvalidIOIndex) { // 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 @@ TEST_P(MemoryDomainAllocateTest, SameRoleSpecifiedTwice) { // 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 @@ TEST_P(MemoryDomainAllocateTest, ConflictRankBetweenRoleAndDesc) { 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 @@ TEST_P(MemoryDomainAllocateTest, ConflictDimensionsBetweenRoleAndDesc) { 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 @@ TEST_P(MemoryDomainAllocateTest, ConflictRankWithScalarRole) { 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 @@ class MemoryDomainCopyTestBase : public MemoryDomainTestBase { 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 @@ class MemoryDomainExecutionTest 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 @@ class MemoryDomainExecutionTest 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 @@ TEST_P(MemoryDomainExecutionTest, InvalidDimensions) { 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 58db98f374..9ace1a9591 100644 --- a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp +++ b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp @@ -51,6 +51,10 @@ constexpr auto kShortDuration = std::chrono::milliseconds{5}; 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 @@ static MaybeResults executeSynchronously(const std::shared_ptr<IPreparedModel>& 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 runExecutionTest(const std::shared_ptr<IPreparedModel>& preparedModel, 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 3be4c1b97d..29e2471777 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 @@ static void validate(const std::shared_ptr<IPreparedModel>& preparedModel, 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 @@ void validateRequest(const std::shared_ptr<IPreparedModel>& preparedModel, const 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 2d91b8edd9..0c3a19674e 100644 --- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp @@ -127,6 +127,8 @@ void validateModel(const std::shared_ptr<IDevice>& device, const Model& model); // 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 @@ void validateEverything(const std::shared_ptr<IDevice>& device, const Model& mod 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 @@ INSTANTIATE_GENERATED_TEST(ValidationTest, [](const std::string& testName) { 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 9b81ee116e..4312d3a4a1 100644 --- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h @@ -52,7 +52,7 @@ void createPreparedModel(const std::shared_ptr<IDevice>& device, const Model& mo 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/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp index 9f8b9bbbfd..5f36dff2cd 100644 --- a/neuralnetworks/utils/service/Android.bp +++ b/neuralnetworks/utils/service/Android.bp @@ -35,12 +35,15 @@ cc_library_static { "neuralnetworks_utils_hal_1_1", "neuralnetworks_utils_hal_1_2", "neuralnetworks_utils_hal_1_3", + "neuralnetworks_utils_hal_aidl", "neuralnetworks_utils_hal_common", ], shared_libs: [ + "android.hardware.neuralnetworks-V1-ndk_platform", "android.hardware.neuralnetworks@1.0", "android.hardware.neuralnetworks@1.1", "android.hardware.neuralnetworks@1.2", "android.hardware.neuralnetworks@1.3", + "libbinder_ndk", ], } diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp index a59549dbf9..c83bcc916c 100644 --- a/neuralnetworks/utils/service/src/Service.cpp +++ b/neuralnetworks/utils/service/src/Service.cpp @@ -16,7 +16,9 @@ #include "Service.h" +#include <aidl/android/hardware/neuralnetworks/IDevice.h> #include <android-base/logging.h> +#include <android/binder_manager.h> #include <android/hardware/neuralnetworks/1.0/IDevice.h> #include <android/hardware/neuralnetworks/1.1/IDevice.h> #include <android/hardware/neuralnetworks/1.2/IDevice.h> @@ -31,6 +33,7 @@ #include <nnapi/hal/1.1/Service.h> #include <nnapi/hal/1.2/Service.h> #include <nnapi/hal/1.3/Service.h> +#include <nnapi/hal/aidl/Service.h> #include <functional> #include <memory> @@ -42,11 +45,12 @@ namespace android::hardware::neuralnetworks::service { namespace { +namespace aidl_hal = ::aidl::android::hardware::neuralnetworks; using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>; -void getDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice, - std::vector<nn::SharedDevice>* devices, - std::unordered_set<std::string>* registeredDevices) { +void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice, + std::vector<nn::SharedDevice>* devices, + std::unordered_set<std::string>* registeredDevices) { CHECK(devices != nullptr); CHECK(registeredDevices != nullptr); @@ -66,18 +70,52 @@ void getDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice, } } +void getAidlDevices(std::vector<nn::SharedDevice>* devices, + std::unordered_set<std::string>* registeredDevices) { + CHECK(devices != nullptr); + CHECK(registeredDevices != nullptr); + + std::vector<std::string> names; + constexpr auto callback = [](const char* serviceName, void* names) { + static_cast<std::vector<std::string>*>(names)->emplace_back(serviceName); + }; + + // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so + // there is no need for a workaround supported on lower levels. + if (__builtin_available(android __ANDROID_API_S__, *)) { + AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor, + static_cast<void*>(&names), callback); + } + + for (const auto& name : names) { + if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) { + auto maybeDevice = aidl_hal::utils::getDevice(name); + if (maybeDevice.has_value()) { + auto device = std::move(maybeDevice).value(); + CHECK(device != nullptr); + devices->push_back(std::move(device)); + } else { + LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code + << ": " << maybeDevice.error().message; + } + } + } +} + std::vector<nn::SharedDevice> getDevices() { std::vector<nn::SharedDevice> devices; std::unordered_set<std::string> registeredDevices; - getDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices, - ®isteredDevices); - getDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices, - ®isteredDevices); - getDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices, - ®isteredDevices); - getDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices, - ®isteredDevices); + getAidlDevices(&devices, ®isteredDevices); + + getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices, + ®isteredDevices); + getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices, + ®isteredDevices); + getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices, + ®isteredDevices); + getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices, + ®isteredDevices); return devices; } diff --git a/power/stats/aidl/Android.bp b/power/stats/aidl/Android.bp index 454c69a771..0dbf9b49e0 100644 --- a/power/stats/aidl/Android.bp +++ b/power/stats/aidl/Android.bp @@ -41,4 +41,5 @@ aidl_interface { enabled: true, }, }, + host_supported: true, } diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal index d20133235e..a4e8811993 100644 --- a/radio/1.6/IRadio.hal +++ b/radio/1.6/IRadio.hal @@ -544,4 +544,43 @@ interface IRadio extends @1.5::IRadio { * 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 a53d7c1212..9788345f3f 100644 --- a/radio/1.6/IRadioIndication.hal +++ b/radio/1.6/IRadioIndication.hal @@ -23,7 +23,9 @@ import @1.6::LinkCapacityEstimate; 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 @@ interface IRadioIndication extends @1.5::IRadioIndication { */ oneway currentLinkCapacityEstimate_1_6(RadioIndicationType type, LinkCapacityEstimate lce); - /** * Indicates current signal strength of the radio. * @@ -113,4 +114,27 @@ interface IRadioIndication extends @1.5::IRadioIndication { */ 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 d65c6d0fe4..33fe94fa4a 100644 --- a/radio/1.6/IRadioResponse.hal +++ b/radio/1.6/IRadioResponse.hal @@ -27,6 +27,7 @@ import @1.6::RadioResponseInfo; 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 @@ interface IRadioResponse extends @1.5::IRadioResponse { * RadioError:RADIO_NOT_AVAILABLE * RadioError:MODEM_ERR * RadioError:INVALID_ARGUMENTS + * RadioError:REQUEST_NOT_SUPPORTED */ oneway setDataThrottlingResponse(RadioResponseInfo info); @@ -432,7 +434,61 @@ interface IRadioResponse extends @1.5::IRadioResponse { * 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 95eba69948..3fd31cc7da 100644 --- a/radio/1.6/types.hal +++ b/radio/1.6/types.hal @@ -1027,18 +1027,6 @@ struct RouteSelectionDescriptor { */ 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 @@ struct ImsiEncryptionInfo { @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 91d98cbce1..e060dae6b8 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 @@ TEST_P(RadioHidlTest_v1_6, getSlicingConfig) { 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 @@ TEST_P(RadioHidlTest_v1_6, setDataThrottling) { 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 @@ TEST_P(RadioHidlTest_v1_6, setDataThrottling) { 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 @@ TEST_P(RadioHidlTest_v1_6, setDataThrottling) { 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 @@ TEST_P(RadioHidlTest_v1_6, setDataThrottling) { 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 @@ TEST_P(RadioHidlTest_v1_6, setCarrierInfoForImsiEncryption_1_6) { 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 @@ TEST_P(RadioHidlTest_v1_6, setCarrierInfoForImsiEncryption_1_6) { ::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_F(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 23378b53d0..4fc17e54d0 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 @@ class RadioResponse_v1_6 : public ::android::hardware::radio::V1_6::IRadioRespon ::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 @@ class RadioResponse_v1_6 : public ::android::hardware::radio::V1_6::IRadioRespon 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 @@ class RadioIndication_v1_6 : public ::android::hardware::radio::V1_6::IRadioIndi 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 e7a96807a9..8292131740 100644 --- a/radio/1.6/vts/functional/radio_indication.cpp +++ b/radio/1.6/vts/functional/radio_indication.cpp @@ -412,3 +412,16 @@ Return<void> RadioIndication_v1_6::cellInfoList_1_6( ::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 d0c2984d13..2b6d1bb57e 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::getIMSIForAppResponse( } 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 @@ Return<void> RadioResponse_v1_6::acknowledgeRequest(int32_t /*serial*/) { /* 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 @@ Return<void> RadioResponse_v1_6::getSlicingConfigResponse( 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 117abf3211..8667f0ab4f 100644 --- a/radio/config/1.3/types.hal +++ b/radio/config/1.3/types.hal @@ -31,6 +31,11 @@ struct HalDeviceCapabilities { * <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 895ae08c23..50038eb478 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::Return; 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 11e3cce147..5501ae25e8 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::setModemsConfigResponse( } 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 54cb4b8ebb..6766d99311 100644 --- a/security/keymint/aidl/Android.bp +++ b/security/keymint/aidl/Android.bp @@ -19,7 +19,8 @@ aidl_interface { 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 5adbdc10ca..6da124f601 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 21721bfa39..90f2e6ee54 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 d9d9c13e3b..c952a3152a 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 feba9d0ca3..004988326b 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 470d53405c..645f0a72ee 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/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl index 9b0b6f6a77..d04d49cea8 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * 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. @@ -31,19 +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.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, +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 5a15aad765..0df709609f 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 d7ec0068f6..6b4a9aefb2 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 91e289950b..69ec4cefbb 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 3205a461af..2e07924382 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 926f2ecd52..dfc98f0066 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 bb186694ce..4f6fb28cd3 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 @@ interface IKeyMintDevice { 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 28a83da0fa..5ac2b4a139 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 8387ecc9dd..88c479c7d2 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 91ac7be061..008381f282 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 b85203fd2f..9f77d3e3d5 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 4500288542..9560d8d2b5 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 d959ac4536..2113e42a8e 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 2b65567d8f..4b3c659ffe 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 ee8abda648..c5a1e011d2 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 fc57cd22e3..7a0b074fe5 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 f891de6c8e..b84bec1fc0 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 30b38e1f01..8095e8ce04 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 bfb6ea1e98..dba4a8a06e 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 64cce78bd5..d1610b4d6f 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 628476d7e8..0d278e0af9 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 ccb040437f..7591318289 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 58f8bd3278..a7d1de5fd4 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 8300b0d75c..18208939eb 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 @@ package android.hardware.security.keymint; /** * 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 8167cebacd..b4bc60c05b 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 @@ import android.hardware.security.keymint.KeyParameter; * 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 aaf9f3caa4..2304a580a5 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 @@ import android.hardware.security.keymint.KeyParameter; /** * 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 629c89f02e..749da81aa8 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 @@ package android.hardware.security.keymint; /** * 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 0e5d898804..21dfdd554c 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 @@ package android.hardware.security.keymint; /** * 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 0000000000..3ea14a1b97 --- /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 b44da5a51c..a8768c3ec9 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 @@ package android.hardware.security.keymint; /** * 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 b9d16467b0..5b1c10c2c5 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 @@ package android.hardware.security.keymint; /** * 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 95b38f2958..0e2c5f29c8 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 @@ package android.hardware.security.keymint; /** * 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 57150d5da6..0933bd560b 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 @@ import android.hardware.security.secureclock.Timestamp; * 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 33f71b8d3c..2d9d0ff86a 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 @@ package android.hardware.security.keymint; * 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 384416e692..17aab25a0c 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 @@ import android.hardware.security.secureclock.TimeStampToken; * 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 @@ interface IKeyMintDevice { */ 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 1c2511b34e..5ad54cda19 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.HardwareAuthToken; 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 1b09e9dfb7..1cb50ba11c 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 @@ import android.hardware.security.keymint.ProtectedData; * 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 { @@ -165,7 +167,7 @@ interface IRemotelyProvisionedComponent { * protected: bstr .cbor { * 1 : -8, // Algorithm : EdDSA * }, - * unprotected: bstr .size 0 + * unprotected: { }, * payload: bstr .cbor SignatureKey, * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) * ] @@ -190,7 +192,7 @@ interface IRemotelyProvisionedComponent { * protected: bstr .cbor { * 1 : -8, // Algorithm : EdDSA * }, - * unprotected: bstr .size 0 + * unprotected: { }, * payload: bstr .cbor Eek, * signature: bstr PureEd25519(.cbor EekSignatureInput) * ] @@ -239,7 +241,7 @@ interface IRemotelyProvisionedComponent { * protected : bstr .cbor { * 1 : 5, // Algorithm : HMAC-256 * }, - * unprotected : bstr .size 0, + * unprotected : { }, * // Payload is PublicKeys from keysToSign argument, in provided order. * payload: bstr .cbor [ * PublicKey ], * tag: bstr @@ -256,7 +258,7 @@ interface IRemotelyProvisionedComponent { * @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 3a32e4d224..25fdee3d75 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 @@ import android.hardware.security.keymint.SecurityLevel; * 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 69bec2d79f..c589ca14d4 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 @@ import android.hardware.security.keymint.KeyCharacteristics; /** * This structure is returned when a new key is created with generateKey(), importKey() or * importWrappedKey(). + * @hide */ @VintfStability parcelable KeyCreationResult { diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl index 6ad8e3d922..da3d52122c 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 @@ package android.hardware.security.keymint; /** * 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 ae0d152f16..8da75784de 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 @@ import android.hardware.security.keymint.SecurityLevel; /** * 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 0cd53c2fbb..f89612593b 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 @@ package android.hardware.security.keymint; * 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 bf6c9b204d..b69e6787e7 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 @@ import android.hardware.security.keymint.Tag; /** * 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 a4f5154e62..59016f2c3b 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.KeyPurpose; 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 @@ union KeyParameterValue { 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 978a02723c..c874fc3a07 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 @@ package android.hardware.security.keymint; /** * 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 da85a5048f..a26094c4b9 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 @@ package android.hardware.security.keymint; /** * 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 { @@ -29,7 +30,7 @@ parcelable MacedPublicKey { * * MacedPublicKey = [ // COSE_Mac0 * protected: bstr .cbor { 1 : 5}, // Algorithm : HMAC-256 - * unprotected: bstr .size 0, + * unprotected: { }, * payload : bstr .cbor PublicKey, * tag : bstr HMAC-256(K_mac, MAC_structure) * ] diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl index 80b73bd0dc..fbb373b873 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 @@ package android.hardware.security.keymint; * 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 1ec3bf0718..44f316fde7 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 @@ package android.hardware.security.keymint; /** * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to * authenticate the keysToSign (see keysToSignMac output argument). + * @hide */ @VintfStability parcelable ProtectedData { @@ -80,7 +81,7 @@ parcelable ProtectedData { * bstr .cbor { // Protected params * 1 : -8, // Algorithm : EdDSA * }, - * bstr .size 0, // Unprotected params + * { }, // Unprotected params * bstr .size 32, // MAC key * bstr PureEd25519(DK_priv, .cbor SignedMac_structure) * ] @@ -127,7 +128,7 @@ parcelable ProtectedData { * protected: bstr .cbor { * 1 : -8, // Algorithm : EdDSA * }, - * unprotected: bstr .size 0, + * unprotected: { }, * payload: bstr .cbor BccPayload, * // First entry in the chain is signed by DK_pub, the others are each signed by their * // immediate predecessor. See RFC 8032 for signature representation. diff --git a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl index ecbde8c97c..80c63b2de3 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 @@ package android.hardware.security.keymint; * 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 aa9aa6f1c9..6243bb9b78 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 @@ import android.hardware.security.keymint.TagType; /** * 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 a273af3f8c..1ba6ededf2 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 @@ package android.hardware.security.keymint; /** * 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 63b91fefdf..ebdc9b7790 100644 --- a/security/keymint/aidl/default/Android.bp +++ b/security/keymint/aidl/default/Android.bp @@ -39,6 +39,17 @@ cc_binary { 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 2373b2682b..4dbaa05d54 100644 --- a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp +++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp @@ -156,7 +156,7 @@ StatusOr<bytevec /* pubkeys */> validateAndExtractPubkeys(bool testMode, } auto protectedParms = macedKeyItem->asArray()->get(kCoseMac0ProtectedParams)->asBstr(); - auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asBstr(); + auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asMap(); auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr(); auto tag = macedKeyItem->asArray()->get(kCoseMac0Tag)->asBstr(); if (!protectedParms || !unprotectedParms || !payload || !tag) { @@ -322,8 +322,8 @@ ScopedAStatus RemotelyProvisionedComponent::generateEcdsaP256KeyPair(bool testMo 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 @@ ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest( 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 e8d2343091..65b1bbc87e 100644 --- a/security/keymint/aidl/default/RemotelyProvisionedComponent.h +++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.h @@ -39,8 +39,8 @@ class RemotelyProvisionedComponent : public BnRemotelyProvisionedComponent { 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 0000000000..e5a93457c2 --- /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 db53a8f8fa..9b797de802 100644 --- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp @@ -97,9 +97,9 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) { ASSERT_NE(protParms, nullptr); ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n 1 : 5,\n}"); - auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asBstr(); + auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap(); ASSERT_NE(unprotParms, nullptr); - ASSERT_EQ(unprotParms->value().size(), 0); + ASSERT_EQ(unprotParms->size(), 0); auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr(); ASSERT_NE(payload, nullptr); @@ -150,9 +150,9 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) { ASSERT_NE(protParms, nullptr); ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n 1 : 5,\n}"); - auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asBstr(); + auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap(); ASSERT_NE(unprotParms, nullptr); - ASSERT_EQ(unprotParms->value().size(), 0); + ASSERT_EQ(unprotParms->size(), 0); auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr(); ASSERT_NE(payload, nullptr); @@ -227,11 +227,12 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { 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); @@ -279,7 +280,7 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { .add(ALGORITHM, HMAC_256) .canonicalize() .encode()) - .add(cppbor::Bstr()) // unprotected + .add(cppbor::Map()) // unprotected .add(cppbor::Array().encode()) // payload (keysToSign) .add(std::move(keysToSignMac)); // tag @@ -297,11 +298,12 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { 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 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { 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); @@ -364,7 +368,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { .add(ALGORITHM, HMAC_256) .canonicalize() .encode()) - .add(cppbor::Bstr()) // unprotected + .add(cppbor::Map()) // unprotected .add(cborKeysToSign_.encode()) // payload .add(std::move(keysToSignMac)); // tag @@ -384,10 +388,12 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) { 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 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) { 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 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) { 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/keymint/support/cppcose.cpp b/security/keymint/support/cppcose.cpp index c626adeccb..bafb2b6bc9 100644 --- a/security/keymint/support/cppcose.cpp +++ b/security/keymint/support/cppcose.cpp @@ -85,7 +85,7 @@ ErrMsgOr<cppbor::Array> constructCoseMac0(const bytevec& macKey, const bytevec& return cppbor::Array() .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode()) - .add(cppbor::Bstr() /* unprotected */) + .add(cppbor::Map() /* unprotected */) .add(payload) .add(tag.moveValue()); } @@ -97,7 +97,7 @@ ErrMsgOr<bytevec /* payload */> parseCoseMac0(const cppbor::Item* macItem) { } auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr(); - auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asBstr(); + auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap(); auto payload = mac->get(kCoseMac0Payload)->asBstr(); auto tag = mac->get(kCoseMac0Tag)->asBstr(); if (!protectedParms || !unprotectedParms || !payload || !tag) { @@ -115,7 +115,7 @@ ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macIt } auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr(); - auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asBstr(); + auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap(); auto payload = mac->get(kCoseMac0Payload)->asBstr(); auto tag = mac->get(kCoseMac0Tag)->asBstr(); if (!protectedParms || !unprotectedParms || !payload || !tag) { @@ -168,7 +168,7 @@ ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map prote return cppbor::Array() .add(protParms) - .add(bytevec{} /* unprotected parameters */) + .add(cppbor::Map() /* unprotected parameters */) .add(payload) .add(*signature); } @@ -185,7 +185,7 @@ ErrMsgOr<bytevec> verifyAndParseCoseSign1(bool ignoreSignature, const cppbor::Ar } const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr(); - const cppbor::Bstr* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asBstr(); + const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap(); const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr(); const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr(); diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp index 111cb309b0..3e4f3f750e 100644 --- a/security/keymint/support/remote_prov_utils.cpp +++ b/security/keymint/support/remote_prov_utils.cpp @@ -83,7 +83,7 @@ ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(bool ignoreSignature, const cppbor: } const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr(); - const cppbor::Bstr* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asBstr(); + const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap(); const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr(); const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr(); diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp index c8e5c025ff..c78be3b20c 100644 --- a/security/secureclock/aidl/Android.bp +++ b/security/secureclock/aidl/Android.bp @@ -16,7 +16,8 @@ aidl_interface { 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 377889716a..4ecc1e4430 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 00a8bb256d..d105ac8f6c 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 bebeb5cb9c..2e0e389d9e 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 577dd8f231..a742ff0dad 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 @@ import android.hardware.security.secureclock.TimeStampToken; * 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 dd957325e9..71b4278d55 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 @@ import android.hardware.security.secureclock.Timestamp; /** * 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 27758e1d25..5061aa4a7c 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 @@ package android.hardware.security.secureclock; * 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 6dfa4175c7..56c8e1d361 100644 --- a/security/secureclock/aidl/vts/functional/Android.bp +++ b/security/secureclock/aidl/vts/functional/Android.bp @@ -39,11 +39,11 @@ cc_test { 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 4861c7c7af..0000000000 --- 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 2509936d99..e76efe7f5d 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 9b65046060..e15fd49aa6 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 906303f15b..eca8d87f57 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 @@ import android.hardware.security.sharedsecret.SharedSecretParameters; * 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 @@ import android.hardware.security.sharedsecret.SharedSecretParameters; * 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 @@ interface ISharedSecret { /** * 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 @@ interface ISharedSecret { * 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 691b3f1386..814469980b 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 @@ package android.hardware.security.sharedsecret; * 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 1bc5bebc91..d3747fc071 100644 --- a/security/sharedsecret/aidl/vts/functional/Android.bp +++ b/security/sharedsecret/aidl/vts/functional/Android.bp @@ -39,11 +39,11 @@ cc_test { 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 c6697bcda5..0000000000 --- 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 83f6ef39db..842612087f 100644 --- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp +++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp @@ -114,14 +114,14 @@ class SharedSecretAidlTest : public ::testing::Test { 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 @@ vector<shared_ptr<ISharedSecret>> SharedSecretAidlTest::allSharedSecrets_; 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, GetParameters) { } 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 @@ TEST_F(SharedSecretAidlTest, ComputeSharedSecret) { // 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 @@ inline final_action<F> finally(const F& f) { } 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, ComputeSharedSecretCorruptNonce) { } 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 c4f92c8386..63e4eb0704 100644 --- a/sensors/common/utils/EventMessageQueueWrapper.h +++ b/sensors/common/utils/EventMessageQueueWrapper.h @@ -33,7 +33,7 @@ namespace sensors { 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 8cf5003f91..47a8cc0b4a 100644 --- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h +++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h @@ -462,6 +462,7 @@ TEST_P(SensorsHidlTest, InjectSensorEventData) { // 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 @@ TEST_P(SensorsHidlTest, InjectSensorEventData) { ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status); } - getEnvironment()->unregisterCallback(); ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); } @@ -603,7 +603,7 @@ void SensorsHidlTest::runFlushTest(const std::vector<SensorInfoType>& sensors, b << " 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 6fdc97ca29..ed739cf782 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.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp b/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp index 103f2dca6c..c5b4b2fe58 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 @@ using ::android::hardware::tv::cec::V1_1::IHdmiCecCallback; #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 @@ TEST_P(HdmiCecTest, ClearAddLogicalAddress) { 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; diff --git a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp index 8092d5e7d2..15ea3e9896 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 @@ TEST_P(TvInputHidlTest, OpenAnOpenedStreamsTest) { 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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl new file mode 100644 index 0000000000..de3ad3c032 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// 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.vibrator; +@VintfStability +parcelable ActivePwle { + float startAmplitude; + float startFrequency; + float endAmplitude; + float endFrequency; + int duration; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl new file mode 100644 index 0000000000..d38c584d76 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// 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.vibrator; +@Backing(type="int") @VintfStability +enum Braking { + NONE = 0, + CLAB = 1, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl new file mode 100644 index 0000000000..fa7b43abd0 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// 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.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 0995d2d7af..3be58a1490 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 0b4b527359..50de13fc27 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 0d2b340a6c..adf0f2009f 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 808644a4b5..af5e15871b 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 1f2d946836..b7afb663cf 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 @@ interface IVibrator { 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 @@ interface IVibrator { 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 f99ecc1143..99d6d2290d 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 8e3ac88e8c..290c68d877 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/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl new file mode 100644 index 0000000000..584bcf4a47 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// 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.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 0000000000..fd5f8d1973 --- /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 0000000000..2bc51db3f6 --- /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 0000000000..00675ed0fc --- /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 cba76dc745..592d151d32 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 @@ interface IVibrator { * 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 @@ interface IVibrator { 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. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_GET_RESONANT_FREQUENCY) * - * @return Measured resonant frequency in Hz. + * @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. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_GET_Q_FACTOR) * - * @return Measured 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 0000000000..813c7dcb33 --- /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 bf61bfec91..c6682b318f 100644 --- a/vibrator/aidl/default/Vibrator.cpp +++ b/vibrator/aidl/default/Vibrator.cpp @@ -26,9 +26,16 @@ namespace vibrator { 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 @@ ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { 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 @@ ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) { 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 a2af9637ed..4203bf212c 100644 --- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h +++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h @@ -46,6 +46,15 @@ class Vibrator : public BnVibrator { 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 2540d0b1d5..a9d1ed5a51 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::ProcessState; 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 @@ const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStr 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 @@ class VibratorAidl : public testing::TestWithParam<std::tuple<int32_t, int32_t>> 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, OnThenOffBeforeTimeout) { } 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 @@ TEST_P(VibratorAidl, ValidateEffect) { 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 @@ TEST_P(VibratorAidl, ValidateEffect) { 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 @@ TEST_P(VibratorAidl, ValidateEffectWithCallback) { 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, ValidateEffectWithCallback) { } 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 @@ TEST_P(VibratorAidl, InvalidEffectsUnsupported) { 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 @@ TEST_P(VibratorAidl, InvalidEffectsUnsupported) { 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, ChangeVibrationExternalControl) { 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 @@ TEST_P(VibratorAidl, GetSupportedPrimitives) { 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 @@ TEST_P(VibratorAidl, GetPrimitiveDuration) { 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 @@ TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) { 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 @@ TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) { 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, ComposeUnsupportedPrimitives) { 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 @@ TEST_P(VibratorAidl, ComposeCallback) { 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 @@ TEST_P(VibratorAidl, ComposeCallback) { 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 @@ TEST_P(VibratorAidl, AlwaysOn) { 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, AlwaysOn) { } 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 @@ std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() { 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 @@ std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() { 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 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl); 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 7c04c6967a..0887c6b5c1 100644 --- a/wifi/1.5/Android.bp +++ b/wifi/1.5/Android.bp @@ -20,6 +20,7 @@ hidl_interface { "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 66d0a9c2f9..28b808ed32 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 @@ import @1.4::IWifi; * 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 5a3e2883d5..e199850c1a 100644 --- a/wifi/1.5/IWifiChip.hal +++ b/wifi/1.5/IWifiChip.hal @@ -303,4 +303,25 @@ interface IWifiChip extends @1.4::IWifiChip { 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 0000000000..ff276306fd --- /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 125a50fcca..338a8f13c1 100644 --- a/wifi/1.5/default/hidl_struct_util.cpp +++ b/wifi/1.5/default/hidl_struct_util.cpp @@ -954,27 +954,29 @@ bool convertLegacyVectorOfDebugRxPacketFateToHidl( 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 @@ bool convertLegacyLinkLayerRadioStatsToHidl( 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 @@ bool convertLegacyLinkLayerStatsToHidl( } 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 e70d7baa8a..4b4ebd6138 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 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { 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 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { 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 da98db8296..b9f20a4615 100644 --- a/wifi/1.5/default/wifi.cpp +++ b/wifi/1.5/default/wifi.cpp @@ -50,13 +50,21 @@ bool Wifi::isValid() { } 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 @@ Return<void> Wifi::debug(const hidl_handle& handle, } 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::startInternal() { 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 825c0bc182..840bdfd927 100644 --- a/wifi/1.5/default/wifi.h +++ b/wifi/1.5/default/wifi.h @@ -52,8 +52,11 @@ class Wifi : public V1_5::IWifi { // 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 @@ class Wifi : public V1_5::IWifi { // 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 @@ class Wifi : public V1_5::IWifi { 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 0499f456c1..961f9da4c2 100644 --- a/wifi/1.5/default/wifi_chip.cpp +++ b/wifi/1.5/default/wifi_chip.cpp @@ -747,6 +747,13 @@ Return<void> WifiChip::getUsableChannels( 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 @@ WifiChip::getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask, 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 92d639f8b5..bd40ead35a 100644 --- a/wifi/1.5/default/wifi_chip.h +++ b/wifi/1.5/default/wifi_chip.h @@ -184,6 +184,8 @@ class WifiChip : public V1_5::IWifiChip { 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 @@ class WifiChip : public V1_5::IWifiChip { 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 45ad84b8c1..848fbd6114 100644 --- a/wifi/1.5/default/wifi_legacy_hal.cpp +++ b/wifi/1.5/default/wifi_legacy_hal.cpp @@ -1676,6 +1676,10 @@ WifiLegacyHal::getUsableChannels(uint32_t band_mask, uint32_t iface_mode_mask, 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 8ebc66aaa6..2bb7631efa 100644 --- a/wifi/1.5/default/wifi_legacy_hal.h +++ b/wifi/1.5/default/wifi_legacy_hal.h @@ -716,6 +716,8 @@ class WifiLegacyHal { 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 6212960d7a..dd860d6920 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 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { 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 0543004f52..3c197916eb 100644 --- a/wifi/1.5/types.hal +++ b/wifi/1.5/types.hal @@ -253,6 +253,21 @@ struct StaLinkLayerIfaceStats { 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 f453df7585..2230da8609 100644 --- a/wifi/hostapd/1.3/types.hal +++ b/wifi/hostapd/1.3/types.hal @@ -25,7 +25,7 @@ package android.hardware.wifi.hostapd@1.3; * 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 { |